CGImageRef getRowBytes возвращаемое значение больше чем (ширина * каналы)

Я пытаюсь преобразовать CGImageRef в OpenCV cv :: Mat.

Все отлично работает с 4-канальными изображениями, но для изображений в градациях серого происходит сбой, потому что функция GetRowBytes CGImageRef возвращает значение, превышающее значение mat.step [0] (равное ширине изображения).

Например, у меня есть CGImageRef градаций серого шириной 500 пикселей, а функция CGImageGetBytesPerRow возвращает 512.

Почему он возвращает это значение? И как мне правильно создать мой cv :: Mat?

  - (cv::Mat) CVGrayscaleMatWithCGImage:(CGImageRef)image
{
// NSLog(@"%zu", CGImageGetBytesPerRow(image)); -> return 512
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGFloat cols = CGImageGetWidth(image);
CGFloat rows = CGImageGetHeight(image);
cv::Mat cvMat = cv::Mat(rows, cols, CV_8UC1); // 8 bits per component, 1 channel

CGContextRef contextRef = CGBitmapContextCreate(cvMat.data,
cols,
rows,
8,
cvMat.step[0], // Bytes per row -> return 500
colorSpace,
kCGImageAlphaNone |
kCGBitmapByteOrderDefault);

CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image);
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace);

return cvMat;

}

0

Решение

Я наконец получил это на работу. Количество байтов в строке должно быть кратным 16.

Вот код:

- (cv::Mat) CVGrayscaleMatWithCGImage:(CGImageRef)image
{

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGFloat cols = CGImageGetWidth(image);
CGFloat rows = CGImageGetHeight(image);
cv::Mat cvMat = cv::Mat(rows, cols, CV_8UC1); // 8 bits per component, 1 channel

unsigned long rowBytes = cvMat.step[0];
if (rowBytes % 16) {
rowBytes = ((rowBytes / 16) + 1) * 16;
}

CGContextRef contextRef = CGBitmapContextCreate(cvMat.data,
cols,
rows,
8,
rowBytes,
colorSpace,
kCGImageAlphaNone |
kCGBitmapByteOrderDefault);

CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image);
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace);

return cvMat;

}
0

Другие решения