图像数据不足(PDF文件生成)

时间:2012-02-28 23:33:05

标签: java pdf-generation pdfbox

我正在使用 PDFBox 生成PDF文件,但是当我尝试绘制从字节数组中收到的图像时,我收到以下错误:

  

图片数据不足

这是我的代码的基本结构:

    public ByteArrayOutputStream generatePDF() {                

        .. Variable Declaration

        // Creating Document
        document = new PDDocument();

        // Creating Pages       
        for(int i = 0; i < arrayVar.length; i++) {

            // Adding page to document
            page = new PDPage();

            // Creating FONT Attributes
            fontNormal = PDType1Font.HELVETICA;
            fontBold = PDType1Font.HELVETICA_BOLD;

            // Building Front & Back Invoice Images         
            singleImageMap = // Getting Map With Array Of Bytes from Web Service Call;

            if(singleImageMap != null && !singleImageMap.isEmpty()) {

                            arrayFront = Utils.readImage((byte[]) singleImageMap.get(Constants.WS_IMAGE_FRONT));
            arrayBack = Utils.readImage((byte[]) singleImageMap.get(Constants.WS_IMAGE_BACK));

            fileFront = new ByteArrayInputStream(arrayFront);
            fileBack = new ByteArrayInputStream(arrayBack);                 
                bufferedImageFront = ImageIO.read(fileFront);
                bufferedImageBack = ImageIO.read(fileBack);                 

                rescaledFrontImg = Scalr.resize(bufferedImageFront, 500);
                rescaledBackImg = Scalr.resize(bufferedImageBack, 500);

                front = new PDJpeg(document, rescaledFrontImg);
                back = new PDJpeg(document, rescaledBackImg);

            }

            // Next we start a new content stream which will "hold" the to be created content.
            contentStream = new PDPageContentStream(document, page);                

            // Let's define the content stream
            contentStream.beginText();
            contentStream.setFont(fontNormal, 8);
            contentStream.moveTextPositionByAmount(200, 740);
            contentStream.drawString("NAME: " + arrayVar[i].getParameter(Constants.NAME));
            contentStream.endText();

            if(front != null && back != null) {
                contentStream.drawImage(front, 55, 500);
                contentStream.drawImage(back, 55, 260); 
            }           

            // Add Page
            document.addPage(page);

            // Let's close the content stream       
            contentStream.close();

        }

        // Let's create OutputStream object
        output = new ByteArrayOutputStream(); 

        // Finally Let's save the PDF
        document.save(output);
        document.close();

        return output;
    }
  

由于我从Web服务收到PNG文件,因此我使用以下方法转换为JPG:

    public static byte[] readImage(byte[] file) throws Exception {

    ImageInputStream is = ImageIO.createImageInputStream(new ByteArrayInputStream(file));

    BufferedImage originalImage = ImageIO.read(is);         
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    ImageIO.write(originalImage, "jpg", baos ); 

    byte[] imageInByte = baos.toByteArray();

    return imageInByte;
}

根据此链接:

  

https://issues.apache.org/jira/browse/PDFBOX-849

它指出错误是因为PDJepg对象应该在创建contentStream之前创建,但这就是我在代码中所做的。

我不确定我的代码结构是否有问题,或者我正在处理从Web服务调用中获取的图像字节的方式可能存在错误。

有没有人知道可能出现什么问题?

更新

我做了什么Zelter Ady,实际上我从Web服务获得的图像是有效的,因为我能用它生成一个物理文件,所以问题应该是在图像的操作周围,事情我不知道我错过了什么。

5 个答案:

答案 0 :(得分:3)

我遇到了同样的问题。对于某些图像,Acrobat无法显示包含此消息的页面:

  

图像数据不足

我的问题来自某些jpeg图片中的colorModel。 要跟踪哪些图像不正常,请按log.warn(img.getColorModel());

记录BufferedImage colorModel
[VisualLocatorServlet.doGet:142] ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@4b7fce transparency = 1 has alpha = false isAlphaPre = false
[VisualLocatorServlet.doGet:142] ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@4b7fce transparency = 1 has alpha = false isAlphaPre = false
[VisualLocatorServlet.doGet:142] ColorModel: #pixelBits = 8 numComponents = 1 color space = java.awt.color.ICC_ColorSpace@19ef899 transparency = 1 has alpha = false isAlphaPre = false

显然,失败的图像是8位编码。

为了解决这个问题,我做了以下事情:

