Rotate byte array of JPEG after onPictureTaken
Asked Answered
S

4

17

Is there a way to rotate byte array without decoding it to Bitmap?

Currently in jpeg PictureCallback I just write byte array directly to file. But pictures are rotated. I would like to rotate them without decoding to bitmap with hope that this will conserve my memory.

    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;
    BitmapFactory.decodeByteArray(data, 0, data.length, o);

    int orientation;
    if (o.outHeight < o.outWidth) {
        orientation = 90;
    } else {
        orientation = 0;
    }

    File photo = new File(tmp, "demo.jpeg");

    FileOutputStream fos;
    BufferedOutputStream bos = null;
    try {
        fos = new FileOutputStream(photo);
        bos = new BufferedOutputStream(fos);
        bos.write(data);
        bos.flush();
    } catch (IOException e) {
        Log.e(TAG, "Failed to save photo", e);
    } finally {
        IOUtils.closeQuietly(bos);
    }
Sung answered 20/5, 2013 at 14:34 Comment(3)
Hi. Did you managed to do this ? Thanks man.Triste
@Paul: see https://mcmap.net/q/708226/-rotate-byte-array-of-jpeg-after-onpicturetakenLivvie
How can you use androidmediautil to solve this problem?Adur
S
2

I don't think that there is such possibility. Bytes order depends from picture encoding (png, jpeg). So you are forced to decode image to do something with it.

Systematic answered 20/5, 2013 at 14:44 Comment(2)
But Android documentation states that public final void takePicture (Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg). So in Camera.PictureCallback jpeg I will always receive JPEG image data.Sung
But there is no method to rotate jpeg. Best thing you can do is to change Exif data. Not everything support this and it wont be true rotate.Systematic
B
5

Try this. It will solve the purpose.

Bitmap storedBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, null);

Matrix mat = new Matrix();                        
mat.postRotate("angle");  // angle is the desired angle you wish to rotate            
storedBitmap = Bitmap.createBitmap(storedBitmap, 0, 0, storedBitmap.getWidth(), storedBitmap.getHeight(), mat, true);
Breakfast answered 22/8, 2013 at 17:0 Comment(2)
Please, read the question - I need to rotate byte array without decoding it to Bitmap.Sung
clearly mentioned that rotation needs to be done without decoding.Adur
L
3

You can set JPEG rotation via Exif header without decoding it. This is the most efficient method, but some viewers may still show a rotated image.

Alternatively, you can use JPEG lossless rotation. Unfortunately, I am not aware of free Java implementations of this algorithm.

Update on SourceForge, there is a Java open source class LLJTran. The Android port is on GitHub.

Livvie answered 20/5, 2013 at 17:46 Comment(5)
Have you tried LLJtran for Android? It take 16s to rotate 2M jpeg file tested on Samsung Galaxy S1. Anyway to shorten the process time?Cobra
Oh, too bad. Thanks for sharing. I will give it a look in spare time.Livvie
Please have on a look on this to see if I have done something wrong with the library.Cobra
Is there a simpler way to rotate and store full size image from the byte array without converting it to bitmap @AlexCohnAdur
@therealprashant: unfortunately, there does not seem to be one. As many commenters noticed, LLJTran is not up to this challenge with the present-day typical picture sizes, memory and CPU.Livvie
S
2

I don't think that there is such possibility. Bytes order depends from picture encoding (png, jpeg). So you are forced to decode image to do something with it.

Systematic answered 20/5, 2013 at 14:44 Comment(2)
But Android documentation states that public final void takePicture (Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg). So in Camera.PictureCallback jpeg I will always receive JPEG image data.Sung
But there is no method to rotate jpeg. Best thing you can do is to change Exif data. Not everything support this and it wont be true rotate.Systematic
F
2

Try like this,

private byte[] rotateImage(byte[] data, int angle) {
    Log.d("labot_log_info","CameraActivity: Inside rotateImage");
    Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length, null);
    Matrix mat = new Matrix();
    mat.postRotate(angle);
    bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream);
    return stream.toByteArray();
}

You can call the rotateImage by providing the image data which is getting from onPictureTaken method and an angle for rotation.

Eg: rotateImage(data, 90);

Fizz answered 15/9, 2021 at 16:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.