使用PHP和Imagick将CMYK PDF转换为SRGB JPG

3

我正在尝试使用Imagick和PHP将PDF文档的第一页转换为JPEG。只要PDF的颜色空间是SRGB,转换就会成功,并且生成的图像颜色正确。但是,如果PDF具有CMYK颜色空间,则在转换后,图像颜色偏离(明暗程度要么更亮要么更暗)。

目前我正在使用以下软件:

  • PHP 7.4.3
  • ImageMagick 6.9.10-23 Q16 x86_64 20190101 (deb package)
  • Ghostscript 9.50 (2019-10-15)

我正在Windows 10上的WSL2上工作。

我的测试PDF可以在这里找到。

由于我对转换结果不满意,首先我试图看看是否可能使用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();

结果:

enter image description here

PHP代码的结果与CLI版本和原始PDF的结果不同。结果与运行以下CLI命令相同:

convert -density 300 input.pdf[0] -colorspace srgb -layers flatten -strip output.jpg

命令看起来几乎相同,但是颜色空间的转换发生在后面。 我的问题是:在我的PHP代码中缺少哪个步骤才能实现与命令相同的结果。
convert -density 300 -colorspace srgb input.pdf[0] -layers flatten -strip output.jpg

额外信息: 我还尝试使用颜色配置文件来进行颜色空间转换。而不是

$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文件的结果。

1
在读取输入PDF之前,您需要更改颜色空间,就像您使用密度一样。ImageMagick使用Ghostscript来读取PDF文件,但它无法处理带有Alpha的CMYK。因此,在读取PDF时,您必须将其转换为sRGB。 - fmw42
@fmw42 谢谢!我尝试在读取 PDF 之前使用 $image->setImageColorSpace(Imagick::COLORSPACE_SRGB); 设置颜色空间,但这并没有起作用。现在我发现我错过了 setColorSpace() 方法,使用这个方法转换可以按预期工作。再次感谢! - Tomasz Nguyen
1个回答

4

感谢 @fmw42 的帮助,我解决了问题。为了解决它,需要在读取pdf之前使用 setColorSpace() 来设置颜色空间。

$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();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接