0

This question has been asked many times already but i cannot seem to find what i want exactly. I am trying to create a camera app where I want to display the YUV or RGB value into the log when I point my camera to some color. The values must me 0...255 range for RGB or correspondent YUV color format. I can manage the conversion between them as there are many such examples on stack overflow. However, i cannot store the values into 3 separate variables and display them in the log.

so far i have managed to get

package com.example.virus.bpreader;

public class CaptureVideo extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback {

private SurfaceHolder mHolder;
private Camera mCamera;
private int[] pixels;

public CaptureVideo(Context context, Camera cameraManager) {
    super(context);

    mCamera = cameraManager;
    mCamera.setDisplayOrientation(90);

    //get holder and set the class as callback
    mHolder = getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
}

@Override
public void surfaceCreated(SurfaceHolder holder) {

    //when the surface is created, let the camera start the preview
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
        mCamera.cancelAutoFocus();

        Camera.Parameters params = mCamera.getParameters();
        //get fps
        params.getSupportedPreviewFpsRange();
        //get resolution
        params.getSupportedPreviewSizes();
        //stop auto exposure
        params.setAutoExposureLock(false);

        // Check what resolutions are supported by your camera
        List<Camera.Size> sizes = params.getSupportedPictureSizes();
        // Iterate through all available resolutions and choose one
        for (Camera.Size size : sizes) {
            Log.i("Resolution", "Available resolution: " + size.width + " " + size.height);
        }
        //set resolution at 320*240
        params.setPreviewSize(320,240);

        //set frame rate at 10 fps
        List<int[]> frameRates = params.getSupportedPreviewFpsRange();
        int last = frameRates.size() - 1;
        params.setPreviewFpsRange(10000, 10000);
        //set Image Format
        //params.setPreviewFormat(ImageFormat.NV21);
        mCamera.setParameters(params);


    } catch (IOException e) {
        e.printStackTrace();
    }


}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    //need to stop the preview and restart on orientation change
    if (mHolder.getSurface() == null) {
        return;
    }
    //stop preview
    mCamera.stopPreview();

    //start again
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
    } catch (IOException e) {
        e.printStackTrace();
    }


}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    //stop and release
    mCamera.startPreview();
    mCamera.release();
}

@Override
public void onPreviewFrame(byte[] data, Camera camera) {

    int frameHeight = camera.getParameters().getPreviewSize().height;
    int frameWidth = camera.getParameters().getPreviewSize().width;
    // number of pixels//transforms NV21 pixel data into RGB pixels
    int rgb[] = new int[frameWidth * frameHeight];
    // convertion
    int[] myPixels = decodeYUV420SP(rgb, data, frameWidth, frameHeight);

    Log.d("myPixel", String.valueOf(myPixels.length));

}

//yuv decode
int[] decodeYUV420SP(int[] rgb, 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 RGB
            rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) | 0xff);
        }
    }
return rgb;
}
}

Here the decode method should give a hex format of RGB color space (quite sure its all right as most of the answers are the same). The problem i am facing is when i am not quite sure how to call it inside the OnPreviewFrame method so that it displays the RGB values separately into the log.

N.B like i said i have seen lot of similar questions but could not find a solution to it. I do not want to store the file (image/video) as i only need the RGB/YUV values from the live camera preview when i point the camera to some color.

I need the rgb or yuv values because i want to plot a graph out of it against time.

Any help will be much appreciated.

Mill3r
  • 544
  • 1
  • 10
  • 31
  • You're not getting any values inside the `onPreviewFrame` method? inside your log? – MadScientist Sep 28 '17 at 10:08
  • exactly my problem. i updated the question with how i was trying to get values inside onPreviewFrame. but from what i understand, myPixels will return an array. how do i separate it into RGB? – Mill3r Sep 28 '17 at 10:09
  • Are you sure that your device supports 320x240 pixel resolution and 10 FPS? Even if it does, the logcat cannot print out ~230K integers 10 times per second. You can print out RGB at one pixel at this rate. – Alex Cohn Sep 28 '17 at 12:11
  • yes it does support both the resolution and fps. but i did not actually get what you mean by ~230K integers.. previously i was using opencv and there it did print out the RGB values correctly.. However, there i could not control the fps nor resolution hence i started using the camera api. – Mill3r Sep 28 '17 at 14:31

1 Answers1

0

Well if the problem is to get separate values of R, G And B from the RGB array, check this SO post here.

Hope it helps!

MadScientist
  • 2,134
  • 14
  • 27
  • i tried to follow this but for some reason if i log something inside the decode or onPreviewFrame i do not get any this on the logcat. – Mill3r Sep 28 '17 at 10:26
  • you wont because you method, `decodeYUV` returns void. hence your pixel array is empty. ` int[] myPixels = decodeYUV420SP(rgb, data, frameWidth, frameHeight);` Thus, try making rgb[] return from the method, or use the data[] to log RGB values. – MadScientist Sep 28 '17 at 10:30
  • i did that after i posted this question. i changed void to `int[]`, and added `return rgb;` in the end. then when i add `int color = (int)Long.parseLong(myPixels, 16); int r = (color >> 16) & 0xFF; int g = (color >> 8) & 0xFF; int b = (color >> 0) & 0xFF` inside `onPreviewFrame`, it ask me to add String.valueOf. I did that too. but still no use. – Mill3r Sep 28 '17 at 10:39
  • ok. do one thing, log the array values. like log `myPixels.length` just to check if its not 0 – MadScientist Sep 28 '17 at 10:44
  • I have updated the code. Can you take a look at it again please and tell me if the way im trying to log inside onPreviewFrame is correct. I am not getting anything return in log. Also take another look at the decode method. i apologies for the trouble. – Mill3r Sep 28 '17 at 11:07
  • You're not getting any logs or you're not getting any value in the logs? also, try logging `data.length` once. your code otherwise seems perfectly well – MadScientist Sep 28 '17 at 11:57
  • You see I have give a myPixel tag to the log. So when I filter the log with that tag, the logcat is empty.. nothing shows up... I am really confused what is happening.. – Mill3r Sep 28 '17 at 12:05
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/155524/discussion-between-mill3r-and-madscientist). – Mill3r Sep 28 '17 at 14:28