user682765
user682765

Reputation: 1229

Region of interest

I am interested to capture only part of the cameraPreview. I have a rectangle which has a onTouchListener. I can use this to drag my region of interest anywhere on the camera preview. My ultimate goal is to capture only that part of the preview. But I am not able to find a way. Is there any API I can make use of? Can anyone guide me here.

Thanks

Upvotes: 2

Views: 3144

Answers (1)

mmeyer
mmeyer

Reputation: 3608

There's no support for that in the API that I know of but I have successfully done something similar.

Basically you'll need to:

  • implement Camera.PreviewCallback
  • decode the YUV preview frame to RGB
  • make a temp bitmap from the RGB bytes
  • scale the rect from your on screen rect to the appropriate size for the preview frames dimensions
  • then finally, use createBitmap (Bitmap source, int x, int y, int width, int height) to crop a new bitmap from the temp one.

Note that there is no API supported YUV decoder until FROYO via the YuvImage class which you can use something like:

YuvImage yuvimage=new YuvImage(yuv,ImageFormat.NV21,width,height,null);
            ByteArrayOutputStream baos=new ByteArrayOutputStream();
            yuvimage.compressToJpeg(new Rect(0,0,width,height), 100, baos);
            rgb =  BitmapFactory.decodeByteArray(baos.toByteArray(), 0, baos.size());

If youre only going to support 2.2 and later, your could skip the temp bitmap and use the YuvImage.compressToJpeg to crop to your scaled rect.

For OS versions prior to 2.2 you'll need you own implementation of YUV decode which can be done as follows:

/**
     * Decodes YUV frame to a buffer which can be use to create a bitmap
     * decode Y, U, and V values on the YUV 420 buffer described as YCbCr_422_SP by Android 
     * @param out the outgoing array of RGB bytes
     * @param fg the incoming frame bytes
     * @param width of source frame
     * @param height of source frame
     * @throws NullPointerException
     * @throws IllegalArgumentException
     */
    public static void decodeYUV(int[] out, byte[] fg, int width, int height)
            throws NullPointerException, IllegalArgumentException {
        int sz = width * height;
        if (out == null)
            throw new NullPointerException("buffer out is null");
        if (out.length < sz)
            throw new IllegalArgumentException("buffer out size " + out.length
                    + " < minimum " + sz);
        if (fg == null)
            throw new NullPointerException("buffer 'fg' is null");

        if (fg.length < sz)
            throw new IllegalArgumentException("buffer fg size " + fg.length
                    + " < minimum " + sz * 3 / 2);

        int i, j;
        int Y, Cr = 0, Cb = 0;
        for (j = 0; j < height; j++) {
            int pixPtr = j * width;
            final int jDiv2 = j >> 1;
            for (i = 0; i < width; i++) {
                Y = fg[pixPtr];
                if (Y < 0)
                    Y += 255;
                if ((i & 0x1) != 1) {
                    final int cOff = sz + jDiv2 * width + (i >> 1) * 2;
                    Cb = fg[cOff];
                    if (Cb < 0)
                        Cb += 127;
                    else
                        Cb -= 128;
                    Cr = fg[cOff + 1];
                    if (Cr < 0)
                        Cr += 127;
                    else
                        Cr -= 128;
                }
                int R = Y + Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5);
                if (R < 0)
                    R = 0;
                else if (R > 255)
                    R = 255;
                int G = Y - (Cb >> 2) + (Cb >> 4) + (Cb >> 5) - (Cr >> 1)
                        + (Cr >> 3) + (Cr >> 4) + (Cr >> 5);
                if (G < 0)
                    G = 0;
                else if (G > 255)
                    G = 255;
                int B = Y + Cb + (Cb >> 1) + (Cb >> 2) + (Cb >> 6);
                if (B < 0)
                    B = 0;
                else if (B > 255)
                    B = 255;
                out[pixPtr++] = (0xff000000 + (B << 16) + (G << 8) + R);
            }
        }

    }

Credit: http://groups.google.com/group/android-developers/browse_thread/thread/c85e829ab209ceea/3f180a16a4872b58?lnk=gst&q=onpreviewframe&pli=1

Upvotes: 2

Related Questions