PHP Imagemagick如何将JPG图片的黑色背景变为透明?

8
我有一个用于创建 PDF 缩略图的 PHP 脚本,具体如下:
<?php
$file ="test.pdf";
$im = new imagick(realpath($file).'[0]');
$im->setImageFormat("jpg");
$im->resizeImage(200,200,1,0);
// start buffering
ob_start();
$thumbnail = $im->getImageBlob();
$contents =  ob_get_contents();
ob_end_clean();
echo "<img src='data:image/jpg;base64,".base64_encode($thumbnail)."' />";
?>

但是生成的jpg文件背景是黑色而不是白色。我该怎么解决这个问题?

提供有关所讨论的jpg文件的副本或链接将会很有帮助,同时也请附上生成输出结果的屏幕截图。 - Laurence Burke
劳伦斯·伯克:这里是生成的图片http://i.imgur.com/jyQC6.jpg。 - Alfred
你的CSS样式是什么样的?能否提供原始JPG链接? - Laurence Burke
@Laurence Burke,上面那个是原始的jpg文件。我没有任何样式... - Alfred
8个回答

27

之前发布的答案都不能解决我的问题,但下面这个可以:

$image = new Imagick;

$image->setResolution(300, 300);

$image->readImage("{$originalPath}[0]");

$image->setImageFormat('jpg');

$image->scaleImage(500, 500, true);

$image->setImageAlphaChannel(Imagick::VIRTUALPIXELMETHOD_WHITE);

我使用Laravel框架,然后将转换后的图像使用Laravel文件系统进行存储。

Storage::put($storePath, $image->getImageBlob());

更新:最近我更换了操作系统,虽然之前在Ubuntu上运行正常,但在我的Mac上某些图片仍然是黑色的。

我不得不将脚本更改为以下内容:

$image = new Imagick;

$image->setResolution(300, 300);

$image->setBackgroundColor('white');

$image->readImage("{$originalPath}[0]");

$image->setImageFormat('jpg');

$image->scaleImage(500, 500, true);

$image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);

$image->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE);

在读取图像之前设置背景颜色似乎很重要。我还会将可能存在的图层展平并删除阿尔法通道。我感觉我在我的Ubuntu机器上尝试了ALPHACHANNEL_REMOVE,但它没有起作用,希望读者能在这些答案之间找到适合自己的方法。


当上传多页PDF时,只有第一页可以正常工作,而其他页面无法正常工作。 - Y. Joy Ch. Singha

1
如果您的 Imagick 版本不是最新的,则 setImageBackgroundColor 可能会出错。
交换以下行
$im->setImageBackgroundColor("red");

对于这个(Imagick版本>=2.1.0)

$im->setBackgroundColor(new ImagickPixel("red"));

或(Imagick 版本 < 2.1.0)

$im->setBackgroundColor("red");

我在我的问题中做了一些更改,请看一下,你的建议不起作用。 - Alfred
@blasteralfred,你能提供一份PDF的访问权限吗?我认为问题可能与PDF有关,而不是你现在提供的代码。更新后的代码在我拥有的PDF上可以正常运行。 - carlgarner

1

我通过以下方式解决了它:

$im = new imagick(realpath($file).'[0]');
$im->setCompression(Imagick::COMPRESSION_JPEG);
$im->setCompressionQuality(100);
$im->setImageFormat("jpeg");
$im->writeImage("imagename.jpg");

setCompressionQuality not actualy working in this situation. For change quality use setImageCompressionQuality - vatavale

1

在创建新的imagick()之后,只需使用flattenImages():

$im = new Imagick('file.pdf[0]');
$im = $im->flattenImages();

编辑:flattenImages方法已被弃用和删除。请使用

$im = $im->mergeImageLayers( imagick::LAYERMETHOD_FLATTEN );

1
将这段代码 $im->setimageformat("jpg"); 修改为 $im->setimageformat("png");,如果遇到背景颜色问题。

1

只需添加此内容即可防止 JPG 图像生成黑色背景

-alpha off

3
哪里?请以问题的格式给出答案,所以在这种情况下有效的 PHP。 - Luke Vincent
1
$im->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE ); - Chris

0

在无数次尝试将PDF文件与JPEG图像合并而不出现黑色区域的情况下,我找到了解决方案:使用函数transformImageColorspace

按照以下顺序使用可以完美地工作:

$im = new Imagick();
$im->readImage("file.pdf");

$im->transformImageColorspace(Imagick::COLORSPACE_SRGB);

$im->setImageFormat('jpeg');
$im->writeImage('image.jpg');

0

我想补充一下之前提供的出色和有帮助的答案,如果你的PDF有多个页面,就需要采用稍微不同的方法。

让我感到惊讶的是,Imagick类实现了Iterable接口,这意味着你可以通过foreach循环来处理每一页(因为似乎只有在最后一页上才能看到图层、颜色和透明通道的变化生效),而每一页都会以一个独立的Imagick对象呈现给你:

$im = new Imagick('path/to/file.pdf');
foreach ($im as $c => $page)
{
    // do what you need to do with each page and then...
    $im->writeImage('path/to/image-'.$c.'.jpg');
}

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