Интересующая область

Мне интересно захватить только часть cameraPreview. У меня есть прямоугольник с onTouchListener. Я могу использовать это, чтобы перетащить интересующую меня область в любое место на предварительном просмотре камеры. Моя конечная цель — захватить только ту часть предварительного просмотра. Но я не могу найти способ. Есть ли какой-либо API, который я могу использовать? Может ли кто-нибудь вести меня здесь.

Спасибо


person user682765    schedule 21.04.2011    source источник


Ответы (1)


В известном мне API нет поддержки для этого, но я успешно сделал что-то подобное.

В основном вам нужно:

  • реализовать Camera.PreviewCallback
  • декодировать кадр предварительного просмотра YUV в RGB
  • сделать временную растровую карту из байтов RGB
  • масштабируйте прямоугольник от вашего прямоугольника на экране до соответствующего размера для размеров предварительного просмотра
  • затем, наконец, используйте createBitmap (источник растрового изображения, int x, int y, int width, int height), чтобы обрезать новое растровое изображение из временного.

Обратите внимание, что декодер YUV, поддерживаемый API, отсутствует до FROYO через класс YuvImage, который вы можете использовать примерно так:

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

Если вы собираетесь поддерживать только 2.2 и более поздние версии, вы можете пропустить временное растровое изображение и использовать YuvImage.compressToJpeg для обрезки до вашего масштабированного прямоугольника.

Для версий ОС до 2.2 вам понадобится собственная реализация декодирования YUV, которую можно сделать следующим образом:

/**
     * 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);
            }
        }

    }

Источник: http://groups.google.com/group/android-developers/browse_thread/thread/c85e829ab209ceea/3f180a16a4872b58?lnk=gst&q=onpreviewframe&pli=1

person mmeyer    schedule 21.04.2011