php уменьшить изображение без потери качества
Php уменьшить изображение без потери качества
Сжимание изображений средствами php
Рабочий код для уменьшения веса изображений без потери качества
Каждый веб-разработчик рано или поздно сталкивается с проблемой медленной загрузки сайта. На скорость загрузки сайта влияет несколько причин, но самой распрастранённой конечно же является большое количество графических файлов, расположенных на страницах сайта. Зачастую, столкнувшись с данной проблемой, программисты сжимают все используемые на сайте изображения путём изменения качества или размера изображений в худшую сторону, используя специальные онлайн сервисы. Но что если на сайте должно присутствовать добавление контента пользователями, и любой пользователь сможет загрузить фото размером 7-8 МБ, тем самым увеличив скорость загрузки сайта. Именно для таких случаев у каждого веб-разработчика должна быть собственная библиотека (или просто функция) для работы с изображениями, а именно для сжатия качества картинок.
Если вы ещё не верите в существование подобной магической функции языка php, то внимательно посмотрите на следующий пример.
Далее представлен рабочий php-код для уменьшения веса изображений с помощью которого вы сможете существенно уменьшить размер изображения и при этом практически не изменив их качества.
Вызов данной функции может быть примерно таким.
Размер изображения уменьшился более чем в 8 раз! При этом потеря качества практически незаметна.
Как видите, данная функция может творить чудеса! На этом всё. Сжимайте изображения и будьте счастливы.
Оптимизация загруженных изображений с помощью php (jpeg)
при запуске скорости страницы в Google Chrome он предлагает оптимизировать / сжать изображения. Эти изображения в основном загружаются пользователями, поэтому мне нужно будет оптимизировать их во время загрузки. То, что я нахожу об оптимизации изображений jpeg с помощью php, похоже на использование следующих функций GD:
поскольку я изменяю размер изображений после загрузки, я уже вытягиваю Изображение через эти функции и, кроме того, я использую imagecopyresampled() после imagecreatefromjpeg() чтобы изменить ее размер.
но тогда скорость страницы все еще говорит мне, что эти изображения можно оптимизировать. Как я могу выполнить эту оптимизацию в PHP-скрипте? Установка более низкого качества в imagejpeg () также не имеет значения.
4 ответов
функция imagejpeg, где вы назначаете качество. Если вы уже устанавливаете соответствующее значение, то вы мало что еще можете сделать.
скорость страницы, вероятно, считает, что все изображения выше определенного размера «нуждаются в сжатии», возможно, просто убедитесь, что они все такие же маленькие, как разумные (с точки зрения высоты/ширины) и сжатые.
вы можете найти больше о скорости страницы, и это предложения по сжатию на pagespeed docs http://code.google.com/speed/page-speed/docs/payload.html#CompressImages который описывает некоторые из методов / инструментов для сжатия соответствующим образом.
Я также только что прочитал следующее:
поэтому, возможно (если вы действительно хотите придерживаться предложений Google), вы можете использовать PHP exec для запуска одного из этих инструментов в файлах по мере их загрузки.
чтобы сжать php, вы делаете следующее (Похоже, вы уже делаете это):
Эффективное изменение размера картинок при помощи ImageMagick
В наше время всё чаще сайты сталкиваются с необходимостью введения отзывчивого дизайна и отзывчивых картинок – а в связи с этим есть необходимость эффективного изменения размера всех картинок. Система должна работать так, чтобы каждому пользователю по запросу отправлялась картинка нужного размера – маленькие для пользователей с небольшими экранами, большие – для больших экранов.
Веб таким образом работает отлично, но для доставки картинок разных размеров разным пользователям необходимо все эти картинки сначала создать.
Множество инструментов занимается изменением размера, но слишком часто они выдают большие файлы, аннулирующие выигрыш в быстродействии, который должен приходить вместе с отзывчивыми картинками. Давайте рассмотрим, как при помощи ImageMagick, инструмента командной строки, быстренько изменять размеры картинок, сохраняя превосходное качество и получая файлы небольших объёмов.
Большие картинки == большие проблемы
Средняя веб-страница весит 2 Мб, из них 2/3 – картинки. Миллионы людей ходят в интернет через 3G, или ещё хуже. 2Мб-сайты в этих случаях работают ужасно. Даже на быстром соединении такие сайты могут израсходовать лимиты трафика. Работа веб-дизайнеров и разработчиков – упростить и улучшить жизнь пользователя.
Очень маленькие сайты могут просто сохранить несколько вариантов всех картинок. Но что, если у вас их дофига? Например, в магазине может быть сотня тысяч картинок – не делать же их варианты вручную.
ImageMagick
Как работает изменение размера картинок
По определению, при изменении размера картинки меняется количество пикселей в ней. Если её увеличивают, на выходе будет больше пикселей, чем на входе; при уменьшении – наоборот. Задача состоит в том, как лучше всего сохранить содержимое исходной картинки при помощи другого количества пикселей.
Увеличение картинок изобразить проще, так что начнём с него. Рассмотрим картинку с квадратиком 4х4 пикселя, который мы хотим удвоить до 8х8. По сути, мы берём эту картинку и натягиваем на новую сетку – это называется resampling (дискретизация). Чтобы сделать дискретизацию картинки 4х4 на 8х8, нужно куда-то вставить 48 лишних пикселей. У них должен быть какой-то цвет – процесс его подбора зовётся интерполяцией. При дискретизации алгоритм, выбирающий, как работает интерполяция, называется фильтром дискретизации.
Фильтров таких есть множество. Проще всего добавить четыре ряда и четыре столбца любого цвета. Ну, скажем, красного. Это будет фоновая интерполяция, когда на пустых местах появляется цвет фона (красный). В фотошопе это делается через “Image” → “Canvas Size” вместо “Image” → “Image Size”.
Это, конечно, нам не подойдёт. Картинка не будет похожа на исходную. Фоновая интерполяция используется только для добавления новых пикселей, да и тогда она бесполезна при изменении размера.
Ещё одна простая интерполяция – сделать цвет новых пикселей такой же, как у их соседей – это интерполяция по ближайшим соседям. Для картинок, особенно для нашего квадратика, результат будет гораздо лучше.
При понижающей дискретизации, то есть, уменьшении картинки, не так-то просто сделать интерполяцию по ближайшим соседям. Нужно принять, что в математических целях можно оперировать дробными пикселями. Для начала новая сетка применяется к оригинальной картинке. Поскольку пикселей стало меньше, а размер их больше, некоторые из них содержат по нескольку цветов.
Но у настоящих пикселей есть только один цвет. Результирующий цвет каждого пикселя новой решётки определяется цветом по его центру. Поэтому иногда интерполяцию по ближайшим соседям при уменьшении называют точечной дискретизацией.
Но если это что-то посложнее линии и квадратов, такой метод выдаёт зазубренные и квадратные картинки. Он работает быстро, выдаёт мелкие файлы, но выглядит плохо.
Большинство фильтров используют вариации интерполяции по ближайшим соседям – они делают точечную дискретизацию по нескольким точкам и как-то вычисляют некий средний цвет для них. В билинейной интерполяции считается взвешенное среднее цветов.
Но такой фильтр влияет на размер файла, потому что он вместе с округлыми краями добавляет новые цвета. У оригинальной картинки было всего два цвета, теперь же у нас их больше. А при прочих равных, чем больше цветов, тем тяжелее файл.
И что же это означает для нас
Нам нужно как-то уменьшать количество цветов, не теряя в качестве. Больше всего на это влияет выбор фильтра, но и другие настройки тоже могут.
Оптимальные настройки для ImageMagick
Основы ImageMagick
У ImageMagick дофига настроек и функций, и найти нужную довольно тяжело. Нас интересуют две функции, convert и mogrify. Они выполняют схожие действия, но mogrify работает с несколькими файлами сразу, а convert – по одному.
Использовать mogrify можно также, с небольшим дополнением:
Тут IM берёт все файлы JPEG из текущей директории (*.jpg), изменяет их размер до 300 пикселей в ширину и сохраняет их в директории output.
Функции можно комбинировать:
Это тоже изменяет размер input.jpg до 300 пискелей, но устанавливает качество JPEG в 75 перед сохранением в output.jpg.
Тестирование и результаты
Тестируя различные настройки IM, я стремился уменьшить размер файлов, не ухудшая их качества – так, чтобы их не отличить было от опции фотошопа «Save for Web». Я использовал для проверки как субъективное мнение, так и объективное – измерял структурные различия (structural dissimilarity, DSSIM). DSSIM сравнивает две картинки и выдаёт оценку. Чем меньше оценка, тем больше они похожи. 0 означает идентичность. Я добивался оценки DSSIM не более 0,0075. А в одном из исследований в прошлом году было установлено, что обычно люди не могут на глаз отличить картинки с DSSIM менее 0,015.
Протестировав различные изображения разных размеров в форматах JPEG и PNG я пришёл к выводу, что следующие настройки IM создают наименьшие результаты, которые при этом практически неотличимы от выдачи фотошопа:
Разберём их подробнее.
Mogrify или Convert
IM использует convert для обработки картинок по одной, а mogrify обычно нужен для пакетной обработки. В идеальном мире результаты их работы должны совпадать. К сожалению, в convert есть ошибка, из-за которой он игнорирует некоторые из настроек (-define jpeg:fancy-upsampling=off), поэтому пришлось использовать mogrify.
Дискретизация (resampling)
Выбор фильтра дискретизации в IM почему-то запутан. Есть три способа это сделать:
Примеры работы двенадцати различных функций изменения размера
Очевиднее всего использовать –resize, но результаты получаются слишком большими. Я проверил 11 разных функций и обнаружил, что лучше всего с уменьшением справляется –thumbnail, как по размеру, так и по качеству. Эта функция работает в три этапа:
Второй способ выбрать фильтр дискретизации – через –filter. У некоторых функций есть встроенные фильтры, а у других есть фильтры по умолчанию, которые можно поменять. На втором шаге работы –thumbnail используется –filter, потому что там используется функция –resize.
Увеличение чёткости (Sharpening)
Фильтр работает так, что сначала применяется гауссово размытие. Первые два числа – это радиус и сигма (в нашем случае, по 0,25 пикселя). После размытия фильтр сравнивает размытую версию с оригиналом, и там, где яркость отличается более, чем заданный порог (0.065), применяется увеличение чёткости заданной силы (8).
Уменьшение цветности
Как я говорил ранее, основная причина увеличения объёма файлов при изменении размера картинок – добавление новых цветов. Поэтому нужно попытаться уменьшить их количество, но без потери качества.
Один из способов – это постеризация (posterization), когда градиенты заменяются на наборы из чётких цветов. Постеризация уменьшает количество уровней цвета – это то, сколько вариантов остаётся у красного, зелёного и синего каналов. Общее количество цветов картинки будет комбинацией цветов этих каналов.
Постеризация может уменьшить объём файла, но и ухудшить качество. Я предлагаю цифру 136, при которой вы получаете небольшой файл, не теряя особо в качестве.
Оригинал
Уменьшение количества цветов
Дизеринг (Dithering) – процесс, который смягчает последствия уменьшения количества цветов, добавляя шума в цветовые наборы, чтобы создать иллюзию большего количества цветов. В теории это хорошая идея.
После дизеринга
Ошибка дизеринга в IM
Цветовое пространство
Цветовой пространство косвенно относится к количеству цветов на картинке. Это пространтсво определяет, какие цвета доступны. На картинке ниже показано, что пространство цветов ProPhoto RGB содержит больше цветов, чем Adobe RGB, которое, в свою очередь, содержит больше, чем sRGB. И все они содержат цветов меньше, чем видит глаз.
sRGB сделали королём цветовых пространств интернета. Его одобрили W3C и другие организации. Он обязателен к поддержке в CSS Color Module Level 3 и в спецификациях SVG и WebP. На него ссылаются в спецификации PNG. В фотошопе это также это цветовое пространство по умолчанию. Короче, sRGB – лучший выбор для веба, и если вы хотите, чтобы ваши картинки правильно отображались, лучше использовать его.
Качество и сжатие
В форматах с потерей качества вроде JPEG качество и сжатие связаны напрямую – чем больше сжатие, тем ниже качество и меньше объём файла. Поэтому нужно найти баланс.
В моих тестах у контрольных картинок и фотошопа было выставлено качество high, или 60. А в настройках IM я рекомендую использовать 82. Почему?
А у форматов без потери качества вроде PNG, качество и сжатие не связаны. Высокое сжатие не меняет вид картинки, а зависит только от уровня загрузки процессора при её обработке. Если не жалеть компьютеры, то нет причин не выставлять максимальное сжатие PNG.
Мета данные
Прогрессивный рендер
JPEGs и PNGs можно сохранять при помощи прогрессивного (progressive) или последовательно (sequential) рендера. По умолчанию выполняется второй, когда пиксели грузятся по рядам, сверху вниз. Прогрессивный означает, что картинка передаётся и выводится постепенно.
У JPEG прогрессивный рендер может произойти в любое количество шагов – это определяется при сохранении файла. Первый шаг – версия низкого разрешения полной картинки; на каждом последующем появляется версия более высокого разрешения, пока не будет выдана вся картинка в высшем разрешении.
У PNG есть вид прогрессивного рендера под названием Adam7 interlacing, когда пиксели выводятся в семь шагов на основе сетки 8х8.
Оба вида рендера можно настроить в IM через –interlace. Но нужно ли?
Такой рендер увеличивает объём файлов. Долгое время считалось, что его нужно включать, поскольку он улучшает пользовательское восприятие. Даже если идеальная картинка не загрузится сразу, он что-нибудь распознает, и это будет лучше, чем ничего.
В прошлом году по результатам исследования стало видно, что пользователи предпочитают последовательный рендер. Это только одно исследование, но всё равно интересное. Так что я решил рекомендовать использовать последовательный рендер через «-interlace none».
Оптимизация картинок
Оптимизаторов есть множество. Я тестировал image_optim, picopt и ImageOptim, и они все прогоняют картинки через серию разных шагов. Я проверял их по очереди и пришёл к выводу, что лучше прогнать файлы через все три в том порядке, в каком они приведены. Правда, после использования image_optim выгода от picopt и ImageOptim становится минимальной. Если у вас нет лишнего времени и процессорной мощности, то использование более одной оптимизации будет чрезмерным.
Результаты (и что, стоило так мучаться?)
Конечно, настройки мои сложны, но для улучшения пользовательского восприятия они нужны. С радостью сообщаю, что потратив время на тесты, я сумел кардинально уменьшить объёмы файлов, не проиграв в качестве.
В среднем объём файлов уменьшился на 35% по сравнению с опцией фотошопа “Save for Web”.
Сравнение с Photoshop Creative Cloud
Мои настройки без оптимизации оказались даже лучше, чем у фотошопа с оптимизацией!
По сравнению с настройками по умолчанию при изменении размера картинок у IM, мои рекомендации выиграли в среднем 82%.
По сравнению с настройками по умолчанию в WordPress, который «под капотом» использует ImageMagick, мои настройки в среднем выиграли 77%.
По сравнению с другими CMS и инструментами, которые используют ImageMagick, мои настройки выигрывали аж до 144%.
Напоминаю, что все картинки получились неотличимыми от вывода фотошопа.
Как реализовать это в своих проектах
bash shell
А вызывать её нужно так:
Node.js
У npm package под названием imagemagick позволяет использовать ImageMagick. При его использовании можно добавить функцию изменения размера следующим образом:
Grunt
Если вы используете Grunt для запуска задач, то специально для вас я сделал задачу по имени grunt-respimg (npm), которая делает всё, что я описал. В свои проекты её можно включать вот так:
А затем её можно выполнить в файле Grunt:
grunt.initConfig( <
respimg: <
default: <
options: <
widths: [200, 400]
>,
files: [ <
expand: true,
cwd: ‘src/img/’,
src: [‘**.
dest: ‘build/img/’
>]
>
>,
>);
grunt.loadNpmTasks(‘grunt-respimg’);
В PHP ImageMagick интегрирован под именем Imagick. К сожалению, там он ограничен и не умеет выполнять всё то, что я рекомендовал – в частности, настраивать фильтр дискретизации на использование функции thumbnail.
Но вам повезло – я создал модуль php-respimg (packagist), который делает всё нужное. Его можно включить в проект при помощи Composer:
А затем изменять размер картинок вот так:
Content Management Systems
Если ваша CMS работает на PHP, берите секцию «PHP» и делайте из неё плагин. Если вы используете WordPress, то вы можете использовать плагин RICG Responsive Images. После его установки для активации надо будет добавить следующее в файл functions.php:
Другие CMS так или иначе дают доступ к функциям по работе с картинками – обратитесь к их документации.
Быстродействие
В своих тестах я обнаружил, что по сравнению с –resize по умолчанию IM занимал в 2.25 раз больше времени на обработку картинок.
Заключение
Дизайнеры и разработчики очень сильно влияют на то, как работает веб. Мы можем сделать сайты более шустрыми, улучшить их восприятие пользователями, и даже вывести наш контент на новые рынки. Урезание объёма картинок делается довольно просто и сильно влияет на увеличение быстродействия сайта – надеюсь, что вся эта информация окажется полезной для вас и позволит вам улучшить ваш сайт для ваших пользователей.
Автоматическое сжатие и оптимизация картинок на сайте
Изображения нужно сжимать для ускорения скорости загрузки сайта, но как это сделать? На многих хостингах нет возможности устанавливать приложения, поэтому использование unix приложений optipng, pngcrush, jpegtran отпадает. Выкачивать картинки и сжимать их FileOptimizer или другими программами не продуктивно т.к. через время всю процедуру нужно повторять.
Решение – использовать сервисы для сжатия изображений по API, например tinypng.com. Поддерживает PNG и JPG до 5mb, бесплатен до 500 фото в месяц.
Напишем скрипт который по крону будет автоматом собирать файлы и отправлять их на сжатие.
База данных
Поиск файлов на сервере
Найдем все картинки в нужных категориях сайта с помощью рекурсивной версии функции glob() и добавим новые в БД.
Таблица заполнится данными:
Отправка файлов на сжатие
Получим ключ к API, для этого нужно зарегистрироваться на странице tinypng.com/developers.
После отправки формы придет письмо с ссылкой в личный кабинет.
Получим запись из БД и отправим POST-запрос в формате JSON:
URL-кодирование str_replace(‘%2F’, ‘/’, rawurlencode($item[‘img’])) нужно для файлов с русскими названиями и пробелами иначе возникают ошибки.
Сервис возвращает данные в JSON:
Соберем и оптимизируем весь код в один файл optimize_img.php
При каждом запуске скрипта идет проверка на наличие несжатых файлов в БД, если очередь закончилась, то идет поиск и добавление новых файлов, и так по кругу.
Запуск по CRON
Чтобы не превысить лимит 500 шт в месяц, скрипт должен запускаться:
31 день * 24 часа = 744 часов / 500 ≈ 1 раз в 1,5 часа, округлим до интервала в 2 часа.
Запуск скрипта в cron по URL выполняется следующий командой:
Временной интервал (минута, час, день, месяц, день недели) :
Мастерхост
Timeweb
RU-CENTER
Отчет о процессе
Чтобы отслеживать состояние процесса оптимизации, можно использовать следующий скрипт.
Изменение размера изображения средствами PHP
Постоянно нам приходится принимать от пользователей различные данные. Довольно часто в этих данных встречаются изображения, которые необходимо сохранить на сервере для дальнейшего использования. Для того чтобы все загруженные изображения одинаково вписывались в общий дизайн сайта, либо занимали меньше дискового пространства, нам необходимо изменять размеры изображения. Конечно, есть функции для проверки ширины и высоты, но согласитесь, будет некорректно сообщать пользователю, что изображение не подходит для вашего сайта.
На этот случай у меня есть один хороший класс под название SimpleImage, который позволяет довольно гибко изменять размеры изображения.
Теперь после того как мы поместили данный файл класса SimpleImage к себе на сервер посмотрим как его можно использовать.
Следующий участок кода загрузит изображение image.jpg, изменить его ширину до 400 пикселей и высоту до 200 пикселей, а затем сохранит как image1.jpg.
Если необходимо изменить размеры изображения, основываясь только на ширине и при этом сохранить его пропорции, то сценарий сам выберет необходимую высоту. Для этого необходимо использовать метод resizeToWidth.
Возможно вы пожелаете изменить размер в процентном соотношении от его оригинала. Для этого существует метод scale, в качестве параметра которому передаются проценты.
У данного класса есть еще один очень полезный метод output, который позволяет выводить изображения прямо в браузер, без предварительного сохранения. Данный метод может быть очень полезен при создании миниатюр.
Автор данного класса Simon Jarvis, на своем сайте предлагает следующий пример для изменения размера изображения загруженного через форму.
Вот такой очень маленький, но довольно функциональный получился класс SimpleImage, который очень пригодиться любому разработчику.