Например: Программист
0,2
рейтинг
2 мая 2010 в 20:56

Разработка → Модификация изображений для сайта, или какие бывают превьюшки

Наверняка каждый из вас делал сайт, где администратор, или даже пользователи, могу закачивать изображения, которые должны отобразится на сайте. Такие изображения можно разделить условно на 2 группы: те, которые вставляются в тело статей, скажем с помощью wysiwyg-редактора, и те, которые закачиваются в отдельное поле и потом выводятся в заранее отведенном месте. Ко вторым относятся всевозможные картинки к новостям, фотографии в фото-галереях, какие-нибудь логотипы партнеров и прочее.

И те и другие требуют какой-то обработки после размещения, но каждая группа имеет свои особенности.

Первая группа изображений (вставляемая через wysiwyg) сложно поддается нахождению, потому что изображения приходится доставать из супа тегов. Но зато такие изображения зачастую требует достаточно простой обработки, пропорционального изменения размеров. Именно из-за сложности нахождения и простоты обработки, чаще всего их не обрабатывают автоматически, а оставляют на откуп администраторам сайтов. Те, в зависимости от своей грамотности и лени, меняют размеры перед размещением на сайте, или нет. Но иногда администраторы даже самых опрятных сайтов не заморачиваются по этому поводу, отчего изображения ужасно долго грузятся, и, в зависимости от браузера, либо выглядят паршиво, либо тормозят при прорисовке. Конечно, скриншоты — еще не самый плохой вариант. Зачастую на разных сайтах можно встретить фотографии с фотокамер, разрешением 3000 пикселей и выше.

Скажу по секрету, мой коллега nex работает над решением этой проблемы с помощью не безызвестного проекта jevix. Думаю, скоро он опубликует статью на эту тему.

Вторая группа изображений отличается простотой получения изображения для обработки и сложностью самой обработки. Часто для одной фотографии нужно создать несколько изображений разного размера и разного качества, так называемые превьюшки, thumbnails. Честно говоря, меня просто удивляет огромное количество библиотек и способов создания превьюшек, имеющих в своем арсенале только 2 параметра — ширина и высота нужной картинки, и, иногда, еще логическая переменная, означающая, сохранять ли пропорции. А между тем, различных способов кадрирования изображения очень много. Тем не менее, на мой взгляд, они прекрасно поддаются класификации и алгоритмизации. Именно этому я бы хотел посвятить большую часть топика.

Теория



Итак, есть закаченные изображения и есть разные места, где они должны выводиться. Начнем с простого — отдельное окно, либо lightbox. Нужно сохранить соотношение сторон и как-то ограничить размеры изображение, чтобы пользователю не пришлось долго ждать загрузки. Скажем 1024×768 пикселей, что для фотографий на сайте вполне достаточно.

image

Именно с этой простой задачей обычно призваны справиться большинство библиотек для создания превьюшек (хотя изображения таких размеров не называют превьюшками, технически разницы нет, нам нужно откорректировать размер изображения по некоторым правилам).

Некоторые библиотеки позволяют дополнительно указать флаг, указывающий на то, что не нужно соблюдать пропорции. Результат получается таким:

image

Честно говоря, мне ни разу не приходилось встречаться со случаями, где такой способ масштабирования был бы уместен.

С большими картинками разобрались. Что же с маленькими, которые самые настоящие превьюшки. Очень часто такие превьюшки располагаются одним списком и к ним добавляется требование — они должны иметь строго указанный размер. Но искажать пропорции попрежнему нельзя. Что же делать? Выручает добавление паддингов — однотонных, в случае однотонного фона под превьюшками, либо прозрачных (хотя это не самый лучший вариант).

image

Но бывает, что и такие паддинги смотрятся немного не к месту. А вот, если бы изображение растягивалось до большей из сторон, а все лишнее отрезалось — было бы самое то.

image

