150

There is a statement in android canvas.drawBitmap(visiblePage, 0, 0, paint);

When I add canvas.rotate(90), there is no effect. But if I write

canvas.rotate(90)
canvas.drawBitmap(visiblePage, 0, 0, paint);

I get no bitmap drawn. So what am I not doing right?

SREE
  • 464
  • 3
  • 20
murli
  • 1,531
  • 2
  • 10
  • 7
  • I have answered this here: http://stackoverflow.com/questions/8608734/android-rotate-bitmap-90-degrees-results-in-squashed-image-need-a-true-rotate-b/14475148#14475148 – EyalBellisha Jan 23 '13 at 08:22

10 Answers10

290

You can also try this one

Matrix matrix = new Matrix();

matrix.postRotate(90);

Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmapOrg, width, height, true);

Bitmap rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);

Then you can use the rotated image to set in your imageview through

imageView.setImageBitmap(rotatedBitmap);
Community
  • 1
  • 1
Aryan
  • 2,909
  • 1
  • 12
  • 2
198
Bitmap source = BitmapFactory.decodeResource(this.getResources(), R.drawable.your_img);

public static Bitmap RotateBitmap(Bitmap source, float angle)
{
      Matrix matrix = new Matrix();
      matrix.postRotate(angle);
      return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}
Arvis
  • 8,273
  • 5
  • 33
  • 46
  • 1
    I'm new with android. Just wondering if I do Bitmap newBitmap = RotateBitmap(oldBitmap, 90), does my 'decoded bitmap' has two memory blocks (for old and new) or are they referring to the same memory, but one is having no rotation, other having rotation?.... My concern is, if I decode R.drawable.picture into oldBitmap, if it suppose takes up 2 MB of memory (Heap I guess?), will newBitmap take additional 2 MB of memory (i.e. 2+2 = 4MB total)? or will the newBitmap only refer to oldBitmap (and thus no extra 2MB is required)? ......... I want to avoid outOfMemory Error at all cost! – Shishir Gupta Mar 01 '14 at 21:59
  • 5
    @ShishirGupta Not tested but by android docs: `If the source bitmap is immutable and the requested subset is the same as the source bitmap itself, then the source bitmap is returned and no new bitmap is created.` – Arvis Mar 03 '14 at 10:30
  • 1
    @Arvis Hey arvis I tried your suggestion and it works for the orientation however now I am getting a much smaller portrait centered image. Any ideas ? – Doug Ray Dec 01 '15 at 02:26
73

Short extension for Kotlin

fun Bitmap.rotate(degrees: Float): Bitmap {
    val matrix = Matrix().apply { postRotate(degrees) }
    return Bitmap.createBitmap(this, 0, 0, width, height, matrix, true)
}

And usage:

val rotatedBitmap = bitmap.rotate(90f)
Pavel Shorokhov
  • 4,485
  • 1
  • 35
  • 44
12

Below is the code to rotate or re size your image in android

public class bitmaptest extends Activity {
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        LinearLayout linLayout = new LinearLayout(this);

        // load the origial BitMap (500 x 500 px)
        Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),
               R.drawable.android);

        int width = bitmapOrg.width();
        int height = bitmapOrg.height();
        int newWidth = 200;
        int newHeight = 200;

        // calculate the scale - in this case = 0.4f
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;

        // createa matrix for the manipulation
        Matrix matrix = new Matrix();
        // resize the bit map
        matrix.postScale(scaleWidth, scaleHeight);
        // rotate the Bitmap
        matrix.postRotate(45);

        // recreate the new Bitmap
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
                          width, height, matrix, true);

        // make a Drawable from Bitmap to allow to set the BitMap
        // to the ImageView, ImageButton or what ever
        BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);

        ImageView imageView = new ImageView(this);

        // set the Drawable on the ImageView
        imageView.setImageDrawable(bmd);

        // center the Image
        imageView.setScaleType(ScaleType.CENTER);

        // add ImageView to the Layout
        linLayout.addView(imageView,
                new LinearLayout.LayoutParams(
                      LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT
                )
        );

        // set LinearLayout as ContentView
        setContentView(linLayout);
    }
}

You can also check this link for details : http://www.anddev.org/resize_and_rotate_image_-_example-t621.html

Arslan Anwar
  • 18,746
  • 19
  • 76
  • 105
8

