I Need to convert UIImage
to NSData
but without using UIImagePngRepresentation
or UIImageJpegRepresentation
, for images from photolib i can use assetlib method as mentioned here Using ALAssetsLibrary and ALAsset take out Image as NSData , but for captured image , assset url is not there hence in that case i need to convert UIImage
directly to bytes with exif data , how can i accomplish this ? please help
-
Why? Multiplatform reasons? That's the only reason I can think of...well if that is the case then try using LodePNG http://lodev.org/lodepng/ – borrrden Mar 06 '13 at 06:37
-
2By using uiimage png and jpeg representation, the size of the image varies, also quality of image for jpeg is reduced even with 1.0 compression quality . I need a way to convert UIImage to bytes directly . – H Bastan Mar 06 '13 at 08:32
-
Of course the size of the image varies...that's the nature of compression. Otherwise all pictures would have a huge filesize (wxhx4 bytes). Also, your size will vary depending on the dimensions of the file. I think you need to describe your problem much better than you currently are. – borrrden Mar 06 '13 at 09:16
-
The files stored in photolib are already in a compressed format right, now when we use say uipngrepresentation then 1. decompress the file and recompress it (this is a overhead if i could directly convert the compressed image stored in photolib to data then this process could be avoided) 2. using png representation EXIF data is lost due to which image is displayed 90 roated – H Bastan Mar 06 '13 at 10:37
-
1You are talking about UIImage. If you have a UIImage, then you've already uncompressed the data. End of story. It seems you don't want to use UIImage though. You just want to change EXIF data on an existing PNG? – borrrden Mar 06 '13 at 10:39
-
@borrrden : I want to save the captured image return by device camera, through UIImagepicker delegate method in document directory, for which i have to convert it in NSData, now if i use UIImagePngRepresentation for converting image to NSData then i lose all the EXIF data due to which image is displayed 90 degree rotated. I just need to avoid this.. – H Bastan Mar 06 '13 at 11:45
-
Have a look here http://stackoverflow.com/questions/1041884/iphone-camera-images-are-rotated-when-uploaded-to-web – borrrden Mar 06 '13 at 14:03
3 Answers
I had a similar problem, but for security reasons I didn't want to write the data to the default file system as suggested by Wes. I also wanted to be able to add metadata to my image. My solution was as follows:
- (NSData *)dataFromImage:(UIImage *)image metadata:(NSDictionary *)metadata mimetype:(NSString *)mimetype
{
NSMutableData *imageData = [NSMutableData data];
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)mimetype, NULL);
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, uti, 1, NULL);
if (imageDestination == NULL)
{
NSLog(@"Failed to create image destination");
imageData = nil;
}
else
{
CGImageDestinationAddImage(imageDestination, image.CGImage, (__bridge CFDictionaryRef)metadata);
if (CGImageDestinationFinalize(imageDestination) == NO)
{
NSLog(@"Failed to finalise");
imageData = nil;
}
CFRelease(imageDestination);
}
CFRelease(uti);
return imageData;
}
To use it, you would do the following:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata];
NSString *mimeType = @"image/jpeg"; // ideally this would be dynamically set. Not defaulted to a jpeg!
// you could add to the metadata dictionary (after converting it to a mutable copy) if you needed to.
// convert to NSData
NSData *imageData = [self dataFromImage:image metadata:metadata mimetype:mimeType];
// ...
}

- 1,203
- 1
- 11
- 21
-
Excution time is way better about 5% of using UIImageJpegRepresentation. but it uses approximatly same memory. but at least it reserve that memory for a very small time. – hasan May 09 '15 at 11:25
H Bastan,
Based on your comment:
...I want to save the captured image return by device camera, through UIImagepicker delegate method in document directory...
It looks like your real goal is to save the image with EXIF data to the documents directory and not specifically getting the UIImage as an NSData object with the EXIF data. In that case, you can do the following in your implementation of imagePickerController:didFinishPickingMediaWithInfo:
// Get your image.
UIImage *capturedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
// Get your metadata (includes the EXIF data).
NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata];
// Create your file URL.
NSFileManager *defaultManager = [NSFileManager defaultManager];
NSURL *docsURL = [[defaultManager URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
NSURL *outputURL = [docsURL URLByAppendingPathComponent:@"imageWithEXIFData.jpg"];
// Set your compression quuality (0.0 to 1.0).
NSMutableDictionary *mutableMetadata = [metadata mutableCopy];
[mutableMetadata setObject:@(1.0) forKey:(__bridge NSString *)kCGImageDestinationLossyCompressionQuality];
// Create an image destination.
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL((__bridge CFURLRef)outputURL, kUTTypeJPEG , 1, NULL);
if (imageDestination == NULL ) {
// Handle failure.
NSLog(@"Error -> failed to create image destination.");
return;
}
// Add your image to the destination.
CGImageDestinationAddImage(imageDestination, capturedImage.CGImage, (__bridge CFDictionaryRef)mutableMetadata);
// Finalize the destination.
if (CGImageDestinationFinalize(imageDestination) == NO) {
// Handle failure.
NSLog(@"Error -> failed to finalize the image.");
}
CFRelease(imageDestination);
From my tests the execution time was about the same or faster than doing:
NSData *data = UIImageJPEGRepresentation(capturedImage, 1.0);
[data writeToURL:outputURL atomically:YES];
...and you get to keep the EXIF data!
You could also dispatch it to a background queue if you want to make sure your UI stays responsive:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// Do the image saving here...
});
Important Note: You will need to add the ImageIO.framework
and the MobileCoreServices.framework
to your target's build phases and import them in the class where you do the image saving:
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>
Other notes It is my understanding that in this case we're not creating a generation loss when saving the image as proposed in the example. We are using UIImage's CGImage property and as the documentation states:
The underlying Quartz image data

- 1,686
- 1
- 12
- 15
-
Thanks its really helpfull, This way if i donot set the compression quality it get saved with original image compression qaulity n thats fine with me , also the image data size also remains the same as photolib and hence this is the perfect way to do this thanks. – H Bastan Apr 08 '13 at 06:16
-
-
I had been stuck for quite some time now. but thanks to your solution I can move forward. Thank you – Asbar May 31 '16 at 06:37
You can try something like this. Not sure if its the best method. But worth a shot. Incase the image URL is available, you can try initWithContentsOfUrl
NSData *data = [[NSData alloc]initWithContentsOfFile:@"/Users/test/isajf/isajf/test.jpg"];

- 2,430
- 3
- 37
- 55
-
hi thanks but am using uiimagepicker to capture image , here it only returns uiimage n not url to image, hence above method would not be usefull – H Bastan Mar 06 '13 at 10:50