10

我用以下代码创建了 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表示。我现在想做什么?

4

3 回答 3

3

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

我之前一直在尝试,我的结论是 PNG 不可能。NSGIFFileType是硬编码的例外,图形上下文比位图表示更受限制(例如,RGBA 仅支持预乘 alpha)。

为了解决这个问题,我转换NSBitmapImageRep为原始 RGBA 位图,使用libimagequant 将其重新映射到调色板,然后使用libpnglodepng写入 PNG 文件。

于 2013-12-16T02:40:36.693 回答
2

可悲的是,我相信您不能使用核心图形。图形上下文不支持只有这么几位的任何东西。

该文档有一个支持的像素格式表。

显然,Carbon 已经(有?)支持它,正如在此处引用的那样,他们还感叹 Cocoa 缺乏对它的支持:

事实证明,基本上 Cocoa/Quartz 不支持将图像下采样为 8 位颜色。它支持绘制它们,并且支持上采样,但不会反过来。我想这是 Apple 的故意设计,目的是摆脱索引图像作为标准图形数据类型 - 毕竟,32 位颜色要简单得多,对吧?嗯,确实如此,但 8 位仍有一些有用的用途。那么该怎么办?一种可能性是使用 Carbon,因为 General/QuickDraw 的 General/GWorld 确实支持下采样等。

这个线程

于 2013-12-10T07:47:46.370 回答
0

好吧,评论可能太长了...

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

所以我想我们必须弄清楚这里的原因。如果您希望能够使用由某些类型的表示支持的 NSImage,我认为这是不可能的。

如果您想天真地降低采样(更改为最接近任何像素的 24/32 位值),那是很有可能的;这将给出 8 位图像的外观。

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

如果您出于某种原因想自己进行下采样,则有两个问题:

  1. 托盘或 CLUT 选择。
  2. 抖动。

如果您不想使用索引颜色,而只想将 8 位分解为 3-3-2 RGB,这会更容易一些,但结果比索引颜色差得多。

4 位有点诡计,因为我什至不知道 4 位颜色的良好历史用途。

在我曾经做过的一个小项目中,我使用索引颜色来显示曼德布罗集的逃生时间......

我刚刚验证它不再起作用(是旧的固定渲染管道 OpenGL)。

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

所以...我想如果您发表评论并说出您为什么要尝试做您正在做的事情,我们可能会提供帮助。

于 2013-12-15T00:58:55.463 回答