如何在不损失图像质量的情况下从JPG中删除exif?
我有一个PHP照片共享应用程序,其中使用ImageMagick将用户上传的图像调整为各种缩略图格式.
I have a PHP photo sharing application in which user-uploaded images are resized into various thumb formats using ImageMagick.
作为一种看似智能"的方式来节省文件大小,我从这些大拇指上剥离了exif信息,如下所示:
As a seemingly "smart" way to save on file size, I am stripping exif info from these thumbs as follow:
$imagick = new Imagick($image);
$imagick->stripImage();
$imagick->writeImage($image);
这有效.它确实删除了EXIF信息,其中30KB的大拇指节省了12KB,而变成18KB.在单个页面上显示许多这样的拇指时,可节省大量资金.
This works. It does remove the EXIF info, where a thumbs of 30KB saves 12KB and becomes 18KB. A significant saving when showing many of such thumbs on a single page.
但是,问题是它工作得太好了.与未剥离的图像相比,所产生的图像似乎丢失了许多颜色信息,并且看起来平坦".
The problem however is that it works a little too well. The resulting images seem to lose a lot of color information and look "flat" compared to their non-stripped versions.
根据我到目前为止的研究,我的理论是以下一项或两项是正确的:
Based on my research so far, my theory is that one or both of the following is true:
- Imagick在剥离过程中会丢弃必要的颜色配置文件信息
- Imagick保存后会重新压缩图像,从而导致图像质量下降
不管造成问题的原因是什么,我都在寻找一种删除EXIF信息的方式,该方式不会影响图像质量或颜色本身.
Regardless of the cause of the problem, I'm looking for a way to remove EXIF information in such a way that it does not affect the image quality or color itself.
这有可能吗?
更新:
根据Gerald Schneider的回答,我尝试在将图像剥离"之前将质量设置强制为100%:
Based on Gerald Schneider's answer, I tried enforcing the quality setting to 100% prior to "stripping" the image:
$imagick = new Imagick($image);
$imagick->setCompression(imagick::COMPRESSION_JPEG);
$imagick->setCompressionQuality(100);
$imagick->stripImage();
$imagick->writeImage($image);
不幸的是,问题仍然存在.下面是示例输出,尽管将质量设置为100%,但图像仍会变平.
Unfortunately, the problem remains. Below is example output where despite setting the quality to 100%, images are still flattened.
在删除所有其他EXIF数据时,请考虑保留ICC配置文件(导致更丰富的色彩):
Consider keeping the ICC profile (which causes richer colors) while removing all other EXIF data:
- 提取ICC配置文件
- EXIF数据条和图像配置文件
- 重新添加ICC配置文件
在PHP + imagick中:
In PHP + imagick:
$profiles = $img->getImageProfiles("icc", true);
$img->stripImage();
if(!empty($profiles))
$img->profileImage("icc", $profiles['icc']);
(重要说明:使用ImageMagick 3.1.0 beta版,我从getImageProfiles()
获得的结果与
(Important note: using the ImageMagick 3.1.0 beta, the result I got from getImageProfiles()
was slightly different from the documentation. I'd advise playing around with the parameters until you get an associative array with the actual profile(s).)
对于命令行ImageMagick:
For command line ImageMagick:
convert image.jpg profile.icm
convert image.jpg -strip -profile profile.icm output.jpg
当然,如果使用ImageMagick,图像将被重新压缩,但至少颜色保持不变.
Images will get recompressed of course if you use ImageMagick, but at least colors stay intact.
希望这会有所帮助.