dragon66 / icafe

Java library for reading, writing, converting and manipulating images and metadata
Eclipse Public License 1.0
203 stars 58 forks source link

Deleting specific IPTC fields? (Update: Enum IPTCApplicationTag.valueOf(String) returning IllegalArgumentException) #97

Closed jimas14 closed 3 years ago

jimas14 commented 3 years ago

First off, this package is great! We currently use drewnoakes for reading IPTC but now that we're using icafe to modify, we'll switch over to using it for reading as well.

The only issue I've experienced so far is in deleting specific IPTC fields. There are methods for removeMetadata given the MediaType (JPG, PNG, etc), but not any IPTC methods for deleting specific IPTC tag values in exif.

My goal is to replace an image binary's IPTC values with values that a user has input into one of our JSON forms (whose fields map back to iptc values). The only possibilities I see with the current icafe package is: 1) Remove all exif data from the jpg, then add the IPTC values I want back to

Can anyone offer guidance on this if what I describe is possible using icafe alone?

Thanks in advance.

dragon66 commented 3 years ago

@jimas14 thanks for your comments. At the moment, you can only add certain IPTC fields which allow multiple values directly through insertMetadata.

For your specific requirement, what you can do is a two step process: first call removeMetadata with IPTC as type which will return the Metadata removed. Second, create a new IPTC metadata, iterate through the removed IPTC, if certain field exists and it is not in the list of user provided IPTC, add this to the new IPTC. If it is in the user provided list, add the one provided by the user. In the end, add all the remaining fields provided by the user and insert this new IPTC back to the intermediate image.

By user provided list, I really mean map which will make it easier to search and remove certain IPTC field as well as adding the remaining user provided fields at the end.

Not ideal but should work.

Wen

jimas14 commented 3 years ago

@dragon66 For some reason I had assumed removeMetadata was void, but now see it returns the same kind of map readMetadata does. That will definitely work for my case.

Thanks so much for the quick reply.

dragon66 commented 3 years ago

@jimas14 Glad to help. The initial implementation did return null but was later changed to get a hold of the original data.

jimas14 commented 3 years ago

@dragon66 I'm having trouble getting the enum constant given the string value of the field. For example when looping for (MetadataEntry item : List<IPTCDataSet>), item.getKey() returns the string value "Object Name". IPTCApplicationTag.valueOf(item.getKey()) then throws an IllegalArgumentException for string "Object Name".

I can't find any valueOf(String value) overrides in IPTCApplicationTag. Is there a way to get the enum constant without having to create my own mapping in code?

jimas14 commented 3 years ago

I ended up making a helper method in my class like

    private IPTCApplicationTag getIPTCTagFromString(String tagName) {
        for (IPTCApplicationTag tag : IPTCApplicationTag.values()) {
            if (StringUtils.equals(tag.getName(), tagName)) {
                return tag;
            }
        }
        return null;
    }
dragon66 commented 3 years ago

@jimas14 As Java doesn't like us to override valueOf, and given the current implementation of ICAFE, calling valueOf will not work in your case. The way you implemented a helper method will work but not efficient as you have to loop for each call.

What you can do is something similar to how IPTCApplicationTag does for fromTag method - to implement a fromName method for IPTCApplicationTag which will look up enum by name. Then instead of alling valueOf, you call fromName to get the enum by it's name.

As the back up implementation is a map and static, it will be way more efficient.

I cannot push code from my work computer and I don't have access to a personal computer at the moment. If possible, can you create a pull request with the changes I recommended and I will merge it to the branch.

Wen