我正在尝试将Planar YpCbCr转换为RGBA,但是它在错误kvImageRoiLargerThanInputBuffer方面失败了。我尝试了两种不同的方法。这是一些代码片段。注意'thumbnail_buffers + 1‘和'thumbnail_buffers + 2’的宽度和高度是'thumbnail_buffers + 0‘的一半,因为我处理的是4:2:0,并且(1/2)*(1/2)每个颜色样本的数量都是luma样本。尽管我要求一个解释(kvImagePrintDiagnosticsToConsole),但这还是失败了。
error = vImageConvert_YpCbCrToARGB_GenerateConversion(
kvImage_YpCbCrToARGBMatrix_ITU_R_709_2,
&fullrange_8bit_clamped_to_fullrange,
&convertInfo,
kvImage420Yp8_Cb8_Cr8, kvImageARGB8888,
kvImagePrintDiagnosticsToConsole);
uint8_t BGRA8888_permuteMap[4] = {3, 2, 1, 0};
uint8_t alpha = 255;
vImage_Buffer dest;
error = vImageConvert_420Yp8_Cb8_Cr8ToARGB8888(
thumbnail_buffers + 0, thumbnail_buffers + 1, thumbnail_buffers + 2,
&dest,
&convertInfo, BGRA8888_permuteMap, alpha,
kvImagePrintDiagnosticsToConsole //I don't think this flag works here
);因此,我再次尝试使用vImageConvert_AnyToAny:
vImage_CGImageFormat cg_BGRA8888_format = {
.bitsPerComponent = 8,
.bitsPerPixel = 32,
.colorSpace = baseColorspace,
.bitmapInfo =
kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little,
.version = 0,
.decode = (CGFloat*)0,
.renderingIntent = kCGRenderingIntentDefault
};
vImageCVImageFormatRef vformat = vImageCVImageFormat_Create(
kCVPixelFormatType_420YpCbCr8Planar,
kvImage_ARGBToYpCbCrMatrix_ITU_R_709_2,
kCVImageBufferChromaLocation_Center,
baseColorspace,
0);
vImageConverterRef icref = vImageConverter_CreateForCVToCGImageFormat(
vformat,
&cg_BGRA8888_format,
(CGFloat[]){0, 0, 0},
kvImagePrintDiagnosticsToConsole,
&error );
vImage_Buffer dest;
error = vImageBuffer_Init( &dest, image_height, image_width, 8, kvImagePrintDiagnosticsToConsole);
error = vImageConvert_AnyToAny( icref, thumbnail_buffers, &dest, (void*)0, kvImagePrintDiagnosticsToConsole); //kvImageGetTempBufferSize我也得到了同样的错误,但是这次我得到了输出到控制台的以下消息。
<Error>: kvImagePrintDiagnosticsToConsole: vImageConvert_AnyToAny: srcs[1].height must be >= dests[0].height但这对我来说没有任何意义。当我有4:2:0的数据时,我的Cb高度怎么能比我的Yp高(和我的最RGB的身高一样)更高呢?(宽度也一样?)我到底做错了什么?我还将进行其他转换(4:4:4,4:2:2,等等),因此非常希望对这些API进行任何澄清。此外,对于这些转换,我的位置应该是什么?上面我使用kCVImageBufferChromaLocation_Center。对吗?
一些新的信息:发布后,我看到了一个明显的错误,但修复它没有帮助。注意,在上面的vImageConvert_AnyToAny中,我只使用图像宽度而不是4*宽度初始化了目标缓冲区,以便为RGBA腾出空间。那一定是问题所在,对吧?不是的。
进一步注意,在vImageConvert_*的情况下,我根本没有初始化目标缓冲区。把这个也修好了,也没什么用。
到目前为止,我已经尝试了六种不同的转换方式--选择一种从(vImageConvert_* \ vImageConvert_AnyToAny)中选择一种,从其中选择一种--每次提供适当数量的输入缓冲区--仔细检查缓冲区是否考虑到每个平面上每个像素的样本数。每次我得到:
<Error>: kvImagePrintDiagnosticsToConsole: vImageConvert_AnyToAny: srcs[0].width must be >= dests[0].width这对我来说毫无意义。如果我的luma飞机是100宽,我的RGBA缓冲区应该是400宽。请提供从YCC到RGBA的任何指导或工作代码将不胜感激。
发布于 2020-10-13 04:42:51
好吧,我想出来了--部分是用户错误,一部分是苹果的错误。我在想vImage_Buffer的宽度和高度是错误的。例如,我指定为4 * image_width的输出缓冲区,以及每像素8位,而它应该只是image_width和每像素32位--内存数量相同,但给API发送了错误的信息。我想,这一行上的文字'8‘使我无法记住那个插槽是什么。我一定学过很多次了--说出你的神奇数字吧。
不管怎么说,现在是窃听器部分。使输入和输出缓冲区正确的宽度,高度,像素深度固定所有对低级别vImageConvert_420Yp8_Cb8_Cr8ToARGB8888和朋友的调用。例如,在平面YCC情况下,您的Cb和Cr缓冲器的宽度和高度自然只有Yp平面的一半。然而,在vImageConvert_AnyToAny的情况下,这些缓冲区导致呼叫失败,说一些愚蠢的事情,比如我需要我的Cb平面具有与我的Yp平面相同的维度,即使是4:2:0。这似乎是苹果在调用底层代码之前所做的一些预谋中的一个缺陷。
我通过简单地制作太大的输入缓冲区,并且只在左上象限中填充Cb和Cr数据来解决vImageConvert_AnyToAny错误。这些数据是在转换过程中发现的。我用vImageBuffer_Init()做了这些太大的缓冲,苹果在这里分配了浪费的太大的malloc。我并没有试着手工制作vImage_Buffer--按我所需的大小和内存分配。这可能会奏效,或者苹果会爬到杂草里,相信它的宽度和高度。如果你手工制作rowBytes,你最好说出关于rowBytes的真相。
我要先给这个答案留一段时间,然后再给它打上记号,希望苹果公司的人能看到这个问题,修复这个错误,或许还会得到灵感,来改进我们这些蹒跚而行的人的文档。
https://stackoverflow.com/questions/64324316
复制相似问题