0

我想了解在构建 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 位)上对齐?

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

4

1 回答 1

2

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

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

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

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

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

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

于 2012-02-05T03:06:04.797 回答