3

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.

Community
  • 1
  • 1
Patricia
  • 5,019
  • 14
  • 72
  • 152

2 Answers2

9

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;
    }
}
modusCell
  • 13,151
  • 9
  • 53
  • 80
  • One more thing....how could I return the changed NSData instead of writing out to file? – Patricia Jul 16 '14 at 16:12
  • 1
    Interesting, I have tested saved images with photoshop and preview on my computer, DPI looks ok to me. – modusCell Jul 16 '14 at 17:29
  • 1
    Correct, both Preview.app and Photoshop. – modusCell Jul 16 '14 at 19:27
  • I found my problem!! Woo-Hoo!!! I am writing out the image using the ALAssetsLibrary. I was using the method the takes the parameter ALAssetOrientation instead of the metadata NSDictionary. – Patricia Jul 16 '14 at 22:58
4

While trying to employ this solution for exporting JPEGs, I found that Photoshop wouldn't honour the DPI as exported. It turns out that Photoshop actively ignores the JFIF header information (and, in fact, doesn't even export it itself when it writes out JPEGs).

I ditched the JFIF section entirely. Most modern image libraries look at the TIFF/EXIF data first, so including that (and only that) seems to work well. Your mileage may vary, so be sure to test as many export destinations as you can!

However, the TIFF data is missing the ResolutionUnit tag, without which Photoshop will ignore XResolution and YResolution. It can have three values:

1 = No absolute unit of measurement. Used for images that may have a non-square aspect ratio, but no meaningful absolute dimensions. 2 = Inch. 3 = Centimeter.

Setting ResolutionUnit to 2 is required for DPI (dots per inch), for example:

[EXIFDictionary setObject:@(2) forKey:(NSString *)kCGImagePropertyTIFFResolutionUnit];
Dafydd Williams
  • 1,232
  • 12
  • 14