Как удалить exif из JPG без потери качества изображения?

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

как, казалось бы," умный " способ сохранить размер файла, я удаляю информацию exif из этих больших пальцев следующим образом:

$imagick = new Imagick($image);
$imagick->stripImage();
$imagick->writeImage($image);

это работает. Он удаляет информацию EXIF, где большие пальцы 30KB экономит 12KB и становится 18KB. Значительная экономия при показе многих таких больших пальцев на одной странице.

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

основываясь на моих исследованиях до сих пор, моя теория заключается в том, что одно или оба из следующих верно:

  • Imagick выбрасывает необходимую информацию о цветовом профиле в рамках процесса зачистки
  • Imagick сжимает изображение после его сохранения, теряя качество

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

это вообще возможно?

обновление:

основываясь на ответе Джеральда Шнайдера, я попытался установить настройку качества на 100% до "зачистки" изображения:

$imagick = new Imagick($image);
$imagick->setCompression(imagick::COMPRESSION_JPEG);
$imagick->setCompressionQuality(100);
$imagick->stripImage();
$imagick->writeImage($image);

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

enter image description here

2 ответов


подумайте о сохранении профиля ICC (который вызывает более насыщенные цвета) при удалении всех других данных EXIF:

  1. извлечь профиль ICC
  2. Strip EXIF данные и профиль изображения
  3. добавить профиль ICC обратно

в PHP + imagick:

$profiles = $img->getImageProfiles("icc", true);

$img->stripImage();

if(!empty($profiles))
    $img->profileImage("icc", $profiles['icc']);

(важное примечание: используя бета-версию ImageMagick 3.1.0, результат, который я получил от getImageProfiles() немного отличался от документация. Я бы посоветовал поиграть с параметры, пока вы не получите ассоциативный массив с фактическим профилем(профилями).)

для командной строки ImageMagick:

convert image.jpg profile.icm
convert image.jpg -strip -profile profile.icm output.jpg

изображения будут повторно сжаты, конечно, если вы используете ImageMagick, но, по крайней мере, цвета остаются нетронутыми.

надеюсь, что это помогает.


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

EXIF может быть только максимум 64KB в файле JPEG, однако я не уверен, что это точно 64KB, поэтому я бы начал с этого.