Resize and Rotate Image - Example

Basic Tutorials concerning: GUI, Views, Activites, XML, Layouts, Intents, ...

Resize and Rotate Image - Example

Postby mauri » Mon Jan 21, 2008 5:28 pm

Resize and Rotate Image - Example


What you learn: You will learn how to rotate ans resize images(Bitmaps) using a Matrix.

:?: Problems/Questions: Write them right below...

Difficulty: 1 of 5 :)

The source:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public class bitmaptest extends Activity {
  2.     @Override
  3.     public void onCreate(Bundle icicle) {
  4.         super.onCreate(icicle);
  5.         LinearLayout linLayout = new LinearLayout(this);
  6.        
  7.         // load the origial BitMap (500 x 500 px)
  8.         Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),
  9.                R.drawable.android);
  10.        
  11.         int width = bitmapOrg.width();
  12.         int height = bitmapOrg.height();
  13.         int newWidth = 200;
  14.         int newHeight = 200;
  15.        
  16.         // calculate the scale - in this case = 0.4f
  17.         float scaleWidth = ((float) newWidth) / width;
  18.         float scaleHeight = ((float) newHeight) / height;
  19.        
  20.         // createa matrix for the manipulation
  21.         Matrix matrix = new Matrix();
  22.         // resize the bit map
  23.         matrix.postScale(scaleWidth, scaleHeight);
  24.         // rotate the Bitmap
  25.         matrix.postRotate(45);
  26.  
  27.         // recreate the new Bitmap
  28.         Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
  29.                           width, height, matrix, true);
  30.    
  31.         // make a Drawable from Bitmap to allow to set the BitMap
  32.         // to the ImageView, ImageButton or what ever
  33.         BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
  34.        
  35.         ImageView imageView = new ImageView(this);
  36.        
  37.         // set the Drawable on the ImageView
  38.         imageView.setImageDrawable(bmd);
  39.      
  40.         // center the Image
  41.         imageView.setScaleType(ScaleType.CENTER);
  42.        
  43.         // add ImageView to the Layout
  44.         linLayout.addView(imageView,
  45.                 new LinearLayout.LayoutParams(
  46.                       LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT
  47.                 )
  48.         );
  49.        
  50.         // set LinearLayout as ContentView
  51.         setContentView(linLayout);
  52.     }
  53. }
Parsed in 0.036 seconds, using GeSHi 1.0.8.4
Attachments
android.png
Image for the Example
android.png (24.2 KiB) Viewed 297357 times
User avatar
mauri
Junior Developer
Junior Developer
 
Posts: 13
Joined: Tue Dec 04, 2007 7:14 pm

Top

Postby plusminus » Mon Jan 21, 2008 5:37 pm

Hello mauri,

thx for sharing your code, never realized the Matrix-Parameter in Bitmap.createBitmap, is damn useful :)

Best Regards,
plusminus

PS: Added some introducing lines to your code
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby venkat » Tue Jan 22, 2008 6:08 am

Thanks mauri, this is what exactly i am looking for.
Regards,
Venkat.
venkat
Senior Developer
Senior Developer
 
Posts: 152
Joined: Tue Nov 27, 2007 5:42 am
Location: India

real time transformation

Postby ecelino » Fri Mar 21, 2008 8:22 pm

thank you. i've been looking for this code.

but this is a bit expensive in processing and memory usage. it will be a lot better if we can do this in real time. does anyone knows how?

i am trying to create a game and i used BitmapDrawable to hold my .png images. i need a way to transform my BitmapDrawable objects in real time without creating new BitmapDrawable whenever i want to transform the image.

also, does anyone knows how to apply transformation to an existing BitmapDrawble object? again, without creating new one.

thank you very much.
ecelino
Once Poster
Once Poster
 
Posts: 1
Joined: Mon Feb 18, 2008 1:26 pm

Rotating using matrix continuously shrinks the image.

Postby chonada » Fri Mar 28, 2008 9:23 am

I am doing a photoeditor application and we have a button to rotate the image in the canvas (which is actually an image switcher), now while i did the rotation using the Matrix, i found that the image is shrinking when rotating (noticeable when rotating continuously), code snippet given below, any suggestions will be appreciated.
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. mSwitcher.setDrawingCacheEnabled(true);         // mSwitcher is the ImageSwitcher
  3.  
  4. bmp = mSwitcher.getDrawingCache();
  5.  
  6. aMatrix = new Matrix();
  7.  
  8. aMatrix.setRotate(90.0f);
  9.  
  10. flippedBmp = Bitmap.createBitmap(bmp, 0, 0, bmp.width(), bmp.height(), aMatrix, false);
  11.  
  12. mSwitcher.setImageDrawable(new BitmapDrawable(flippedBmp));
  13.  
  14. mSwitcher.setDrawingCacheEnabled(false);
  15.  
  16.  
Parsed in 0.033 seconds, using GeSHi 1.0.8.4

Thanx in advance.
chonada
Once Poster
Once Poster
 
Posts: 1
Joined: Mon Mar 03, 2008 5:40 am

Postby plusminus » Fri Mar 28, 2008 2:19 pm

Hello chonada,

maybe this is a float-number accuracy problem, as if [font=Lucida Console]90.0f ~= 90[/font] :?

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Top

Re: real time transformation

Postby wonderoid » Fri Mar 28, 2008 3:55 pm

ecelino wrote:thank you. i've been looking for this code.

but this is a bit expensive in processing and memory usage. it will be a lot better if we can do this in real time. does anyone knows how?

i am trying to create a game and i used BitmapDrawable to hold my .png images. i need a way to transform my BitmapDrawable objects in real time without creating new BitmapDrawable whenever i want to transform the image.

also, does anyone knows how to apply transformation to an existing BitmapDrawble object? again, without creating new one.

thank you very much.

Modifying the rotation/ scaling of the canvas you are drawing on should do it. I used it for drawing paths, and don't know if it will work for bitmaps but why wouldn't it? C being a canvas object you can
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. c.scale(scaleFactorX, scaleFactorY);
  2.  
  3. c.translate(dX, dY);
Parsed in 0.034 seconds, using GeSHi 1.0.8.4

and also rotate it.
(Btw do not forget to push your current state into stack otherwise you will be altering the canvas cumulatively, probably not what you want. It is simply;
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.         canvas.save();
  2.  
  3.         // do whatever
  4.  
  5.         canvas.restore();
Parsed in 0.035 seconds, using GeSHi 1.0.8.4

)
wonderoid
Junior Developer
Junior Developer
 
Posts: 10
Joined: Sat Feb 16, 2008 10:33 pm

Postby kiran » Tue Apr 01, 2008 6:42 am

Hi,

Using this code, the image displayed is resized again to 600x600 on a keypress Now the initial values of x and y are not correct. The image gets displayed starting from the x,y coordinates of the previously displayed image. And if an image with bigger dimension is rotated the application crashes after some continuous rotations. pls help..

Thanks in andvance
:) smile it is the key that fits the lock of everybody's heart
User avatar
kiran
Experienced Developer
Experienced Developer
 
Posts: 78
Joined: Thu Nov 22, 2007 11:36 am
Location: India

great rotating the canvas rotates the image now????

Postby rahul_mawkins » Wed Apr 02, 2008 12:29 am

How do we rotate the canvas with angle x so that while moving the tip of the arrow is always in the path direction
i.e driving direction

Any help will be rewarded
cheers
RM
rahul_mawkins
Developer
Developer
 
Posts: 34
Joined: Wed Feb 27, 2008 4:09 am

help with some modification to existing code

Postby neel » Thu Oct 23, 2008 4:46 am

Hi,

i made a small modification just for testing purpose and need some help.

i basically have a for loop which goes from 1 to 5 and i want to see the image being rotated 5 times i.e once every time the for loop iterates from 1 to 5. basically i just give a call to 'make()' function which has the code for drawing and displaying the image.

however, when i run the code, i see the image being rotated only once. please can you help me resolve this. is there some function that i need to call explicitly every time to let the Android system display the image on screen for every rotation.

here is the code that i am testing.

Code: Select all
package com.d5;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.ImageView.ScaleType;


public class Test extends Activity {



   float degrees =0;
   Thread t;
    @Override
    public void onCreate(Bundle icicle) {
       android.util.Log.i("ACTIVITY STARTED", "start");
        super.onCreate(icicle);

       begin();

    }

    public void begin(){

    t = new Thread(){
          public void run(){
           android.util.Log.i("INSIDE RUN", "inside run");
         for ( int j = 1; j <=5; j++){// for starts

              android.util.Log.i("INSIDE FOR", "inside for");

               try{
               degrees+=10;
              android.util.Log.i("Degrees: ",String.valueOf(degrees));
                   make(degrees);
                android.util.Log.i("CAME BACK FROM MAKE", "");
                   // i just want the code to wait 3 sec before it rotates the image again
                   sleep(3000);
               }catch(Exception e){
                  e.printStackTrace();
               }

           }// for ends

       }// run ends

    };// thread ends

  t.start();


}// start ends

    public void make(float x){
       android.util.Log.i("INSIDE MAKE", "inside make");
        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(x);

        // 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 inearLayout as ContentView
        setContentView(linLayout);


        android.util.Log.i("GOING OUT OF MAKE", "going out of make");
    }

}



please help, thank you
neel
Developer
Developer
 
Posts: 31
Joined: Fri Feb 15, 2008 5:09 am
Location: San Jose

