通过NSData将NSImage对象保存到文件 - 丢失信息

时间:2013-11-06 12:21:31

标签: objective-c file nsdata nsimage

您好,感谢您的阅读!我正在尝试将NSImage对象写入磁盘上的文件,但由于从原始NSImage中提取NSData对象时某些“图像属性”丢失,因此遇到了问题。

为了说明问题,我有以下代码。原始的NSImage对象被称为'image',我将其传递给imageDump(最后输出),然后我从中提取NSData对象,以便将其写入文件,但这样做似乎删除了一些图像属性。我再次调用imageDump(最后再次输出),但这次注意了一些属性是如何被删除的。例如CGImageGetBitsPerPixel:从32开始,但在第二次调用imageDump时它现在是24?

在将NSData对象写入磁盘之前提取NSData对象时,如何防止删除这些图像属性?

NSLog(@"/n PRINTING THE IMAGE PASSED TO THIS METHOD\n");
[self imageDump:[image CGImageForProposedRect:NULL context:NULL hints:NULL]];

NSData *imageData =  [image TIFFRepresentation];
NSImage *montysImage = [[NSImage alloc ] initWithData:imageData];

NSLog(@"/n PRINTING THE IMAGE THAT WAS FIRST CONVERTED TO NSDATA AND THEN BACK\n");
[self imageDump:[montysImage CGImageForProposedRect:NULL context:NULL hints:NULL]];

-(void)imageDump:(CGImageRef)cgimage  {


    size_t width  = CGImageGetWidth(cgimage);
    size_t height = CGImageGetHeight(cgimage);

    size_t bpr = CGImageGetBytesPerRow(cgimage);
    size_t bpp = CGImageGetBitsPerPixel(cgimage);
    size_t bpc = CGImageGetBitsPerComponent(cgimage);
    size_t bytes_per_pixel = bpp / bpc;

    CGBitmapInfo info = CGImageGetBitmapInfo(cgimage);

    NSString *file = @"file";

    NSLog(
          @"\n"
          "===== %@ =====\n"
          "CGImageGetHeight: %d\n"
          "CGImageGetWidth:  %d\n"
          "CGImageGetColorSpace: %@\n"
          "CGImageGetBitsPerPixel:     %d\n"
          "CGImageGetBitsPerComponent: %d\n"
          "CGImageGetBytesPerRow:      %d\n"
          "CGImageGetBitmapInfo: 0x%.8X\n"
          "  kCGBitmapAlphaInfoMask     = %s\n"
          "  kCGBitmapFloatComponents   = %s\n"
          "  kCGBitmapByteOrderMask     = %s\n"
          "  kCGBitmapByteOrderDefault  = %s\n"
          "  kCGBitmapByteOrder16Little = %s\n"
          "  kCGBitmapByteOrder32Little = %s\n"
          "  kCGBitmapByteOrder16Big    = %s\n"
          "  kCGBitmapByteOrder32Big    = %s\n",
          file,
          (int)width,
          (int)height,
          CGImageGetColorSpace(cgimage),
          (int)bpp,
          (int)bpc,
          (int)bpr,
          (unsigned)info,
          (info & kCGBitmapAlphaInfoMask)     ? "YES" : "NO",
          (info & kCGBitmapFloatComponents)   ? "YES" : "NO",
          (info & kCGBitmapByteOrderMask)     ? "YES" : "NO",
          (info & kCGBitmapByteOrderDefault)  ? "YES" : "NO",
          (info & kCGBitmapByteOrder16Little) ? "YES" : "NO",
          (info & kCGBitmapByteOrder32Little) ? "YES" : "NO",
          (info & kCGBitmapByteOrder16Big)    ? "YES" : "NO",
          (info & kCGBitmapByteOrder32Big)    ? "YES" : "NO"  );



    CGDataProviderRef provider = CGImageGetDataProvider(cgimage);
    NSData* data = (__bridge id)CGDataProviderCopyData(provider);
    //[data autorelease];
    const uint8_t* bytes = [data bytes];

    printf("Pixel Data:\n");
    for(size_t row = 0; row < height; row++)
    {
        for(size_t col = 0; col < width; col++)
        {
            const uint8_t* pixel = &bytes[row * bpr + col * bytes_per_pixel];

            printf("(");
            for(size_t x = 0; x < 3; x++) // 3 WAS -> bytes_per_pixel - changed to remove the alpha component.
            {
                printf("%.2X", pixel[x]);
                if( x < 3 - 1 ) // 3 WAS -> bytes_per_pixel - changed to remove the alpha component.
                    printf(",");
            }

            printf(")");
            if( col < width - 1 )
                printf(", ");
        }

        printf("\n");
    }
}

