使用Imagick php扩展将多页PDF转换为JPG时出现黑色背景

9

在使用Imagick php扩展将多页PDF转换为JPG时,如何最好地纠正黑色背景?

以下是我应用程序中使用的代码:

    $imagick = new Imagick($file);
    $imagick->setResolution(150,150);
    $imagick->setImageFormat("jpg");
    $imagick->setImageCompression(imagick::COMPRESSION_JPEG);
    $imagick->setImageCompressionQuality(70);
    foreach ($imagick as $c => $_page) {
        $_page->setImageBackgroundColor('white');
        $_page->adaptiveResizeImage($maxsize,$maxsize,true);
        $_page->writeImage("$file-$c.jpg");
    }

我知道可以使用flattenImage方法来移除黑色背景,例如:

    $imagick = $imagick->flattenImages();

但是当文件有多个页面时,flattenImages方法会将所有页面放在同一张图像上,因此生成的所有JPG副本中都是最后一页的复制。 如果有人能帮助我,我将不胜感激。

你能否发布一个PDF示例? - Danack
当然,这是一个例子: http://www.faceo.com.br/temp/Manual%20Split%20hiwall%20YORK-1.pdf 以及其中生成的一个jpg: http://www.faceo.com.br/temp/Manual%20Split%20hiwall%20YORK-1.pdf-10.jpg - fcaserio
1
嗯,没有压力...但如果它解决了你的问题,怎么样点击一下那个接受按钮?;-) - Danack
2个回答

11

先写出可工作的代码 - 解释会在后面提供:

这段代码虽然能够运行,但是非常缓慢:

$file = "./YORK.pdf";

$maxsize = 500;

$imagick = new Imagick($file);
$imagick->setResolution(150,150);
$imagick->setImageFormat("jpg");
$imagick->setImageCompression(imagick::COMPRESSION_JPEG);
$imagick->setImageCompressionQuality(70);

foreach ($imagick as $c => $_page) {
    $_page->setImageBackgroundColor('white');
    $_page->adaptiveResizeImage($maxsize,$maxsize,true);
    $_page->setImageCompose(\Imagick::COMPOSITE_ATOP);
    $_page->flattenImages();
    $_page->writeImage("$file-$c-compose.jpg");
}

这段代码可行且运行速度较快:

foreach ($imagick as $c => $_page) {
    $_page->setImageBackgroundColor('white');
    $_page->adaptiveResizeImage($maxsize,$maxsize,true);
    $blankPage = new \Imagick();
    $blankPage->newPseudoImage($_page->getImageWidth(), $_page->getImageHeight(), "canvas:white");
    $blankPage->compositeImage($_page, \Imagick::COMPOSITE_ATOP, 0, 0);
    $blankPage->writeImage("$file-$c.jpg");
}
我认为正在发生的是,在生成图像时,ImageMagick正在执行以下操作:
  • 将各个层转换为JPG格式
  • 将它们叠加在一起。
对于具有透明度的每个图层,因为JPG不支持透明度,它会将透明度渲染为黑色,然后合并。上述代码使合成按正确顺序进行。
解决问题的另一种方法是将输出设置为PNG格式。由于PNG支持透明度,具有透明度的各个层被正确地合并,然后如果您确实想要,可以将最终图像转换为JPG。
在工作流中使用PNG作为中间格式可能还会产生略微更高质量的输出,因为它可能会跳过“保存为JPG并解码”的步骤。我建议您在可能的情况下始终使用PNG,并仅在向最终用户提供文件时将其转换为JPG,如果您真的需要那额外的压缩比。

谢谢,把图像放在一个新的白色画布上是个好方法! - fcaserio
我仍然有一个问题,即页面上出现黑色背景(对我来说是带有文字和图像的最后一页)。将“Imagick :: COMPOSITE_ATOP”替换为“Imagick :: COMPOSITE_OVER”似乎可以解决这个问题。 - MarcinWolny

0

使用 Laravel 开发多页 PDF 的可工作代码

if ($request->has('pdf_file')) 
        {
            $getPdfFile = $request->file('pdf_file');

            $originalname = $getPdfFile->getClientOriginalName();

            $path = $getPdfFile->storeAs('PdfToJpg', $originalname);
        }

        // file name without extension
        $filename_without_ext = pathinfo($originalname, PATHINFO_FILENAME);

        //get the upload file
        $storagePath = storage_path('app/PdfToJpg/' . $originalname);

        $imagick = new Imagick();

        $imagick->setResolution(300, 300);
        
        $imagick->readImage($storagePath);

        $pages = (int)$imagick->getNumberImages();

        for ( $i = 0; $i < $pages; $i ++ ) {
            $imagick->readImage($storagePath . '[' . $i . ']' );
            $imagick->setImageCompressionQuality( 100 );
            $imagick->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
            $imagick->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE);
            $imagick->writeImage( storage_path('app/PdfToJpg/') . $i . '.jpg' );
        }

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