如何创建NSImage的8位,4位和1位表示

时间:2013-08-02 11:32:46

标签: macos cocoa nsimage nsbitmapimagerep

我用以下代码创建了32位NSImage。

 NSBitmapImageRep *sourceRep = [[NSBitmapImageRep alloc] initWithData: imageData];

        // create a new bitmap representation scaled down

            NSBitmapImageRep *newRep = 
                [[NSBitmapImageRep alloc] 
                    initWithBitmapDataPlanes: NULL
                    pixelsWide: imageSize
                    pixelsHigh: imageSize
                    bitsPerSample: 8
                    samplesPerPixel: 4
                    hasAlpha: YES
                    isPlanar: NO
                    colorSpaceName: NSCalibratedRGBColorSpace
                    bytesPerRow: 0
                    bitsPerPixel: 0];

            // save the graphics context, create a bitmap context and set it as current
            [NSGraphicsContext saveGraphicsState] ;
            NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep: newRep];
            [NSGraphicsContext setCurrentContext: context] ;

            // draw the bitmap image representation in it and restore the context
            [sourceRep drawInRect: NSMakeRect(0.0f, 0.0f, imageSize, imageSize)] ;
            [NSGraphicsContext restoreGraphicsState] ;

            // set the size of the new bitmap representation
            [newRep setSize: NSMakeSize(imageSize,imageSize)] ;

            NSDictionary *imageProps2 = [NSDictionary dictionaryWithObjectsAndKeys:
                                         [NSNumber numberWithFloat:1.0], kCGImageDestinationLossyCompressionQuality,
                                         nil];
            imageData = [newRep representationUsingType: NSPNGFileType properties: imageProps2];
  NSImage *bitImage  = [[NSImage alloc]initWithData:imageData];

现在我需要创建8位(256色),4位(16色),1位(黑白)NSBitmapImageRep表示。我现在想做什么?

3 个答案:

答案 0 :(得分:3)

不幸的是,Cocoa似乎不支持对调色板图像进行操作。

我一直trying that before,我的结论是PNG不可能。 NSGIFFileType是一个硬编码的例外,图形上下文比位图表示even more limited(例如RGBA仅支持预乘alpha)。

要解决此问题,我convert NSBitmapImageRep to raw RGBA bitmap,使用libimagequant to remap it to a palette然后libpnglodepng撰写PNG文件。

答案 1 :(得分:2)

可悲的是,我相信你不能使用核心图形。图形上下文不支持任何位数。

文档的表格为supported pixel formats

显然,Carbon已经(有?)支持它,正如这里所提到的那样,他们也哀叹Cocoa缺乏对它的支持:

  

事实证明,基本上Cocoa / Quartz不支持将图像下采样为8位颜色。它支持绘制它们,它支持上采样,但不支持其他方式。我想这是Apple的一个故意设计,它将索引图像作为标准图形数据类型 - 毕竟,32位颜色更简单,对吧?嗯,它是,但仍然有用于8位。那么该怎么办?一种可能性是使用Carbon,因为General / QuickDraw的General / GWorld确实支持下采样等。

来自this thread

答案 2 :(得分:0)

那么评论可能太长了......

看起来这似乎是不可能的...所有可可的绘图部分似乎都想要使用24位颜色空间...我能够制作一个8位NSBitmapImageRep但它是灰度。

所以我想我们必须在这里找出为什么。如果您希望能够使用由某些类型的表示支持的NSImages,我认为这是不可能的。

如果你想天真地下采样(改为最接近任何像素的24/32位值),这是非常可能的;这将是给出8位图像的外观。

如果您希望能够以良好的抖动/索引颜色编写这些文件,那么我认为最好的选择是写入支持您想要的图像格式(例如写入256色GIF)。 / p>

如果您想出于某种原因自行进行下采样,那么手头有两个问题:

  1. 托盘或CLUT选择。
  2. 抖动。
  3. 如果您不想使用索引颜色,只想将8位分解为3-3-2 RGB,这样稍微容易一些,但结果比索引颜色差得多。

    4位有点诡计,因为我甚至不知道4位色彩的良好历史使用。

    我使用索引颜色来显示我曾做过的一个小项目中的mandelbrot设置的转义时间......

    我刚刚确认它不再起作用了(旧的固定渲染管道OpenGL)。

    但基本上对于视图,您可以使用glPixelMapuiv将索引颜色映射到字节值,然后使用glDrawPixels显示字节缓冲区;

    所以......我想如果你评论并说出你为什么要做你正在做的事情,我们可以提供帮助。