Adapting JBIG2 decoder to PDFRenderer.

1,508 views
Skip to first unread message

Искандер Искандер

unread,
Aug 22, 2012, 8:42:12 AM8/22/12
to jbig2-imag...@googlegroups.com
Hello. I want to adapt your project to existing open-source "PDFRenderer".  Now it uses buggy, open-source version of JPedal decoder. 
I don't found any documentation about your project. So I think you can help me. I need only to replace this method contents by "JBIG2-imageio" project-cpecific classes (I noted with orange color all old jbig2-decoder classes. Code that not colorized is part of PDFRenderer, so it not to be changed ): 


protected static byte[] decode(PDFObject dict, byte[] source) throws IOException {
    JBIG2Decoder decoder  = new JBIG2Decoder();  ;
    try {
         byte[] globals = getOptionFieldBytes(dict, "JBIG2Globals");
         if (globals != null) {
              decoder.setGlobalData(globals);
         }
         decoder.decodeJBIG2(source);
         } catch (JBIG2Exception ex) {
              IOException ioException  = new IOException(); ;
              ioException.initCause(ex);
              throw ioException;
     }
     return decoder.getPageAsJBIG2Bitmap(0).getData(true);
}

Thanks in help!

krzikams

unread,
Aug 23, 2012, 2:51:54 AM8/23/12
to jbig2-imag...@googlegroups.com
Hello,

usage of jbig2-imageio library is like every other image reader of Java's Image I/O except the handling of global segments which are a specific feature of JBIG2. You can see different examples in the test sources. For instance in JBIG2ImageReaderTest:

...
// Instantiate the reader
BIG2ImageReader imageReader = new JBIG2ImageReader(new JBIG2ImageReaderSpi());


// Set input
imageReader.setInput(imageInputStream);


// Processing globals
JBIG2Globals globals = imageReader.processGlobals(globalsStream);

// Setting globals
imageReader.setGlobals(globals);


// Read a raster or use imageReader.read(..) for a BufferedImage
Raster raster = imageReader.readRaster(imageIndex, null);

...

Give it a try.

Regards,
Matthäus Krzikalla

Искандер Искандер

unread,
Aug 23, 2012, 5:45:34 AM8/23/12
to jbig2-imag...@googlegroups.com
Hello, krzikams. Thanks for your reply, now I adapt and tried your code, but I got an exception:

INFO: JBIG2ReadParam not specified. Default will be used.
java.lang.ArrayIndexOutOfBoundsException: 5986
at com.levigo.jbig2.Bitmap.getByte(Bitmap.java:442)
at com.levigo.jbig2.Bitmap.blitWithShift(Bitmap.java:295)
at com.levigo.jbig2.Bitmap.blit(Bitmap.java:242)
at com.levigo.jbig2.segments.TextRegion.insertIntoRegionBitmap(TextRegion.java:814)



My code now looks like this: 
  DefaultInputStreamFactory disf = new DefaultInputStreamFactory();
  ImageInputStream imageInputStream = disf.getInputStream(new ByteArrayInputStream(source));
  JBIG2ImageReader imageReader = new JBIG2ImageReader(new JBIG2ImageReaderSpi());
// Set input
  imageReader.setInput(imageInputStream);
// Getting globals and convert it from byte[]
  JBIG2Globals globals = imageReader.processGlobals(ImageIO.createImageInputStream(new ByteArrayInputStream(getOptionFieldBytes(dict, "JBIG2Globals"))));
// Setting globals
  imageReader.setGlobals(globals);
  BufferedImage img = imageReader.read(0);
 
// convert to byte[] and return it
WritableRaster raster = img .getRaster();
DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
return ( data.getData() );
 

My problem is that first page don't print (Printed white list. Same problem when using JPedal jbig-2 decoder), and other pages prints as black square. 

Hope for your help.

Искандер Искандер

unread,
Aug 23, 2012, 5:50:55 AM8/23/12
to jbig2-imag...@googlegroups.com
 Attached problem  PDF 
errorPdf.pdf

Matthäus Krzikalla

unread,
Aug 24, 2012, 3:06:12 AM8/24/12
to jbig2-imag...@googlegroups.com
Hello Искандер,

your pdf shows fine in my tests. There must be something wrong with your integration. At first look, the code looks good. Are the parts you provide as input correct?

In addition, please provide a full stacktrace.

Regards,
Matthäus

Kai Steph

unread,
Sep 24, 2012, 4:36:03 AM9/24/12
to jbig2-imag...@googlegroups.com
Hi,

I use the integration of the decoder into the PDFRenderer too. But I found two problems. First there is not always a JBIGGlobals-Section inside the PDF so the if-clause from the original code has to return:

// Getting globals and convert it from byte[]
byte[] globalsA = getOptionFieldBytes(dict, "JBIG2Globals");
if (globalsA != null) {
JBIG2Globals globals = imageReader.processGlobals(ImageIO.createImageInputStream(new ByteArrayInputStream(globalsA)));
// Setting globals
imageReader.setGlobals(globals);
}

The second point is about the return value. The img.getRaster() delivers an array with 1 Byte / 8 Bit per Pixel but the PDFRenderer expects a Raster with 1 Bit per Pixel as defined in the PDF Stream. As far as I can see the Problem is inside the class Bitmaps, where the static function asBufferedImage() creates a 8 Bit IndexColorModel instead of a 1 Bit ICM. Perhaps this Problem should by fixed in the decoder too?

Regards,
Kai



Am Donnerstag, 23. August 2012 11:45:34 UTC+2 schrieb Искандер Искандер:

Kai Steph

unread,
Sep 25, 2012, 2:30:40 AM9/25/12
to jbig2-imag...@googlegroups.com
So another (last) update:

1. Converting to a 1bit-Image was done via drawing the returned Image into a new BufferedImage.
2. The Code has a ressource-leak, as the opened ImageInputStream was not closed. Every Time a new ImageInputStream is opened a file in /tmp/imageio* was created and not deleted. While Batch-processing it took only a short time till a "too many files open"-error. 

So here is my final version of JBig2Decode.java decode-function:

protected static byte[] decode(PDFObject dict, byte[] source) throws IOException {
DefaultInputStreamFactory disf = new DefaultInputStreamFactory();
ImageInputStream imageInputStream = disf.getInputStream(new ByteArrayInputStream(source));
JBIG2ImageReader imageReader = new JBIG2ImageReader(new JBIG2ImageReaderSpi());
// Set input
imageReader.setInput(imageInputStream);
// Getting globals and convert it from byte[]
byte[] globalsA = getOptionFieldBytes(dict, "JBIG2Globals");
if (globalsA != null) {
JBIG2Globals globals = imageReader.processGlobals(ImageIO.createImageInputStream(new ByteArrayInputStream(globalsA)));
// Setting globals
imageReader.setGlobals(globals);
}
BufferedImage img = imageReader.read(0);
// clean up
imageInputStream.close();
imageReader.dispose();
// change color depth
BufferedImage out = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_BYTE_BINARY);
out.getGraphics().drawImage(img, 0, 0, null);
// convert to byte[] and return it
WritableRaster raster = out.getRaster();
DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
return ( data.getData() );
}
I think this version could be returned to the PDFRenderer.

Regards,
Kai

Matthäus Krzikalla

unread,
Oct 2, 2012, 7:06:46 AM10/2/12
to jbig2-imag...@googlegroups.com
Hi,

we ran some benchmarks with different combinations of color models, sample models and data buffer types before we decided to use the 8 bpp sample and color model in combination with byte buffer. The JVM is able to optimize a lot and save time while processing this kind of image data in comparison to some other, especially using 1 bpp.

Regards,
Matthäus

Stefano Lazzaro

unread,
Apr 5, 2013, 3:04:19 AM4/5/13
to jbig2-imag...@googlegroups.com
Hello!
Found this little group fit my problem. An old java software is using PDFRenderer but can't handle JBIG2 coded PDF coming from a Xerox WorkCentre machine.
I'm trying to use this code to extend PDFRender with the posted Jbig2Decode.java class, but it seems to me like there's some missing code. I can't find the 

