B4J Question InputStream exception 'Chunk has bad CRC'

warwound

Expert
Licensed User
Longtime User
Why does my app crash with this exception BUT only when compiled in Release mode, in Debug mode my app works as expected:

Program started.
java.lang.Exception: Chunk has bad CRC.
at com.pdfjet.PNGImage.getChunk(PNGImage.java:276)
at com.pdfjet.PNGImage.processPNG(PNGImage.java:234)
at com.pdfjet.PNGImage.<init>(PNGImage.java:65)
at com.pdfjet.Image.<init>(Image.java:129)
at uk.co.martinpearman.b4j.pdfjet.ImageWrapper.Initialize(ImageWrapper.java:43)
at b4j.example.main._createpdfimageexample(main.java:310)
at b4j.example.main._createbutton_action(main.java:121)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
at anywheresoftware.b4a.BA$2.run(BA.java:159)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:179)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:176)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:176)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:76)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:17)
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:67)
at java.lang.Thread.run(Thread.java:724)
main._createpdfimageexample (java line: 328)
java.lang.RuntimeException: Object should first be initialized (PDFjetImage).
at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:28)
at uk.co.martinpearman.b4j.pdfjet.ImageWrapper.SetPosition(ImageWrapper.java:96)
at b4j.example.main._createpdfimageexample(main.java:328)
at b4j.example.main._createbutton_action(main.java:121)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:93)
at anywheresoftware.b4a.BA$2.run(BA.java:159)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:179)
at com.sun.javafx.application.PlatformImpl$4$1.run(PlatformImpl.java:176)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl$4.run(PlatformImpl.java:176)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:76)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:17)
at com.sun.glass.ui.win.WinApplication$3$1.run(WinApplication.java:67)
at java.lang.Thread.run(Thread.java:724)

The offending code is part of a PDF creation library i'm working on:

B4X:
Dim Image1 As PDFjetImage
Image1.Initialize(PDF1, File.OpenInput(File.DirAssets, "eu-map.png"), PDFjetImageTypes.PNG)

The library method signature is:

Initialize (PDFjetPDF As PDF, InputStream1 As InputStream, ImageType As Int)
Initialize the PDFjetImage object.
InputStream1 will be closed when this method completes.


I suspected a corrupt PNG so opened eu-map.png in an image editor and saved it as a new PNG image, still the app crashes in release mode and works in debug mode.

My b4j project also loads a JPG and a BMP image from DirAssets and using the same object and it's Initialize method and these two images work in both debug and release mode:

B4X:
   '   Image1 crashes in Release mode, works in Debug mode
   '   Image2 and Image3 work in both Release and Debug mode
   Dim Image1 As PDFjetImage
   Image1.Initialize(PDF1, File.OpenInput(File.DirAssets, "eu-map.png"), PDFjetImageTypes.PNG)
   
   Dim Image2 As PDFjetImage
   Image2.Initialize(PDF1, File.OpenInput(File.DirAssets, "fruit.jpg"), PDFjetImageTypes.JPG)
   
   Dim Image3 As PDFjetImage
   Image3.Initialize(PDF1, File.OpenInput(File.DirAssets, "mt-map.bmp"), PDFjetImageTypes.BMP)

Why does my InputStream created in debug mode differ from the InputStream created in release mode - is the PNG getting corrupted when compiled?

Any ideas?

Thanks.

Martin.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Any ideas?
Yes. In Debug mode the assets folder is not a virtual folder. The program files are not packed as a jar.

In Release mode all the files are packed into the jar file. This means that the assets files can only be accessed in a special way (one that is based on File.OpenInput).

Try to copy the file from File.DirAssets to File.DirTemp and then work with it.
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Ok, so copying the PNG image to DirTemp and creating an InputStream using the DirTemp location works no problems.

Should an InputStream not be created using a file from DirAssets then?
Why would my InputStreams created from JPG and BMP images in DirAssets work but not the PNG InputStream...

I guess what i'm asking is - is it best practice to always copy files to a 'real' folder before opening them as an InputStream?

Martin.
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
I guess what i'm asking is - is it best practice to always copy files to a 'real' folder before opening them as an InputStream?

Just to answer my last question - i think the answer must be yes.
Looking at the PDF that my b4j code creates i just noticed that the BMP image that it loads from DirAssets is slightly corrupted when added to my PDF document in release mode.
Again in debug mode there is no problem.

I'll make a point of not creating an InputStream from any file located in DirAssets from now on :).

Martin.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I guess what i'm asking is - is it best practice to always copy files to a 'real' folder before opening them as an InputStream?
No. It depends on what your app is doing with the input stream. If it is only reading it sequentially then it should work. For example there shouldn't be a problem loading images with fx.LoadImage. If you do see an issue then there might be a bug.
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Let me briefly explain...

I've wrapped the java PDFjet library for both B4A and B4J and my first tests of the new library are all with B4J.
Looking through the source code i see that an instance of public PNGImage(InputStream inputStream) is created.
The PNGImage processPNG() method is called and passed the InputStream.
processPNG call's the PNGImage getChunk() method and passes the InputStream to getChunk().
And it's the getChunk() method that raises the exception "Chunk has bad CRC".
getChunk() creates an instance of Chunk and it is the Chunk method
public boolean hasGoodCRC that actually decides the CRC is bad:

B4X:
public boolean hasGoodCRC() {
    CRC32 computedCRC = new CRC32();
    computedCRC.update( type, 0, 4 );
    computedCRC.update( data, 0, ( int ) chunkLength );
    return ( computedCRC.getValue() == this.crc );
}

Was that brief i wonder lol!
The entire PDFjet package can be browsed from here: http://b4a.martinpearman.co.uk/pdfjet/src/.
Anyway i don't expect you to debug the PDFjet library for me, but i'll look into the problem more tomorrow and see if i can see what's going wrong.

Thanks.

Martin.
 
Upvote 0
Top