【问题标题】:How "bytesPerRow" is calculated from an NSBitmapImageRep如何从 NSBitmapImageRep 计算“bytesPerRow”
【发布时间】:2012-02-05 11:06:04
【问题描述】:

我想了解在构建 NSBitmapImageRep 时如何计算“bytesPerRow”(在我的例子中,是将浮点数组映射到灰度位图)。

澄清这个细节将有助于我理解内存是如何从浮点数组映射到字节数组(0-255,无符号字符;这些数组都没有显示在下面的代码中)。

Apple 文档说,这个数字是“根据图像的宽度、每个样本的位数,如果数据采用网格配置,则计算每个像素的样本数”。

我在遵循这个“计算”时遇到了麻烦,所以我设置了一个简单的循环来凭经验找到结果。以下代码运行良好:

int Ny = 1; // Ny is arbitrary, note that BytesPerPlane is calculated as we  would expect = Ny*BytesPerRow;
for (int Nx = 0; Nx<320; Nx+=64) {
    // greyscale image representation:
    NSBitmapImageRep *dataBitMapRep = [[NSBitmapImageRep alloc]
       initWithBitmapDataPlanes: nil // allocate the pixel buffer for us
       pixelsWide: Nx 
       pixelsHigh: Ny
       bitsPerSample: 8
       samplesPerPixel: 1  
       hasAlpha: NO
       isPlanar: NO 
       colorSpaceName: NSCalibratedWhiteColorSpace // 0 = black, 1 = white
       bytesPerRow: 0  // 0 means "you figure it out"
       bitsPerPixel: 8]; // bitsPerSample must agree with samplesPerPixel
    long rowBytes = [dataBitMapRep bytesPerRow];
    printf("Nx = %d; bytes per row = %lu \n",Nx, rowBytes);
}

并产生结果:

Nx = 0; bytes per row = 0 
Nx = 64; bytes per row = 64 
Nx = 128; bytes per row = 128 
Nx = 192; bytes per row = 192 
Nx = 256; bytes per row = 256 

所以我们看到字节/行以 64 字节增量跳跃,即使 Nx 一直递增 1 到 320(我没有显示所有这些 Nx 值)。另请注意,对于本次讨论,Nx = 320(最大值)是任意的。

那么从为字节数组分配和映射内存的角度来看,“每行字节数”是如何从第一原理计算出来的呢?上面的结果是否可以使来自单个扫描线的数据在“字”长度边界(我的 MacBook Pro 上为 64 位)上对齐?

感谢您提供任何见解,无法想象这是如何工作的。

【问题讨论】:

  • 注意不要将 64 bytes 与 64 bits 混淆。
  • 是的,谢谢,我似乎经常这样做。

标签: cocoa appkit nsbitmapimagerep


【解决方案1】:

bytesPerRow: 传递 0 意味着比您在评论中所说的要多。来自文档:

如果您传入rowBytes 值0,则分配的位图数据可能会被填充到长字或更大的边界以提高性能。 … 传入一个非零值允许您指定精确的行前移。

所以您会看到它一次增加 64 个字节,因为这就是 AppKit 决定对其进行四舍五入的方式。

每行字节的最低要求要简单得多。它是每像素的字节数乘以每行的像素数。就是这样。

对于由浮点数支持的位图图像表示,您将传递 sizeof(float) * 8bitsPerSample,并且每像素字节数将是 sizeof(float) * samplesPerPixel。每行字节数由此而来;您将每像素字节数乘以像素宽度。

同样,如果它由无符号字节支持,您将通过 sizeof(unsigned char) * 8bitsPerSample,并且每像素字节数将是 sizeof(unsigned char) * samplesPerPixel

【讨论】:

  • 嗨,彼得,感谢您的澄清 cmets。对于我的应用程序,我使用后者(由无符号字节支持),因此 bitsPerSample = 1*8 = 8 和 bytesPerPixel = 1*8 = 8,就像我上面的代码一样,效果很好(图像显示正常)。我只是无法从第一原则计算 AppKit 如何达到 BytesPerRow 的值,因此不能说我理解它。我得到 BytesPerRow = Nx*bytesPerPixel = 320*8 = 2560,与 Appkit (= 320) 相比似乎很大。所以我试图弄清楚 320 是从哪里来的,而且,使用 2560 有什么好处吗?再次感谢。
  • @BruceDean:你的倍数比你应该的多 8 倍。给定每个样本 8 位(= 1 个字节)和每个像素 1 个样本,即每个像素 1 个字节,而不是 8 个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 2011-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多