NSImage和UIImage给出不同的NSData表示

3

场景: 我在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具有不同的坐标系)。


2
你正在对图像执行多次 JPEG 压缩,因此位数不可避免地会发生变化。 - NSAdam
@NSAdam,你能提供避免这种情况的建议吗?对于解决实际问题有什么见解吗? - Tayyab
我想根据图像内容获取某种哈希值以检测完全重复的图像。使用UIImageJPEGRepresentation的sha512哈希可跨多个iOS设备工作(即通过哈希检测到重复项),但在其他平台(如OS X)上失败。 - Tayyab
1
iOS是否允许您访问存储在照片库中的确切图像文件?如果它给您的第一件事已经是某种图像表示,那么您可能会很失望,因为谁知道它在那个时候进行了什么特定的处理。您可以跨iOS设备进行比较的原因是它所做的任何处理在两个设备上都是相同的。然而,在OS X上的图像没有应用此类处理。 - NSAdam
iOS 不会给我一个指向精确文件的引用。但是,我可以获得一个 CGImageRef - (CGImageRef)CGImageWithOptions:(NSDictionary *)options,根据文件说明,这是获取资源的 CGImage 表示形式的一种便利方式。该方法返回可用的最大、最佳表示形式,未经任何调整。 - Tayyab
显示剩余2条评论
1个回答

3

我最终找到了想要的方法。 ALAssetRepresentation 类的 getBytes:fromOffset:length:error: 方法可用于获取与 OS X 中的 [NSData dataWithContentsOfURL:fileURL] 相同的 NSData 对象。请注意,从 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];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接