1

At the moment I have the code:

onPreviewFrame(byte[] data)

            int[] rgbs = new int[480*800];
            decodeYUV(rgbs, data, 480, 800);
            Bitmap bitmap = Bitmap.createBitmap(rgbs, 800, 480, Bitmap.Config.ARGB_8888);
            Matrix matrix = new Matrix();
            matrix.postRotate(90);
            Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap,800,480,true);
            Bitmap rotatedBitmap = Bitmap.createBitmap(scaledBitmap , 0, 0, scaledBitmap .getWidth(), scaledBitmap .getHeight(), matrix, true);

            sbut.setImageBitmap(rotatedBitmap);

where the decodeYUV function is found here

The preview is set up like this:

    param.setPreviewSize(800, 480);
    camera.setDisplayOrientation(90);

So the preview is set in portrait mode, Height = 800, Width = 480.

I end up having to go back to landscape to perform the conversion. And then rotate back to portrait again. I can imagine this is quite slow. Is there a more efficient alternative without a double rotation?

I would like to keep the preview in portrait mode. My end result should be that rotatedBitmap above, which is just portrait again. Any lines in the onPreviewFrame method can be changed.

Community
  • 1
  • 1
Greg Peckory
  • 7,700
  • 21
  • 67
  • 114

1 Answers1

0

In your case, I would 'freeze' the Activity in Potrait mode and use Gravity Sensor to check the rotations without Activity or Camera recreation.

to freeze use this:

this.setRequestedOrientation(
                    ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

to rotate I use this code:

public static void rotateNV21(byte[] input, byte[] output, int width, int height, int rotation) {
        try{
        boolean swap = (rotation == 90 || rotation == 270);
        boolean yflip = (rotation == 90 || rotation == 180);
        boolean xflip = (rotation == 270 || rotation == 180);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int xo = x, yo = y;
                int w = width, h = height;
                int xi = xo, yi = yo;
                if (swap) {
                    xi = w * yo / h;
                    yi = h * xo / w;
                }
                if (yflip) {
                    yi = h - yi - 1;
                }
                if (xflip) {
                    xi = w - xi - 1;
                }
                output[w * yo + xo] = input[w * yi + xi];
                int fs = w * h;
                int qs = (fs >> 2);
                xi = (xi >> 1);
                yi = (yi >> 1);
                xo = (xo >> 1);
                yo = (yo >> 1);
                w = (w >> 1);
                h = (h >> 1);
                // adjust for interleave here
                int ui = fs + (w * yi + xi) * 2;
                int uo = fs + (w * yo + xo) * 2;
                // and here
                int vi = ui + 1;
                int vo = uo + 1;
                output[uo] = input[ui]; 
                output[vo] = input[vi]; 
            }
        }
        }catch (IndexOutOfBoundsException e){
            output = input;
        }
    }
Vyacheslav
  • 26,359
  • 19
  • 112
  • 194
  • I would like for it to be always in portrait mode. i.e- rotating phone shouldn't make a difference. – Greg Peckory Jan 25 '16 at 12:11
  • My problem is, the data is received correctly. But to convert the YUV to RGB correctly I need to do it in landscape mode. Then I need to rotate it back to portrait. Is there anyway to do the conversion in portrait? – Greg Peckory Jan 25 '16 at 12:20
  • Is this new code going to make my code more efficient? T – Greg Peckory Jan 25 '16 at 13:36
  • @GregPeckory , this code can help you to rotate YUV data by 90 degs. – Vyacheslav Jan 25 '16 at 13:37
  • I understand, and thanks for the help. But my question was because I don't think this should be necessary. Because my preview frame is in portrait mode already, hence the `setDisplayOrientation(90)`. Why can't the YUV conversion keep it in portrait mode. Why does it need to rotate to landscape to perform correct conversion? Sorry if I'm not making much sense – Greg Peckory Jan 25 '16 at 13:43
  • @GregPeckory , I think this is because of the concept of UYV420 data format storage. The idea is to use not only current pixel but whole neighbour field. If you recreate camera (unlock, release) with the other dimentions you will receieve pure landscape data. – Vyacheslav Jan 25 '16 at 13:54