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


Black background when converting multi page PDF to JPG with Imagick php extension

使用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");
    }

我知道平坦图像方法可以用来去除黑色背景,例如:

    $imagick = $imagick->flattenImages();

但是,当文件有多个页面时,flawnImages方法会将所有页面放在同一个图像上,因此结果是生成的所有JPG中最后一页的副本。

如果有人能帮我,我将不胜感激。

工作代码优先-下面的解释:

此代码有效,但速度慢得令人难以置信:

$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。由于它支持透明度,具有透明度的各个层可以正确地合并,然后如果你真的想的话,你可以将最终图像转换为JPG

使用PNG作为中间格式也可能产生稍高质量的输出,因为它可能会跳过"保存到JPG并解码"步骤。我建议您尽可能在工作流程中使用PNG,然后只有当您向最终用户提供文件时,如果您确实需要额外的压缩,才转换为JPG。

使用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' );
        }