0

I try to draw an image from a bufferedImage into a PDF using PDFBox but fails, and I get black images and Acrobat Reader warns whith errors like "Out of memory" (but PDF is display).

I use a bufferedImage because I need to draw a JavaFX Image object (with came from call to Funciones.crearImagenDesdeTexto(), is a function which converts a text into an Image) into PDF. Rest of images works well without using bufferedimage.

    PDPixelMap img = null;
    BufferedImage bi;

    try {
        //If item has id, I try to get image with that id (image it's shows OK on PDF)
        img = new PDPixelMap(documento, read(getClass().getResourceAsStream("/com/img/" + item.getId() + ".png")));
    }
    catch (Exception e) {
        //If item has not id or fails load image, I create image on the fly (which contains item name. This not work on PDF, shows black images)
        bi = new BufferedImage(alto, ancho, BufferedImage.TYPE_INT_ARGB);
        bi.createGraphics().drawImage(SwingFXUtils.fromFXImage(Funciones.crearImagenDesdeTexto(item.getNombre()), null), ancho, alto, null);
        img = new PDPixelMap(documento, bi);
    }
    finally {
        contenedor.drawXObject(img, x, y, alto, ancho);
    }

NOTE: crearImagenDesdeTexto() returns a JavaFX Image Object that is create on the fly (I try this function in other parts of the program and works well, function is take from other stackOverflow response).

Marcos
  • 4,827
  • 3
  • 20
  • 28

2 Answers2

0

Your code is confusing, you have three "new PDJpeg" and one of them is in a catch (which should just handle the error). And what does "read()" do? Does it pass a stream or a BufferedImage? If it is a stream, then it is wrong, because PDJpeg is for JPEGs, not for PNG.

The second one

img = new PDJpeg(documento, (getClass().getResourceAsStream("/com/img/" + Byte.toString(item.getId()) + ".png")));

is definitively wrong for the same reason: PDJPeg is not for PNG files / streams.

If you want to create an image from a PNG file / stream, use PDPixelMap.

It is possible to create a PDJpeg object from a BufferedImage, but this is recommended only if the image wasn't encoded before. Because if you would read a BufferedImage from a JPEG, and then use PDJPeg for this, you'll have a slight loss of quality as the image is decoded and encoded again (JPEG is a "lossy" compression format).

If my advice doesn't help, please upload the JPEG file and the PDF somewhere.

Also make sure that you're using the latest version, which is 1.8.7.

Update after comments: the parameters to createGraphics.drawImage() should be 0, 0 and not width, height. The two parameters are a location, not a size.

Tilman Hausherr
  • 17,731
  • 7
  • 58
  • 97
  • Assuming that you meant "sometimes" where you wrote "perhaps" - have you verified that the BufferedImage is not black? Just do ImageIO.write(bufferedImage,"png",new File("..../debug.png")) to see whether it isn't black before. Also, I still wonder what "read()" does, does it deliver a stream or a BufferedImage? Is this ImageIO.read()? (Then it delivers a BufferedImage, which is fine) It would be best to separate the steps, i.e. first load your image into a BufferedImage (and a try/catch for this), and then construct the PDPixelMap (and a try/catch). This would make it easier for you to debug. – Tilman Hausherr Oct 23 '14 at 13:31
  • Using "Exception" instead of e.g. "IOException" also brings the danger that you catch "too much". You want to catch only the case that the file doesn't exist, not other unknown exceptions that could indicate different problems. – Tilman Hausherr Oct 23 '14 at 13:33
  • Assuming that "alto" = height and "ancho" = width, then you mixed it up at two places (unless you want it that way). – Tilman Hausherr Oct 23 '14 at 13:42
  • `read()` from `javax.​imageio.​ImageIO` package which returns a BufferedImage. alto=height, ancho=width I take the same units so yes, I mixed them. – Marcos Oct 23 '14 at 13:52
  • I check to save image as you say (ImageIO.write...), and file is empty. I don't understand why isn't working because I use the same function (Funciones.crearImagenDesdeTexto(item.getNombre()) to show images in a JavaFX panel for example, and works well. – Marcos Oct 23 '14 at 14:05
  • the parameters to createGraphics().drawImage - shouldn't these be 0, 0 instead of ancho alto???? That is the location. – Tilman Hausherr Oct 23 '14 at 14:47
0

Finally, I find a solution (thanks also to Tilman Hausherr):

private void dibujarImagen(Item i, int x, int y, int alto, int ancho) throws IOException {
    PDPixelMap img = null;

    try {
        img = new PDPixelMap(documento, read(getClass().getResourceAsStream("/com/img/" + i.getId() + ".png")));
    }
    catch (IllegalArgumentException e) {
        img = new PDPixelMap(documento, SwingFXUtils.fromFXImage(Funciones.crearImagenDesdeTexto(i.getNombre()),null));
    }
    finally {
        contenedor.drawXObject(img, x, y, alto, ancho);
    }
}
Marcos
  • 4,827
  • 3
  • 20
  • 28