2017-08-04 2 views
1
ausgetauscht.

Ein Beispiel von Sylvain Ratabouil Android NDK (2nd Edition), die Bildvorschauen von der Kamera erhält und nativ verarbeitet, von YUV zu RGB konvertiert und einen Farbfilter darauf anwendet.Rote und blaue Farben werden in Android

Der Code ist sehr einfach und das Problem tritt in den Filter, die diese Funktion übergeben wird:

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

Ziel ist ein Verweis auf eine Image
Quelle ist die Rahmenvorschaudaten
Filter sind der Farbfilter

Wenn der Code wie folgt lautet:

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

Die Bitmaps werden mit roten und blauen Farben angezeigt, kein Problem mit Grün.

Wenn ich die roten und blauen Farbfiltern wie folgt auszutauschen:

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

* Ändern 0xFF0000FF Filter mit 0xFFFF0000 für das rote Bild und umgekehrt.

Im nativen Teil, was es die Filter hat sie gilt nur mit dem Bit-Operator und (&):

bitmapContent[yIndex] &= pFilter; 

niemand kennt, während die Farben vertauscht? Weil ich dachte, dass 0xFFFF0000 rot war und nicht 0xFF0000FF. Hier

ist die Dekodierungsfunktion:

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(); 
} 

Und hier, wie die Bitmaps zugeordnet sind:

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

Stellen Sie sicher, dass der Fehler nicht in dem Code liegt, in dem Sie diese Bilder anzeigen, sonst sieht dieser Teil des Codes gut für mich aus. – ZeekHuge

+1

Verwenden Sie OpenCV zufällig (wie es BGR standardmäßig verwendet)? – AKarthik10

+0

Ich habe die Frage editiert, um de nativen Code zu posten. – PedroNakano

Antwort

0

Ihre decode() Funktion ist für NV21 Videoformat fest einprogrammiert, aber die Kamera für YV12 eingestellt werden könnte . Dies könnte für einen Farbwechsel verantwortlich sein. Beachten Sie, dass YV12 für einige Auflösungen Zeilenabstand haben kann (NV21 ist garantiert "voll gepackt").

PS es kann wesentlich schneller sein, die drei Ebenen in einem Lauf zu generieren, und es ist nicht klar, ob Integer-Operationen wirklich schneller sind als Floaten auf den modernen CPUs.

Wenn die Auflösung hoch ist und die Verarbeitungszeit wichtig ist, sollten Sie die Verwendung von pigscript in Betracht ziehen.

+0

Großartig!Mein Telefon verwendet YV12 als Standard. Und danke für den Tipp, um die Leistung zu verbessern. – PedroNakano

Verwandte Themen