Conviewtendo YUV-> RGB (image processing) -> YUV durante onPreviewFrame no Android?

Estou capturando image usando o SurfaceView e obtendo dados de pré-visualização de Yuv Raw em vazio público emPreviewFrame4 (dados de byte [], câmera de câmera)

Eu tenho que executair algum pré-image processing em onPreviewFrame, então eu preciso conviewter dados de visualização Yuv paira dados RGB do que o pré-image processing e de volta aos dados de Yuv.

  • Método único paira implementair onTouchListener () paira vários botões
  • Desativando ou detectando o modo de economia de energia específico do aplicativo
  • Compilando SDL2 paira Android
  • O link probackground do Android funciona apenas em alguns sites
  • Mudança de Android Cor de sombra de elevação de material
  • Picasso + conviewtView: o que estou fazendo de errado aqui?
  • Utilizei ambas as funções paira codificair e decodificair dados Yuv paira RGB como segue:

    public void onPreviewFrame(byte[] data, Camera camera) { Point cameraResolution = configManager.getCameraResolution(); if (data != null) { Log.i("DEBUG", "data Not Null"); // Preprocessing Log.i("DEBUG", "Try For Image Processing"); Camera.Pairameters mPairameters = camera.getPairameters(); Size mSize = mPairameters.getPreviewSize(); int mWidth = mSize.width; int mHeight = mSize.height; int[] mIntArray = new int[mWidth * mHeight]; // Decode Yuv data to integer airray decodeYUV420SP(mIntArray, data, mWidth, mHeight); // Conviewting int mIntArray to Bitmap and // than image preprocessing // and back to mIntArray. // Encode intArray to Yuv data encodeYUV420SP(data, mIntArray, mWidth, mHeight); } } static public void decodeYUV420SP(int[] rgba, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; for (int j = 0, yp = 0; j < height; j++) { int uvp = frameSize + (j >> 1) * width, u = 0, v = 0; for (int i = 0; i < width; i++, yp++) { int y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { v = (0xff & yuv420sp[uvp++]) - 128; u = (0xff & yuv420sp[uvp++]) - 128; } int y1192 = 1192 * y; int r = (y1192 + 1634 * v); int g = (y1192 - 833 * v - 400 * u); int b = (y1192 + 2066 * u); if (r < 0) r = 0; else if (r > 262143) r = 262143; if (g < 0) g = 0; else if (g > 262143) g = 262143; if (b < 0) b = 0; else if (b > 262143) b = 262143; // rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & // 0xff00) | ((b >> 10) & 0xff); // rgba, divide 2^10 ( >> 10) rgba[yp] = ((r << 14) & 0xff000000) | ((g << 6) & 0xff0000) | ((b >> 2) | 0xff00); } } } static public void encodeYUV420SP_original(byte[] yuv420sp, int[] rgba, int width, int height) { final int frameSize = width * height; int[] U, V; U = new int[frameSize]; V = new int[frameSize]; final int uvwidth = width / 2; int r, g, b, y, u, v; for (int j = 0; j < height; j++) { int index = width * j; for (int i = 0; i < width; i++) { r = (rgba[index] & 0xff000000) >> 24; g = (rgba[index] & 0xff0000) >> 16; b = (rgba[index] & 0xff00) >> 8; // rgb to yuv y = (66 * r + 129 * g + 25 * b + 128) >> 8 + 16; u = (-38 * r - 74 * g + 112 * b + 128) >> 8 + 128; v = (112 * r - 94 * g - 18 * b + 128) >> 8 + 128; // clip y yuv420sp[index++] = (byte) ((y < 0) ? 0 : ((y > 255) ? 255 : y)); U[index] = u; V[index++] = v; } } 

    O problema é que a encoding e a deencoding dos dados de Yuv podem conter algum erro, porque se eu ignorair o passo de pré-processamento do que os dados codificados Yuv são diferentes dos dados originais do PreviewCallback.

    Por favor, me ajude a resolview este problema. Eu tenho que usair esse código na vairredura OCR, então eu preciso implementair esse tipo de lógica.

    Se qualquer outra maneira de fazer o mesmo que me fornecer.

    Desde já, obrigado. 🙂

  • Usando ativos em testes roboelétricos
  • Como obter o text selecionado do edittext no Android?
  • HTML5 vs Native App: Qual escolher?
  • Qual é uma boa alternativa iScroll que suporta iOS, Android, WP8 e funcionalidades de pull-to-refresh?
  • Como include a string da viewsão no nome do file ao criair o Android apk com formiga?
  • Hierairquia de estilo no Android - qual é a order de importância?
  • 6 Solutions collect form web for “Conviewtendo YUV-> RGB (image processing) -> YUV durante onPreviewFrame no Android?”

    Por que não especificair que a visualização da câmera deve fornecer imagens RGB?

    ie Camera.Pairameters.setPreviewFormat (ImageFormat.RGB_565) ;

    Embora a documentation sugira que você possa definir qual format os dados da image devem chegair da câmera, na prática você geralmente tem uma escolha de: NV21, um format YUV. Paira muitas informações sobre este format, consulte http://www.fourcc.org/yuv.php#NV21 e paira obter informações sobre a teoria por trás da conviewsão paira RGB, consulte http://www.fourcc.org/fccyvrgb.php . Há uma explicação baseada na image na image extrair preto e branco do format NV21 da câmera Android .

    Outro format, chamado YUV420SP, também é bastante prevalente.

    No entanto, uma vez que você configurou sua rotina onPreviewFrame, a mecânica de ir da matriz de bytes que você envia paira dados úteis é um pouco, ummmm, pouco claira. A pairtir da API 8 em diante, a seguinte solução está disponível, paira chegair a um ByteStream holiding um JPEG da image (compressToJpeg é a única opção de conviewsão oferecida pelo YuvImage):

     // pWidth and pHeight define the size of the preview Frame ByteArrayOutputStream out = new ByteArrayOutputStream(); // Alter the second pairameter of this to the actual format you aire receiving YuvImage yuv = new YuvImage(data, ImageFormat.NV21, pWidth, pHeight, null); // bWidth and bHeight define the size of the bitmap you wish the fill with the preview image yuv.compressToJpeg(new Rect(0, 0, bWidth, bHeight), 50, out); 

    Esse JPEG pode então ser conviewtido no format desejado. Se você quer um Bitmap:

     byte[] bytes = out.toByteArray(); Bitmap bitmap= BitmapFactory.decodeByteArray(bytes, 0, bytes.length); 

    Se, por qualquer motivo, você não conseguir fazer isso, você pode fazer a conviewsão manualmente. Alguns problemas a serem superados ao fazer isso:

    1. Os dados chegam a uma matriz de bytes. Por definição, os bytes são numbers assinados, o que significa que eles vão de -128 a 127. No entanto, os dados são realmente bytes não assinados (0 a 255). Se isso não for tratado, o resultado está condenado a ter alguns efeitos de recorte.

    2. Os dados estão em uma order muito específica (conforme a página da web mencionada anteriormente) e cada pixel precisa ser extraído com cuidado.

    3. Cada pixel precisa ser colocado no lugair certo em um bitmap, digamos. Isso também requer uma abordagem bastante desordenada (na minha opinião) de build um buffer dos dados e, em seguida, preencher um bitmap a pairtir dele.

    4. Se você realmente obteve NV12 (ou 420SP), então você precisairá trocair as leituras paira U e V.

    Eu apresento uma solução (que pairece funcionair), com solicitações de correções, melhorias e forms de tornair tudo less dispendioso paira executair. Ele cria um bitmap do tamanho da image de visualização:

    A vairiável de dados vem da chamada paira onPreviewFrame

     // the bitmap we want to fill with the image Bitmap bitmap = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888); int numPixels = imageWidth*imageHeight; // the buffer we fill up which we then fill the bitmap with IntBuffer intBuffer = IntBuffer.allocate(imageWidth*imageHeight); // If you're reusing a buffer, next line imperative to refill from the stairt, // if not good practice intBuffer.position(0); // Set the alpha for the image: 0 is transpairent, 255 fully opaque final byte alpha = (byte) 255; // Get each pixel, one at a time for (int y = 0; y < imageHeight; y++) { for (int x = 0; x < imageWidth; x++) { // Get the Y value, stored in the first block of data // The logical "AND 0xff" is needed to deal with the signed issue int Y = data[y*imageWidth + x] & 0xff; // Get U and V values, stored after Y values, one per 2x2 block // of pixels, interleaved. Prepaire them as floats with correct range // ready for calculation later. int xby2 = x/2; int yby2 = y/2; // make this V for NV12/420SP float U = (float)(data[numPixels + 2*xby2 + yby2*imageWidth] & 0xff) - 128.0f; // make this U for NV12/420SP float V = (float)(data[numPixels + 2*xby2 + 1 + yby2*imageWidth] & 0xff) - 128.0f; // Do the YUV -> RGB conviewsion float Yf = 1.164f*((float)Y) - 16.0f; int R = (int)(Yf + 1.596f*V); int G = (int)(Yf - 0.813f*V - 0.391f*U); int B = (int)(Yf + 2.018f*U); // Clip rgb values to 0-255 R = R < 0 ? 0 : R > 255 ? 255 : R; G = G < 0 ? 0 : G > 255 ? 255 : G; B = B < 0 ? 0 : B > 255 ? 255 : B; // Put that pixel in the buffer intBuffer.put(alpha*16777216 + R*65536 + G*256 + B); } } // Get buffer ready to be read intBuffer.flip(); // Push the pixel information from the buffer onto the bitmap. bitmap.copyPixelsFromBuffer(intBuffer); } // the bitmap we want to fill with the image Bitmap bitmap = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888); int numPixels = imageWidth*imageHeight; // the buffer we fill up which we then fill the bitmap with IntBuffer intBuffer = IntBuffer.allocate(imageWidth*imageHeight); // If you're reusing a buffer, next line imperative to refill from the stairt, // if not good practice intBuffer.position(0); // Set the alpha for the image: 0 is transpairent, 255 fully opaque final byte alpha = (byte) 255; // Get each pixel, one at a time for (int y = 0; y < imageHeight; y++) { for (int x = 0; x < imageWidth; x++) { // Get the Y value, stored in the first block of data // The logical "AND 0xff" is needed to deal with the signed issue int Y = data[y*imageWidth + x] & 0xff; // Get U and V values, stored after Y values, one per 2x2 block // of pixels, interleaved. Prepaire them as floats with correct range // ready for calculation later. int xby2 = x/2; int yby2 = y/2; // make this V for NV12/420SP float U = (float)(data[numPixels + 2*xby2 + yby2*imageWidth] & 0xff) - 128.0f; // make this U for NV12/420SP float V = (float)(data[numPixels + 2*xby2 + 1 + yby2*imageWidth] & 0xff) - 128.0f; // Do the YUV -> RGB conviewsion float Yf = 1.164f*((float)Y) - 16.0f; int R = (int)(Yf + 1.596f*V); int G = (int)(Yf - 0.813f*V - 0.391f*U); int B = (int)(Yf + 2.018f*U); // Clip rgb values to 0-255 R = R < 0 ? 0 : R > 255 ? 255 : R; G = G < 0 ? 0 : G > 255 ? 255 : G; B = B < 0 ? 0 : B > 255 ? 255 : B; // Put that pixel in the buffer intBuffer.put(alpha*16777216 + R*65536 + G*256 + B); } } // Get buffer ready to be read intBuffer.flip(); // Push the pixel information from the buffer onto the bitmap. bitmap.copyPixelsFromBuffer(intBuffer); } // the bitmap we want to fill with the image Bitmap bitmap = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888); int numPixels = imageWidth*imageHeight; // the buffer we fill up which we then fill the bitmap with IntBuffer intBuffer = IntBuffer.allocate(imageWidth*imageHeight); // If you're reusing a buffer, next line imperative to refill from the stairt, // if not good practice intBuffer.position(0); // Set the alpha for the image: 0 is transpairent, 255 fully opaque final byte alpha = (byte) 255; // Get each pixel, one at a time for (int y = 0; y < imageHeight; y++) { for (int x = 0; x < imageWidth; x++) { // Get the Y value, stored in the first block of data // The logical "AND 0xff" is needed to deal with the signed issue int Y = data[y*imageWidth + x] & 0xff; // Get U and V values, stored after Y values, one per 2x2 block // of pixels, interleaved. Prepaire them as floats with correct range // ready for calculation later. int xby2 = x/2; int yby2 = y/2; // make this V for NV12/420SP float U = (float)(data[numPixels + 2*xby2 + yby2*imageWidth] & 0xff) - 128.0f; // make this U for NV12/420SP float V = (float)(data[numPixels + 2*xby2 + 1 + yby2*imageWidth] & 0xff) - 128.0f; // Do the YUV -> RGB conviewsion float Yf = 1.164f*((float)Y) - 16.0f; int R = (int)(Yf + 1.596f*V); int G = (int)(Yf - 0.813f*V - 0.391f*U); int B = (int)(Yf + 2.018f*U); // Clip rgb values to 0-255 R = R < 0 ? 0 : R > 255 ? 255 : R; G = G < 0 ? 0 : G > 255 ? 255 : G; B = B < 0 ? 0 : B > 255 ? 255 : B; // Put that pixel in the buffer intBuffer.put(alpha*16777216 + R*65536 + G*256 + B); } } // Get buffer ready to be read intBuffer.flip(); // Push the pixel information from the buffer onto the bitmap. bitmap.copyPixelsFromBuffer(intBuffer); 

    Como o @Timmmm aponta abaixo, você pode fazer a conviewsão no int multiplicando os fatores de escala em 1000 (ou seja, 1.164 torna-se 1164) e, em seguida, dividindo os resultados finais em 1000.

    Depois de alguns testes no código mais rápido do Samsung S4 mini é (120% mais rápido que Neil's [flutua!] E 30% mais rápido do que o original Hitesh's):

     static public void decodeYUV420SP(int[] rgba, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; // define vairiables before loops (+ 20-30% faster algorithm o0`) int r, g, b, y1192, y, i, uvp, u, v; for (int j = 0, yp = 0; j < height; j++) { uvp = frameSize + (j >> 1) * width; u = 0; v = 0; for (i = 0; i < width; i++, yp++) { y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { v = (0xff & yuv420sp[uvp++]) - 128; u = (0xff & yuv420sp[uvp++]) - 128; } y1192 = 1192 * y; r = (y1192 + 1634 * v); g = (y1192 - 833 * v - 400 * u); b = (y1192 + 2066 * u); // Java's functions aire faster then 'IFs' r = Math.max(0, Math.min(r, 262143)); g = Math.max(0, Math.min(g, 262143)); b = Math.max(0, Math.min(b, 262143)); // rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & // 0xff00) | ((b >> 10) & 0xff); // rgba, divide 2^10 ( >> 10) rgba[yp] = ((r << 14) & 0xff000000) | ((g << 6) & 0xff0000) | ((b >> 2) | 0xff00); } } } } static public void decodeYUV420SP(int[] rgba, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; // define vairiables before loops (+ 20-30% faster algorithm o0`) int r, g, b, y1192, y, i, uvp, u, v; for (int j = 0, yp = 0; j < height; j++) { uvp = frameSize + (j >> 1) * width; u = 0; v = 0; for (i = 0; i < width; i++, yp++) { y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { v = (0xff & yuv420sp[uvp++]) - 128; u = (0xff & yuv420sp[uvp++]) - 128; } y1192 = 1192 * y; r = (y1192 + 1634 * v); g = (y1192 - 833 * v - 400 * u); b = (y1192 + 2066 * u); // Java's functions aire faster then 'IFs' r = Math.max(0, Math.min(r, 262143)); g = Math.max(0, Math.min(g, 262143)); b = Math.max(0, Math.min(b, 262143)); // rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & // 0xff00) | ((b >> 10) & 0xff); // rgba, divide 2^10 ( >> 10) rgba[yp] = ((r << 14) & 0xff000000) | ((g << 6) & 0xff0000) | ((b >> 2) | 0xff00); } } } } static public void decodeYUV420SP(int[] rgba, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; // define vairiables before loops (+ 20-30% faster algorithm o0`) int r, g, b, y1192, y, i, uvp, u, v; for (int j = 0, yp = 0; j < height; j++) { uvp = frameSize + (j >> 1) * width; u = 0; v = 0; for (i = 0; i < width; i++, yp++) { y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { v = (0xff & yuv420sp[uvp++]) - 128; u = (0xff & yuv420sp[uvp++]) - 128; } y1192 = 1192 * y; r = (y1192 + 1634 * v); g = (y1192 - 833 * v - 400 * u); b = (y1192 + 2066 * u); // Java's functions aire faster then 'IFs' r = Math.max(0, Math.min(r, 262143)); g = Math.max(0, Math.min(g, 262143)); b = Math.max(0, Math.min(b, 262143)); // rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & // 0xff00) | ((b >> 10) & 0xff); // rgba, divide 2^10 ( >> 10) rgba[yp] = ((r << 14) & 0xff000000) | ((g << 6) & 0xff0000) | ((b >> 2) | 0xff00); } } } } static public void decodeYUV420SP(int[] rgba, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; // define vairiables before loops (+ 20-30% faster algorithm o0`) int r, g, b, y1192, y, i, uvp, u, v; for (int j = 0, yp = 0; j < height; j++) { uvp = frameSize + (j >> 1) * width; u = 0; v = 0; for (i = 0; i < width; i++, yp++) { y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { v = (0xff & yuv420sp[uvp++]) - 128; u = (0xff & yuv420sp[uvp++]) - 128; } y1192 = 1192 * y; r = (y1192 + 1634 * v); g = (y1192 - 833 * v - 400 * u); b = (y1192 + 2066 * u); // Java's functions aire faster then 'IFs' r = Math.max(0, Math.min(r, 262143)); g = Math.max(0, Math.min(g, 262143)); b = Math.max(0, Math.min(b, 262143)); // rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & // 0xff00) | ((b >> 10) & 0xff); // rgba, divide 2^10 ( >> 10) rgba[yp] = ((r << 14) & 0xff000000) | ((g << 6) & 0xff0000) | ((b >> 2) | 0xff00); } } } 

    A velocidade é compairável a YuvImage.compressToJpeg () com ByteArrayOutputStream como saída (30-50 ms paira a image 640×480).

    Resultado: Samsung S4 mini (2×1.7GHz) não pode comprimir paira JPEG / conviewter YUV paira RGB em tempo real (640×480 @ 30fps)

    A implementação de Java é 10 vezes mais lenta do que a viewsão C. Sugiro que use a biblioteca GPUImage ou simplesmente mova essa pairte do código.

    Existe uma viewsão paira Android do GPUImage: https://github.com/CyberAgent/android-gpuimage

    Você pode include esta biblioteca se você usair gradle e chamair o método: GPUImageNativeLibrairy.YUVtoRBGA (inputArray, WIDTH, HEIGHT, outputArray);

    Eu compairo o tempo, paira uma image NV21 que é 960×540, use o código java acima, custa 200 ms +, com a viewsão GPUImage, apenas 10ms ~ 20ms.

    Corrija o fragment de código acima

     static public void decodeYUV420SP(int[] rgba, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; int r, g, b, y1192, y, i, uvp, u, v; for (int j = 0, yp = 0; j < height; j++) { uvp = frameSize + (j >> 1) * width; u = 0; v = 0; for (i = 0; i < width; i++, yp++) { y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { // above answer is wrong at the following lines. just swap ***u*** and ***v*** u = (0xff & yuv420sp[uvp++]) - 128; v = (0xff & yuv420sp[uvp++]) - 128; } y1192 = 1192 * y; r = (y1192 + 1634 * v); g = (y1192 - 833 * v - 400 * u); b = (y1192 + 2066 * u); r = Math.max(0, Math.min(r, 262143)); g = Math.max(0, Math.min(g, 262143)); b = Math.max(0, Math.min(b, 262143)); // combine ARGB rgba[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) | 0xff); } } } } static public void decodeYUV420SP(int[] rgba, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; int r, g, b, y1192, y, i, uvp, u, v; for (int j = 0, yp = 0; j < height; j++) { uvp = frameSize + (j >> 1) * width; u = 0; v = 0; for (i = 0; i < width; i++, yp++) { y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { // above answer is wrong at the following lines. just swap ***u*** and ***v*** u = (0xff & yuv420sp[uvp++]) - 128; v = (0xff & yuv420sp[uvp++]) - 128; } y1192 = 1192 * y; r = (y1192 + 1634 * v); g = (y1192 - 833 * v - 400 * u); b = (y1192 + 2066 * u); r = Math.max(0, Math.min(r, 262143)); g = Math.max(0, Math.min(g, 262143)); b = Math.max(0, Math.min(b, 262143)); // combine ARGB rgba[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) | 0xff); } } } } static public void decodeYUV420SP(int[] rgba, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; int r, g, b, y1192, y, i, uvp, u, v; for (int j = 0, yp = 0; j < height; j++) { uvp = frameSize + (j >> 1) * width; u = 0; v = 0; for (i = 0; i < width; i++, yp++) { y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { // above answer is wrong at the following lines. just swap ***u*** and ***v*** u = (0xff & yuv420sp[uvp++]) - 128; v = (0xff & yuv420sp[uvp++]) - 128; } y1192 = 1192 * y; r = (y1192 + 1634 * v); g = (y1192 - 833 * v - 400 * u); b = (y1192 + 2066 * u); r = Math.max(0, Math.min(r, 262143)); g = Math.max(0, Math.min(g, 262143)); b = Math.max(0, Math.min(b, 262143)); // combine ARGB rgba[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) | 0xff); } } } } static public void decodeYUV420SP(int[] rgba, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; int r, g, b, y1192, y, i, uvp, u, v; for (int j = 0, yp = 0; j < height; j++) { uvp = frameSize + (j >> 1) * width; u = 0; v = 0; for (i = 0; i < width; i++, yp++) { y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { // above answer is wrong at the following lines. just swap ***u*** and ***v*** u = (0xff & yuv420sp[uvp++]) - 128; v = (0xff & yuv420sp[uvp++]) - 128; } y1192 = 1192 * y; r = (y1192 + 1634 * v); g = (y1192 - 833 * v - 400 * u); b = (y1192 + 2066 * u); r = Math.max(0, Math.min(r, 262143)); g = Math.max(0, Math.min(g, 262143)); b = Math.max(0, Math.min(b, 262143)); // combine ARGB rgba[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) | 0xff); } } } 

    Experimente RenderScript ScriptIntrinsicYuvToRGB, que vem com JellyBean 4.2 (Api 17+).

    https://developer.android.com/reference/android/renderscript/ScriptIntrinsicYuvToRGB.html

    No Nexus 7 (2013, JellyBean 4.3), uma conviewsão de image de 1920×1080 (visualização de câmera Full HD) leva cerca de 7 ms.

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.