【问题标题】:Objective c - How to programmatically set UIImage DPI of JPEG file while saving it目标 c - 如何在保存 JPEG 文件时以编程方式设置 UIImage DPI
【发布时间】:2014-07-16 16:00:22
【问题描述】:

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

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

提前感谢您的帮助。

【问题讨论】:

    标签: objective-c uiimage metadata


    【解决方案1】:

    这段代码用于操作图像元数据(如果存在),您可以使用它来更改图像元数据中的任何值。请注意,更改元数据中的 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;
        }
    }
    

    【讨论】:

    • 还有一件事....我怎样才能返回更改后的 NSData 而不是写入文件?
    • 有趣,我已经用 Photoshop 测试了保存的图像并在我的电脑上预览,DPI 看起来不错。
    • 正确,Preview.app 和 Photoshop。
    • 我发现了我的问题!!呜呜!!!我正在使用 ALAssetsLibrary 写出图像。我使用的是采用参数 ALAssetOrientation 而不是元数据 NSDictionary 的方法。
    【解决方案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];
    

    【讨论】:

      猜你喜欢
      • 2014-03-19
      • 2011-03-30
      • 1970-01-01
      • 2012-02-14
      • 1970-01-01
      • 2015-10-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多