图像尺寸与尺寸不同

时间:2013-10-03 08:57:28

标签: objective-c image macos nsdata nsimage

我使用Macintosh .tiff扫描了一张图片(millions of colors),这意味着24 bits per pixel。我获得的扫描图像具有以下属性:size = 330KB和维度= 348 * 580 pixels。由于每像素有24位,因此大小实际应为348 * 580 * 3 = 605KB

有什么不正确的吗?我还使用此代码从扫描图像的URL中提取图像原始数据:

NSString * urlName = [url path];
NSImage *image = [[NSImage alloc] initWithContentsOfFile:urlName];
NSData *imageData = [image TIFFRepresentation];
CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)CFBridgingRetain(imageData), NULL);
CGImageRef imageRef =  CGImageSourceCreateImageAtIndex(source, 0, NULL);
NSUInteger numberOfBitsPerPixel = CGImageGetBitsPerPixel(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
NSUInteger width = CGImageGetWidth(imageRef);

从这段代码中,我得到的信息与图像中每个像素的宽度,高度和位数相同。

基本上,我必须使用此图像的信息并以其他形式将其复制到其他位置,因此如果我无法获得正确的信息,则最终产品不可重现。这可能有什么问题?

P.S。:如果需要一些其他信息来回答这个问题,那么我很乐意提供这个。

2 个答案:

答案 0 :(得分:1)

最常见的图片格式jpgpngtiff压缩图片,这就是文件大小低于每个像素w*h*bits的原因。

JPEG使用有损压缩,PNG使用无损压缩,TIFF可以解压缩,使用有损压缩或无损压缩。

有损压缩意味着压缩过程中会丢失一些颜色信息,因此图像看起来与压缩前的图像不完全相同,但您可以使用有损压缩进一步减小文件大小。

无损压缩的一个例子是run length encoding,这基本上意味着如果你有几个具有相同颜色的连续像素,你只需要说N像素值为(R,G,B)而不是说(R,G,B),(R,G,B),...,(R,G,B)

答案 1 :(得分:1)

前几天你问过(差不多)同样的问题但没有得到答案。我没有时间回答你的问题,但现在是时候写一些评论了。

首先,您的问题和(大多数)答案和评论显示对NSImageNSImageRep和存储在文件系统中的图像存在很大误解。

存储在文件系统中的图像是一个复杂的数据结构,它不仅包含图像的所有像素(如果是光栅图像),还包含大量元数据:注释,某些日期,有关相机的信息,缩略图图像和所有这些有时以不同的格式:exif,photoshop,xml等。所以你不能假设文件的大小与计算机中的图像有关,要在屏幕上显示或要求一些特殊的属性。要获得这些数据以供进一步使用,您可以这样做:

NSData *imgData = [NSData dataWithContentsOfURL:url];

NSData *imgData = [NSData dataWithContentsOfFile:[url path]];

或者您直接将图像作为NSImage的对象加载:

NSImage *image = [[NSImage alloc] initWithContentsOfURL:url];  // similar methods:see the docs

而且,如果您现在认为这是转换为Cocoa结构的文件图像数据,那么您就错了。 NSImage类的对象不是图像,它只是零,一个或多个图像表示的容器。 Gif,jpg,png图像总是只有一个表示,tiff可能有一个以上,icns有大约5或6个图像表示。

现在我们想要一些关于图像表示的信息:

for( NSUInteger i=0; i<[[image representations] count]; i++ ){
   // let us assume we have an NSBitmapImagedRep
   NSBitmapImageRep *rep = [[image representations] objectAtIndex:i];
   // get informations about this rep
   NSUInteger pixelX = [rep pixelsWide];
   NSUInteger pixelY = [rep pixelsHigh];
   CGFloat sizeX = [rep size].width;
   CGFloat sizeY = [rep size].height;
   CGFloat resolutionX = 72.0*pixelX/sizeX;
   CGFloat resolutionY = 72.0*pixelY/sizeY;

   // test if there are padding bits per pixel
   if( [rep bitsPerSample]>=8 ){
       NSInteger paddingBits = [rep bitsPerPixel] - [rep bitsPerSample]*[rep samplesPerPixel];

   // test if there are padding bytes per row
   NSInteger paddingBytes = [rep bytesPerRow] - ([rep bitsPerPixel]*[rep pixelsWide]+7)/8;

   NSUInteger bitmapSize =  [rep bytesPerRow] * [rep pixelsHigh];
}

另一句话:你说:

  

我用Macintosh扫描了数百万种颜色的图像(.tiff)   表示每像素24位。

不,不一定如此。如果一个像素只有三个组件,由于某些优化规则,它不仅可以使用24个,有时也可以使用32位。问代表。它会告诉你真相。并要求bitmsapFormat! (文档中的详细信息)。

最后:你不需要使用CG功能。 NSImage和NSImageRep可以做到这一切。