Add an NSDictionary to image metadata - ios

I'm trying to save an image with some custom metadata to a Photo Album. The custom metadata I would like to save should be in the form of a NSDictionary. Until now I have only succeeded in inserting an NSArray into the image metadata by using something like below:
NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
[metadata setObject:#[#"ele1", #"ele2"] forKey:(NSString*)kCGImagePropertyIPTCKeywords];
NSMutableDictionary *meta = [[NSMutableDictionary alloc] init];
[meta setObject:metadata forKey:(NSString*)kCGImagePropertyIPTCDictionary];
// pass the meta dictionary into writeImageDataToSavedPhotosAlbum
But what I would like is to pass a dictionary into setObject.
Has anyone succeeded in inserting a custom metadata into an image where the metadata is an NSDIctionary?
Additional information
I'm using the code I found here Save CUSTOM metadata in an image taken from AVFoundation in iOS, to add a dictionary to the image metadata but still no luck. The original file is in the temporary directory and the final file is created via writeImageDataToSavedPhotosAlbum. Like in the link, the resulting image doesn't contain the dictionary. Any idea?
CGImageSourceRef source = CGImageSourceCreateWithData((CFMutableDataRef)data, NULL);
NSDictionary *metadata = [(NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source,0,NULL)autorelease];
NSMutableDictionary *metadataAsMutable = [metadata mutableCopy];
NSMutableDictionary *RAWDictionary = [[metadataAsMutable objectForKey:(NSString *)kCGImagePropertyRawDictionary]mutableCopy];
if(!RAWDictionary) {
RAWDictionary = [NSMutableDictionary dictionary];
}
[RAWDictionary setValue:#"value1" forKey:#"key1"];
[RAWDictionary setValue:#"value2" forKey:#"key2"];
[metadataAsMutable setObject:RAWDictionary forKey:(NSString *)kCGImagePropertyRawDictionary];
NSMutableData *newData = [NSMutableData data];
CFStringRef UTI = CGImageSourceGetType(source);
CGImageDestinationRef destination = CGImageDestinationCreateWithData((CFMutableDataRef)newData, UTI, 1, NULL);
if(!destination) {
NSLog(#"***Could not create image destination ***");
}
CGImageDestinationAddImageFromSource(destination,source,0, (CFDictionaryRef)metadataAsMutable);
BOOL success = NO;
success = CGImageDestinationFinalize(destination);
if(!success) {
NSLog(#"***Could not create data from image destination ***");
}

Try this :
//covert image to nsdata format
NSData *imageData = [[NSData alloc]initWithContentsOfFile:#"your image path"];
NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
[metadata setObject:imageData forKey:#"imageData"];

Related

How do I convert NSData to file format (.mp4/.m4a)

I have some NSData variables which contain .m4a/.mp4 file formats. I've tried looking at ways to convert the NSData into file format, with no luck. I need to convert it into a file, change some of it's metadata, and convert it back to NSData. Here's some code:
// This JSON basically gets the url of a .m4a
NSArray *preview = [JSON valueForKeyPath:#"results.previewUrl"];
_previewData = [NSMutableData dataWithContentsOfURL:[NSURL URLWithString:[preview objectAtIndex:0]]];
[_previewData writeToFile:path atomically:YES];
ANMovie* file = [[ANMovie alloc] initWithFile:_previewData]; // or .mp4
NSData* jpegCover = UIImageJPEGRepresentation(artworkImage, 1.0);
ANMetadata* metadata = [[ANMetadata alloc] init];
metadata.albumCover = [[ANMetadataImage alloc] initWithImageData:jpegCover type:ANMetadataImageTypeJPG];
[file setMovieMetadata:metadata];
[file close];
I'm guessing [[ANMovie alloc] initWithFile:] expects a file, and you've passed it, I'm also assuming here, an NSData*.
Try:
ANMovie* file = [[ANMovie alloc] initWithFile:path];

How can I extract exif data from a THM file in iOS?

I'm trying to view the media track creation date in the exif data of a THM file. Using the command line utility exiftool, I am able to see this property. How can I see it using objective c?
This is what I've tried so far.
[self downloadImageWithURL:[candidateVideo objectForKey:#"thmURL"] completionBlock:^(BOOL succeeded, NSData *data) {
if (succeeded) {
CGImageSourceRef source=CGImageSourceCreateWithData((__bridge CFDataRef)data,NULL);
NSDictionary* metaData=(__bridge NSDictionary*)CGImageSourceCopyPropertiesAtIndex(source,0,NULL);
NSMutableDictionary* metaDataMutable=[metaData mutableCopy];
//recalculate validity with the images exif data
NSMutableDictionary *EXIFDictionary = [[metaDataMutable objectForKey:(NSString *)kCGImagePropertyExifDictionary]mutableCopy];
NSLog(#"wut");
}
}];
But my EXIFDictionary is nil.
I've also tried this and my dictionary has some key value pairs but there are only 3 and they are not what I need. I've tried using UIIMageJPEGRepresenation() and UIImagePNGRepresentation() to no avail. Too bad there is no UIImageTHMRepresentation()...
[self downloadImageWithURL:[candidateVideo objectForKey:#"thmURL"] completionBlock:^(BOOL succeeded, NSData *data) {
if (succeeded) {
UIImage* thumbnail = [[UIImage alloc] initWithData:data];
NSData* pngData=UIImageJPEGRepresentation(thumbnail,1.0);
CGImageSourceRef source=CGImageSourceCreateWithData((__bridge CFDataRef)pngData,NULL);
NSDictionary* metaData=(__bridge NSDictionary*)CGImageSourceCopyPropertiesAtIndex(source,0,NULL);
NSMutableDictionary* metaDataMutable=[metaData mutableCopy];
//recalculate validity with the images exif data
NSMutableDictionary *EXIFDictionary = [[metaDataMutable objectForKey:(NSString *)kCGImagePropertyExifDictionary]mutableCopy];
NSLog(#"wut");
}
}];

how to load plist data into array in IOS property list

NSString *path = [[NSBundle mainBundle] pathForResource:#"recipes" ofType:#"plist"]];
NSDictionary *dict = [[NSDictionary alloc] initwithContentOfFile:path];
NSArray *textData=[NSArray new];
textData = [dict objectForkey:#"TableData"];
textData is my array name,
recipes is plist name
after excuting my text data is being empty...
where is the mistake.
The problem is that you converting .plist to dictionary in the wrong way. Check dict property, it should be nil. Code to create NSDictionary from .plist file is listed below:
CFPropertyListRef plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,
(__bridge CFDataRef)propertyListData,
kCFPropertyListImmutable, NULL);
NSDictionary *settings = (__bridge NSDictionary *)plist;
Try this:
textData = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"recipes" ofType:#"plist"]];
Anyways, you may can take a look of this tutorial:
http://ios-blog.co.uk/tutorials/how-to-populate-a-uitableview-from-a-plist-property-list/

GDataXML updating xml data

I am trying to update an xml file. After suggestion I ended up choosing GdataXml.
So I am trying to update options.xml file.
Original File
<Dat>
<Name>Tom</Name>
<Option>1</Option>
</Dat>
I need to change "Tom" to "Jim" and save in the same file
Here is the code I tried.
-(void)saveToXML
{
NSString* path = [[NSBundle mainBundle] pathForResource:#"options" ofType:#"xml"];
NSData *xmlData = [[NSMutableData alloc] initWithContentsOfFile:path];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
GDataXMLElement *rootElement = [GDataXMLElement elementWithName:#"Dat"];
NSArray *mySettings = [doc.rootElement elementsForName:#"Dat"];
for (GDataXMLElement *mySet in mySettings)
{
NSString *name;
NSArray *names = [mySet elementsForName:#"Name"];
if (names.count > 0)
{
GDataXMLElement *childElement = (GDataXMLElement *) [names objectAtIndex:0];
name = childElement.stringValue;
NSLog(childElement.stringValue);
[childElement setStringValue:#"Jim"];
}
}
[xmlData writeToFile:path atomically:YES];
}
But this is not updating options.xml file. Can some one help on this ?
The missing line of code you are looking for is
NSData *xmlData = doc.XMLData;
from Anupdas answer on your last question. You are currently reading a file into memory, initializing a new object using that memory, updating that new object and then writing the original file's memory into the new file location. So essentially you are reading a file and then writing the same file back to the file location.

Memory Leak in NSMutableDictionary initWithContentsOfFile

This is my code: (customNames and customNamesArray are static variables)
-(void) loadCustomDataFromDisk
{
NSString *fullPath = [self filePathAndFileName: #"customData.plist"];
if ( ![[NSFileManager defaultManager] fileExistsAtPath: fullPath] )
{
NSLog(#"Loading file fails: File not exist");
customNames = [[NSMutableDictionary alloc] init];
customNamesArray = [[NSMutableArray alloc] init];
}
else
{
NSMutableDictionary *customItems = [[NSMutableDictionary alloc] initWithContentsOfFile: fullPath];
customNames = [customItems objectForKey: #"customNamesDict"];
customNamesArray = [customItems objectForKey: #"customNamesArray"];
if (!customItems)
NSLog(#"Error loading file");
[customItems release];
}
}
-(void) saveCustomDataToDisk
{
NSString *path = [self filePathAndFileName: #"customData.plist"];
NSMutableDictionary *customItems = [[NSMutableDictionary alloc] init];
[customItems setObject: customNames forKey: #"customNamesDict"];
[customItems setObject: customNamesArray forKey: #"customNamesArray"];
BOOL success;
success = [customItems writeToFile:path atomically:YES];
if (!success)
NSLog(#"Error writing file: customDataDict.plist");
[customItems release];
}
According to Build and Analyze, I have a potential leak in loading customItems
NSMutableDictionary *customItems = [[NSMutableDictionary alloc] initWithContentsOfFile: fullPath];
true enough, according to Instruments, I do have a leak in that part. But when I tried release or autoreleasing customItems, my app crashes. Even if I change NSMutableDictionary to NSDictionary, I still have the leak.
How do I fix this?
Any help would be very much appreciated. :) Thanks :)
You have to retain customNames and customNamesArray because you are using reference from dictionary customItems and after passing reference you are releasing it.
customNames = [[customItems objectForKey: #"customNamesDict"] retain];
customNamesArray = [[customItems objectForKey: #"customNamesArray"] retain];
Now you can release customItems.
Your code is right as I can see. You can see answer here and may be it helps - Leak problem with initWithContentsOfFile
I have only one question: You create NSString *fullPath and never release it. Is it autoreleased string? If so - your code is fine.

Resources