【问题标题】:NSImage and UIImage give different NSData representationsNSImage 和 UIImage 给出不同的 NSData 表示
【发布时间】:2026-01-26 19:55:02
【问题描述】:

场景: 我在 iPhone 相机胶卷中有一张图像。我使用ALAssetLibrary 访问它并获得一个ALAsset 对象。我使用类似于以下代码的内容从中获得了 UIImageNSData 对象。

ALAssetRepresentation *rep = [myasset defaultRepresentation];
CGImageRef iref = [rep fullResolutionImage];
if (iref)
{
    UIImage *largeimage = [UIImage imageWithCGImage:iref ];
    NSData * data = UIImageJPEGRepresentation(largeimage, 1.0f);
}

然后,我使用 Image Capture 将相机胶卷中的图像复制到我的 Mac 上。然后我在我的 Mac 代码中使用 NSImage 打开复制的图像并尝试使用以下代码获取 NSData 表示。

NSImage * image = [[NSImage alloc] initWithContentsOfURL:fileURL];
NSBitmapImageRep *imgRep = [[image representations] objectAtIndex: 0];
NSData *data = [imgRep representationUsingType: NSJPEGFileType properties: nil];

问题: 不幸的是,我得到的两个NSData 表示非常不同。我希望能够在两种情况下获得相同的NSData 表示(因为它是同一个文件)。然后我可以继续对NSData 对象进行哈希处理并比较哈希值以得出两者(可能)是相同图像的结论。理想情况下,我想要以下两个功能;

//In iOS
-(NSData *) getDataFromALAsset:(ALAsset*)asset;
//or 
-(NSData *) getDataFromUIImage:(UIImage*)image;

//In OS X
-(NSData *) getDataFromFileAtURL:(NSURL*)url;
//or 
-(NSData *) getDataFromNSImage:(NSImage*)image;

这样我在 OS X 和 iOS 中得到的 NSData* 表示是完全相同的,因为它们来自同一个源图像。

我尝试过的:

我尝试过如何从ALAsset 对象中获取 UIImage 对象,我尝试过UIImagePNGRepresentation(以及在 OS X 中获取NSData 的对应方法)。我还尝试使用不同的参数来获取 OS X 中的表示,但没有任何结果。我还尝试在两个平台上创建CGIImageRef,将其转换为位图并逐个像素读取它们,甚至那些似乎已关闭(是的,我确实意识到NSBitmapImageRep 具有不同的坐标系统)。

【问题讨论】:

  • 您正在对图像执行多次 JPEG 压缩,因此位不可避免地会发生变化。
  • @NSAdam 你能建议一种方法来避免这种情况吗?对解决实际问题有何见解?
  • 我也尝试使用 CGImageRef 获取 NSData 对象,但这也不起作用。
  • 你真正想做什么?
  • iOS 是否允许您访问存储在照片库中的确切图像文件?如果它给你的第一件事已经是某种图像表示,那么你可能不走运,因为谁知道到那时它可能已经完成了哪些具体处理。您可以在 iOS 设备之间进行比较的原因是,无论它在两个设备上做什么处理都是相同的。然而,OS X 上的图像没有应用这样的处理。

标签: ios objective-c uiimage nsimage nsimagerep


【解决方案1】:

我最终确实找到了一种方法来做我想做的事。 ALAssetRepresentation 类的getBytes:fromOffset:length:error: 方法可用于获取NSData 对象,该对象与OS X 中的[NSData dataWithContentsOfURL:fileURL] 相同。请注意,无法从UIImage 执行此操作,因为UIImage 会对图像进行一些处理。以下是请求的函数的外观。

//In iOS
-(NSData *) getDataFromALAsset:(ALAsset*)asset {
    ALAssetRepresentation *rep = [asset defaultRepresentation];
    Byte *buffer = (Byte*)malloc(rep.size);
    NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
    NSData *assetData = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
    return assetData;
}

//In OS X
-(NSData *) getDataFromFileAtURL:(NSURL*)url
{
    return [NSData dataWithContentsOfURL:url];
}

【讨论】:

    最近更新 更多