Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotating images on android. Is there a better way?

I have an app that displays quite a few images for the user, and we've been seeing a lot of error reports with OutOfMemoryError exception.

What we currently do is this:

// Check if image is a landscape image
if (bmp.getWidth() > bmp.getHeight()) {
    // Rotate it to show as a landscape
    Matrix m = image.getImageMatrix();
    m.postRotate(90);
    bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true);
}
image.setImageBitmap(bmp);

The obvious problem with this is that we have to recreate the bitmap from the image on memory and rotate the matrix, this is quite expensive for the memory.

My question is simple:

Is there a better way to rotate images without causing OutOfMemoryError?

like image 461
Draiken Avatar asked Nov 28 '11 11:11

Draiken


People also ask

How do I rotate a picture without losing quality?

To perform a lossless left/right rotate or vertical/horizontal flip, go to Tools > JPEG Lossless Rotate. Alternatively, you can also find the Tools menu by right clicking on the image. The rotate clockwise or counterclockwise icons are also lossless for JPEG files.

Does rotating photos reduce quality?

The short answer is “no.” The camera's sensor elements (sensels) are arranged in a grid and the resultant picture elements (pixels) are arranged in a grid.


1 Answers

2 methods of rotating a large image:

  1. using JNI , like on this post.

  2. using a file : it's a very slow way (depending on the input and the device , but still very slow) , which puts the decoded rotated image into the disk first , instead of putting it into the memory .

code of using a file is below:

private void rotateCw90Degrees()
  {
  Bitmap bitmap=BitmapFactory.decodeResource(getResources(),INPUT_IMAGE_RES_ID);
  // 12 => 7531
  // 34 => 8642
  // 56 =>
  // 78 =>
  final int height=bitmap.getHeight();
  final int width=bitmap.getWidth();
  try
    {
    final DataOutputStream outputStream=new DataOutputStream(new BufferedOutputStream(openFileOutput(ROTATED_IMAGE_FILENAME,Context.MODE_PRIVATE)));
    for(int x=0;x<width;++x)
      for(int y=height-1;y>=0;--y)
        {
        final int pixel=bitmap.getPixel(x,y);
        outputStream.writeInt(pixel);
        }
    outputStream.flush();
    outputStream.close();
    bitmap.recycle();
    final int newWidth=height;
    final int newHeight=width;
    bitmap=Bitmap.createBitmap(newWidth,newHeight,bitmap.getConfig());
    final DataInputStream inputStream=new DataInputStream(new BufferedInputStream(openFileInput(ROTATED_IMAGE_FILENAME)));
    for(int y=0;y<newHeight;++y)
      for(int x=0;x<newWidth;++x)
        {
        final int pixel=inputStream.readInt();
        bitmap.setPixel(x,y,pixel);
        }
    inputStream.close();
    new File(getFilesDir(),ROTATED_IMAGE_FILENAME).delete();
    saveBitmapToFile(bitmap); //for checking the output
    }
  catch(final IOException e)
    {
    e.printStackTrace();
    }
  }
like image 103
android developer Avatar answered Nov 15 '22 19:11

android developer