Details
-
Bug
-
Status: Closed
-
Critical
-
Resolution: Fixed
-
None
-
None
Description
I'm using the "last stable version" of Apache Sanselan 0.97 in an Android project (app). I have not upgraded to Commons Imaging yet, since the website says there is no stable release yet. Meanwhile, there are bugs in Sanselan.
If I run the sample code method WriteExifMetadataExample.changeExifMetadata on an image, which updates the Apterture and GPS tags, the resulting image fails to validate (through Phil Harvey's ExifTool software):
> exiftool.exe -validate -error -warning -a "..\20171030_21481_COPY.jpg" Validate : 19 Warnings (17 minor) Warning : [minor] Odd offset for IFD0 tag 0x010f Warning : [minor] Odd offset for IFD0 tag 0x011a Warning : [minor] Odd offset for IFD0 tag 0x011b Warning : [minor] Odd offset for IFD0 tag 0x0131 Warning : [minor] Odd offset for IFD0 tag 0x0132 Warning : [minor] Odd offset for ExifIFD tag 0x829a Warning : [minor] Odd offset for ExifIFD tag 0x829d Warning : [minor] Odd offset for ExifIFD tag 0x9003 Warning : [minor] Odd offset for ExifIFD tag 0x9004 Warning : [minor] Odd offset for ExifIFD tag 0x9202 Warning : [minor] Odd offset for ExifIFD tag 0x9205 Warning : [minor] Odd offset for ExifIFD tag 0x920a Warning : [minor] Odd offset for ExifIFD tag 0x9286 Warning : Non-standard count (1) for GPS tag 0x0001 GPSLatitudeRef Warning : [minor] Odd offset for GPS tag 0x0002 Warning : Non-standard count (1) for GPS tag 0x0003 GPSLongitudeRef Warning : [minor] Odd offset for GPS tag 0x0004 Warning : [minor] Odd offset for IFD1 tag 0x011a Warning : [minor] Odd offset for IFD1 tag 0x011b
I need some advice on how to proceed here. Since Sanselan does not appear to do what it should (even on very basic metadata editing), am I correct to assume that the current version of Commons Imaging does a better job?
Attachments
Attachments
- 20171030_21481_COPY.jpg
- 937 kB
- Joakim Knudsen
- before.html
- 44 kB
- Bruno P. Kinoshita
- after.html
- 46 kB
- Bruno P. Kinoshita
- Gaboxjellyfish-changedexifmetadata.jpg
- 3.17 MB
- Bruno P. Kinoshita
- Gaboxjellyfish.jpg
- 3.17 MB
- Bruno P. Kinoshita
- 20171030_214812_copy_desktop.JPG
- 937 kB
- Joakim Knudsen
- 20171030_214812.jpg
- 937 kB
- Joakim Knudsen
- DSC_5506_copy_desktop.JPG
- 2.45 MB
- Joakim Knudsen
- DSC_5506.JPG
- 2.45 MB
- Joakim Knudsen
- DSC_3338_imaging_205.JPG
- 2.67 MB
- Joakim Knudsen
- DSC_3338.JPG
- 2.67 MB
- Joakim Knudsen
- DSC_3338_imaging_205_UC.JPG
- 2.67 MB
- Joakim Knudsen
- Samsung Note 8 Android.jpg
- 1.11 MB
- Joakim Knudsen
Activity
Hi joakimk,
Thanks for the detailed report, and the link to the forum discussion. Comparing the output of the exiftool's htmldump, from a normal JPEG and another image created with WriteExifMetadataExample.changeExifMetadata (not quite the one you used, but from Commons Imaging tests), I can confirm there are odd offsets and also markers that were changed.
Going to add a sample before, and another after. Plus the code, and the output HTML files for posterity and for working on this issue.
Attaching original file from https://en.wikipedia.org/wiki/Talk%3ABox_jellyfish#/media/File:Gaboxjellyfish.jpg.
First HTML dump generated with `exiftool -validate -error -warning -a -G1 -htmldump Gaboxjellyfish.jpg > before.html`. Second file generated with `exiftool -validate -error -warning -a -G1 -htmldump Gaboxjellyfish-changedexifmetadata.jpg > after.html`.
Here's the code to reproduce the issue:
public static void main(String[] args) throws Exception { WriteExifMetadataExample example = new WriteExifMetadataExample(); // This is broken example.changeExifMetadata(new File("/home/kinow/Downloads/Gaboxjellyfish.jpg"), new File("/home/kinow/Downloads/Gaboxjellyfish-changedexifmetadata.jpg")); } }
The `WriteExifMetadataExample` class is in the test src folder.
Not sure if its implementation is correct. Could be that it simply needs updating to latest changes. Or may be a real bug.
Had a bit more of time. So removed the code in the example that changes the the metadata (aperture, GPS). The changed code simply retrieved the TIFF metadata, and then called a code as below:
new ExifRewriter().updateExifMetadataLossless(jpegImageFile, os,
outputSet);
And the output still presents the issue. So looks like we can focus on the ExifRewriter method call and onwards.
Thanks for looking into this! I have checked the current snapshot of Commons Imaging, and the bug does not seem to be present there. As Damjan Jovanovic pointed out to me, this has been fixed somewhere along the way. However, I need a version which will run on Android, and, as far as I can tell (though I haven't tried), the current version of the library won't/can't run on Android.
Are you using the latest snapshot of Apache Commons Imaging? Or of Apache Sanselan? I tested the latest code from Git for Apache Commons Imaging, and the odd offsets were present in the generated image.
I'm using Sanselan 0.97 for my project, since this is an Android app. The details in this bug report, and the discussion at the Exiftool forum, all relate to Sanselan. The main concern with the generated image (as attached in this report) is that it corrupts the Maker Notes, and that it completely restructures the metadata (compared to the original image). The odd offsets are also a problem, but a relatively minor one.
I have also tested with Commons Imaging (in a separate, small test project) and although the image still contains the odd offsets, it does look a lot better than the one produced by Sanselan.
However, since I am dependant on an Android compatible library, I am hoping this bug might be fixed in the Sanselan library. If that is not possible, I'd like to know the status of making Commons Imaging available for Android?
Thanks again, and sorry for the confusion!
No confusion at all. I've started to learn the code base and get myself used to the library recently. If I recall correctly, the development on Sanselan stopped, and it was since then moved to Apache Commons Imaging.
Not sure what are the requirements for Commons Imaging to be available for Android. Perhaps building the current sources into a jar would work?
There are a few blockers for a 1.0 release. But we could still try to release alpha/beta versions before that. In case having the JAR in a Maven repository is a requirement for you, and an -alpha or -beta works for you too. Even easier if you could use a -SNAPSHOT version.
Well, I could certainly give it a try! I haven't tried compiling for Android because I read online that Android does not support java.awt (which is required for Imaging).
However, the Android release of Sanselan was apparently made by removing the parts of the code which relied on awt – perhaps this can also be done for Imaging?
https://stackoverflow.com/a/24147677/2736813
I've been seeing various sets of error messages (from ExifTool) when validating the images run through the same (sample) code, and it seems the output depends on the input. Maybe that's not surprising? What I mean is, when I started this bug report, the JPEG I was testing on (20171030_24812.JPG – attached) was taken by a Samsung Galaxy Note 8.0. The sample Sanselan code (WriteExifMetadataExample, which sets Aperture and GPS tags) resulted in various odd offsets, and some warnings on "non-standard count" on the GPS coordinates.
However – and this is why I've been so confused – JPEGs taken with my Sony Xperia Z5 Compact, when run through the very same sample code, produce more severe (AFAIK) errors. Note the Maker Notes error below – this does not occur on the Samsung input file. I've added these two original JPEGs, and their "copy_desktop" versions after Sanselan processing.
$ ./exiftool.exe -validate -warning -error -a DSC_5506_copy_desktop.JPG Validate : 16 Warnings (14 minor) Warning : [minor] Odd offset for IFD0 tag 0x011a Warning : [minor] Odd offset for IFD0 tag 0x011b Warning : [minor] Odd offset for ExifIFD tag 0x829a Warning : [minor] Odd offset for ExifIFD tag 0x829d Warning : [minor] Odd offset for ExifIFD tag 0x9201 Warning : [minor] Odd offset for ExifIFD tag 0x9202 Warning : [minor] Odd offset for ExifIFD tag 0x9204 Warning : [minor] Odd offset for ExifIFD tag 0x920a Warning : [minor] Possibly incorrect maker notes offsets (fix by -628?) Warning : [minor] Odd offset for ExifIFD tag 0x9290 Warning : [minor] Odd offset for ExifIFD tag 0x9292 Warning : [minor] Odd offset for ExifIFD tag 0xa404 Warning : Non-standard count (1) for GPS tag 0x0001 GPSLatitudeRef Warning : Non-standard count (1) for GPS tag 0x0003 GPSLongitudeRef Warning : [minor] Odd offset for IFD1 tag 0x011a Warning : [minor] Odd offset for IFD1 tag 0x011b
$ ./exiftool.exe -validate -warning -error -a 20171030_214812_copy_desktop.JPG Validate : 19 Warnings (17 minor) Warning : [minor] Odd offset for IFD0 tag 0x010f Warning : [minor] Odd offset for IFD0 tag 0x011a Warning : [minor] Odd offset for IFD0 tag 0x011b Warning : [minor] Odd offset for IFD0 tag 0x0131 Warning : [minor] Odd offset for IFD0 tag 0x0132 Warning : [minor] Odd offset for ExifIFD tag 0x829a Warning : [minor] Odd offset for ExifIFD tag 0x829d Warning : [minor] Odd offset for ExifIFD tag 0x9003 Warning : [minor] Odd offset for ExifIFD tag 0x9004 Warning : [minor] Odd offset for ExifIFD tag 0x9202 Warning : [minor] Odd offset for ExifIFD tag 0x9205 Warning : [minor] Odd offset for ExifIFD tag 0x920a Warning : [minor] Odd offset for ExifIFD tag 0x9286 Warning : Non-standard count (1) for GPS tag 0x0001 GPSLatitudeRef Warning : [minor] Odd offset for GPS tag 0x0002 Warning : Non-standard count (1) for GPS tag 0x0003 GPSLongitudeRef Warning : [minor] Odd offset for GPS tag 0x0004 Warning : [minor] Odd offset for IFD1 tag 0x011a Warning : [minor] Odd offset for IFD1 tag 0x011b
New example files, from two different sources. The problems vary according to the input file.
Are you able to reproduce/verify the differences in the two jpeg files (from different manufacturers)? It would be interesting to run the two image files through Commons Imaging, too (as opposed to Sanselan 0.97 which I experiments with), and see if the warnings in the output still varies. Perhaps it is to be expected that different camera makers and different vendor OS will produce differently structured JPEG metadata? But, as long as it's according to standards (validates OK) this library should be able to handle the differences.
>Are you able to reproduce/verify the differences in the two jpeg files
Let me try it.
>Perhaps it is to be expected that different camera makers and different vendor OS will produce differently structured JPEG metadata?
Yup, that seems to be quite normal. It increases the complexity for troubleshooting some issues, so thanks heaps for attaching the examples from different cameras.
I can reproduce it. Though a bit different, the result.
I used 20171030_214812.jpg, and the code I posted before. Got odd offsets, but for GPSLongitude and Model only. The rest of the data seems to be good.
Really weird, will have to slowly understand the code, in order to fully understand what's going on. Thanks again for the input samples.
Hi Joakim,
So I've found a way to get exiftool's htmldump to have no odd offsets. Push a single commit here https://github.com/kinow/commons-imaging/tree/tiff-odd-offsets-1
I slowly read the code, and found that these two parts were simply adding the length in bytes of the field plus a previous offset. Which could result in odd offsets. It would help me a lot if you were able to checkout my branch, `mvn clean package`, use the jar in your app, and let me know if that works fine for you.
Once I realized where the odd bytes were coming from, this seemed like the simplest solution (occam's razor). But before we consider this naive solution as a definitive solution, I'd like to:
- have a confirmation that the odd bytes is gone and the metadata and image are still valid/good/correct/etc
- have a better understand of the different between a TIFFOutputItem and TIFFOutputField. The latter has a method, writeField, that seems to be correctly handling offsets oddness.
- write a unit test
- find the parts of the specification that define that behaviour, and add links to them here, in the unit test, and in the javadoc of the class where the fix is applied
Hello Bruno,
that is truly an impressive job – the code in the `tiff-odd-offsets-1` branch (compiled into a JAR and included in a separate test project) does indeed seem to fix the problems! The sample code, setting the Aperture and GPS tags, produces no warnings and simply "validates OK" by ExifTool. Furthermore, I ventured to add my code for writing the UserComment EXIF tag (which requires a bit of manual work, with padding and an "ASCII marker"), and also that seems to pass the validation! I've added this code below, and I've also attached a new set of images.
I think this seems to be a very good starting point for further work
What I want to try next is to see if this current snapshot of Commons Imaging can work on Android "as is", even though it depends on java.awt which is apparently not supported on Android. You see, I realize I've been running Sanselan v0.97 on Android in my app, and not some "Android port" of Sanselan. Even though my app produces errors and warnings on java.awt, it is indeed working on Android – at least the parts I've been using...
Here's my code for updating the UserComment tag:
{ // TEST: Try setting UserComment (in Exif dir) String textToSet = "This is a test comment"; final TiffOutputDirectory exifDirectory = outputSet.getOrCreateExifDirectory(); // use Unicode (UTF-16) -- with padding (windows is not so happy with utf8) // the marker has to be written with ASCII bytes, regardless of the encoding it actually describes (and which the following content is encoded in)! // https://forums.adobe.com/thread/375932 byte[] ASCIIMarker = new byte[]{ 0x55, 0x4E, 0x49, 0x43, 0x4F, 0x44, 0x45, 0x00 }; // spells out UNICODE\0 byte[] comment = textToSet.getBytes(ENCODING_UTF16); // private static String ENCODING_UTF16 = "UTF-16LE"; // pad with \0 if (total) length is odd (\0 byte automatically added by arraycopy) int pad = (ASCIIMarker.length + comment.length) % 2; byte[] bytesComment = new byte[ASCIIMarker.length + comment.length + pad]; System.arraycopy(ASCIIMarker, 0, bytesComment, 0, ASCIIMarker.length); System.arraycopy(comment, 0, bytesComment, ASCIIMarker.length, comment.length); if (pad > 0) bytesComment[bytesComment.length-1] = 0x00; TiffOutputField exif_comment = new TiffOutputField(ExifTagConstants.EXIF_TAG_USER_COMMENT, FieldType.UNDEFINED, bytesComment.length - pad, bytesComment); System.out.println("ExifWriter UserComment, writing " + bytesComment.length + " bytes (pad " + pad + ")"); // remove old field exifDirectory.removeField(ExifTagConstants.EXIF_TAG_USER_COMMENT); // add new field exifDirectory.add(exif_comment); }
New sample images:
DSC_3338.JPG | Original image (Sony Z5 Compact) |
DSC_3338_imaging_205.JPG | Aperture and GPS modified (sample code) |
DSC_3338_imaging_205_UC.JPG | UserComment also added |
I've tried using the JAR in my app, running it on Android (on actual devices) and, although errors and warnings are logged, the library works. I.e., to the same degree as Sanselan did, except that the JPEGs produced now actually validate
Perhaps it might be possible to factor out the parts of the library which are not compatible with Android, and thus make an Android release? Guess that's another task/issue, though.
I'm attaching a JPEG edited on Android.
Updating the check list.
[ X ] have a confirmation that the odd bytes is gone and the metadata and image are still valid/good/correct/etc * Thanks for testing Joakim! [ X ] have a better understand of the different between a TIFFOutputItem and TIFFOutputField. The latter has a method, writeField, that seems to be correctly handling offsets oddness. * Will attach a screen shot of my notes. But basically, TiffOutputField uses TifOutputItem. The item contains the offset, length, value (another item), etc. And the output field has the bytes, field type, tag, count, etc. The field is properly writing TIFF data with the correct number of bytes. The item just holds that data, and its write method writes the bytes as is. [ ] write a unit test * Pending now. Just need to craft the example files for pass/fail tests. [ X ] find the parts of the specification that define that behaviour, and add links to them here, in the unit test, and in the javadoc of the class where the fix is applied * The library of the US congress holds some interesting archival information https://www.loc.gov/preservation/digital/formats/fdd/fdd000022.shtml, with links to many documents. I'm using this file https://www.itu.int/itudoc/itu-t/com16/tiff-fx/docs/tiff6.pdf. In the IFD and following sections it is possible to find text supporting the issue here. Page 21 for instance: "providing the offset was an even number greater than or equal to 8"
I'm intending to proceed with the change as is, provided with a unit test. Unless there's objection here or in the mailing list.
Even though it didn't happen with TiffImageWriterLossy, the same could happen there. Provided that you give as input a file with odd offsets, I believe we would get a resulting file with odd offsets too. The TiffImageWriterLossy seems to not alter the location of the fields, whereas TiffImageWriterLossless does, finding some times that the new offset is odd (and which is being fixed in this ticket).
Regarding the code snippet I posted earlier, about writing the UserComment
field. I had to do quite a bit of manual work to ensure adhering to the
Exif specification. Should some of this perhaps be incorporated into the
library?
Joakim
7. des. 2017 10.50 p.m. skrev "Joakim Knudsen" <joakim.grahl@gmail.com>:
Wonderful news! Great job and thanks :-D
Regarding the code snippet I posted earlier, about writing the UserComment
field. I had to do quite a bit of manual work to ensure adhering to the
Exif specification. Should some of this perhaps be incorporated into the
library?
I am not sure when/where users would want to use it, but only because I am slowly understanding the code base, and for TIFF/EXIF, I don't really have much practical use (my use case is more properly handling images for IIIF, and in getting a release of Imaging out of the door so I can experiment imaging with Cantaloupe image server).
But I assume it would be a different issue? If you could create a new issue, explaining the use case for that, and where you think it should go in Imaging, I'd be more than happy to review it.
Thanks Joakim!!!
Bruno
Apache Commons Imaging 1.0-alpha1 released (long ago, just closing the remaining issues marked as Resolved)
I have attached the file producing the output from above.