【问题标题】:Get displayed size of an image in a pdf with PDFBox使用 PDFBox 获取 pdf 中图像的显示大小
【发布时间】:2021-11-28 08:19:01
【问题描述】:

我正在尝试计算每页上 PDF“占用”中的图像百分比。我有以下代码:

PDPageTree list = document.getPages();
int pageNumber = 0;
float imagePerPage = 0;
for (PDPage page : list) {
    BufferedImage pageImage = renderer.renderImage(pageNumber, 2);
    float pageWidth = pageImage.getWidth();
    float pageHeight = pageImage.getHeight();
    PDResources pdResources = page.getResources();

    int i = 1;
    for (COSName name : pdResources.getXObjectNames()) {
        PDXObject object = pdResources.getXObject(name);
        if (object instanceof PDImageXObject) {
            PDImageXObject image = (PDImageXObject) object;
            BufferedImage bufferedImage = image.getImage();
            float imageWidth = bufferedImage.getWidth();
            float imageHeight = bufferedImage.getHeight();

            int sumr = 0;
            int sumg = 0;
            int sumb = 0;
            for (int x = 0; x < imageWidth; x++) {
                for (int y = 0; y < imageHeight; y++) {
                    Color pixel = new Color(bufferedImage.getRGB(x, y));
                    sumr += pixel.getRed();
                    sumg += pixel.getGreen();
                    sumb += pixel.getBlue();
                }
            }
            int num = image.getWidth() * image.getHeight();
            Color avg = new Color(sumr / num, sumg / num, sumb / num);
            if (!new Color(0, 0, 0).equals(avg)) {
                String filename = "extracted-image-" + i + ".png";
                ImageIO.write(
                    image.getImage(),
                    "png",
                    new File(filename)
                );
                imagePerPage++;
            }
            i++;
        }
    }
    System.out.println("Image per page ratio is: " + imagePerPage);
    imagePerPage = 0;
    pageNumber++;
}

但是,bufferedImage.getWidth() 和 bufferedImage.getHeight() 返回图像的实际大小(以像素为单位)。如何获得每张图片的显示尺寸?

更新 1

我尝试使用 PrintImageLocations.java 示例来检索显示图像大小。但是,对于实际的 pdf,它似乎给出了错误的响应。

如果此 PDF 的媒体框宽度为 612,高度为 792,则 25(宽度)和 16.61(高度)的图像的缩放数字似乎不正确。毕竟,每张图片至少有总宽度的三分之一。

【问题讨论】:

  • 请看 PrintImageLocations.java 例子
  • 这个例子对我没有帮助。我不需要打印显示尺寸,我需要检索它们。
  • 我的意思是您更改源代码以便“检索”它们而不是“打印”它们。
  • 它似乎没有让我得到正确的值。我会相应地更新我的描述。
  • 现在我们需要 PDF。

标签: java image pdf pdfbox


【解决方案1】:

使用 pdfbox 文档网站上的示例为我做了一些有用的事情

package br.gov.pb.mp.framework.util.pdf;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.pdfbox.contentstream.PDFStreamEngine;
import org.apache.pdfbox.contentstream.operator.DrawObject;
import org.apache.pdfbox.contentstream.operator.Operator;
import org.apache.pdfbox.contentstream.operator.state.Concatenate;
import org.apache.pdfbox.contentstream.operator.state.Restore;
import org.apache.pdfbox.contentstream.operator.state.Save;
import org.apache.pdfbox.contentstream.operator.state.SetGraphicsStateParameters;
import org.apache.pdfbox.contentstream.operator.state.SetMatrix;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.util.Matrix;

public class ImageSizeExtractor extends PDFStreamEngine {

    private Map<String, float[]> pageImages;

    public ImageSizeExtractor() throws IOException {
        // preparing PDFStreamEngine
        addOperator(new Concatenate());
        addOperator(new DrawObject());
        addOperator(new SetGraphicsStateParameters());
        addOperator(new Save());
        addOperator(new Restore());
        addOperator(new SetMatrix());
        
        pageImages = new HashMap<String, float[]>();
    }

    public Map<String, float[]> getPageImages() {
        return pageImages;
    }

    public void setPageImages(Map<String, float[]> pageImages) {
        this.pageImages = pageImages;
    }

    @Override
    protected void processOperator(Operator operator, List<COSBase> operands) throws IOException {
        String operation = operator.getName();
        if ("Do".equals(operation)) {
            COSName objectName = (COSName) operands.get(0);
            // get the PDF object
            PDXObject xobject = getResources().getXObject(objectName);
            // check if the object is an image object
            if (xobject instanceof PDImageXObject) {
                PDImageXObject image = (PDImageXObject) xobject;
                int imageWidth = image.getWidth();
                int imageHeight = image.getHeight();

                System.out.println("\nImage [" + objectName.getName() + "]");

                Matrix ctmNew = getGraphicsState().getCurrentTransformationMatrix();
                float imageXScale = ctmNew.getScalingFactorX();
                float imageYScale = ctmNew.getScalingFactorY();

                System.out.println("displayed size  = " + imageXScale + ", " + imageYScale + " in user space units");
                
                float[] xy = {imageXScale,imageYScale};
                pageImages.put(objectName.getName(), xy);
                
            } else if (xobject instanceof PDFormXObject) {
                PDFormXObject form = (PDFormXObject) xobject;
                showForm(form);
            }
        } else {
            super.processOperator(operator, operands);
        }
    }

}

使用上述类的方法。

public static boolean analyseImageEntirePagePdfAto(byte[] sourcePdf) throws Throwable {
        boolean containsEntirePageImage = false;
        PDDocument docAto = PDDocument.load(sourcePdf);
        int p = 0;
        PDPageTree pageTree = docAto.getPages();
        if (!containsEntirePageImage) {
            for (PDPage pagina : pageTree) {
                p++;
                PDFTextStripper reader = new PDFTextStripper();
                reader.setStartPage(p);
                reader.setEndPage(p);
                String pageText = reader.getText(docAto);
                pageText = pageText.replaceAll("\r\n", "");
                if (pageText == "" || pageText == null) {
                    containsEntirePageImage = true;
                    break;
                }
                float ph = pagina.getMediaBox().getHeight();
                float pw = pagina.getMediaBox().getWidth();
                float pageArea = ph * pw;
                ImageSizeExtractor imageSizeExtractor = new ImageSizeExtractor();
                imageSizeExtractor.processPage(pagina);
                if (!imageSizeExtractor.getPageImages().entrySet().isEmpty()) {
                    for (Map.Entry<String, float[]> entry : imageSizeExtractor.getPageImages().entrySet()) {
                        float[] imageMeasures = entry.getValue();
                        float imageArea = imageMeasures[0] * imageMeasures[1];
                        float imgPercent = (imageArea / pageArea) * 100;

                        if (imgPercent > 80) {
                            containsEntirePageImage = true;
                            break;
                        }
                    }
                }
            }
        }
        return containsEntirePageImage;
    }

processPage(PDPage page)方法在PDFStreamEngine类中

【讨论】:

    猜你喜欢
    • 2017-05-07
    • 1970-01-01
    • 2012-09-09
    • 2012-02-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    • 2018-09-29
    相关资源
    最近更新 更多