I would simplify comm1x's Kotlin extension function even more:

fun Bitmap.rotate(degrees: Float) =
    Bitmap.createBitmap(this, 0, 0, width, height, Matrix().apply { postRotate(degrees) }, true)
Gnzlt
  • 4,383
  • 2
  • 22
  • 24
8

Using Java createBitmap() method you can pass the degrees.

Bitmap bInput /*your input bitmap*/, bOutput;
float degrees = 45; //rotation degree
Matrix matrix = new Matrix();
matrix.setRotate(degrees);
bOutput = Bitmap.createBitmap(bInput, 0, 0, bInput.getWidth(), bInput.getHeight(), matrix, true);
Googlian
  • 6,077
  • 3
  • 38
  • 44
5

By default the rotation point is the Canvas's (0,0) point, and my guess is that you may want to rotate it around the center. I did that:

protected void renderImage(Canvas canvas)
{
    Rect dest,drawRect ;

    drawRect = new Rect(0,0, mImage.getWidth(), mImage.getHeight());
    dest = new Rect((int) (canvas.getWidth() / 2 - mImage.getWidth() * mImageResize / 2), // left
                    (int) (canvas.getHeight()/ 2 - mImage.getHeight()* mImageResize / 2), // top
                    (int) (canvas.getWidth() / 2 + mImage.getWidth() * mImageResize / 2), //right
                    (int) (canvas.getWidth() / 2 + mImage.getHeight()* mImageResize / 2));// bottom

    if(!mRotate) {
        canvas.drawBitmap(mImage, drawRect, dest, null);
    } else {
        canvas.save(Canvas.MATRIX_SAVE_FLAG); //Saving the canvas and later restoring it so only this image will be rotated.
        canvas.rotate(90,canvas.getWidth() / 2, canvas.getHeight()/ 2);
        canvas.drawBitmap(mImage, drawRect, dest, null);
        canvas.restore();
    }
}
Haggai
  • 458
  • 1
  • 5
  • 13
1

If you rotate bitmap, 90 180 270 360 is ok but for other degrees canvas will draw bitmap with different size.

So,the best way is

canvas.rotate(degree,rotateCenterPoint.x,rotateCenterPoint.y);  
canvas.drawBitmap(...);
canvas.rotate(-degree,rotateCenterPoint.x,rotateCenterPoint.y);//rotate back
David Wang
  • 934
  • 1
  • 12
  • 16
0

Just be careful of Bitmap type from java platform call like from comm1x's and Gnzlt's answers, because it might return null. I think it is also more flexible if the parameter can be any Number and use infix for readability, depends on your coding style.

infix fun Bitmap.rotate(degrees: Number): Bitmap? {
    return Bitmap.createBitmap(
        this,
        0,
        0,
        width,
        height,
        Matrix().apply { postRotate(degrees.toFloat()) },
        true
    )
}

How to use?

bitmap rotate 90
// or
bitmap.rotate(90)
HendraWD
  • 2,984
  • 2
  • 31
  • 45
-1

In case your goal is to have a rotated image in an imageView or file you can use Exif to achieve that. The support library now offers that: https://android-developers.googleblog.com/2016/12/introducing-the-exifinterface-support-library.html

Below is its usage but to achieve your goal you have to check the library api documentation for that. I just wanted to give a hint that rotating the bitmap isn't always the best way.

Uri uri; // the URI you've received from the other app
InputStream in;
try {
  in = getContentResolver().openInputStream(uri);
  ExifInterface exifInterface = new ExifInterface(in);
  // Now you can extract any Exif tag you want
  // Assuming the image is a JPEG or supported raw format
} catch (IOException e) {
  // Handle any errors
} finally {
  if (in != null) {
    try {
      in.close();
    } catch (IOException ignored) {}
  }
}

int rotation = 0;
int orientation = exifInterface.getAttributeInt(
    ExifInterface.TAG_ORIENTATION,
    ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
  case ExifInterface.ORIENTATION_ROTATE_90:
    rotation = 90;
    break;
  case ExifInterface.ORIENTATION_ROTATE_180:
    rotation = 180;
    break;
  case ExifInterface.ORIENTATION_ROTATE_270:
    rotation = 270;
    break;
}

dependency

compile "com.android.support:exifinterface:25.1.0"

Ultimo_m
  • 4,724
  • 4
  • 38
  • 60