Java 图像数据不足(生成PDF文件)
我正在使用PDFBox生成PDF文件,但是当我尝试绘制从字节数组接收的图像时,我得到以下错误: 图像数据不足 这是我的代码的基本结构:Java 图像数据不足(生成PDF文件),java,pdf-generation,pdfbox,Java,Pdf Generation,Pdfbox,我正在使用PDFBox生成PDF文件,但是当我尝试绘制从字节数组接收的图像时,我得到以下错误: 图像数据不足 这是我的代码的基本结构: public ByteArrayOutputStream generatePDF() { .. Variable Declaration // Creating Document document = new PDDocument(); // Creat
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;
}
根据此链接:
它指出错误是因为应该在创建contentStream之前创建PDJepg对象,但我在代码中就是这么做的
我不确定我的代码结构是否有问题,或者在处理从Web服务调用获取的图像字节时是否有错误
有人知道问题出在哪里吗
更新
我做了Zelter Ady所做的事情,事实上,我从Web服务获得的图像是有效的,因为我能够用它生成一个物理文件,所以问题应该在图像操作的某个地方,问题是我不知道我缺少了什么。在构建pdf之前,请尝试将图像保存在一个文件中,只需查看图像是否完整并可以保存即可 您可以使用类似的方法来测试接收到的图像:
System.IO.File.WriteAllBytes("c:\\tmp.png", (byte[]) singleImageMap.get(Constants.FRONT));
然后在imageviewer中打开图像。如果图像无法打开,则此处有错误。如果图像正常。。。。至少你知道这部分还可以 在生成pdf之前,请尝试将图像保存到文件中,以查看图像是否完整并可以保存 您可以使用类似的方法来测试接收到的图像:
System.IO.File.WriteAllBytes("c:\\tmp.png", (byte[]) singleImageMap.get(Constants.FRONT));
然后在imageviewer中打开图像。如果图像无法打开,则此处有错误。如果图像正常。。。。至少你知道这部分还可以 经过大量调试后,我发现问题出在这里:
front = new PDJpeg(document, rescaledFrontImg);
back = new PDJpeg(document, rescaledBackImg);
PDJpeg类有两个构造函数:
PDJpeg(PDDocument doc, BufferedImage bi)
PDJpeg(PDDocument doc, InputStream is)
我正在传递一个BuffereImage,在某个我仍然无法理解的点上,我假设所有的字节都没有被完全发送,因此我得到了一个消息,图像数据不足
解决方案:我传递了一个InputStream而不是BuffereImage
我仍然不知道为什么我在使用BuffereImage时会出错,可能我需要执行某种.push?经过大量调试后,我发现问题出在这里:
front = new PDJpeg(document, rescaledFrontImg);
back = new PDJpeg(document, rescaledBackImg);
PDJpeg类有两个构造函数:
PDJpeg(PDDocument doc, BufferedImage bi)
PDJpeg(PDDocument doc, InputStream is)
我正在传递一个BuffereImage,在某个我仍然无法理解的点上,我假设所有的字节都没有被完全发送,因此我得到了一个消息,图像数据不足
解决方案:我传递了一个InputStream而不是BuffereImage
我仍然不知道为什么我在使用BuffereImage时会出错,也许我需要执行某种.push?我也有同样的问题。对于某些图像,Acrobat无法显示包含以下消息的页面: 图像数据不足 我的问题来自一些jpeg图像中的颜色模型。 为了跟踪哪些图像不正常,我通过log.warnimg.getColorModel记录BuffereImage colorModel 显然,失败的图像是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位重新创建BuffereImage。BuffereImage.TYPE_3BYTE_BGR.我也有同样的问题。对于某些图像,Acrobat无法显示包含以下消息的页面: 图像数据不足 我的问题来自一些jpeg图像中的颜色模型。 为了跟踪哪些图像不正常,我通过log.warnimg.getColorModel记录BuffereImage colorModel 显然,失败的图像是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位重新创建BuffereImage。BuffereImage.TYPE_3BYTE_BGR.这可能是Adobe viewer端的问题,而不是创建时的问题。更新到10.1.4或9.5.2后,Acrobat最新版本存在一个已知问题:“图像数据不足”错误:
这可能是Adobe viewer方面的问题,而不是创建时的问题。更新到10.1.4或9.5.2后,Acrobat最新版本存在一个已知问题:“图像数据不足”错误:
这个代码对我有用
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);
}
参考/礼貌:
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>
这个代码对我有用
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);
}
参考/礼貌:
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>
好啊我这样做了,我验证了我得到了一个有效的字节数组,因为我能够在物理文件夹中创建图像。所以现在我肯定问题不是来自Web服务调用响应,我不确定问题出在哪里,我不知道PDFBox是否无法处理该文件。Ok。我这样做了,我验证了我得到了一个有效的字节数组,因为我能够在物理文件夹中创建图像。所以现在我肯定问题不是来自Web服务调用响应,我不确定问题出在哪里,我不知道PDFBox是否无法处理该文件。