2012-02-28 14 views
1

Я использую PDFBox для создания PDF-файлов, однако, когда я пытаюсь нарисовать изображение, которое я получаю из массива байтов, которые я получаю следующую ошибку:Недостаточно данных для изображения (PDF-файл поколение)

Insufficient data for an image

Это основная структура моего кода:

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; 
    } 

Since I receive a PNG file from the Web Service I do the conversion to JPG with the following method:

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, но это то, что я в моем коде.

Я не уверен, есть ли проблема со структурой моего кода или что, возможно, есть ошибка в том, как я обрабатываю байты изображений, которые получаю от вызова веб-службы.

У кого-нибудь есть идея, что может быть проблемой?

UPDATE

Я сделал то, что Цельтер Ади да и образ, который я получаю от веб-службы является действительным, так как я был в состоянии генерировать физический файл с ним, так что проблема должна быть где-то около манипуляции с изображением, дело в том, что я не знаю, чего мне не хватает.

ответ

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()?

1

Перед сборкой pdf попытайтесь сохранить изображение в файле, просто чтобы увидеть, что изображение завершено и может быть сохранено.

Вы можете использовать что-то вроде этого, чтобы проверить полученное изображение:

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

, а затем открыть изображение в ImageViewer. Если изображение не может быть открыто, тогда у вас есть ошибка здесь. Если изображение в порядке ... по крайней мере, вы знаете, что эта часть в порядке!

+0

Ok. Я сделал это, и я подтвердил, что получаю правильный массив байтов, так как мне удалось создать изображения в физической папке. Итак, теперь, когда я уверен, что проблема связана не с ответом на вызов веб-службы, я не уверен, где лежит проблема, я не знаю, не может ли PDFBox обрабатывать файл. –

3

У меня такая же проблема.С некоторых изображений, Acrobat не удалось отобразить страницы с этим сообщением:

Insufficient data for an image

Моя проблема возникла из ColorModel в некоторых Jpeg изображений. Для того, чтобы отслеживать, какие изображения не были нормально, я войти в BufferedImage ColorModel от log.warn(img.getColorModel());

[VisualLocatorServlet.doGet:142] ColorModel: #pixelBits = 24 numComponents = 3 color space = [email protected] transparency = 1 has alpha = false isAlphaPre = false 
[VisualLocatorServlet.doGet:142] ColorModel: #pixelBits = 24 numComponents = 3 color space = [email protected] transparency = 1 has alpha = false isAlphaPre = false 
[VisualLocatorServlet.doGet:142] ColorModel: #pixelBits = 8 numComponents = 1 color space = [email protected] 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); 
... 

Главное, чтобы воссоздать BufferedImage в 24бит. (BufferedImage.TYPE_3BYTE_BGR).

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/