Objective c - How to programmatically set UIImage DPI of JPEG file while saving it

metadata, objective-c, uiimage

Solution

This piece of code for manipulating image metadata -if exists- and you can use this to change any values in image meta data. Please be aware changing DPI value in metadata does not actually process image and change DPI.

#import <ImageIO/ImageIO.h>


-(NSData *)changeMetaDataInImage
{
    NSData *sourceImageData = [[NSData alloc] initWithContentsOfFile:@"~/Desktop/1.jpg"];
    if (sourceImageData != nil)
    {
        CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)sourceImageData, NULL);

        NSDictionary *metadata = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(source, 0, NULL);

        NSMutableDictionary *tempMetadata = [metadata mutableCopy];
        [tempMetadata setObject:[NSNumber numberWithInt:300] forKey:@"DPIHeight"];
        [tempMetadata setObject:[NSNumber numberWithInt:300] forKey:@"DPIWidth"];

        NSMutableDictionary *EXIFDictionary = [[tempMetadata objectForKey:(NSString *)kCGImagePropertyTIFFDictionary] mutableCopy];
        [EXIFDictionary setObject:[NSNumber numberWithInt:300] forKey:(NSString *)kCGImagePropertyTIFFXResolution];
        [EXIFDictionary setObject:[NSNumber numberWithInt:300] forKey:(NSString *)kCGImagePropertyTIFFYResolution];

        NSMutableDictionary *JFIFDictionary = [[NSMutableDictionary alloc] init];
        [JFIFDictionary setObject:[NSNumber numberWithInt:300] forKey:(NSString *)kCGImagePropertyJFIFXDensity];
        [JFIFDictionary setObject:[NSNumber numberWithInt:300] forKey:(NSString *)kCGImagePropertyJFIFYDensity];
        [JFIFDictionary setObject:@"1" forKey:(NSString *)kCGImagePropertyJFIFVersion];

        [tempMetadata setObject:EXIFDictionary forKey:(NSString *)kCGImagePropertyTIFFDictionary];
        [tempMetadata setObject:JFIFDictionary forKey:(NSString *)kCGImagePropertyJFIFDictionary];

        NSMutableData *destinationImageData = [NSMutableData data];

        CFStringRef UTI = CGImageSourceGetType(source);

        CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)destinationImageData, UTI, 1, NULL);

        CGImageDestinationAddImageFromSource(destination, source,0, (__bridge CFDictionaryRef) tempMetadata);

        CGImageDestinationFinalize(destination);

        return destinationImageData;
    }
}

Problem

I have read that you can change the meta data of an image to set the dpi to another value other than the default 72. I tried the solution in this question but had the same problem as the author of that question. The image metadata properties in the original image seems to take precedence over modifications. I am using the ALAssetsLibrary to write an image to the photo library on my iPhone. I need to dpi to be 500 instead of the standard 72dpi. I know it is possible to change the properties by manipulating the bits directly (as shown here), but am hoping that iOS gives a better solution. Thank you in advance for your help.

Original source

Related problems