Postby plusminus » Thu Oct 23, 2008 6:44 am

You should call setContentView only once in onCreate() :!:

You'd create a View (maybe extend ImageView), which has a method to draw its content rotated.

Best Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby neel » Thu Oct 23, 2008 7:13 am

Hi plusminus,

is is possible for you to please provide some code snippet for doing that.

I initially had this code where on click of 'KEY_EVENT' i was able to rotate the image clockwise and anti-clockwise. I want to remove the KEY_EVENT and just make it work using a for loop.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. import android.app.Activity;
  3.  
  4. import android.graphics.Bitmap;
  5.  
  6. import android.graphics.BitmapFactory;
  7.  
  8. import android.graphics.Matrix;
  9.  
  10. import android.graphics.drawable.BitmapDrawable;
  11.  
  12. import android.os.Bundle;
  13.  
  14. import android.view.KeyEvent;
  15.  
  16. import android.view.ViewGroup.LayoutParams;
  17.  
  18. import android.widget.ImageView;
  19.  
  20. import android.widget.LinearLayout;
  21.  
  22. import android.widget.ImageView.ScaleType;
  23.  
  24.  
  25.  
  26. public class bitmaptest extends Activity {
  27.  
  28.         float degrees =0;
  29.  
  30.     @Override
  31.  
  32.     public void onCreate(Bundle icicle) {
  33.  
  34.         super.onCreate(icicle);
  35.  
  36.         make(degrees);
  37.  
  38.     }
  39.  
  40.     public void make(float x){
  41.  
  42.         android.util.Log.i("INSIDE MAKE", "inside make");
  43.  
  44.         LinearLayout linLayout = new LinearLayout(this);
  45.  
  46.        
  47.  
  48.         // load the origial BitMap (500 x 500 px)
  49.  
  50.         Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),
  51.  
  52.                R.drawable.android);
  53.  
  54.        
  55.  
  56.         int width = bitmapOrg.width();
  57.  
  58.         int height = bitmapOrg.height();
  59.  
  60.         int newWidth = 200;
  61.  
  62.         int newHeight = 200;
  63.  
  64.        
  65.  
  66.         // calculate the scale - in this case = 0.4f
  67.  
  68.         float scaleWidth = ((float) newWidth) / width;
  69.  
  70.         float scaleHeight = ((float) newHeight) / height;
  71.  
  72.        
  73.  
  74.         // createa matrix for the manipulation
  75.  
  76.         Matrix matrix = new Matrix();
  77.  
  78.         // resize the bit map
  79.  
  80.         matrix.postScale(scaleWidth, scaleHeight);
  81.  
  82.         // rotate the Bitmap
  83.  
  84.         matrix.postRotate(x);
  85.  
  86.  
  87.  
  88.         // recreate the new Bitmap
  89.  
  90.         Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
  91.  
  92.                           width, height, matrix, true);
  93.  
  94.    
  95.  
  96.         // make a Drawable from Bitmap to allow to set the BitMap
  97.  
  98.         // to the ImageView, ImageButton or what ever
  99.  
  100.         BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
  101.  
  102.        
  103.  
  104.         ImageView imageView = new ImageView(this);
  105.  
  106.        
  107.  
  108.         // set the Drawable on the ImageView
  109.  
  110.         imageView.setImageDrawable(bmd);
  111.  
  112.      
  113.  
  114.         // center the Image
  115.  
  116.         imageView.setScaleType(ScaleType.CENTER);
  117.  
  118.        
  119.  
  120.         // add ImageView to the Layout
  121.  
  122.         linLayout.addView(imageView,
  123.  
  124.           new LinearLayout.LayoutParams(
  125.  
  126.                       LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT
  127.  
  128.                 )
  129.  
  130.         );
  131.  
  132.        
  133.  
  134.         // set LinearLayout as ContentView
  135.  
  136.         setContentView(linLayout);
  137.  
  138.         android.util.Log.i("GOING OUT MAKE", "going out make");
  139.  
  140.     }
  141.  
  142.     @Override
  143.  
  144.     public boolean onKeyDown(int keyCode, KeyEvent event) {
  145.  
  146.          
  147.  
  148.          if(keyCode==KeyEvent.KEYCODE_DPAD_UP)// rotate clockwise
  149.  
  150.              // zoomControler+=10;
  151.  
  152.                 {
  153.  
  154.                  degrees=degrees+10;
  155.  
  156.                 make(degrees);
  157.  
  158.                  //make(10);
  159.  
  160.                  android.util.Log.i("ONE","rotating clockwise by "+String.valueOf(degrees)+" degrees");
  161.  
  162.                  android.util.Log.i("DEGREES","current value "+String.valueOf(degrees)+" degrees");
  163.  
  164.                 }
  165.  
  166.          
  167.  
  168.          
  169.  
  170.          if(keyCode==KeyEvent.KEYCODE_DPAD_DOWN) // rotate anti-clockwise
  171.  
  172.          {
  173.  
  174.                  degrees=degrees-10;
  175.  
  176.                  make(degrees);
  177.  
  178.                  //make(10);
  179.  
  180.                  android.util.Log.i("TWO","rotating anti-clockwise by "+String.valueOf(degrees)+" degrees");
  181.  
  182.                  android.util.Log.i("DEGREES","current value "+String.valueOf(degrees)+" degrees");
  183.  
  184.                  
  185.  
  186.          }
  187.  
  188.          
  189.  
  190.         // invalidate();
  191.  
  192.          return true;
  193.  
  194.     }
  195.  
  196. }
  197.  
  198.  
