目标c - 如何以保存方式编程设置JPEG文件的UIImage DPI

时间:2014-07-16 16:00:22

标签: objective-c uiimage metadata

我已经读过您可以更改图像的元数据,将dpi设置为默认值72以外的其他值。我在this question中尝试了解决方案,但遇到的问题与该问题的作者相同。原始图像中的图像元数据属性似乎优先于修改。

我正在使用ALAssetsLibrary将图像写入iPhone上的照片库。我需要dpi而不是标准的72dpi。我知道可以通过直接操作位来更改属性(as shown here),但我希望iOS提供更好的解决方案。

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:7)

这段用于处理图像元数据的代码 - 如果存在 - 您可以使用它来更改图像元数据中的任何值。请注意,更改元数据中的DPI值实际上不会处理图像并更改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;
    }
}

答案 1 :(得分:2)

在尝试使用此解决方案导出JPEG时,我发现Photoshop不会像导出那样尊重DPI。事实证明,Photoshop主动忽略了JFIF标题信息(事实上,当它写出JPEG时,它甚至不会自己导出它。)

我完全放弃了JFIF部分。大多数现代图像库首先查看TIFF / EXIF数据,因此包括(并且只有那个)似乎运行良好。您的里程可能会有所不同,因此请务必尽可能多地测试出口目的地!

但是,TIFF数据缺少ResolutionUnit标记,否则Photoshop将忽略XResolutionYResolution。它可以有三个值:

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.

DPI(每英寸点数)需要将ResolutionUnit设置为2,例如:

[EXIFDictionary setObject:@(2) forKey:(NSString *)kCGImagePropertyTIFFResolutionUnit];