getOptionFieldBytes(dict, "JBIG2Globals");

method anywhere. How do you implement it?

Thank you!

Matthäus Krzikalla

unread,
Apr 5, 2013, 3:38:50 AM4/5/13
to jbig2-imag...@googlegroups.com
Hello Stefano,


I can't find the 

getOptionFieldBytes(dict, "JBIG2Globals");

method anywhere. How do you implement it?

Please take a look at the forked project on github.com (PDFrenderer on Github.com). There is the Jbig2Decode.java class you're searching for.

Regards,
Matthäus
Message has been deleted

Matthäus Krzikalla

unread,
Apr 5, 2013, 4:24:51 AM4/5/13
to jbig2-imag...@googlegroups.com
Hallo Stefano,

the way getOptionFieldBytes(..) is implemented is independant. Our JBIG2-decoder has a different API. That means, the implementation of decode(..) must be changed in order to integrate our classes.

Feel free to ask, if you run into questions while integrating our classes.

Regards,
Matthäus

 


2013/4/5 Stefano Lazzaro <stefano.l...@gmail.com>
Thanks a lot Matthäus,
I see this Jbig2Decode.java uses jpedal decoder instead of working with levigo classes.
Is it ok anyway? I'm a little confused.

--
Sie haben diese Nachricht erhalten, weil Sie der Google Groups-Gruppe jbig2-imageio-discuss beigetreten sind.
Um Ihr Abonnement für diese Gruppe zu beenden und keine E-Mails mehr von dieser Gruppe zu erhalten, senden Sie eine Email an jbig2-imageio-di...@googlegroups.com.
Weitere Optionen: https://groups.google.com/groups/opt_out
 
 

Stefano Lazzaro

unread,
Apr 5, 2013, 8:03:30 AM4/5/13
to jbig2-imag...@googlegroups.com
Got it. I customized the decode method in Jbig2Decode.java of PDFrenderer using the one posted in this discussion and... IT WORKS LIKE A CHARM!!!
I have to finish my test box but it seems perfect. Those f***ing JBIG2 Xerox pdf are converted in images with no problem. All with my code untouched!
You really, really, really saved a lot of work to me!

Thanks a lot!


2013/4/5 Stefano Lazzaro <stefano.l...@gmail.com>
Um Ihr Abonnement für diese Gruppe zu beenden und keine E-Mails mehr von dieser Gruppe zu erhalten, senden Sie eine Email an jbig2-imageio-discuss+unsub...@googlegroups.com.
Weitere Optionen: https://groups.google.com/groups/opt_out
 
 

Искандер Искандер

unread,
Apr 9, 2013, 7:31:32 AM4/9/13
to jbig2-imag...@googlegroups.com
Hello, Stefano. Code which I provide in this discussion didn't work for me. So I forget about this problem and continue using buggy JPedal's decoder. Can you share your code (especially customized decode method)?   Thanks.

пятница, 5 апреля 2013 г., 18:03:30 UTC+6 пользователь Stefano Lazzaro написал:

Matthäus Krzikalla

unread,
Apr 9, 2013, 8:05:22 AM4/9/13
to jbig2-imag...@googlegroups.com
Please look at Kai Steph's code in comment from 25.09.2012. This should also be the base for Stefano's code.

Искандер Искандер

unread,
Apr 9, 2013, 9:44:19 AM4/9/13
to jbig2-imag...@googlegroups.com

Matthäus, thanks. I tried this code. But I get an exception with your library:

INFO: JBIG2ReadParam not specified. Default will be used.
java.lang.ArrayIndexOutOfBoundsException: 5986
at com.levigo.jbig2.Bitmap.getByte(Bitmap.java:120)
at com.levigo.jbig2.image.Bitmaps.blitShifted(Bitmaps.java:498)
at com.levigo.jbig2.image.Bitmaps.blit(Bitmaps.java:445)
at com.levigo.jbig2.segments.TextRegion.blit(TextRegion.java:800)
at com.levigo.jbig2.segments.TextRegion.decodeSymbolInstances(TextRegion.java:447)
at com.levigo.jbig2.segments.TextRegion.getRegionBitmap(TextRegion.java:303)
at com.levigo.jbig2.JBIG2Page.createNormalPage(JBIG2Page.java:182)
at com.levigo.jbig2.JBIG2Page.createPage(JBIG2Page.java:152)
at com.levigo.jbig2.JBIG2Page.composePageBitmap(JBIG2Page.java:143)
at com.levigo.jbig2.JBIG2Page.getBitmap(JBIG2Page.java:123)
at com.levigo.jbig2.JBIG2ImageReader.read(JBIG2ImageReader.java:221)
at javax.imageio.ImageReader.read(Unknown Source)
at com.sun.pdfview.decode.JBig2Decode.decode(Unknown Source)
at com.sun.pdfview.decode.JBig2Decode.decode(Unknown Source)
at com.sun.pdfview.decode.PDFDecoder.decodeStream(Unknown Source)
at com.sun.pdfview.PDFObject.decodeStream(Unknown Source)
at com.sun.pdfview.PDFObject.getStream(Unknown Source)
at com.sun.pdfview.PDFObject.getStream(Unknown Source)
at com.sun.pdfview.PDFObject.getStream(Unknown Source)
at com.sun.pdfview.PDFImage.getImage(Unknown Source)
at com.sun.pdfview.PDFRenderer.drawImage(Unknown Source)
at com.sun.pdfview.PDFImageCmd.execute(Unknown Source)
at com.sun.pdfview.PDFRenderer.iterate(Unknown Source)
at com.sun.pdfview.BaseWatchable.run(Unknown Source)
at ru.itcorp.datateh.brbpm.multiprint.dao.PrintFormats$1.print(PrintFormats.java:129)
at sun.print.RasterPrinterJob.printPage(Unknown Source)
at sun.print.RasterPrinterJob.print(Unknown Source)
at sun.print.Win32PrintJob.printableJob(Unknown Source)
at sun.print.Win32PrintJob.print(Unknown Source)
at com.company.print.applet.MyApplet.doPrintDocuments(MyApplet.java:281)
at java.security.AccessController.doPrivileged(Native Method)
at java.lang.Thread.run(Unknown Source)
апр 09, 2013 7:34:31 PM com.levigo.jbig2.util.log.JDKLogger info
INFO: JBIG2ReadParam not specified. Default will be used.
java.lang.ArrayIndexOutOfBoundsException: 5986
at com.levigo.jbig2.Bitmap.getByte(Bitmap.java:120)
at com.levigo.jbig2.image.Bitmaps.blitShifted(Bitmaps.java:498)
at com.levigo.jbig2.image.Bitmaps.blit(Bitmaps.java:445)
at com.levigo.jbig2.segments.TextRegion.blit(TextRegion.java:800)
at com.levigo.jbig2.segments.TextRegion.decodeSymbolInstances(TextRegion.java:447)
at com.levigo.jbig2.segments.TextRegion.getRegionBitmap(TextRegion.java:303)
at com.levigo.jbig2.JBIG2Page.createNormalPage(JBIG2Page.java:182)
at com.levigo.jbig2.JBIG2Page.createPage(JBIG2Page.java:152)
at com.levigo.jbig2.JBIG2Page.composePageBitmap(JBIG2Page.java:143)
at com.levigo.jbig2.JBIG2Page.getBitmap(JBIG2Page.java:123)
at com.levigo.jbig2.JBIG2ImageReader.read(JBIG2ImageReader.java:221)
at javax.imageio.ImageReader.read(Unknown Source)
at com.sun.pdfview.decode.JBig2Decode.decode(Unknown Source)
at com.sun.pdfview.decode.JBig2Decode.decode(Unknown Source)
at com.sun.pdfview.decode.PDFDecoder.decodeStream(Unknown Source)
at com.sun.pdfview.PDFObject.decodeStream(Unknown Source)
at com.sun.pdfview.PDFObject.getStream(Unknown Source)
at com.sun.pdfview.PDFObject.getStream(Unknown Source)
at com.sun.pdfview.PDFObject.getStream(Unknown Source)
at com.sun.pdfview.PDFImage.getImage(Unknown Source)
at com.sun.pdfview.PDFRenderer.drawImage(Unknown Source)
at com.sun.pdfview.PDFImageCmd.execute(Unknown Source)
at com.sun.pdfview.PDFRenderer.iterate(Unknown Source)
at com.sun.pdfview.BaseWatchable.run(Unknown Source)
at ru.itcorp.datateh.brbpm.multiprint.dao.PrintFormats$1.print(PrintFormats.java:129)
at sun.print.RasterPrinterJob.printPage(Unknown Source)
at sun.print.RasterPrinterJob.print(Unknown Source)
at sun.print.Win32PrintJob.printableJob(Unknown Source)
at sun.print.Win32PrintJob.print(Unknown Source)
at com.company.print.applet.MyApplet.doPrintDocuments(MyApplet.java:281)
at java.security.AccessController.doPrivileged(Native Method)
at java.lang.Thread.run(Unknown Source)

