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);
    }
Martynas Jurkus
  • 9,231
  • 13
  • 59
  • 101

4 Answers4

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);
user2453055
  • 975
  • 1
  • 9
  • 19
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.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • 1
    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? – Yeung Sep 02 '14 at 04:15
  • Oh, too bad. Thanks for sharing. I will give it a look in spare time. – Alex Cohn Sep 02 '14 at 06:22
  • Please have on a look on [this](http://stackoverflow.com/a/25603218/1099884) to see if I have done something wrong with the library. – Yeung Sep 02 '14 at 08:01
  • Is there a simpler way to rotate and store full size image from the byte array without converting it to bitmap @AlexCohn – therealprashant Feb 26 '15 at 05:22
  • @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. – Alex Cohn Feb 28 '15 at 10:57
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.

user123
  • 1,053
  • 15
  • 27
  • 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. – Martynas Jurkus May 20 '13 at 14:54
  • 1
    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. – user123 May 20 '13 at 14:57
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);

Codemaker2015
  • 12,190
  • 6
  • 97
  • 81