为什么使用此代码生成的 PDF 质量如此之低?

发布于 2024-11-13 04:39:21 字数 2217 浏览 3 评论 0原文

我有以下代码。它用于将各种图像附件(和 pdf)合并到一个 PDF 中。由于某种原因,当我将单个 PDF 放入代码中时,与原始 PDF 相比,最终结果看起来非常糟糕。此外,我可以在源 PDF 中选择文本,但在生成的 PDF 中却不能。

任何帮助将不胜感激。

// PDF object
$pdf = new Imagick();
$max_resolution = array('x' => 100, 'y' => 100);

foreach($attachment_ids as $attachment_id) {
    $attachment = DAO_Attachment::get($attachment_id);
    $file = Storage_Attachments::get($attachment);
    // Temporarily store our attachment
    $im = new Imagick();
    $im->readImageBlob($file);
    // We need to reset the iterator otherwise only one page will be rotated
    $im->resetIterator();

    // Get the resolution
    $resolution = $im->getImageResolution();
    if($resolution['x'] > $max_resolution['x']) {
        $max_resolution['x'] = $resolution['x'];
    }
    if($resolution['y'] > $max_resolution['y']) {
        $max_resolution['y'] = $resolution['y'];
    }

    $num_pages = $im->getNumberImages();

    $rotation = array_shift($rotations);
    $degrees = $rotation > 0 ? 360 - $rotation : 0;
    $pages = array();

    if($degrees > 0) {
        // Rotate each page
        for($i = 1; $i <= $num_pages; $i++) {
            $im->nextImage();
            $im->rotateImage(new ImagickPixel(), $degrees);
        }
    }

    // We need to reset the iterator again so all of our pages will be added to the pdf
    $im->resetIterator();

    // If the image format isn't a pdf, convert it to a png
    if($im->getImageFormat !== 'pdf') {
        $im->setImageFormat('png');
        // Opacity
        if(method_exists($im, 'setImageOpacity'))
            $im->setImageOpacity(1.0);
    }

    $im->setImageCompression(imagick::COMPRESSION_LOSSLESSJPEG); 
    $im->setImageCompressionQuality(100);
    $im->stripImage();

    // Add the rotated attachment to the PDF
    $pdf->addImage($im);

    // Free
    $im->destroy();
}

// Create a composite
$pdf->setImageFormat('pdf');

// Compress output
$pdf->setImageCompression(imagick::COMPRESSION_LOSSLESSJPEG); 
$pdf->setImageCompressionQuality(100);
$pdf->stripImage();

// Set resolution
$pdf->setImageResolution($max_resolution['x'], $max_resolution['y']);

I have the following code. It's used to combine various image attachments (and pdfs) into one PDF. For some reason, when I take even a single PDF and put it through the code, the end result comes out looking very bad compared to the original PDF. In addition, I can select text in the source PDF, but in the generated one I cannot.

Any help would be greatly appreciated.

// PDF object
$pdf = new Imagick();
$max_resolution = array('x' => 100, 'y' => 100);

foreach($attachment_ids as $attachment_id) {
    $attachment = DAO_Attachment::get($attachment_id);
    $file = Storage_Attachments::get($attachment);
    // Temporarily store our attachment
    $im = new Imagick();
    $im->readImageBlob($file);
    // We need to reset the iterator otherwise only one page will be rotated
    $im->resetIterator();

    // Get the resolution
    $resolution = $im->getImageResolution();
    if($resolution['x'] > $max_resolution['x']) {
        $max_resolution['x'] = $resolution['x'];
    }
    if($resolution['y'] > $max_resolution['y']) {
        $max_resolution['y'] = $resolution['y'];
    }

    $num_pages = $im->getNumberImages();

    $rotation = array_shift($rotations);
    $degrees = $rotation > 0 ? 360 - $rotation : 0;
    $pages = array();

    if($degrees > 0) {
        // Rotate each page
        for($i = 1; $i <= $num_pages; $i++) {
            $im->nextImage();
            $im->rotateImage(new ImagickPixel(), $degrees);
        }
    }

    // We need to reset the iterator again so all of our pages will be added to the pdf
    $im->resetIterator();

    // If the image format isn't a pdf, convert it to a png
    if($im->getImageFormat !== 'pdf') {
        $im->setImageFormat('png');
        // Opacity
        if(method_exists($im, 'setImageOpacity'))
            $im->setImageOpacity(1.0);
    }

    $im->setImageCompression(imagick::COMPRESSION_LOSSLESSJPEG); 
    $im->setImageCompressionQuality(100);
    $im->stripImage();

    // Add the rotated attachment to the PDF
    $pdf->addImage($im);

    // Free
    $im->destroy();
}

// Create a composite
$pdf->setImageFormat('pdf');

// Compress output
$pdf->setImageCompression(imagick::COMPRESSION_LOSSLESSJPEG); 
$pdf->setImageCompressionQuality(100);
$pdf->stripImage();

// Set resolution
$pdf->setImageResolution($max_resolution['x'], $max_resolution['y']);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

岁月蹉跎了容颜 2024-11-20 04:39:21

这对您来说可能已经很明显了,但低质量的图像不会产生高质量的 pdf。我不知道Imagick的pdf生成功能有多好,但从你的代码看来你正在转换图像?您可以通过对 TcPDF 执行相同的操作进行比较,但如果图像质量较低,我怀疑您会得到更好的结果。

此外,如果您可以访问比通常的网络优化格式更高 DPI 分辨率的图像,我建议您使用这些图像来构建 PDF。质量会好很多。

This may be obvious to you already but a low quality image will not result in a high quality pdf. I don't know how good Imagick's pdf generation capabilities are, but it seems from your code you are converting images? You could compare by doing the same thing with TcPDF, though if the image is low quality I doubt you will get better results.

Also, if you have access to higher DPI resolution images than the usual web-optimised format, I recommend you use those to build your PDF instead. The quality will be a lot better.

一曲爱恨情仇 2024-11-20 04:39:21

ImageMagick 使用 GhostScript 将 PDF 转换为各种光栅图像格式。 GhostScript 在这方面非常擅长,但您通过将页面缩小到最大 100x100 来限制它。

72 dpi 下的 8.5x11(英寸)页面为 612x792 像素。

也许您的意思是限制 DPI 而不是分辨率?输出仍然无法很好地缩放(矢量格式与像素格式),但我怀疑这将是一个很大的改进。

ImageMagick uses GhostScript to convert PDFs to various raster image formats. GhostScript is quite good at this, but you're hand-cuffing it by scaling the page down to a max of 100x100.

An 8.5x11 (inches) page at 72 dpi, is 612x792 pixels.

Perhaps you meant to restrict DPI rather than resolution? The output still won't scale all that well (vector formats vs pixel formats), but I suspect it would be a big improvement.

话少心凉 2024-11-20 04:39:21

事实证明,这个问题的答案是使用 setResolution() 设置 DPI。我们在使用 readImageBlob() 读取包含图像的文件之前执行此操作,因为它将根据当前分辨率更改图像的 DPI(因此之后进行设置)不会工作)。

您还可以使用一些数学知识并使用 resampleImage() 来完成此操作,但 setResolution() 似乎非常适合我们。

It turns out the answer to this is to set the DPI using setResolution(). We do this before using readImageBlob() to get read the file containing our image, as it will change the DPI of the image based on the current resolution (so setting it afterwards won't work).

You could also use some math and use resampleImage() to do it after the fact, but setResolution() seems to be working perfectly for us.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文