3

I would need to take an existing jpg file and modify the title, the description and the keywords in its IPTC entries. There are several topics here on this but all either without answer or with partial answers. I already know how to read the IPTC informations, but would need to edit them. Could somebody shed some light on this much researched and less known topic?

what i have is:

NSString: title
NSString: description
NSArray: keywords
NSString: path to the file

I would like to take an existing image with existing IPTC data and replace the existing entries with these, but preserve all other IPTC entries such as location, date and so on. All I know so far is that i need to use CGImageDestination.

Thanks

user2452250
  • 777
  • 2
  • 11
  • 26

2 Answers2

4

You should first read the metadata from the file:

CGImageSourceRef source = CGImageSourceCreateWithURL((__bridge CFURLRef)url, NULL);
NSDictionary *props = (__bridge_transfer NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source, 0, NULL);

In the code above, url is the URL of your image file. props will have all the metadata of the image at the destination URL.

Then, you copy that data to a new mutable, empty data source:

//new empty data to write the final image data to
NSMutableData *resultData = [NSMutableData data];
CGImageDestinationRef imgDest = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)(resultData), imageType, 1, NULL);

Finally, let's assume you've modified the metadata in a new NSDictionary instance (called modifiedMetadata in this example):

//copy image data
CGImageDestinationAddImageFromSource(imgDest, source, 0, (__bridge CFDictionaryRef)(modifiedMetadata));
BOOL success = CGImageDestinationFinalize(imgDest);

This would write the metadata to the destination image. At least in my case, it works perfectly.

To save the image data to an actual file, you can write the data regularly, e.g:

[resultData writeToFile:fileName atomically:YES];
Can Poyrazoğlu
  • 33,241
  • 48
  • 191
  • 389
  • this is better and easy way and works fine unless you want to add/remove individual properties. – modusCell May 26 '14 at 18:46
  • @mohacs I did actually add some properties when I was using this code. – Can Poyrazoğlu May 26 '14 at 18:49
  • yes you could for sure but as i mention in my answer you can't add all of them (may be a bug) for instance in IPTC definition ByLine points creator and it receives an array but you can't (Photoshop does not see) add it with image/io just because of it i am using XMP Toolkit. if you can manage to add it that would be great. also i did not try with image/io but with XMP toolkit i can add metas to many file type as like pdf, video etc. – modusCell May 26 '14 at 19:06
  • @mohacs I see.. I used it to replace EXIF/TIFF metadata from photos, and I didn't bother with IPTC a lot. I can't see why it wouldn't work, but if you say so.. :) – Can Poyrazoğlu May 26 '14 at 19:12
  • @mohacs aha:) burası bayağı Türk doldu :) – Can Poyrazoğlu May 26 '14 at 19:25
  • hi guys! thanks for the answers, i am testing this one out right now and will report back. all i need to do is ADD/EDIT title, description and keywords.. thats it! :) – user2452250 May 26 '14 at 19:40
  • 1
    ok a few questions here: 1) modifiedMetatada: how can i EDIT the existing metadata? can you expand your example to include the edit of the title please? 2) can the destination file be the same as the source file? 3) does this code actually SAVE the file or just prepare it with all content for saving? Thanks! this will help many people beside me.. :) – user2452250 May 26 '14 at 19:50
  • and i do also get "use of undeclared identifier "imageType"" – user2452250 May 26 '14 at 19:56
  • 2
    NSMutableDictionary *dicti = [modifiedMetatada objectForKey@"{IPTC}"]; gives you the IPTC dictionary. if you want to change title [dicti setObject:@"MY TITLE HERE" forKey:@"Caption/Abstract"]; then you can add dicti to modifiedMetatada [modifiedMetatada setObject:dicta forKey@"{IPTC}"]; – modusCell May 26 '14 at 21:19
  • @user2452250 2) sure 3) i've updated my answer: you end up with a data object that you can directly write to disk. – Can Poyrazoğlu May 27 '14 at 12:18
  • Great thanks! will try as soon as I am at home! could you please also include mohacs comment (2 comments above this, in regard of editing the values) and include the missing line where you declare imageType? just for completeness. as soon as I test it i will mark it as accepted! thanks for your help! and nice pictures you have i am a photographer myself – user2452250 May 27 '14 at 12:29
  • hello! everything works except the saving part. the file is not saved and i do not get any error message. – user2452250 May 27 '14 at 16:11
  • i just found that it is saving the file but with the old keyowrds. how can i assign the new keywords to the resultData? – user2452250 May 27 '14 at 16:19
  • for some reason ` [dicti setObject:@"MY Description HERE" forKey:@"Caption/Abstract"];` does not work. this information is not saved to the file. whilst the tile is. any idea why? – user2452250 May 27 '14 at 17:55
  • The problem is this: http://stackoverflow.com/questions/19033974/how-do-you-overwrite-image-metadata added a 50+ boutny for the fix. – user2452250 May 27 '14 at 18:41
3

you should use XMP Toolkit SDK, you can find detailed information at adobe SDK page implementing is little bit tricky but once you add static libraries to your project you can read and write XMP information, it covers IPTC namespace as well upon others namespaces as like dublin-core etc.

After you add libraries to project code like this.

#include "XMP.incl_cpp"
#include "XMP.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>

-(void)readIPTC
{
    SXMPMeta::Initialize()
    SXMPMeta imageMeta;

    if(imageMeta.DoesPropertyExist(kXMP_NS_DC, "title"))
    {
        std::string MyString;
        imageMeta.GetArrayItem(kXMP_NS_DC, "title", 1, &MyString, 0);
        [textField setStringValue:[NSString stringWithCString:MyString.c_str() encoding:[NSString defaultCStringEncoding]]];
    }
}

writing is pretty much same.

imageMeta.SetProperty(<#XMP_StringPtr schemaNS#>, <#XMP_StringPtr propName#>, <#XMP_StringPtr propValue#>)

you can find all namespace constants in documentation as like kXMP_NS_DC XMP NameSpace DublinCore etc.

Apple's Image/IO suppose to cover all but for instance you can read byline entry from IPTC with Image/IO however you can't write it.

Image/IO Reference

CGImageProperties Reference

modusCell
  • 13,151
  • 9
  • 53
  • 80
  • i think i might have to use your solution as the other doesnt seem to work properly. i can save the title but for some reason the description does not get saved. – user2452250 May 27 '14 at 18:18
  • mohacs, please look at the other question where the Bounty. my last comment. Thanks for all your help! – user2452250 May 28 '14 at 17:35