控制台输出:

2013-11-06 22:52:01.082 LibraryBuilder[20792:303] /n PRINTING THE IMAGE PASSED TO THIS METHOD
2013-11-06 22:52:01.082 LibraryBuilder[20792:303] 
===== file =====
CGImageGetHeight: 6
CGImageGetWidth:  7
CGImageGetColorSpace: <CGColorSpace 0x60000003b840> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; Color LCD)
CGImageGetBitsPerPixel:     32
CGImageGetBitsPerComponent: 8
CGImageGetBytesPerRow:      64
CGImageGetBitmapInfo: 0x00002006
  kCGBitmapAlphaInfoMask     = YES
  kCGBitmapFloatComponents   = NO
  kCGBitmapByteOrderMask     = YES
  kCGBitmapByteOrderDefault  = NO
  kCGBitmapByteOrder16Little = NO
  kCGBitmapByteOrder32Little = YES
  kCGBitmapByteOrder16Big    = YES
  kCGBitmapByteOrder32Big    = NO
Pixel Data:
(F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (EA,D9,C2)
(F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7)
(F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7)
(F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7)
(B3,B3,B3), (B3,B3,B3), (B3,B3,B3), (B3,B3,B3), (B3,B3,B3), (B3,B3,B3)
(F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7)
(F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7)

2013-11-06 22:52:01.122 LibraryBuilder[20792:303] /n PRINTING THE IMAGE THAT WAS FIRST CONVERTED TO NSDATA AND THEN BACK
2013-11-06 22:52:01.122 LibraryBuilder[20792:303] 
===== file =====
CGImageGetHeight: 6
CGImageGetWidth:  7
CGImageGetColorSpace: <CGColorSpace 0x618000032f40> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; Color LCD)
CGImageGetBitsPerPixel:     24
CGImageGetBitsPerComponent: 8
CGImageGetBytesPerRow:      18
CGImageGetBitmapInfo: 0x00000000
  kCGBitmapAlphaInfoMask     = NO
  kCGBitmapFloatComponents   = NO
  kCGBitmapByteOrderMask     = NO
  kCGBitmapByteOrderDefault  = NO
  kCGBitmapByteOrder16Little = NO
  kCGBitmapByteOrder32Little = NO
  kCGBitmapByteOrder16Big    = NO
  kCGBitmapByteOrder32Big    = NO
Pixel Data:
(F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (C2,D9,EA)
(F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7)
(F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7)
(F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7)
(B3,B3,B3), (B3,B3,B3), (B3,B3,B3), (B3,B3,B3), (B3,B3,B3), (B3,B3,B3)
(F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7)
(F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7), (F7,F7,F7)

1 个答案:

答案 0 :(得分:0)

目前尚不清楚任何数据是否真的丢失了。有很多方法可以表示完全相同的图像,并且您正在做一堆扭曲来转储可能修改其格式的数据(不改变它的绘制方式)。比如,如果图像存储BRG或RGB或BGR并不重要,但这些将修改转储的外观。

在您的实例中,如果您的原始图像具有透明度通道但它始终是100%不透明的,则-TIFFRepresentation调用可能(合理地)决定不写出透明度通道,因此当您在其中读取它时走了但这并没有改变图像的绘制方式。

您不会在转储中显示Alpha通道,因此不清楚您是否丢失了任何数据,但其他一切看起来都很正常。