Setting EXIF metadata with MagickSetImageAttribute?

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
sacha

Setting EXIF metadata with MagickSetImageAttribute?

Post by sacha »

[Apologies - I mis-posted this in the Developer forum]

I have a small test program which attempts to alter the "Model" EXIF tag:

Code: Select all

def main () {
  local wand = NewMagickWand()
  MagickReadImage(wand, info("argv 1"))
  print(MagickGetImageAttribute(wand, "EXIF:Model"))
  MagickSetImageAttribute(wand, "EXIF:Model", "TEST")
  print(MagickGetImageAttribute(wand, "EXIF:Model"))
  MagickWriteImage(wand, "/tmp/tst.jpg")
  DestroyMagickWand(wand)
}
It produces the following output:

Canon DIGITAL IXUS..
TEST

So it seems that the attribute is being set in the wand.

However, the output image /tmp/tst.jpg still gives Canon DIGITAL IXUS when I query it using an Exif utility.

Similarly, I can't seem to set EXIF metadata with the convert command line tool:

Code: Select all

% identify -format "%[EXIF:Model]" canon-ixus.jpg 
Canon DIGITAL IXUS..
% convert canon-ixus.jpg -set "EXIF:Model" TEST /tmp/tst.jpg
% identify -format "%[EXIF:Model]" /tmp/tst.jpg   
Canon DIGITAL IXUS..
% convert canon-ixus.jpg -set "[EXIF:Model]" TEST /tmp/tst.jpg
% identify -format "%[EXIF:Model]" /tmp/tst.jpg 
Canon DIGITAL IXUS..
Any clues?
sacha

Post by sacha »

Ok, I've looked at the IM source code and as far as I can tell, it's not possible to alter the values in the EXIF/IPTC/etc profile in such a way that they will be written to an output image.

From my reading of the code:

When an image is read, its various profiles (EXIF, IPTC etc) are stored in the internal image structure in a member profiles (image->profiles) as binary blobs.

The GetAttribute code will extract the attribute from the relevant profile stored in image->profiles, and cache the extracted value in image->attributes. The SetAttribute code will set the attribute in image->attributes.

But nowhere can I see code that will alter image->profiles from the values in image->attributes.

So, I think the only way to change the EXIF data written to the output image is to manipulate the EXIF profile directly. If the profile returned by MagickGetImageProfile() is genuinely a blob, then it might be possible to modify it using another library such as libexif. I'll give it a go.

If anyone can confirm my interpretation of things, that'd be helpful.
sacha

Post by sacha »

That seems to have worked. Using libexif I can manipulate the profile blob directly:

Code: Select all

  def main () {
    # load an image with some EXIF data
    local wand = NewMagickWand()
    MagickReadImage(wand, info("argv 1"))
    print(MagickGetImageAttribute(wand, "EXIF:Model"))

    # fetch the EXIF blob
    local profile = MagickGetImageProfile(wand, "exif")
    local data = exif_data_new()
    exif_data_load_data(data, profile)

    # poke a new camera model into it
    exif_data_set_entry(data, 0, "Model", "TEST") 

    # set the profile
    profile = exif_data_save_data(data)
    MagickSetImageProfile(wand, "exif", profile)

    # save the image
    MagickWriteImage(wand, "/tmp/tst.jpg")

    # tidy up
    exif_data_free(data)
    DestroyMagickWand(wand)
  }
[/code]
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Post by anthony »

When dealing with JPG images you generally do NOT want to read then write the image to just change its meta data, because read-write cycle will degrade the image due to the JPG lossy compression.

For just changing meta-date without modifying the image, you are better off using format specific programs to do this, as these programs will just transfer the image data without interpreting it from the old file to the new (or even the same) file.


If you are modifying the image, then do the meta-data modifications at the same time. In this case IM meta-data modifications is perfectally fine.

Point limit the read-write cycles to JPG images, Always try to start from the original source image, or save intermediate images using loss-less image formats like PNG or TIFF. JPEG sould only be written to as a final 'for actual use' step.

If the original is in JPG format, preverve it, back it up to CD or DVD, but do not lose it, and try to use it as the first source for all new image manipulations.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
mact

Post by mact »

Moin,

I remember having seen a flag or function in IM that would prevend the image from being decompressed when being read in so that you could deal with profiles only without degrading the image.
I cannot find that bit of info, unfortunately.

Marc
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Post by anthony »

I have not heard of such a flag. Sorry.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply