使用 PHP 和 Imagick 将 CMYK PDF 转换为 SRGB JPG
Convert CMYK PDF to SRGB JPG using PHP and Imagick
我正在尝试使用 Imagick 和 PHP 将 PDF 文档的第一页转换为 JPEG。只要 PDF 的颜色space 是 SRGB,转换就会成功,并且生成的图像具有正确的颜色。但是,如果 PDF 具有 CMYK 颜色space,转换后图像颜色会关闭(更亮或更暗)。
我目前正在使用以下软件:
- PHP 7.4.3
- ImageMagick 6.9.10-23 Q16 x86_64 20190101(deb 包)
- Ghostscript 9.50 (2019-10-15)
我正在 Windows 10 上开发 WSL2。
可以找到我的测试PDF here。
因为我对转换结果不满意,所以我首先尝试看看是否可以使用 Imagick cli 进行成功转换。经过反复试验,我发现以下命令产生了最好的结果:
convert -density 300 -colorspace srgb input.pdf[0] -layers flatten -strip output.jpg
结果:
然后我将命令重写为 PHP:
$input = 'input.pdf';
$output = 'output.pdf';
$image = new Imagick();
$image->setResolution(300, 300);
$image->readImage("{$input}[0]");
$image->transformImageColorspace(Imagick::COLORSPACE_SRGB);
$image = $image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
$image->setImageFormat('jpeg');
$image->stripImage();
$image->writeImage($output);
$image->destroy();
结果:
PHP代码的结果与CLI版本和原始PDF的结果不一样。结果与我 运行 te 以下 CLI 命令相同:
convert -density 300 input.pdf[0] -colorspace srgb -layers flatten -strip output.jpg
该命令看起来几乎相同,但是颜色 space 的转换稍后发生。
我的问题是:在我的 PHP 代码中我错过了哪一步才能获得与命令相同的结果
convert -density 300 -colorspace srgb input.pdf[0] -layers flatten -strip output.jpg
附加信息:
我还尝试使用颜色配置文件进行颜色 space 转换。而不是
$image->transformImageColorspace(Imagick::COLORSPACE_SRGB);
我用过
$cmyk = file_get_contents('USWebCoatedSWOP.icc');
$rgb = file_get_contents('sRGB_v4_ICC_preference.icc');
$image->profileImage('icc', $cmyk);
$image->profileImage('icc', $rgb);
除了这两个配置文件,我还尝试了其他CMYK(CoatedFOGRA39、JapanColor2001Coated...)和SRGB(AdobeRGB1998、AppleRGB、sRGB_v4_ICC_preference_displayclass...)配置文件的组合。
但是,我找不到接近 CLI 输出结果和原始 PDF 文件的配置文件组合。
感谢@fmw42,我能够解决我的问题。要修复它,请在阅读 pdf 之前使用 setColorSpace()
设置颜色 space。
$input = 'input.pdf';
$output = 'output.pdf';
$image = new Imagick();
$image->setResolution(300, 300);
$image->setColorSpace(Imagick::COLORSPACE_SRGB); // Add this line
$image->readImage("{$input}[0]");
// $image->transformImageColorspace(Imagick::COLORSPACE_SRGB); // You don't need this line
$image = $image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
$image->setImageFormat('jpeg');
$image->stripImage();
$image->writeImage($output);
$image->destroy();
我正在尝试使用 Imagick 和 PHP 将 PDF 文档的第一页转换为 JPEG。只要 PDF 的颜色space 是 SRGB,转换就会成功,并且生成的图像具有正确的颜色。但是,如果 PDF 具有 CMYK 颜色space,转换后图像颜色会关闭(更亮或更暗)。
我目前正在使用以下软件:
- PHP 7.4.3
- ImageMagick 6.9.10-23 Q16 x86_64 20190101(deb 包)
- Ghostscript 9.50 (2019-10-15)
我正在 Windows 10 上开发 WSL2。
可以找到我的测试PDF here。
因为我对转换结果不满意,所以我首先尝试看看是否可以使用 Imagick cli 进行成功转换。经过反复试验,我发现以下命令产生了最好的结果:
convert -density 300 -colorspace srgb input.pdf[0] -layers flatten -strip output.jpg
结果:
然后我将命令重写为 PHP:
$input = 'input.pdf';
$output = 'output.pdf';
$image = new Imagick();
$image->setResolution(300, 300);
$image->readImage("{$input}[0]");
$image->transformImageColorspace(Imagick::COLORSPACE_SRGB);
$image = $image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
$image->setImageFormat('jpeg');
$image->stripImage();
$image->writeImage($output);
$image->destroy();
结果:
PHP代码的结果与CLI版本和原始PDF的结果不一样。结果与我 运行 te 以下 CLI 命令相同:
convert -density 300 input.pdf[0] -colorspace srgb -layers flatten -strip output.jpg
该命令看起来几乎相同,但是颜色 space 的转换稍后发生。
我的问题是:在我的 PHP 代码中我错过了哪一步才能获得与命令相同的结果
convert -density 300 -colorspace srgb input.pdf[0] -layers flatten -strip output.jpg
附加信息: 我还尝试使用颜色配置文件进行颜色 space 转换。而不是
$image->transformImageColorspace(Imagick::COLORSPACE_SRGB);
我用过
$cmyk = file_get_contents('USWebCoatedSWOP.icc');
$rgb = file_get_contents('sRGB_v4_ICC_preference.icc');
$image->profileImage('icc', $cmyk);
$image->profileImage('icc', $rgb);
除了这两个配置文件,我还尝试了其他CMYK(CoatedFOGRA39、JapanColor2001Coated...)和SRGB(AdobeRGB1998、AppleRGB、sRGB_v4_ICC_preference_displayclass...)配置文件的组合。
但是,我找不到接近 CLI 输出结果和原始 PDF 文件的配置文件组合。
感谢@fmw42,我能够解决我的问题。要修复它,请在阅读 pdf 之前使用 setColorSpace()
设置颜色 space。
$input = 'input.pdf';
$output = 'output.pdf';
$image = new Imagick();
$image->setResolution(300, 300);
$image->setColorSpace(Imagick::COLORSPACE_SRGB); // Add this line
$image->readImage("{$input}[0]");
// $image->transformImageColorspace(Imagick::COLORSPACE_SRGB); // You don't need this line
$image = $image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
$image->setImageFormat('jpeg');
$image->stripImage();
$image->writeImage($output);
$image->destroy();