Как сохранить изображение с определенным размером файла? - PullRequest
23 голосов
/ 23 ноября 2010

Я создаю систему PHP, в которой пользователи могут создавать визуально сложное изображение, конечное требование которого составляет 50 КБ или менее .

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

Текст может быть любого цвета и одного из множества шрифтов.Это означает, что конечное изображение может быть довольно визуально сложным и непредсказуемым (за исключением размеров изображения).

Тогда у меня будет требование иметь размер файла окончательного изображения не более 50 КБ (это внешнее требование, которое нельзя изменить).

Последнее требование (опять же, внешнее): формат изображения должен быть .jpeg, .png или .gif .

Я просмотрел документацию GraphicsMagick , но нигде не могу найти упоминания о возможности установить размер файла и автоматически рассчитать сжатие .

У меня естьЯ подумал, что это можно сделать программно через цикл сжатия -> сохранить ->, но я могу себе представить, что это потребует значительных ресурсов процессора, поскольку я не могу заранее рассчитать размер файла на основе сжатия.Вот почему я спрашиваю, была ли проблема решена в GraphicsMagick.

Редактировать

Чтобы понять, почему существуют внешние требования:

Пользователь будет использовать эту систему для создания плоского изображения, которое он затем сохранит на своем ПК.Затем это изображение должно быть загружено в Adroll для использования в кампании ретаргетинга.

Вот Требования Adroll к изображению.Моя система будет предоставлять только изображения размером 728x90, 300x250 и 120x600.

Редактировать 27 ноября 2010

Так как это не представляется возможным с GraphicsMagick, яЯ готов рассмотреть другие решения, такие как непосредственное взаимодействие с библиотеками сжатия (libpng и т. д.), которые могут обеспечить функциональность.

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


В качестве аналогии для тех, кто склонен к этому пути:

Я после того, что A * ищет: у него есть определенное начало/ конечная точка, и находит наилучший из возможных маршрутов в самое быстрое время.

Чего я надеялся избежать, так это то, что «Поиск в ширину / глубину» должен искать: определенные начальные / конечные точки, но могут не попасть в оптимальныйрешение однажды найдет локальный минимум и может полностью выкинуть вычислительно.

Ответы [ 9 ]

11 голосов
/ 27 ноября 2010

Поскольку не существует способа сжатия до целевого размера, о котором я знаю, я предлагаю поискать косвенное решение:

  1. Сделайте небольшую статистику (возможно, сжимая множество изображений с различными JPEGкоэффициенты сжатия), чтобы узнать, что означает средний сжатый размер и его стандартное отклонение для данного уровня качества.
  2. Принимая изображение, попробуйте сжать его с подходящим качеством.Если полученный файл слишком велик, уменьшите качество и повторите попытку.При желании, если оно окажется слишком маленьким, вы также можете повысить качество.
  3. Остановитесь, когда полученное изображение будет "близко" к вашему целевому размеру, но меньше.

Чтобы разработатьбит по математике в шаге 2:

Если вы выберете начальное качество так, чтобы ваш средний расчетный размер + 3 * стандартное отклонение <ваш целевой размер, то 99,7% сжатий приведут к соответственно небольшому файлу напервая попытка (при условии нормального распределения сжатых размеров). </p>

Вы можете настроить начальное качество и логику, которая увеличивает или уменьшает его, как вы хотите, балансируя между меньшей нагрузкой на сервер и файлами ближе к вашему максимальному размеру ("лучше использовать ваши ограничения).

9 голосов
/ 02 декабря 2010

Посмотрите на следующий пакет:

http://www.phpclasses.org/package/3810-PHP-Optimize-images-to-fit-in-a-given-file-size-limit.html

Довольно круто - я бы сказал, что автор заслуживает пива;)

Пример изображения, котороена самом деле 61081 байт (первое изображение в формате JPEG, показывающее размер файла в изображении?):

alt text

1 голос
/ 26 ноября 2010

Можно ли использовать GraphicMagick "-limit disk 50mb" в коалиции с "-list resource", чтобы вы могли проверить это на раннем этапе (или даже на самом деле опрашивать) процесс и внести необходимые изменения?

http://www.graphicsmagick.org/GraphicsMagick.html#details-limit

0 голосов
/ 03 декабря 2010

Возможно, вы смотрите на проблему под неправильным углом. Выбрав использовать PNG и свернув метаданные, хранящиеся в изображении, вы уменьшите размер файла. Это потому, что PNG является растровой структурой. Пока GMagick не хранит текст в качестве метаданных, это не повлияет на размер файла. Только глубина цвета (которую вы также можете контролировать) будет влиять на размер файла. Не чередование без фильтрации по размеру файла должно по существу совпадать с размером шаблона. До тех пор, пока размер шаблонов не превышает 50 КБ, с вами все будет в порядке.

0 голосов
/ 02 декабря 2010

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

