【问题标题】:How to create NSBitmapImageRep from scratch?如何从头开始创建 NSBitmapImageRep?
【发布时间】:2014-08-05 00:48:24
【问题描述】:

首先:我想用NSBezierPath在我的应用程序中绘制一些简单的按钮图,所以我想我应该创建一个NSBitmapImageRep,获取CGImage,创建一个@ 987654324@ ,然后在按钮上调用 setImage:。如果我错了,请纠正我。

所以我去看看如何创建一个NSBitmapImage 并发现了这个: **initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bitmapFormat:bytesPerRow:bitsPerPixel:**

哇哦。

请记住,我正在寻找类似于 initWithSize: 的东西,我应该为这些值添加什么?

【问题讨论】:

    标签: image cocoa nsbezierpath nsbitmapimagerep


    【解决方案1】:

    您无需为数据平面分配空间。下面是创建一个带有 alpha 组件的空 32 位 NSBitmapImageRep 的调用。

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

    【讨论】:

      【解决方案2】:

      任何特殊原因,您不是简单地创建一个新的NSImage 并通过使用焦点锁定将绘图代码括起来来绘制它

      NSImage* anImage = [[NSImage alloc] initWithSize:NSMakeSize(100.0,  100.0)];
      [anImage lockFocus];
      
      // Do your drawing here...
      
      [anImage unlockFocus];
      

      Cocoa Drawing Guide 是你的朋友,顺便说一句)

      【讨论】:

      • 我没有意识到你可以做到这一点。我浏览了可可绘图指南,但我一定错过了。
      • @PopKernel 不客气。是的,只是创建一个没有任何特定约束的图像真的很简单
      【解决方案3】:

      The documentation 解释得很好。

      planes 参数有点混乱。它基本上是指向像素指针的指针。因此,如果您将像素放在一个名为“pixels”的变量指向的数组中,如下所示:

      unsigned char* pixels = malloc (width * height * 4); // assumes ARGB 8-bit pixels
      NSBitmapImageRep* myImageRep = [[NSBitmapImageRep alloc] initWithDataPlanes:&pixels
      ... etc...];
      

      其余参数非常简单。 pixelWidthpixelHeight 正是您所期望的。其他值都对应于您的数据的排列方式。您是否使用每通道 8 位的 ARGB 数据?还是每通道 32 位的 RGBA?

      NSDeviceRGBColorSpace 可能足以满足您对色彩空间的使用。

      isPlanar 通道应该是 NO,如果您要传入一个指向图像数据的指针。

      【讨论】:

      • 我应该提一下,我发现自己摸不着头脑的部分原因是我对位图图像术语的了解有点……点菜。例如,文档告诉我,对于 bps 参数“所有组件……每个样本都有相同的位。bps 应该是以下值之一:1、2、4、8、12 或 16。”但我不确定为每个样本提供更多位有什么好处。
      • 这是可以理解的。 (而且他们还忽略了 32 是一个有效值。)在大多数情况下,您的眼睛将无法检测到任何高于 8 的值。但是,如果您要对结果进行多次图像处理,额外的位(如果超过 8 位)可能会很有用。在您的情况下,正如您所描述的那样,8 可能就可以了。
      • 您实际上不必分配这些像素,而是为 dataPlanes 传递 NULL。我发布了一个答案,其中包含您想要的标准空 NSBitmapImageRep 的所有适当参数
      • 很公平。在我的使用中,我倾向于需要先分配缓冲区,然后使用其他方法将一些数据放入其中,例如从中创建一个 CGBitmapContext 或其他方法,然后将其转换为 NSBitmapImageRep。我也倾向于需要跟踪缓冲区,所以想手动控制它的生命周期。但你是对的,你不需要那样做。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-21
      • 2021-04-12
      • 2021-11-18
      • 2018-08-04
      • 2011-12-25
      相关资源
      最近更新 更多