byte[] buffer = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
BufferedImage img = ImageIO.read(new URL(visual));
/* resample 8-bits to 24-bits if necessary to fix pdf corruption */             
if(img.getColorModel().getNumColorComponents()==1){
  log.warn("components #1"+img.getColorModel());
  BufferedImage out = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
  Graphics2D g2 = out.createGraphics();
  g2.setBackground(Color.WHITE);
  g2.drawImage(i, 0, 0, null);
  g2.dispose();
  log.warn("redrawn image "+img.getColorModel());
}
ImageIO.write(img, "jpeg", out);
...

重点是重新创建24位的BufferedImage。 (BufferedImage.TYPE_3BYTE_BGR)。

答案 1 :(得分:2)

这可能是Adobe查看者方面的问题,而不是创建时的问题。最新的Acrobat版本存在一个已知问题:更新到10.1.4或9.5.2后出现“图像数据不足”错误:

http://blogs.adobe.com/dmcmahon/2012/08/21/acrobat-insufficient-data-for-an-image-error-after-updating-to-10-1-4-or-9-5-2/

答案 2 :(得分:1)

在构建pdf之前,尝试将图像保存在文件中,只是为了查看图像已完成并可以保存。

您可以使用类似的方法测试收到的图像:

System.IO.File.WriteAllBytes("c:\\tmp.png", (byte[]) singleImageMap.get(Constants.FRONT));

然后在imageviewer中打开图像。如果图像无法打开,那么你在这里有错误。如果图像没问题......至少你知道这部分还可以!

答案 3 :(得分:1)

经过大量调试后,我发现问题出在这里:

front = new PDJpeg(document, rescaledFrontImg);
back = new PDJpeg(document, rescaledBackImg);

PDJpeg 类有两个构造函数:

PDJpeg(PDDocument doc, BufferedImage bi)
PDJpeg(PDDocument doc, InputStream is)

我正在传递 BufferedImage ,并且在某些时候我仍然无法弄清楚,我假设所有字节都没有被完全发送,因此我收到消息“图像数据不足”

解决方案:我传递了一个InputStream而不是BufferedImage。

我仍然不知道为什么我使用BufferedImage得到了这个错误,也许我需要做某种.push()?

答案 4 :(得分:0)

此代码对我有用。

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import org.apache.commons.imaging.Imaging;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;

public void generatePdfFromTifPbox(File sourceFile, String destinationPath) throws Exception {
    //sourceFile is tiff file, destinationPath is pdf destination path with pdf file name
    PDDocument doc = new PDDocument();
    List<BufferedImage> bimages = Imaging.getAllBufferedImages(sourceFile);
    for (BufferedImage bi : bimages) {
    PDPage page = new PDPage();
    doc.addPage(page);
    PDPageContentStream contentStream = new PDPageContentStream(doc, page);
    try {
    // the .08F can be tweaked. Go up for better quality,
    // but the size of the PDF will increase
    PDImageXObject image = JPEGFactory.createFromImage(doc, bi, 0.08f);
    Dimension scaledDim = getScaledDimension(new Dimension(image.getWidth(), image.getHeight()),
    new Dimension((int) page.getMediaBox().getWidth(), (int) page.getMediaBox().getHeight()));
    contentStream.drawImage(image, 1, 1, scaledDim.width, scaledDim.height);
    } finally {
    contentStream.close();
    }
    }
    doc.save(destinationPath);
    }


private Dimension getScaledDimension(Dimension imgSize, Dimension boundary) {
    int original_width = imgSize.width;
    int original_height = imgSize.height;
    int bound_width = boundary.width;
    int bound_height = boundary.height;
    int new_width = original_width;
    int new_height = original_height;

    // first check if we need to scale width
    if (original_width > bound_width) {
    // scale width to fit
    new_width = bound_width;
    // scale height to maintain aspect ratio
    new_height = (new_width * original_height) / original_width;
    }

    // then check if we need to scale even with the new height
    if (new_height > bound_height) {
    // scale height to fit instead
    new_height = bound_height;
    // scale width to maintain aspect ratio
    new_width = (new_height * original_width) / original_height;
    }

    return new Dimension(new_width, new_height);
    }

参考/礼貌: http://www.paulzepernick.com/java/java-apache-pdfbox-convert-multipage-tiff-to-pdf/

Maven依赖项:

<dependency>
   <groupId>org.apache.pdfbox</groupId>
   <artifactId>pdfbox</artifactId>
   <version>2.0.3</version> 
</dependency> 
    
    
<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-imaging</artifactId>
   <version>1.0-alpha1</version>
</dependency>
相关问题