0

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.

Attempt 1:

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

Attempt 2:

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

Attempt 3:

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

Attempt 4 (from Converting YUV->RGB(Image processing)->YUV during onPreviewFrame in android?)

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 < 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. 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] & 0xff) - 128.0f;
                float V = (float)(data[numPixels + 2*xby2 + 1 + yby2*imageWidth] & 0xff) - 128.0f;
                // Do the YUV -> 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 < 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);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
        byte[] bytes = out.toByteArray();

        CamUtil.byteArrayToJPEG(View6Activity.this, bytes, "temp.jpg");
    }
};

All these approaches are giving me green and pink garbage images. Can anyone help?

Community
  • 1
  • 1
Serge Anido
  • 623
  • 2
  • 7
  • 11
  • Do you judge by the `temp.jpg` file, produced by `CamUtil.byteArrayToJPEG()`? Maybe, the problem is with this function? Maybe, it assumes a yuv image, and not a bitmap? – Alex Cohn Jan 06 '14 at 19:51
  • Yes I'm judging by the `temp.jpg` file. `byteArrayToJPEG` creates a new `FileOutputStream`, writes the byte array to it, then closes the stream. – Serge Anido Jan 07 '14 at 14:46
  • When I look at the first attempt, there is no RGB involved at all. But are you sure that `previewSize` and `previewFormat` are correct? – Alex Cohn Jan 07 '14 at 15:07
  • 2
    Ok have found the problem now - my size settings were being changed by a function in my `CameraPreview` class. Thanks Alex. – Serge Anido Jan 08 '14 at 07:45
  • please see my answer: http://stackoverflow.com/questions/9325861/converting-yuv-rgbimage-processing-yuv-during-onpreviewframe-in-android/36565200#36565200 – promenade Apr 12 '16 at 06:34

0 Answers0