CGImageRef getRowBytes返回值大于(width * channels)

时间:2014-04-29 09:37:10

标签: c++ objective-c macos opencv cgimage

我试图将CGImageRef转换为OpenCV cv :: Mat。

4通道图像的一切正常,但对于灰度图像,它会崩溃,因为CGImageRef GetRowBytes函数返回的值大于mat.step [0]值(等于图像的宽度)。

例如,我有一个500像素宽的灰度CGImageRef,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;

}

1 个答案:

答案 0 :(得分: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;

}