Can you help me with it?

I also attached PDF file where I get an error. When printing page №1 is white.. Rest pages (2-4) are printed fine. 

Thanks.

вторник, 9 апреля 2013 г., 18:05:22 UTC+6 пользователь Matthäus Krzikalla написал:
errorPdf.pdf

Matthäus Krzikalla

unread,
Apr 9, 2013, 9:48:36 AM4/9/13
to jbig2-imag...@googlegroups.com
This might be a bug. Please submit an issue in google code project (http://code.google.com/p/jbig2-imageio/)

Matthäus Krzikalla

unread,
Apr 9, 2013, 9:53:16 AM4/9/13
to jbig2-imag...@googlegroups.com
I tested the PDF. The decoder runs fine in the default integration. Do you set globals correctly?


Am Dienstag, 9. April 2013 15:44:19 UTC+2 schrieb Искандер Искандер:

Искандер Искандер

unread,
Apr 9, 2013, 10:01:55 AM4/9/13
to jbig2-imag...@googlegroups.com

Искандер Искандер

unread,
Apr 9, 2013, 10:05:48 AM4/9/13
to jbig2-imag...@googlegroups.com

All pages except first printed fine. On first page I get this exception, so it not printed and it blank 

Stefano Lazzaro

unread,
Apr 10, 2013, 3:36:18 AM4/10/13
to jbig2-imag...@googlegroups.com
I confirm the 
java.lang.ArrayIndexOutOfBoundsException: 5986 at com.levigo.jbig2.Bitmap.getByte(Bitmap.java:122)
decoding the errorPdf.pdf uploaded here.

Matthäus Krzikalla

unread,
Apr 10, 2013, 4:06:42 AM4/10/13
to jbig2-imag...@googlegroups.com
The first page has a small embedded JBIG2 image. I was able to reproduce the exception. I will create an issue in project's bug tracker. Please look at http://code.google.com/p/jbig2-imageio/issues/list for further tracking.

Matthäus Krzikalla

unread,
Apr 10, 2013, 5:04:35 AM4/10/13
to jbig2-imag...@googlegroups.com
A fix is commited. There was a bug in Bitmaps-class (see http://code.google.com/p/jbig2-imageio/issues/detail?id=15)

A new release is planned next week. But feel free to checkout and test.


Am Dienstag, 9. April 2013 16:05:48 UTC+2 schrieb Искандер Искандер:

Искандер Искандер

unread,
Apr 10, 2013, 8:01:45 AM4/10/13
to jbig2-imag...@googlegroups.com
Thank you very much! Your fix helped me! Now all works fine! 
Reply all
Reply to author
Forward
0 new messages