0

我尝试使用 vImageConvert_RGB888toPlanar8 从图像中提取所有 3 个通道,然后将它们与 vImageConvert_Planar8toRGB888 一起放回原处,但图像完全搞砸了。这是为什么?

vImage_Buffer blueBuffer;
blueBuffer.data = (void*)blueImageData.bytes;
blueBuffer.width = size.width;
blueBuffer.height = size.height;
blueBuffer.rowBytes = [blueImageData length]/size.height;

vImage_Buffer rBuffer;
rBuffer.width = size.width;
rBuffer.height = size.height;
rBuffer.rowBytes = size.width;
void *rPixelBuffer = malloc(size.width * size.height);
if(rPixelBuffer == NULL)
{
    NSLog(@"No pixelbuffer");
}
rBuffer.data = rPixelBuffer;

vImage_Buffer gBuffer;
gBuffer.width = size.width;
gBuffer.height = size.height;
gBuffer.rowBytes = size.width;
void *gPixelBuffer = malloc(size.width * size.height);
if(gPixelBuffer == NULL)
{
    NSLog(@"No pixelbuffer");
}
gBuffer.data = gPixelBuffer;

vImage_Buffer bBuffer;
bBuffer.width = size.width;
bBuffer.height = size.height;
bBuffer.rowBytes = size.width;
void *bPixelBuffer = malloc(size.width * size.height);
if(bPixelBuffer == NULL)
{
    NSLog(@"No pixelbuffer");
}
bBuffer.data = bPixelBuffer;

vImageConvert_RGB888toPlanar8(&blueBuffer, &rBuffer, &gBuffer, &bBuffer, kvImageNoFlags);

size_t destinationImageBytesLength = size.width*size.height*3;
const void* destinationImageBytes = valloc(destinationImageBytesLength);
NSData* destinationImageData = [[NSData alloc] initWithBytes:destinationImageBytes length:destinationImageBytesLength];
vImage_Buffer destinationBuffer;
destinationBuffer.data = (void*)destinationImageData.bytes;
destinationBuffer.width = size.width;
destinationBuffer.height = size.height;
destinationBuffer.rowBytes = [destinationImageData length]/size.height;

vImage_Error result = vImageConvert_Planar8toRGB888(&rBuffer, &gBuffer, &bBuffer, &destinationBuffer, 0);
NSImage* image = nil;
if(result == kvImageNoError)
{
    //TODO: If you need color matching, use an appropriate colorspace here
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef)(destinationImageData));
    CGImageRef finalImageRef = CGImageCreate(size.width, size.height, 8, 24, destinationBuffer.rowBytes, colorSpace, kCGBitmapByteOrder32Big|kCGImageAlphaNone, dataProvider, NULL, NO, kCGRenderingIntentDefault);
    CGColorSpaceRelease(colorSpace);
    CGDataProviderRelease(dataProvider);
    image = [[NSImage alloc] initWithCGImage:finalImageRef size:NSMakeSize(size.width, size.height)];
    CGImageRelease(finalImageRef);
}
free((void*)destinationImageBytes);
return image;
4

3 回答 3

1

使用vImage意味着仅使用像素。所以你绝不能使用图像(或 imageRep)的大小,你只能使用像素宽和像素高。全部替换size.widthpixelsWide,全部size.height替换为pixelsHigh。Apple 有 vImage 的示例代码,它们使用大小值!不要相信他们!并非所有 Apple 示例代码都是正确的。

图像或 imageRep 的大小决定了应在屏幕(或打印机)上绘制多大的图像。尺寸值具有长度的尺寸,单位是米、厘米、英寸或(如在 Cocoa 中)1/72 英寸又名点。它们表示为浮点值。

PixelsWide 和 pixelHigh 没有维度和单位(它们只是数字)并且表示为 int 值。

您的代码中可能存在更多错误,但第一步应该是替换所有大小值。

于 2013-07-25T11:31:03.417 回答
1

严格来说,您需要 kCGBitmapByteOrderDefault 而不是 kCGBitmapByteOrder32Big。32Big 对于 24 位像素格式没有多大意义。

这似乎是一个薄弱环节:

destinationBuffer.rowBytes = [destinationImageData length]/size.height;

检查它是否是正确的数字。

输出图片将有助于诊断问题。还要检查控制台,看看 CG 是否给你任何喷射。您是否尝试使用 vImageCreateCGImageFromBuffer() 和 kvImagePrintDiagnosticsToConsole 来查看它是否有什么要说的?

于 2014-08-02T17:47:53.337 回答
0

使用 vImage 意味着仅使用像素。所以你绝不能使用图像(或 imageRep)的大小,你只能使用像素宽和像素高。将所有 size.width 替换为 pixelWide,将所有 size.height 替换为 pixelHigh。Apple 有 vImage 的示例代码,它们使用大小值!不要相信他们!并非所有 Apple 示例代码都是正确的。

图像或 imageRep 的大小决定了应在屏幕(或打印机)上绘制多大的图像。尺寸值具有长度的尺寸,单位是米、厘米、英寸或(如在 Cocoa 中)1/72 英寸又名点。它们表示为浮点值。

PixelsWide 和 pixelHigh 没有维度和单位(它们只是数字)并且表示为 int 值。

您的代码中可能存在更多错误,但第一步应该是替换所有大小值。

于 2013-08-12T12:11:00.350 回答