Menu

#55 Blank pages (B&W JPEG) in converted PDF in normal PDF viewer

open
5
2011-04-10
2009-12-15
Anonymous
No

Not the same as "Blank pages when viewing converted PDF in normal PDF viewer - ID: 1721414" , maybe related to "Make B&W JPEG files compatible - ID: 1456026"? : When converting PDFs, 8bit B&W JPEGs appears as blank pages in normal PDFs viewer. PDF viewers tested: OSX viewer, Kindle2. Jomic 0.9.30 (Apr 20, 2008) in OSX.

Discussion

  • Dave Korn

    Dave Korn - 2010-08-26

    I have this problem too, and I've figured out what is causing the PDF viewer to fail to display the generated PDF: the image is a 256-color jpeg sure enough, and manually chopping off the PDF header allows it to be viewed as a jpeg. The problem is that the pdf stream header contains the line "/ColorSpace /DeviceRGB", which is incorrect. Manually changing it to "DeviceGray" in a hex editor made the PDF viewable! So this should be easy to fix :)

     
  • Dave Korn

    Dave Korn - 2010-08-26

    I spoke too soon. The problem appears to be a weakness of the pdfbox library; org.pdfbox.pdmodel.graphics.xobject.PDJPeg unconditionally calls "setColorSpace( PDDeviceRGB.INSTANCE );" in several places, and has no interface to specify a b'n'w jpeg.

     
  • Dave Korn

    Dave Korn - 2010-08-26

    Actually, it's ok, we can change the PDJpeg's color space setting after creating it and before rendering it, I think, like so ...

    Index: source/net/sf/jomic/comic/CreatePdfComicTask.java

    --- source/net/sf/jomic/comic/CreatePdfComicTask.java (revision 2132)
    +++ source/net/sf/jomic/comic/CreatePdfComicTask.java (working copy)
    @@ -34,6 +34,7 @@
    import org.pdfbox.pdmodel.PDPage;
    import org.pdfbox.pdmodel.common.PDRectangle;
    import org.pdfbox.pdmodel.edit.PDPageContentStream;
    +import org.pdfbox.pdmodel.graphics.color.PDDeviceGray;
    import org.pdfbox.pdmodel.graphics.xobject.PDJpeg;

    /**
    @@ -106,6 +107,11 @@
    try {
    PDPage page = new PDPage();
    PDJpeg jpeg = new PDJpeg(pdfDocument, imageStream);
    + if (!needsTrim && isJpegImage) {
    + // Check if B'n'W image.
    + // If so, call:
    + jpeg.setColorSpace( new PDDeviceGray() );
    + }
    PDPageContentStream contentStream = new PDPageContentStream(pdfDocument, page);

    try {

    ... but I don't know how to detect the format from the raw FileInputStream or File yet.

     
  • Dave Korn

    Dave Korn - 2010-08-26

    I have come up with a patch that fixes the problem for me. I'm not 100% sure about reusing the "if (!needsTrim && isJpegImage)" condition before checking for a b'n'w image, I did it because I guessed that in the case where it has to create a RenderedImage that it would be implicitly promoted to rgb, but I could be wrong, in which case the test should be removed from the line after the PDJpeg is constructed.

    I don't seem to be able to access the "attach file" feature here, though. I'll paste it into the comment, but the whitespace will get mangled; for an unmangled version, see http://pastebin.com/1qjRjf9m

    Thank you Thomas for such a useful bit of software! :-)

    Index: source/net/sf/jomic/tools/ImageTools.java

    --- source/net/sf/jomic/tools/ImageTools.java (revision 2132)
    +++ source/net/sf/jomic/tools/ImageTools.java (working copy)
    @@ -399,6 +399,60 @@
    return (ImageReader) ImageIO.getImageReaders(imageStream).next();
    }

    + /**
    + * Get an image type specifier for <code>imageStream</code> or <code>null</code> if no image
    + * stream or reader is available.
    + *
    + * @see ImageIO#getImageReaders(java.lang.Object)
    + * @see ImageReader#setInput(java.lang.Object)
    + * @see ImageReader#getNumImages(boolean)
    + * @see ImageReader#getRawImageType(int)
    + */
    + public ImageTypeSpecifier getImageTypeSpecifier(ImageInputStream imageStream)
    + throws IOException {
    + ImageTypeSpecifier result = null;
    +
    + if (imageStream != null) {
    + Iterator readerRider = ImageIO.getImageReaders(imageStream);
    +
    + while ((result == null) && readerRider.hasNext()) {
    + ImageReader reader = (ImageReader) readerRider.next();
    +
    + reader.setInput(imageStream);
    + if (reader.getNumImages(true) <= 0) {
    + continue;
    + }
    + result = reader.getRawImageType(reader.getMinIndex());
    + assert result != null;
    + if (logger.isDebugEnabled()) {
    + logger.debug("image format=" + result);
    + }
    + }
    + }
    + return result;
    + }
    +
    + /**
    + * Get an image type specifier for <code>imageFile</code> or <code>null</code> if no image
    + * reader is available for it.
    + *
    + * @see ImageIO#createImageInputStream(java.lang.Object)
    + */
    + public ImageTypeSpecifier getImageTypeSpecifier(File imageFile)
    + throws IOException {
    + ImageTypeSpecifier result = null;
    + ImageInputStream imageStream = ImageIO.createImageInputStream(imageFile);
    +
    + if (imageStream != null) {
    + try {
    + result = getImageTypeSpecifier(imageStream);
    + } finally {
    + imageStream.close();
    + }
    + }
    + return result;
    + }
    +
    public int getLeftRotation(int rotation) {
    assertIsValidRotation(rotation);

    Index: source/net/sf/jomic/comic/CreatePdfComicTask.java

    --- source/net/sf/jomic/comic/CreatePdfComicTask.java (revision 2132)
    +++ source/net/sf/jomic/comic/CreatePdfComicTask.java (working copy)
    @@ -34,6 +34,7 @@
    import org.pdfbox.pdmodel.PDPage;
    import org.pdfbox.pdmodel.common.PDRectangle;
    import org.pdfbox.pdmodel.edit.PDPageContentStream;
    +import org.pdfbox.pdmodel.graphics.color.PDDeviceGray;
    import org.pdfbox.pdmodel.graphics.xobject.PDJpeg;

    /**
    @@ -106,6 +107,14 @@
    try {
    PDPage page = new PDPage();
    PDJpeg jpeg = new PDJpeg(pdfDocument, imageStream);
    +
    + if (!needsTrim && isJpegImage) {
    + // Check if B'n'W image.
    + if (imageTools.getImageTypeSpecifier(imageFile).getNumComponents() == 1) {
    + // If so, set color space; PDJpeg ctor can't do it for us.
    + jpeg.setColorSpace(new PDDeviceGray());
    + }
    + }
    PDPageContentStream contentStream = new PDPageContentStream(pdfDocument, page);

    try {

     
  • Dave Korn

    Dave Korn - 2010-08-26

    Updated version of the patch now available at http://pastebin.com/mgZx9Zx8

    I found a bug in the original version; it is apparently possible for ImageReader.getRawImageType() to return NULL, when handling what appeared to be an ordinary-seeming jpeg file.

    In the updated version of the patch, this possibility is handled by allowing for null returns from ImageTools.getImageTypeSpecifier() and falling back to the old behaviour (i.e. letting pdfbox assume this is a colour jpeg) in CreatePdfComicTask.addImageFile() if so.

    Whitespace-mangled version of the updated patch follows, JFTR:

    Index: source/net/sf/jomic/tools/ImageTools.java

    --- source/net/sf/jomic/tools/ImageTools.java (revision 2132)
    +++ source/net/sf/jomic/tools/ImageTools.java (working copy)
    @@ -399,6 +399,59 @@
    return (ImageReader) ImageIO.getImageReaders(imageStream).next();
    }

    + /**
    + * Get an image type specifier for <code>imageStream</code> or <code>null</code> if no image
    + * stream or reader is available.
    + *
    + * @see ImageIO#getImageReaders(java.lang.Object)
    + * @see ImageReader#setInput(java.lang.Object)
    + * @see ImageReader#getNumImages(boolean)
    + * @see ImageReader#getRawImageType(int)
    + */
    + public ImageTypeSpecifier getImageTypeSpecifier(ImageInputStream imageStream)
    + throws IOException {
    + ImageTypeSpecifier result = null;
    +
    + if (imageStream != null) {
    + Iterator readerRider = ImageIO.getImageReaders(imageStream);
    +
    + while ((result == null) && readerRider.hasNext()) {
    + ImageReader reader = (ImageReader) readerRider.next();
    +
    + reader.setInput(imageStream);
    + if (reader.getNumImages(true) <= 0) {
    + continue;
    + }
    + result = reader.getRawImageType(reader.getMinIndex());
    + if (result != null && logger.isDebugEnabled()) {
    + logger.debug("image format=" + result);
    + }
    + }
    + }
    + return result;
    + }
    +
    + /**
    + * Get an image type specifier for <code>imageFile</code> or <code>null</code> if no image
    + * reader is available for it.
    + *
    + * @see ImageIO#createImageInputStream(java.lang.Object)
    + */
    + public ImageTypeSpecifier getImageTypeSpecifier(File imageFile)
    + throws IOException {
    + ImageTypeSpecifier result = null;
    + ImageInputStream imageStream = ImageIO.createImageInputStream(imageFile);
    +
    + if (imageStream != null) {
    + try {
    + result = getImageTypeSpecifier(imageStream);
    + } finally {
    + imageStream.close();
    + }
    + }
    + return result;
    + }
    +
    public int getLeftRotation(int rotation) {
    assertIsValidRotation(rotation);

    Index: source/net/sf/jomic/comic/CreatePdfComicTask.java

    --- source/net/sf/jomic/comic/CreatePdfComicTask.java (revision 2132)
    +++ source/net/sf/jomic/comic/CreatePdfComicTask.java (working copy)
    @@ -25,6 +25,7 @@
    import java.util.Map;

    import javax.imageio.ImageIO;
    +import javax.imageio.ImageTypeSpecifier;

    import net.sf.jomic.tools.ImageTools;
    import net.sf.jomic.tools.StringTools;
    @@ -34,6 +35,7 @@
    import org.pdfbox.pdmodel.PDPage;
    import org.pdfbox.pdmodel.common.PDRectangle;
    import org.pdfbox.pdmodel.edit.PDPageContentStream;
    +import org.pdfbox.pdmodel.graphics.color.PDDeviceGray;
    import org.pdfbox.pdmodel.graphics.xobject.PDJpeg;

    /**
    @@ -106,6 +108,15 @@
    try {
    PDPage page = new PDPage();
    PDJpeg jpeg = new PDJpeg(pdfDocument, imageStream);
    +
    + if (!needsTrim && isJpegImage) {
    + // Check if B'n'W image.
    + ImageTypeSpecifier its = imageTools.getImageTypeSpecifier(imageFile);
    + if (its != null && its.getNumComponents() == 1) {
    + // If so, set color space; PDJpeg ctor can't do it for us.
    + jpeg.setColorSpace(new PDDeviceGray());
    + }
    + }
    PDPageContentStream contentStream = new PDPageContentStream(pdfDocument, page);

    try {

     
  • Thomas Aglassinger

    I updated the nightly build to use PDFBox 1.5, which has a lot of improvements and can open a lot more PDF documents than the version included with Jomic 0.9.30.

    Does that fix your problem?

     
  • Thomas Aglassinger

    • assigned_to: nobody --> roskakori
     

Log in to post a comment.