I can not understand why metaDic is always null.
There is a code.
CFDataRef dataRef = CGDataProviderCopyData(CGImageGetDataProvider(img.CGImage)); //(UIImage *img)
CGImageSourceRef mySourceRef = CGImageSourceCreateWithData(dataRef, NULL);
NSDictionary *metaDic = (NSDictionary *) CGImageSourceCopyPropertiesAtIndex(mySourceRef,0,NULL);
NSDictionary *tiffDic = (NSDictionary *)[metaDic objectForKey:(NSString *)kCGImagePropertyTIFFDictionary];
NSString *AuthorName = [tiffDic objectForKey:(NSString *)kCGImagePropertyTIFFArtist];
I did some variants of getting picture. And here what I have discovered:
One way of getting picture with its info - I need to get it from site and there what I've got:
// NSURL *UrlPath - path of picture image.jpg from web site
NSData *dataImg = [NSData dataWithContentsOfURL:UrlPath];
CGImageSourceRef mySource = CGImageSourceCreateWithData((CFDataRef)dataImg, NULL);
NSDictionary *metaDic = (NSDictionary *) CGImageSourceCopyPropertiesAtIndex(mySource,0,NULL);
NSDictionary *tiffDic = [metaDic objectForKey:(NSString *)kCGImagePropertyTIFFDictionary];
/// Log of tiffDic
tiffDic = {
Artist =(
"mr. Smith"
);
}
another way - read picture from NSBoudle mainBundle:
// NSURL *NSBundleUrl - - path of the same picture image.jpg from [[NSBundle mainBundle]
CGImageSourceRef mySource = CGImageSourceCreateWithURL( (CFURLRef) NSBundleUrl, NULL);
NSDictionary *metaDic = (NSDictionary *) CGImageSourceCopyPropertiesAtIndex(mySource,0,NULL);
NSDictionary *tiffDic = [metaDic objectForKey:(NSString *)kCGImagePropertyTIFFDictionary];
/// Log of tiffDic
tiffDic = {
Artist = "mr. Smith";
}
why it get braces as array for name of artist when the picture data come from web site?
Your data path looks something like this:
UIImage -> CGImage -> CGDataProvider -> CGImageSource
It's that third step that is cleansing your image of metadata. CGDataProviders are an "older" mechanism for getting data into Quartz with "limited functionality" - meaning - amongst other things - they do not support metadata.
Try something like this instead:
NSData* jpegData = UIImageJPEGRepresentation(image,1.0);
CFDataRef dataRef = (__bridge CFDataRef)jpegData;
CGImageSourceRef source = CGImageSourceCreateWithData(dataRef, NULL);
Data path:
UIImage -> NS/CFData -> CGImageSource
That will preserve the metadata.
You may not have much luck getting the authorName this way if you use the UIImage
as your starting point. UIImage
strips out a lot of the metadata that may accompany the original image source (the TiffDict seems to get stripped down to just the orientation
tag). You really want to be reading the 'uninterpreted' data from it's source and extracting metadata without reading the image data (that is one of the benefits of using a CGImageSourceRef
).
I have a little test project up on github that compares methods of extracting image metadata from various sources - filesystem, network URL, asset library, camera, maybe you should take a look.
update
As Peter points out (and my project shows) - you shouldn't be using the UIImage, but the original data source. As in your case it is a filesystem source, something like this:
NSString* path = @"/path/to/resource";
NSData *data = [NSData dataWithContentsOfFile:path];
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
Or better still (as Peter points out again!) you can use CGImageSourceCreateWithURL
and skip that NSData
step altogether.
The data provider of a CGImage provides raw pixels, not PNG or TIFF or other external-format data with metadata included. Consequently, there are no properties to get.
I wouldn't be surprised if that source can't even give you an image, since it has no way of knowing what pixel format to interpret the data in.
You need to create the image source with the URL or data you got the original image from, not the pixel data of that image. Ideally, you should create the image source first, and then create the image and its properties from the image source.