簡體   English   中英

我無法讓 vImage(加速框架)將 420Yp8_Cb8_Cr8(平面)轉換為 ARGB8888

[英]I can't get vImage (Accelerate Framework) to convert 420Yp8_Cb8_Cr8 (planar) to ARGB8888

我正在嘗試將平面 YpCbCr 轉換為 RGBA,但由於錯誤 kvImageRoiLargerThanInputBuffer 而失敗。 我嘗試了兩種不同的方法。 這是一些代碼片段。 注意 'thumbnail_buffers + 1' 和 'thumbnail_buffers + 2' 的寬度和高度是 'thumbnail_buffers + 0' 的一半,因為我處理的是 4:2:0 並且有 (1/2)*(1/2) 一樣多的色度每個樣本作為亮度樣本。 這默默地失敗了(即使我要求解釋(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 高度的一半(與我的 dest RGB 高度相同)? (寬度也是如此?)我到底做錯了什么? 我還將進行其他轉換(4:4:4、4:2:2 等),因此對這些 API 的任何說明都將不勝感激。 此外,對於這些轉換,我的站點應該是什么? 上面我使用 kCVImageBufferChromaLocation_Center。 那是對的嗎?

一些新信息:自從發布此信息后,我看到了一個明顯的錯誤,但修復它並沒有幫助。 請注意,在上面的 vImageConvert_AnyToAny 情況下,我僅使用圖像寬度而不是 4*width 初始化目標緩沖區,以便為 RGBA 騰出空間。 那一定是問題吧? 不。

進一步注意,在 vImageConvert_* 的情況下,我根本沒有初始化目標緩沖區。 也修復了它,但沒有幫助。

到目前為止,我已經嘗試了六種不同的轉換方式,從 (vImageConvert_* | vImageConvert_AnyToAny) 中選擇一種,並從 (kvImage420Yp8_Cb8_Cr8 | kvImage420Yp8_CbCr8 | kvImage444CrYpCb8) 中選擇一種,提供適當數量的輸入緩沖區,每次都仔細檢查緩沖區每個平面每個像素的樣本數。 每次我得到:

<Error>: kvImagePrintDiagnosticsToConsole: vImageConvert_AnyToAny: srcs[0].width must be >= dests[0].width

這對我來說毫無意義。 如果我的亮度平面是 100 寬,我的 RGBA 緩沖區應該是 400 寬。 請從 YCC 到 RGBA 的任何指導或工作代碼將不勝感激。

好的,我想通了——部分是用戶錯誤,部分是 Apple 錯誤。 我在想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。 這似乎是 Apple 在調用執行工作的低級代碼之前完成的一些預檢中的錯誤。

我通過簡單地制作太大的輸入緩沖區並且只填充左上象限中的 Cb 和 Cr 數據來解決vImageConvert_AnyToAny錯誤。 在轉換過程中在那里發現數據就好了。 我使用vImageBuffer_Init()制作了這些太大的緩沖區,其中 Apple 分配了浪費的太大的 malloc。 我沒有嘗試手工制作vImage_Buffer的 - 謊稱大小並僅分配我需要的內存。 這可能會奏效,或者蘋果可能會因為信任寬度和高度而爬進雜草中。 如果你手工制作一個,你最好說出關於rowBytes的真相。

在將其標記為正確之前,我將保留這個答案,希望 Apple 的某個人看到這一點並修復該錯誤,並且可能會受到啟發,為我們這些絆腳石的人改進文檔。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM