2017-08-04 84 views
1

以Sylvain Ratabouil Android NDK(第2版)爲例,它從相機獲取圖像預覽並自然處理,從YUV轉換爲RGB並將顏色過濾器應用於其中。Android中換入紅色和藍色

的代碼非常簡單,在傳遞給該功能的過濾器出現問題:

public native void decode(Bitmap target, byte[] source, int filter); 

目標是一個ImageView的基準
是幀預覽數據
濾波器是濾色器

當碼是這樣的:

decode(mImageRed, data, 0xFFFF0000); 
decode(mImageGreen, data, 0xFF00FF00); 
decode(mImageBlue, data, 0xFF0000FF); 

位圖以紅色和藍色交換顯示,沒有綠色問題。

當我換了紅色和藍色濾色片是這樣的:

decode(mImageRed, data, 0xFF0000FF); 
decode(mImageGreen, data, 0xFF00FF00); 
decode(mImageBlue, data, 0xFFFF0000); 

*改變0xFF0000FF濾波器0xFFFF0000地址爲紅色圖像,反之亦然。

在本地部分,它的作用是剛剛與位運算符和(&)應用過濾器:

bitmapContent[yIndex] &= pFilter; 

有誰知道,而色彩交換?因爲我認爲0xFFFF0000是紅色的而不是0xFF0000FF。

這裏是解碼功能:

void JNICALL 
decode(JNIEnv *pEnv, jclass pClass, jobject pTarget, jbyteArray pSource, jint pFilter) { 

    // Retrieves bitmap information and locks it for drawing. 
    AndroidBitmapInfo bitmapInfo; 
    uint32_t *bitmapContent; 

    if (AndroidBitmap_getInfo(pEnv, pTarget, &bitmapInfo) < 0) 
     abort(); 

    if (bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888) 
     abort(); 

    if (AndroidBitmap_lockPixels(pEnv, pTarget, (void **) &bitmapContent) < 0) 
     abort(); 

    // Accesses source array data. 
    jbyte *source = (*pEnv)->GetPrimitiveArrayCritical(pEnv, pSource, 0); 
    if (source == NULL) 
     abort(); 

    int32_t frameSize = bitmapInfo.width * bitmapInfo.height; 
    int32_t yIndex, uvIndex, x, y; 
    int32_t colorY, colorU, colorV; 
    int32_t colorR, colorG, colorB; 
    int32_t y1192; 

    // Processes each pixel and converts YUV to RGB color. 
    // Algorithm originates from the Ketai open source project. 
    // See http://ketai.googlecode.com/. 
    for (y = 0, yIndex = 0; y < bitmapInfo.height; y++) { 
     colorU = 0; 
     colorV = 0; 
     // Y is divided by 2 because UVs are subsampled vertically. 
     // This means that two consecutives iterations refer to the 
     // same UV line (e.g when Y=0 and Y=1). 
     uvIndex = frameSize + (y >> 1) * bitmapInfo.width; 
     for (x = 0; x < bitmapInfo.width; x++, yIndex++) { 
      // Retrieves YUV components. UVs are subsampled 
      // horizontally too, hence %2 (1 UV for 2 Y). 
      colorY = max(toInt(source[yIndex]) - 16, 0); 
      if (!(x % 2)) { 
       colorV = toInt(source[uvIndex++]) - 128; 
       colorU = toInt(source[uvIndex++]) - 128; 
      } 
      // Computes R, G and B from Y, U and V. 
      y1192 = 1192 * colorY; 
      colorR = (y1192 + 1634 * colorV); 
      colorG = (y1192 - 833 * colorV - 400 * colorU); 
      colorB = (y1192 + 2066 * colorU); 

      colorR = clamp(colorR, 0, 262143); 
      colorG = clamp(colorG, 0, 262143); 
      colorB = clamp(colorB, 0, 262143); 

      // Combines R, G, B and A into the final pixel color. 
      bitmapContent[yIndex] = color(colorR, colorG, colorB); 
      bitmapContent[yIndex] &= pFilter; 
     } 
    } 

    (*pEnv)->ReleasePrimitiveArrayCritical(pEnv, pSource, source, 0); 
    if (AndroidBitmap_unlockPixels(pEnv, pTarget) < 0) 
     abort(); 
} 

這裏如何位圖被分配:

mImageR = Bitmap.createBitmap(size.width, size.height, Bitmap.Config.ARGB_8888); 
mImageG = Bitmap.createBitmap(size.width, size.height, Bitmap.Config.ARGB_8888); 
mImageB = Bitmap.createBitmap(size.width, size.height, Bitmap.Config.ARGB_8888); 
mImageViewR.setImageBitmap(mImageR); 
mImageViewG.setImageBitmap(mImageG); 
mImageViewB.setImageBitmap(mImageB); 
+0

確保錯誤不在於您顯示這些圖像的代碼中,否則,這部分代碼對我來說看起來很好。 – ZeekHuge

+1

你是否使用過OpenCV(因爲它默認使用BGR)? – AKarthik10

+0

我編輯了問題以發佈de本機代碼。 – PedroNakano

回答

0

decode()功能是硬編碼爲NV21的視頻格式,但相機可以爲YV12設置。這可能會導致顏色「交換」。請注意,對於某些分辨率,YV12可以有行填充(NV21保證「完全打包」)。

PS在一次運行中生成三個平面的速度可能明顯更快,而且不清楚整數運算是否比現代CPU上的浮點運算更快。

如果分辨率高,並且處理時間很重要,請考慮使用renderscript。

+0

太棒了!我的手機默認使用YV12。 並感謝提高性能的提示。 – PedroNakano

相關問題