Objective c 在OS X上打开NSImage时从EXIF读取相机数据

Objective c 在OS X上打开NSImage时从EXIF读取相机数据,objective-c,macos,exif,nsimage,Objective C,Macos,Exif,Nsimage,我正在创建一个可以打开照片、编辑照片和保存照片的照片应用程序。我正在使用GPUImage处理我的照片,EXIF数据在处理过程中丢失。因此,在以这种方式打开文件时,我正在读取EXIF数据: NSImage *img = [[NSImage alloc] initWithContentsOfURL:url]; NSImageRep *rep = [[img representations] objectAtIndex:0]; NSMutableDictionary *exif = [((NSDict

我正在创建一个可以打开照片、编辑照片和保存照片的照片应用程序。我正在使用GPUImage处理我的照片,EXIF数据在处理过程中丢失。因此,在以这种方式打开文件时,我正在读取EXIF数据:

NSImage *img = [[NSImage alloc] initWithContentsOfURL:url];
NSImageRep *rep = [[img representations] objectAtIndex:0];
NSMutableDictionary *exif = [((NSDictionary*)[(id)rep valueForProperty:NSImageEXIFData]) mutableCopy];
它包含几乎所有的EXIF数据,但由于某些原因,它不包括相机制造商和相机型号。保存时,我需要保留所有数据,包括这些字段。打开图像文件时,如何读取整个EXIF数据?我尝试了以下CF方法:


但除了文件大小,我不能用这种方法读取任何数据。有什么方法可以完全读取EXIF数据吗?

我从Apple,Inc.的一个名为ImageApp的示例项目中提取了以下代码。因此,您需要该项目来仔细查看下面的代码。键值绑定到mTree

// AppDelegate.h
@interface AppDelegate : NSObject {
IBOutlet NSTreeController *mTree;
NSURL *mUrl;
}

// AppDelegate.m
- (void)setPictureInfo:(NSString *)filepath {
NSURL *url = [[NSURL alloc] init];
url = [self convertpathURL:filepath:NO]; // Converting a file path to a url
[self getImageInfo:url];
}

- (void)getImageInfo:(NSURL *)url {
if (nil == url) {
    return;
}

if ([url isEqual:mUrl])
    return;

mUrl = url;   
CGImageSourceRef source = NULL;

if (url) source = CGImageSourceCreateWithURL((__bridge CFURLRef)url, NULL);

// CGImageSourceRef source = CGImageSourceCreateWithURL((__bridge CFURLRef)url, NULL);
if (source) {
    // get image properties (height, width, depth, metadata etc.) for display
    NSDictionary *props = (__bridge_transfer NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source, 0, NULL);
    [mTree setContent:[self propTree:props]];
}
else { // couldn't make image source for image, so display nothing
    [mTree setContent:nil];
}
}

static NSString *ImageIOLocalizedString (NSString *key) {
static NSBundle *b = nil;

if (b == nil)
    b = [NSBundle bundleWithIdentifier:@"com.apple.ImageIO.framework"];

// Returns a localized version of the string designated by 'key' in table 'CGImageSource'. 
return [b localizedStringForKey:key value:key table: @"CGImageSource"];
}

- (NSArray *)propTree:(NSDictionary *)branch {
NSMutableArray *tree = [[NSMutableArray alloc] init];   
for (NSInteger i3 = 0; i3 < [branch count]; i3++) {
    NSArray *keys = [[branch allKeys] sortedArrayUsingSelector:@selector(compare:)];
    NSString *key = [keys objectAtIndex:i3];
    NSString *locKey = ImageIOLocalizedString(key);
    id obj = [branch objectForKey:key];
    NSDictionary* leaf = nil;

    if ([obj isKindOfClass:[NSDictionary class]])
        leaf = [NSDictionary dictionaryWithObjectsAndKeys:
                locKey,@"key",  @"",@"val",  [self propTree:obj],@"children",  nil];
    else
        leaf = [NSDictionary dictionaryWithObjectsAndKeys:
                locKey,@"key",  obj,@"val",  nil];

    [tree addObject:leaf];
}
return tree;
}
//AppDelegate.h
@接口AppDelegate:NSObject{
iBStreeController*mTree;
NSURL*mUrl;
}
//AppDelegate.m
-(void)setPictureInfo:(NSString*)文件路径{
NSURL*url=[[NSURL alloc]init];
url=[self-convertpathURL:filepath:NO];//将文件路径转换为url
[self-getImageInfo:url];
}
-(void)getImageInfo:(NSURL*)url{
if(nil==url){
返回;
}
如果([url isEqual:mUrl])
返回;
mUrl=url;
CGImageSourceRef source=NULL;
如果(url)source=CGImageSourceCreateWithURL(((u桥CFURLRef)url,NULL);
//CGImageSourceRef source=CGImageSourceCreateWithURL(((uu桥CFURLRef)url,NULL);
如果(来源){
//获取要显示的图像属性(高度、宽度、深度、元数据等)
NSDictionary*props=(uu桥u传输NSDictionary*)CGImageSourceCopyPropertiesAtIndex(源,0,NULL);
[mTree setContent:[self-propTree:props]];
}
否则{//无法为图像生成图像源,因此不显示任何内容
[mTree setContent:nil];
}
}
静态NSString*ImageIOLocalizedString(NSString*键){
静态NSBundle*b=nil;
如果(b==nil)
b=[NSBundle bundleWithiIdentifier:@“com.apple.ImageIO.framework”];
//返回由表“CGImageSource”中的“key”指定的字符串的本地化版本。
返回[b localizedStringForKey:键值:键表:@“CGImageSource”];
}
-(NSArray*)propTree:(NSDictionary*)分支{
NSMutableArray*树=[[NSMutableArray alloc]init];
对于(NSInteger i3=0;i3<[分支计数];i3++){
NSArray*键=[[branch allKeys]SortedArray使用选择器:@selector(比较:)];
NSString*key=[keys objectAtIndex:i3];
NSString*locKey=ImageIOLocalizedString(键);
id obj=[branch objectForKey:key];
NSDictionary*leaf=nil;
if([obj是kindof类:[NSDictionary类]])
leaf=[NSDictionary Dictionary WithObjectsAndKeys:
骆家辉、@“key”、“val”、“self-propTree:obj]、@“children”、nil];
其他的
leaf=[NSDictionary Dictionary WithObjectsAndKeys:
洛克,“钥匙”,obj,“瓦尔”,无);
[树添加对象:叶];
}
回归树;
}

以什么形式读取数据?这是什么意思?我想按原样读取数据,这并不重要。我所需要做的就是在处理照片后将准确的数据写入新的NSImage。目前,我正在使用此方法获取一个NSDictionary,但它不完整。我只知道如何在NSOutlineView控件中发布整个提取。好的,这也会起作用,如果它可以提取比我的方法更多的内容,我可以检查相关部分。这很有效。由于某种原因,此代码以前不起作用。也许我做错了什么。我可以在完整的字典中分别获取TIFF/EXIF/IPTC元数据,这比我预期的要好。顺便说一句,现在(因为我改变了读取方法),我正在努力将数据写入图像文件。如果您对此有任何想法,您可以在这里提供帮助:我对ImageIOLocalizedString有问题,iOS14-bundle ImageIO不能使用found@ViktorGoltvyanitsa查看原始主题的标签。本主题是关于macOS应用程序和什么?代码本身在我的iOS应用程序中运行了好几年,直到现在。如果您愿意,那么好吧,它在maccatalyst下不适用于macOS。