Rotating images on android. Is there a better way?

后端 未结 3 1010
-上瘾入骨i
-上瘾入骨i 2020-12-31 13:48

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 curr

相关标签:
3条回答
  • 2020-12-31 14:20

    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();
        }
      }
    
    0 讨论(0)
  • 2020-12-31 14:21

    When working with lots of Bitmaps be sure to call recycle() on them as soon as they are not needed. This call will instantly free memory associated with a particular bitmap.

    In your case if you do not need the original bitmap after rotation, then recycle it. Something along the lines of:

    Bitmap result = bmp;
    
    // 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);
        result = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true);
        // rotating done, original not needed => recycle()
        bmp.recycle();
    }
    
    image.setImageBitmap(result);
    
    0 讨论(0)
  • 2020-12-31 14:23

    you can try:

    image.setImageBitmap(null);
    // 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);
    }
    BitmapDrawable bd = new BitmapDrawable(mContext.getResources(), bmp);
    bmp.recycle();
    bmp = null;
    setImageDrawable(bd);
    bd = null;
    
    0 讨论(0)
提交回复
热议问题