Как "bytesPerRow" рассчитывается из NSBitmapImageRep - PullRequest
0 голосов
/ 05 февраля 2012

Я хотел бы понять, как вычисляется «bytesPerRow» при создании NSBitmapImageRep (в моем случае от отображения массива с плавающей точкой до растрового изображения в градациях серого).

Уточнение этой детали поможет мне понять, как отображается память из массива с плавающей точкой в ​​байтовый массив (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 (max) для этого обсуждения произвольно.

Итак, с точки зрения выделения и отображения памяти для байтового массива, как рассчитывается «число байтов на строку» из первых принципов? Является ли приведенный выше результат тем, что данные из одной строки сканирования могут быть выровнены по границе «слова» (64 бита на моем MacBook Pro)?

Спасибо за любые идеи, с трудом представляющие, как это работает.

1 Ответ

2 голосов
/ 05 февраля 2012

Проход 0 для bytesPerRow: означает больше, чем вы сказали в своем комментарии.Из документации:

Если вы передадите значение rowBytes, равное 0, выделенные данные растрового изображения могут быть дополнены так, чтобы они соответствовали длинным словам или большим границам для производительности.… Передавая ненулевое значение, вы можете указать точное продвижение строки.

Таким образом, вы видите, как оно увеличивается на 64 байта за раз, потому что именно так AppKit решил округлить его.

Минимальное требование для байтов на строку намного проще.Это байты на пиксель, количество пикселей на строку.Вот и все.

Для растрового изображения, повторяемого с плавающей точкой, вы передадите sizeof(float) * 8 для bitsPerSample, а число байтов на пиксель будет sizeof(float) * samplesPerPixel.Байт на строку следует из этого;Вы умножаете число байтов на пиксель на ширину в пикселях.

Аналогично, если оно поддерживается байтами без знака, вы передадите sizeof(unsigned char) * 8 для bitsPerSample, а число байтов на пиксель будет * 1020.*.

...