Может показаться, что обрезать изображения не очень гуманно. Но на самом деле, это так только для постеров и логотипов. А если обрезать фотографии, зачастую ничего важного не теряется. Зато при обрезании фотографий есть другая особенность — лица людей чаще всего находятся в верхней части изображения. Отсюда еще одно правило, накладываемое при обрезании фотографии — обрезать сверху нужно чуть меньше, чем снизу.

image

В идеале, положение исходной картинки на результирующей должно настраиваться. Может получится так, что важна только нижняя, или только верхняя часть (актуально, скажем, для грамот).

Иногда картинку нужно вырезать способом, прямо противоположным самому первому. Вместо того, чтобы сделать изображение не больше заданного размера, нужно сделать его не меньше заданного размера. А все, что выступает за края результирующего прямоугольника обрезать не нужно.

image

Иногда бывает нужен какой-то определенный размер по одной из координат, а размер другой координаты может быть произвольным.

image

Например, изображение к статье, которое должно занимать ровно половину ширины колонки. Другой пример — кадры их фильма, которые идут вряд и все должны иметь одинаковую высоту.

А недавно передо мной встала вот такая задача:

image

Закачиваемые логотипы должны располагаться в одну строчку фиксированной высоты. Если задать размер 150×70 и строгое соблюдение размеров с добавлением паддингов, то логотипы с маленькой шириной (первый на рисунке) будут занимать все 150 пикселей в ширину. А если просто сделать фиксированную высоту, то очень низкие и широкие логотипы (второй и третей) будут занимать в ширину слишком много места. Решение пришло в небольшом изменении моей классификации, а именно, я понял, что ширина и высота могут быть независимо друг от друга строгими или нет. Т.е. в данном случае алгоритм был такой — превьюшка размером 150×70 пикселей со строгим соблюдением высоты, но не ширины.

Практика


Как вы понимаете, все эти теоретические выкладки, без практики, гроша ломаного не стоят. Но, к сожалению, кода сегодня не будет. По большей части из-за того, что реализаций несколько и они под разные платформы (PHP и Django) и нужно немного привести их в порядок. Думаю, что когда доведу до блеска версию для Django, сделаю про нее отдельный пост, потому что там будет еще много плюшек, и вскользь упомяну про версию под PHP.

Вместо этого хочу привести список простых флагов и параметров, которые в 90% случаев спасают от написания отдельной функции под каждую превьюшку.