Для .gif и .jpg вам нужно будет найти наиболее подходящее;Ни один из них не может быть предсказан с достаточной уверенностью, и ни один алгоритм не подходит для кодирования с постоянной скоростью передачи битов.Вы можете использовать бинарный поиск , чтобы найти лучшее соответствие.Вы можете выбрать коэффициенты сжатия из заранее определенного списка, чтобы ограничить количество тестовых сжатий, которые вам нужно сделать;например, если ваш список коэффициентов сжатия .jpg равен 4, 6, 8, 12, 18, 27, 44, 66, вам нужно будет сделать не более 4 тестовых сжатий.

.gif и paletted .pngдостаточно похожи, чтобы вы просто выбрали один и забыли о другом.

Будет сложно выбрать между .gif / .png и .jpg на основе результатов сжатия;артефакты, вносимые каждым процессом, совершенно разные.Опять же, вам лучше всего сжать несколько тестовых изображений до целевого размера и исключить один или другой формат на основе тестирования глазного яблока.

0 голосов
/ 02 декабря 2010

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


Существует запатентованный метод от Kuo, Chun-ming, поэтому я не уверен в коммерческой целесообразности его использования:

Способ и электронное устройство для регулировки степени сжатия изображения JPEG

Который основан на этой формуле:

log(NSF) = (log(SF1 / SF2) / log(FileSize1 / FileSize2)) * log(Target / FileSize1) + log(SF1)

Где

SF1 is a first compression parameter
SF2 is a second compression parameter
FileSize1 is the size of the image compressed with SF1
FileSize2 is the size of the image compressed with SF2
Target is the target file size
NSF is the target compression parameter.

Непонятно, если SF1, SF2 и NSF находятся в диапазоне 0-1 или 0-100 и т. Д., И если FileSize1, FileSize2 и Target указаны в байтах, килобайтах и ​​т. Д. Поэкспериментируйте с правильной комбинацией здесь, чтобы узнать правильные единицы измерения.


Второй метод исходит от Рики Д. Нгуена из Массачусетского технологического института:

Управление скоростью и распределение битов для транскодирования JPEG

Он предлагает изменять данные, которые используются для сжатия, пока оно происходит. Эта опция может быть неосуществимой для реализации, так как требует изменения самого кода сжатия.


Из обоих этих примеров , безусловно, можно сохранить файл .jpeg с определенным целевым размером файла.

0 голосов
/ 26 ноября 2010

Существует только три способа уменьшить конечный размер любого изображения:

  1. уменьшить разрешение
  2. уменьшить глубину цвета
  3. уменьшить сложность изображения

Первые два находятся под вашим контролем.Если загруженное изображение выходит с размером файла, превышающим лимит, вы можете попробовать уменьшить его до следующего меньшего доступного размера и посмотреть, подходит ли оно этому.Учитывая, что у вас есть только 3 целевых разрешения, это не будет слишком дорого.Но если вам нужен «большой» размер, то у вас останется вариант 3.

Уменьшение сложности изображения - отвратительный зверь.Вы можете попытаться уменьшить межпиксельный «шум», чтобы получить большие области одного цвета, которые будут очень хорошо сжимать изображения в формате GIF / PNG.Простой фильтр размытия может выполнить это, но он также может разрушить разборчивость любого мелкого шрифта / текста на изображении.Для цели JPG вы можете попытаться понизить качество сжатия, но, опять же, это может испортить изображения, если вы снизите качество слишком низко.Если простые преобразования на стороне сервера не могут с этим справиться, изображение должно быть переделано художником, который создал его в первую очередь.

Единственный практический метод, который я вижу, чтобы автоматизировать это, это сжатиеУпомянутый вами цикл сохранения-теста.Учитывая, что конечные изображения относительно малы, это не будет слишком большой нагрузкой на сервер.Сохранение GIF / PNG является легкой операцией.Сжатие JPG требует больше ресурсов процессора, но, опять же, с небольшими изображениями современный сервер не должен испытывать проблем с выполнением 10 или 20 тестовых изображений в течение одной или двух секунд.

0 голосов
/ 24 ноября 2010

Итак, если я правильно понимаю - вы создаете систему, которая позволяет пользователям писать текст на одном из предоставленных вами изображений шаблонов. Если это правильно, почему вы вообще сохраняете изображение? Вы можете легко снять ограничение в размере 50 Кб, сохранив пользовательские действия самостоятельно. Вы можете сделать что-то вроде: сохранить текст (вместе с его свойствами и местоположением) и шаблон, в котором он находится.

0 голосов
/ 23 ноября 2010

Я не знаю способа автоматического определения результирующего размера файла изображения - это задача библиотеки, генерирующей изображение.Если вы не применяете сжатие самостоятельно, вы не сможете предварительно рассчитать полученный размер.

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

Пример:

  • 50k jpg, 100x200 сжимается 30k
  • 100k jpg, 100x200 сжимается 60k

-> когда вы получите изображение размером 100x202px с 59k, сжатый размер будет приблизительно равен 35k.

...