Parsed in 0.051 seconds, using GeSHi 1.0.8.4
neel
Developer
Developer
 
Posts: 31
Joined: Fri Feb 15, 2008 5:09 am
Location: San Jose

do you have any idea, to make it smooth when rotating?

Postby weldrian » Fri Dec 19, 2008 4:52 am

HI man, thx for the code above, i need that for reference,

i dont mind to click up and down for the rotation;
but do you have any idea, to make it smooth when rotating?
weldrian
Junior Developer
Junior Developer
 
Posts: 23
Joined: Tue Dec 09, 2008 1:30 am

Re: Rotating using matrix continuously shrinks the image.

Postby Kevin Prichard » Sat Jan 24, 2009 8:42 pm

chonada wrote:I am doing a photoeditor application and we have a button to rotate the image in the canvas (which is actually an image switcher), now while i did the rotation using the Matrix, i found that the image is shrinking when rotating (noticeable when rotating continuously), code snippet given below, any suggestions will be appreciated.
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. mSwitcher.setDrawingCacheEnabled(true);         // mSwitcher is the ImageSwitcher
  2. bmp = mSwitcher.getDrawingCache();
  3. aMatrix = new Matrix();
  4. aMatrix.setRotate(90.0f);
  5. <span style="font-weight: bold">flippedBmp = Bitmap.createBitmap(bmp, 0, 0, bmp.width(), bmp.height(), aMatrix, false)</span>
  6. mSwitcher.setImageDrawable(new BitmapDrawable(flippedBmp));
  7. mSwitcher.setDrawingCacheEnabled(false);
  8.  
Parsed in 0.037 seconds, using GeSHi 1.0.8.4

Thanx in advance.


chonada,

Assuming you are running the above code for each step of a rotation, you are first grabbing bmp from mSwitcher, then rotating it, then putting it back into mSwitcher, right? Once the bmp is rotated into flippedBmp, its dimensions are changed, and are greater. But I think that the classes used will fit the rotated image within the target drawing area, which means shrinking.

Think of the diagonal distances, from corner to corner: if you rotate bmp 45 deg, the width and height of flippedBmp are now greater than the original bmp.

You need to have a bmp that is at least as large as the maximum line distance found in the original bmp, in each dimension. Remember the Pythagorean theorem. With the original image spec of w * h, the image resulting from the rotation will need to be sqrt(w^2 + h^2) in both dimensions, to prevent shrinkage, to give it the maximum room needed to arbitrarily rotate without shrinking.

Try changing

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. flippedBmp = Bitmap.createBitmap(bmp, 0, 0, bmp.width(), bmp.height(), aMatrix, false)
  3.  
  4.  
Parsed in 0.037 seconds, using GeSHi 1.0.8.4


to

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. flippedBmp = Bitmap.createBitmap(bmp, 0, 0, Math.hypot(bmp.width(), bmp.height()), Math.hypot(bmp.width(), bmp.height()), aMatrix, false)
  3.  
  4.  
Parsed in 0.037 seconds, using GeSHi 1.0.8.4


This is just a wild guess, haven't run your code, but I have encountered this in the past.
Kevin Prichard
Software Engineer
Kevin Prichard
Once Poster
Once Poster
 
Posts: 1
Joined: Sat Jan 24, 2009 8:14 pm

Postby ranjit0046 » Tue Mar 02, 2010 2:35 pm

plusminus wrote:You should call setContentView only once in onCreate() :!:

You'd create a View (maybe extend ImageView), which has a method to draw its content rotated.

Best Regards,
plusminus



Hi plusminus,

i have a problem that is how to move an image on the emulator screen when i click the button.
i tried several ways but i am unable to get the solution please help me.

regards,
Jack
ranjit0046
Developer
Developer
 
Posts: 47
Joined: Mon Dec 14, 2009 12:46 pm

Top
Next

Return to Novice Tutorials

Who is online

Users browsing this forum: No registered users and 6 guests