-
-
Notifications
You must be signed in to change notification settings - Fork 307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to modify a JPEGImage10Metadata comment value #845
Comments
Hi Steinar, Short answer: Long answer: You should still be able to achieve what you want, see #668. 😀 Try that first, but if you can't make it work, let me know, and we'll see if I can help. |
Thanks, Harald! The workaround of using the default metadata of the writer and replacing the content with the modified metadata tree of the writer worked. Working code example below. Next up for me is to find the exif segment of the metadata, if present, or create one of there isn't one, and then insert 3 values:
Can I do this in a simple way from the existing metadata object (where I can see the exif data in the debugger)?
|
Adding exif to the tree is possibly covered here? #586 (comment) (Seems a little cumbersome...?) Is it easier if the exif segment already exists I wonder? (Edit: yes it easier if the exif segment exists, it says so in the text of the comment above the code example which (I think describes) how to create an exif segment from scratch) |
Tried the approach outlined in #586 (comment) and https://stackoverflow.com/q/36029295 but I got the following error message when setting the metadata:
Here is what I've tried to do: https://gist.github.com/steinarb/0ab59ad7c17b7ac15b757dd67368dad9 Here is the complete stack trace: https://gist.github.com/steinarb/a2ae1019aa90a4ade2ca49387f6135b9 I'm sure there is a simple error copying from the examples, but I'm unable to sport the error. |
Sorry, no time right now, but: |
Did changing to the Your code does a lot, so it would probably help to organize things a little different to make things easier to understand... But I'm fairly sure this was the reason for the exception (as there is no The "plug-in neutral" format is good for getting a few essential values in a standard way, but it's not so good if you need to mess with format specific things like Exif in JPEG. I believe the JPEG native format always has a |
>>>> Harald Kuhr ***@***.***>:
Did changing to the `javax_imageio_jpeg_image_1.0` metadata format help? 😀
Yep. I got to a different error, and now I'm on a third error.
The second error seemed to be a mis-shapen EXIF segment, but then I
changed things around and now I got this one:
javax.imageio.metadata.IIOInvalidTreeException: JPEGvariety and markerSequence nodes must be present
I think maybe it is caused by having two markerSequence?
It's hard to look at the tree-stuff in the debugger, at least the
eclipse debugger: it doesn't show everything and goes a little crazy
after a while when I'm stopped in a breakpoint involving the tree nodes.
Your code does *a lot*, so it would probably help to organize things a little different to make things easier to understand... But I'm fairly sure this was the reason for the exception (as there is no `markerSequece` in the "plug-in neutral" format).
Yup, this is code-in-progress, to put it like that. The final code will
probably look a lot different.
It already looks a lot different, in fact.
I will start reorganizing once I get the first replaced EXIF tag working.
The "plug-in neutral" format is good for getting a few essential values in a standard way, but it's not so good if you need to mess with format specific things like Exif in JPEG.
Yep, I've noticed! :-)
(wasn't too good to find or modify the JFIF comment either, in fact... :-) )
A nice API to modify the metadata, that I see you have spoken of, would
be really nice.
An API to take inspiration from is JDom2 (not to follow, but the
approach/philosophy and how that philosophy makes it much simpler to use
than e.g. regular DOM or JAXP)
Leveraging Optional and streams may also be a good idea:
https://steinar.bang.priv.no/2021/12/28/how-i-learnt-to-like-optional/
https://steinar.bang.priv.no/2022/01/18/chaining-optionals-using-flatmap-and-map/
https://2022.javazone.no/#/program/7a7de418-d373-415c-8bb9-27cd5cd5900d
|
Ok, now I'm back to getting java.io.EOFException. The exception comes when I'm trying to read the metadata of the transformed image in the test and it comes when trying to read a stream containing just "Exif" followed by to 0-byte values. I.e. it looks like the line doesn't do anything:
The size of the bytes ByteArrayOutputStream doesn't change in the above line. This is the current version of the complete code: https://gist.github.com/steinarb/251e02cda3de13c9cc2845a2c9020f4a#file-oldalbumserviceprovider-java-L35 |
I did this instead, and then I got further:
Now the EXIF metadata parses without throwing an EOFException. Current problem: my replacement of the JFIF comment didn't survive the addition of modifying EXIF comments: https://gist.github.com/steinarb/da81e5d71a6d9e44058ef02598972f3a#file-oldalbumserviceprovider-java-L30 |
The latest version (with try-with-resources) closes (and implicitly flushes) the stream, to commit from the memory cache to the underlying Not sure about why the comment didn't survive. As mentioned, there's too much "going on" for me to fully understand what's happening. Try writing this as a test case, and I'll be able to help you better. 😀 Are you sure the PS: This code won't work as intended: var markerSequence = (IIOMetadataNode) metadataAsTree.getElementsByTagName("markerSequence").item(0);
if (markerSequence == null) {
markerSequence = new IIOMetadataNode("markerSequence");
metadataAsTree.appendChild(markerSequence);
} If there is no |
>>>> Harald Kuhr ***@***.***>:
The latest version (with try-with-resources) closes (and implicitly flushes) the stream, to commit from the memory cache to the underlying `ByteArrayOuputStream`. The previous code would probably also have worked if you explicitly invoked `flush()` on the `MemoryCacheImageOutputStream`.
Yes, I followed MemoryCacheImageOutputStream up the inheritance
hierarchy until I found Closable and then went for try-with-resource. :-)
Not sure about why the comment didn't survive. As mentioned, there's too much "going on" for me to fully understand what's happening. Are you sure the `findJfifCommentNode` works? Are you sure there was an existing comment in the file to replace? Are you sure the `ifPresent` block is even executed?
The tree looks different when I use the native tree, and the ifPresent
block is never executed.
I'm trying to find the right node in the new tree. As said I can't see
the tree nodes well in the debugger and the debugger goes a bit crazy
when I try to navigate them.
I found that the comment was put into a node named "com" by stepping
through the build of the native tree in the debugger.
But I found a node named "com" directly under markerSequence and tried
replacing it, but that probably wasn't the right one.
PS: This code won't work as intended:
```java
var markerSequence = (IIOMetadataNode) metadataAsTree.getElementsByTagName("markerSequence").item(0);
if (markerSequence == null) {
markerSequence = new IIOMetadataNode("markerSequence");
metadataAsTree.appendChild(markerSequence);
}
```
If there is no `markerSequence` node, the node list will be empty, and there won't be an item 0...
Thanks! :-) Yes I know. :-)
(I'll make a test case without the node and fix the handling)
|
One thing this odd XML-ish node structure is good for, is that it's.. well.. XML. 😀 You can dump the whole tree like this: new XMLSerializer(System.out, "UTF-8").serialize(tree, false); (using The only thing you won't see there it the
According to the DTD I referenced above, the |
>>>> Harald Kuhr ***@***.***>:
One thing this odd XML-ish node structure *is* good for, is that it's.. well.. XML. 😀
You can dump the whole tree like this:
```java
new XMLSerializer(System.out, "UTF-8").serialize(tree, false);
```
(using `com.twelvemonkeys.xml. XMLSerializer`, other serializers will probably do fine too..)
Oooh! Nice! Thanks! Found it: copy-paste-error!
The only thing you won't see there it the `userObject`s, because the `javax.imageio` API invented `userObject` instead of reusing `userData`, not really sure why...
> I found that the comment was put into a node named "com" by stepping
> through the build of the native tree in the debugger.
>
> But I found a node named "com" directly under markerSequence and tried
> replacing it, but that probably wasn't the right one.
According to the DTD I referenced above, the `com` (JFIF comment) marker is a child of `markerSequence`. It can't appear anywhere else.
I ended up putting the comment as an attribute on markerSequence,
because I had forgotten to change the name of the element I was
searching for.
(I dumped out the tree before and after).
Now it is time to tidy up the code.
Current iteration (before tidying) looks like this: https://gist.github.com/steinarb/497c28d27f59e85614b0f221115199f4
|
Here's the tidied up code: https://gist.github.com/steinarb/ec1c22513a64870a880f21e134ea33fb Now it will reside in a git branch waiting for the OSGi-fied version of Twelvemonkey to be released. 😃 Note that I'm currently just storing the description in the JFIF comment (i.e. the way I did things back in 1996), instead of in the EXIF usercomment. It's trivial to store it there as well. I take suggestions as what to do (store it in the exif user comment? continue to use the JFIF comment? Use both?). Do other programs use any of these fields? I know google photo uses the lastmodifieddate EXIF field. Does any applications out there use the EXIF ImageDescription? Does any applications out there use either the JFIF comment (it has been around for a while...)? |
I thought I mentioned it, but 3.10.0 with your OSGi support was released last week.
Wikipedia lists a few programs, but that's just a small subset. I don't have a list of applications, but mostly use only Preview on MacOS, which displays a lot of TIFF and Exif/GPS metadata. You should probably just test with the software you use, or the software you want to support. For Exif vs JFIF comment, it's a bit of apples and oranges discussion. The COM marker is just a generic "comment", while the TIFF/Exif tags have a specific semantic meaning, allowing for much richer metadata. I don't see a problem using both. There's also IPTC metadata and XMP metadata worth considering, if you want to jump into the meta data rabbit hole... 😀 |
>>>> Harald Kuhr ***@***.***>:
> Now it will reside in a git branch waiting for the OSGi-fied version of Twelvemonkey to be released. 😃
I thought I mentioned it, but [3.10.0 with your OSGi support](https://github.com/haraldk/TwelveMonkeys/releases/tag/twelvemonkeys-3.10.0) was released last week.
Oh, nice! That release had slipped past me. I was busy with other stuff
last week. :-)
I've merged the feature branch to main in the oldalbum application:
https://github.com/steinarb/oldalbum
I will make a new release one of these days.
Read metadata: https://github.com/steinarb/oldalbum/blob/289cd7d6959b596b2775c879dc0039a5ff06f72d/oldalbum.backend/src/main/java/no/priv/bang/oldalbum/backend/OldAlbumServiceProvider.java#L684
Add metadata to downloaded files: https://github.com/steinarb/oldalbum/blob/289cd7d6959b596b2775c879dc0039a5ff06f72d/oldalbum.backend/src/main/java/no/priv/bang/oldalbum/backend/OldAlbumServiceProvider.java#L544
I've also updated my minimal demo application for using twelvemonkeys in OSGi:
https://github.com/steinarb/twelvemonkeys-karaf-demo
> I take suggestions as what to do (store it in the exif user comment? continue to use the JFIF comment? Use both?).
> Do other programs use any of these fields?
[Wikipedia lists a few programs](https://en.wikipedia.org/wiki/Exif#Program_support), but that's just a small subset. I don't have a list of applications, but mostly use only Preview on MacOS, which displays a lot of TIFF and Exif/GPS metadata. You should probably just test with the software you use, or the software you want to support.
Yep! It doesn't really matter if they are used or not as long as I can
embed the metadata for future usage.
For Exif vs JFIF comment, it's a bit of apples and oranges discussion. The COM marker is just a generic "comment", while the TIFF/Exif tags have a specific semantic meaning, allowing for much richer metadata. I don't see a problem using both.
Thanks! I'll add both (but with the current push of master only JFIF).
There's also IPTC metadata and XMP metadata worth considering, if you want to jump into the meta data rabbit hole... 😀
Hm... I'll study IPTC and XMP metadata, and see how much work it would
be to add them. Thanks!
|
Sounds good! I'll close this issue as resolved, unless you have more questions about JPEG metadata? If so just reopen, or create a new, more specific issue. |
I am trying to modify the JFIF comment (note: not an EXIF tag, but the comment in the JFIF metadata) of an image and am running into the issue that the JPEGImage10Metadata object is readonly.
I am trying the approach of getting the metadata as a tree, walking the tree, replacing an attribute and setting the metadata as a tree, as outlined here: https://stackoverflow.com/a/9508479
Is there another way?
I have looked for ways to copy-and-mutate the JPEGImage10Metadata object, but not found any?
(I can see the existing value in the debugger so that it feels kind of annoying not to be able to change it... I've even considered using reflection... 😄 )
Here is the code that I'm trying to run:
The text was updated successfully, but these errors were encountered: