title: YUV to RGB Problems with PreviewCallback in Android
body: <p>I'm trying to process images captured from the preview using PreviewCallback, and am having problems with the conversion of YUV to RGB. I've tried the following approaches (most taken from answers here) and all give green and pink garbage images. None have worked for me so far, so am hoping someone can suggest a new approach. </p>
  
  <p>Attempt 1:</p>
  
  <pre><code>private PreviewCallback previewCallback = new PreviewCallback() {
      @Override
      public void onPreviewFrame(byte[] data, Camera camera) {
  
          YuvImage yuv = new YuvImage(data, previewFormat, previewSize.width, previewSize.height, null);
  
          ByteArrayOutputStream out = new ByteArrayOutputStream();
          yuv.compressToJpeg(new Rect(0, 0, yuv.getWidth(), yuv.getHeight()), 100, out);
          byte[] bytes = out.toByteArray();
  
          CamUtil.byteArrayToJPEG(MyActivity.this, bytes, "temp.jpg");
      }
  };
  </code></pre>
  
  <p>Attempt 2:</p>
  
  <pre><code>private PreviewCallback previewCallback = new PreviewCallback() {
      @Override
      public void onPreviewFrame(byte[] data, Camera camera) {
  
          // functions below can be found easily on Stack Overflow
          int[] rgb = decodeYUV420SP(data, previewSize.width, previewSize.height);
          OR
          int[] rgb = YUV_NV21_TO_RGB(data, previewSize.width, previewSize.height);
  
          Bitmap bitmap =  Bitmap.createBitmap(rgb, 0, previewSize.width, previewSize.width, previewSize.height, Bitmap.Config.ARGB_8888);
  
          ByteArrayOutputStream out = new ByteArrayOutputStream();
          bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
          byte[] bytes = out.toByteArray();
  
          CamUtil.byteArrayToJPEG(View6Activity.this, bytes, "temp.jpg");
      }
  };
  </code></pre>
  
  <p>Attempt 3:</p>
  
  <pre><code>private PreviewCallback previewCallback = new PreviewCallback() {
      @Override
      public void onPreviewFrame(byte[] data, Camera camera) {
  
          // after first setting previewFormat to RGB_565
          Bitmap bitmap = Bitmap.createBitmap(previewSize.width, previewSize.height, Bitmap.Config.RGB_565);
          ByteBuffer buffer = ByteBuffer.wrap(data);
          bitmap.copyPixelsFromBuffer(buffer); 
  
          ByteArrayOutputStream out = new ByteArrayOutputStream();
          bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
          byte[] bytes = out.toByteArray();
  
          CamUtil.byteArrayToJPEG(View6Activity.this, bytes, "temp.jpg");
      }
  };
  </code></pre>
  
  <p>Attempt 4 (from <a href="https://stackoverflow.com/questions/9325861/converting-yuv-rgbimage-processing-yuv-during-onpreviewframe-in-android">Converting YUV-&gt;RGB(Image processing)-&gt;YUV during onPreviewFrame in android?</a>)</p>
  
  <pre><code>private PreviewCallback previewCallback = new PreviewCallback() {
      @Override
      public void onPreviewFrame(byte[] data, Camera camera) {
  
          int imageWidth = previewSize.width;
          int imageHeight = previewSize.height;
  
          // 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 start,
          // if not good practice
          intBuffer.position(0);
  
          // Set the alpha for the image: 0 is transparent, 255 fully opaque
          final byte alpha = (byte) 255;
  
          // Get each pixel, one at a time
          for (int y = 0; y &lt; imageHeight; y++) {
              for (int x = 0; x &lt; 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] &amp; 0xff;
  
                  // Get U and V values, stored after Y values, one per 2x2 block
                  // of pixels, interleaved. Prepare them as floats with correct range
                  // ready for calculation later.
                  int xby2 = x/2;
                  int yby2 = y/2;
                  float U = (float)(data[numPixels + 2*xby2 + yby2*imageWidth] &amp; 0xff) - 128.0f;
                  float V = (float)(data[numPixels + 2*xby2 + 1 + yby2*imageWidth] &amp; 0xff) - 128.0f;
                  // Do the YUV -&gt; RGB conversion
                  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 &lt; 0 ? 0 : R &gt; 255 ? 255 : R;
                  G = G &lt; 0 ? 0 : G &gt; 255 ? 255 : G;
                  B = B &lt; 0 ? 0 : B &gt; 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);
  
          ByteArrayOutputStream out = new ByteArrayOutputStream();
          bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
          byte[] bytes = out.toByteArray();
  
          CamUtil.byteArrayToJPEG(View6Activity.this, bytes, "temp.jpg");
      }
  };
  </code></pre>
  
  <p>All these approaches are giving me green and pink garbage images. Can anyone help?</p>