Как "bytesPerRow" рассчитывается из NSBitmapImageRep

Я хотел бы понять, как вычисляется "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 ответ

Решение

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

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

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

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

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

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

Другие вопросы по тегам