size — массив из 2-х чисел, ширины и высоты. Любое значение (но не оба сразу) может быть 0 (или NULL), что означает, что этот размер не нужно учитывать.
method — метод расчета размера. Либо «не больше заданного размера», либо «не меньше заданного размера», либо «в точности заданный размер».
enlarge — логическое значение, увеличивать маленькие изображения. Не всем нравится, кода картинку 100×100 растягивают до 1024×768
strict size — массив из 2-х логических значений. Означает строгое соответствие размера в результирующем изображении для каждого измерения.
align — массив из 2-х цифр. Означает смещение исходного изображения в результирующем в процентах отдельно для каждого измерения. Как для случаев, когда результирующее изображение больше, так и когда меньше.
back color — цвет, которым заполнятся паддинги.
Александр Карпинский @homm
карма
79,8
рейтинг 0,2
Например: Программист
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (57)

  • +12
    Я попробовала на некоторых сайтах генерировать превьюшки без обрезания и искажения пропорций, и располагать и не в ряд, а «плавающими». А пользователи при создании галереи могут передвигать их вправо-влево, получая не обязательно «строгие» ряды. Иногда такой способ позволяет добиться лучших результатов.



    На эту мысль меня навела покупка «нестандартного» бумажного фотоальбома, в котором на каждой странице можно было разместить 2 вертикальных и 3 горизонтальных фотографии.
    • +1
      К сожалению, такой способ мало применим при резиновой верстке. Плавающие картинки могут очень по разному располагаться при разной ширине окна.
      • +3
        Не спорю. Потому и написала — «иногда».
      • +6
        есть jQuery плагин Masonry, который распологает блоки наиболее компактно. думаю, он мог бы помочь.
        • 0
          К большому сожалению иногда приходится использовать джаваскрипт для таких вещей.
  • +2
    Вот старое, доброе решение:
    This PHP script uploads files and manipulates images very easily. The perfect script to generate thumbnails or create a photo gallery! It can convert, resize and work on uploaded images in many ways, add labels, watermarks and reflections and other image editing features. You can use it for files uploaded through an HTML form, a Flash uploader, or on local files. It uses the GD library.
    • 0
      При беглом взгляде мне не кажется, что эта библиотека умеет то, что требуется. Смотреть более пристально на более чем сотню не сгруппированных параметров не хочется.
  • +4
    Как вариант можно использовать вот это. Да, не спорю может установка и создание самой превьюшки займет не много больше времени — зато ты точно знаешь как эта самая превьюшка будет выглядеть
    • 0
      о! спасибо) а то когда-то потерял эту штуку, все никак найти не мог
    • 0
      Аналог, если кому-то пригодится есть готовый класс для CakePHP.
  • +1
    я в джанге использую уже давно — code.google.com/p/sorl-thumbnail/, только его поддерживать перестали походу, (((( а очень нужно продолжение.
    • 0
      Это отличный пример ничего не умеющего приложения. Я был поражен, сколько кода было написано не пригодного к реальному использованию и не имеющего никаких возможностей для расширения.
      • 0
        покажите мне аналог, который также удобно встраиваеться в джангу и также удобен с обрезкой изображений.
        • 0
          Всему свое время.
          • 0
            Во первых я Вас знаю ) приветствую.)

            Во вторых реально рабочего нормального примера я не смог найти.
  • –2
    ого, какой у вас тут жесткач оказывается
    у нас в Друпале все решается при помощи ImageCache + ImageCache_Actions и пяти кликов

    всем удачи ;)
    • 0
      дайте, пример, чтоб в модель можно было конфигурацию класть, и оригиналы сохранялись.

      Покажите, я же не в претензию.
      • 0
        оригиналы всегда сохраняются, далее при конфигурации вида выбирается какой пресет имаджкеша будет применяться при выводе картинки
  • +1
    Для Drupal есть отличный модуль Image Resize Filter. Он как раз позволяет справится с проблемой номер 1.
    Вставляем картинку через WYSIWYG. Задаем ее размеры (пропорционально тягая за границы) и модуль автоматически создаст миниатюру нужного размера. Таким образом, даже если пользователь админки загрузит картинку очень большого размера — в итоге получим уменьшенную миниатюру нужного размера.
  • +41
    Предложил бы еще один вариант организации галереи, вариации на тему технологий Филипс:


    Набросал на скорую руку из первых попавшихся картинок. Мне кажется алгоритм создания вполне можно автоматизировать на сервере, хотя могу и ошибаться — я не программист.
    • 0
      класс! только переход жестковат
      • +1
        Специально ничего не сглаживал и не подбирал под формат. Просто демонстрация того, что можно сделать с помощью растягивания и размытия.
        • +2
          И легко реализуется, хорошо адаптировали ambilight :)
      • +3
        а мне наоборот нравится так, картинка не будет напоминать размазню
    • +1
      Это хороший интересный способ. Надо взять на вооружение.
    • +2
      Идея отличная!
      А полчаса курения доки по ImageMagick позволят реализовать ее для всех вариантов, описываемых автором поста.
    • +9
      Простейший рабочий вариант с использованием Imagick. Фон масштабирует точно по нужному размеру. Изображение вписывает в фон минус 10% пропорционально. Размытие 10px.

      <?
      	function RenderImage($src_file, $dest_file, $width = '160', $height = '160')
      	{
      		$fon = new Imagick($src_file);
      		$fon -> resizeImage($width, $height, 0, 10);
      		
      		$im = new Imagick($src_file);
      		$im -> thumbnailImage($width - $width / 10, $height - $height / 10, true);
      		$im_width = $im -> getImageWidth();
      		$im_height = $im -> getImageHeight();
      		
      		$fon -> compositeImage($im, Imagick::COMPOSITE_OVER, ($width - $im_width) / 2, ($height - $im_height) / 2);
      		
      		$file = fopen($dest_file, 'w');
      		fwrite($file, $fon -> getImageBlob());
      		fclose($file);
      	}
      	
      	RenderImage('1.jpg', '2.jpg');
      ?>
      


      Исходное изображение


      Результат
      • 0
        Симпатишно.
        Интересно, что получится с картиной «Чёрный квадрат», если сделать из неё привью по той же схеме. Думаю, Малевич разрыдался бы, увидев это ;)
  • –3
    я для этих целей использую Highslide JS
    • +4
      Для преобразования изображений на стороне сервера? оО
  • 0
    Для PHP пользуюсь phpThumb. Могу ошибаться, но, по-моему, он умеет делать ограничение только по одной стороне.

    Ещё у него есть очень полезная фича, которую я теперь всегда использую при создании превьюшек: наложение unsharp mask. Сильно улучшает вид мелкой картинки. Параметры пришлось подобрать один раз, с тех пор работают для всех сайтов, какие делал.

    Другое дело, что алгоритм этот реализован на голом пхп, и занимает достаточно много времени и памяти. Поэтому собираюсь заюзать для тех же целей ImageMagick. Он тоже умеет unsharp, только параметры придется снова подобрать.
    • 0
      Ещё, кстати, бывает, что нужно на картинку наложить свой watermark, или попросту — лого. Это phpThumb также умеет. Самый простой способ — сделать PNG с нужной прозрачностью в нужных местах, и накладывать его.
  • +1
    Вот ещё один случай из практики

    Периодически возникает необходимость для каждой картинки генерить квадратную превьюшку с фрагментом этой картинки. В этом случае мне не годился вариант с уменьшением по меньшей стороне, и последующим обрезанием.

    Например, мне нужна превьюшка 50х50, а исходная картинка размером 1024х768. Если уменьшить её по вертикали до 50px, а потом обрезать, это будет не фрагмент, а просто сильно уменьшенная обрезанная картинка. Вырезать же квадрат из оригинальной картинки тоже плохо — детали слишком мелкие получаются.

    Опытным путем пришёл к такому решению — уменьшаю исходную картинку по меньшей стороне до трёхкратного размера превьюшки (3х50), а дальше делаю случайный сдвиг по высоте и ширине (с учётом того, что картинка обычно прямоугольная) и вырезаю фрагмент 50х50. Если фрагмент получился неинтересный — удаляется и автоматом создаётся новый.
  • 0
    юзаю phpthumb, там есть многое из указанного в посте функционала
    • 0
      плохо что там картинки налету генерятся каждый раз (сужу по демке). а функционал вполне себе.
      можно через реврайт делать.
      например

      если файла нет, то его обрабатывает этот скрипт, складывает в соответствующую папку и отображает. в след раз подгрузится уже уменьшенная картинка. делал таким способом на одном проекте превью
      • 0
        он делает это, надо в конфиге кеширование включить
    • 0
      к сожалению, при обработке phpThumb картинки с прозрачностью результат выглядел более чем глючно.
      поэтому пришлось все превью делать вручную.
  • +2
    Когда подрабатывал контентщиком, один раз пришлось обработать 15000 фоток делая иконки вручную. Потому что нужны были именно сиськи ))) *краснеет
    • 0
      Я думаю, даже бы программист не стал бы придумывать заумный алгоритм, чтобы обработала такие прелести бесчувственная машина =)
      • +1
        Любая прелесть перестанет быть прелестью после 3000 однотипных с ней манипцуляций.
        • 0
          batch в photoshop способен минимизировать проблемы.

          хотя сиськи всё равно выделять руками…
          • 0
            > хотя сиськи всё равно выделять руками…

            С легкой горечью было произнесено. Не? xD
  • 0
    Совет бесплатно — еще один параметр — png картинка, которая ставится поверх. Решается куча задач: от банального копирайта, до закругленных уголков и значка проиграть видео на превью к видео.
    • –1
      Вот нетерплю такое. Те, кто хочет «украсть», чтобы незаконно использовать — украдут полюбому, хоть двадцать пять картинок поверх поставь. А вот обычные пользователи, которым хочется сохранить её для себя, страдают серъезно и мучают тех «кто разбирается» чтобы они им эту картинку сохранили (если очень хочется). На каком-то сайте о клубной жизни, помнится, такая хрень была. Чтобы сохранить найденную фотку с самим собой, нужно было зарегистрироваться.
      • 0
        Ах да, и предварительно использовать интуицию, чтобы догадаться, что для того, чтобы правая клавиша заработала, нужно зарегистрироваться.
        • 0
          А Print Screen запретили что ли? :-)
          Мой основной аргумент для заказчиков, требующих «защиты от всех и вся» — Print Screen запретить невозможно ;-)
  • 0
    А если обрезать фотографии, зачастую ничего важного не теряется.
    я, как фотограф, категорически протестую. С «фотками» («я, жена и Пизанская башня», «Иван Иваныч лицом в салате») обычно ничего страшного не происходит, за исключением отрезания лица или другой важной детали. А вот как раз у фотографий есть такое понятие как композиция, которую очень легко нарушить бездумным кадрированием. Поэтому на всяческих фотосайтах делают превьюшки без обрезания и с сохранением пропорций.
    • +1
      Ну, если только вы хотите найти композицию на превьюшках 100×100 пикселей :)
      Совершенно ясно, что увеличенные копии обрезать ненужно.
      • 0
        композицию на превьюшках как раз отлично видно
        Попробуйте обрезать вот эту превьюшку до квадрата — получится непонятно что
        • –4
          Понять то, что это лавочка я смог только при 200% зуме. Думаю, это о многом говорит :)
          • +2
            это говорит о том, что у вас плохо со зрением. Доктора посещали?
        • 0
          Отсутствие угадываемых деталей на превьюшке подогревает желание посмотреть полную картинку. Если же композиция не угадывается в обрезанном квадарате — то ее скорей всего нету ;-)
  • +2
    Желаю удачи в начинании. Я сам много вожусь с превьюшками и пришел к выводу: на сайте должен быть механизм интерактивного создания превьюшки — на тот случай, когда автомат обрезал некрасиво.

    Совершенно не факт, что «главная часть картинки сверху»! Только человек (автор) может решить что там главное. Это я как фотограф утверждаю :)

    В сети есть плагины-хелперы для ручного создания превью. Можно погуглить «jquery thumbnail resize»

    Ещё хочу сказать про случай «Иногда бывает нужен какой-то определенный размер по одной из координат, а размер другой координаты может быть произвольным.» — на самом деле это частный случай превью без обрезания. Совсем произвольной вторую координату оставлять неразумно. Просто вписываем картинку в очень вытянутый, но не бесконечный (!!!) прямоугольник.
  • 0
    Использую для этих целей неплохой класс Thumb And Crop. Но если вам нужны еще и watermark + всевозможные эффекты, то можно посмотреть в сторону EasyPhpThumbnail Class — это что качается второго типа изображений.

    Для первого типа возможно использования WYSIWYG редактора + спец. плагины для редактирования изображений, либо путем модификации функций самого редактора.
  • 0
    На PHP нравится библиотека Asdio — есть практически все функции, которые необходимы (и драйверы для работы как с GD, так и с Image Magick). Жаль, не обновляется уже.
  • 0
    Согалсен, прочтение документации для imageMagic это не кошерно, да и сам продукт openSrouce не нравится, да?
  • 0
    Странно, что никто не вспомнил более цивильного слова «Миниатюра»

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.