Animating bitmap image in android - android

I have created a bitmap image which is a circle and than as I wanted to animate it so i converted it into bitmapdrawable and than added it to animation drawable..But due to this the circle shaped has changed to oval shape...
So what should I do ?
Is there any other method to animate only the bitmap file. ?
Thanks in advance..

If you're using Canvas, I'd suggest holding a pointer to the current Bitmap and loading all other Bitmaps into an array.
Say,
Bitmap[] frames = new Bitmap[10] //10 frames
Bitmap frame[0] = BitmapFactory.decodeResource(getResources(), R.drawable.circlefram1);
Bitmap frame[1] = BitmapFactory.decodeResource(getResources(), R.drawable.circlefram2);
...
Select the currentFrame by pointing at the frame you're interested in.
Bitmap currentBitmap = frame[3]; // 4th frame
So when you call drawBitmap(currentBitmap) it will only draw the frame you are interested in. You can change the bitmap every so many frames, by assigning an fps to the frame animation.
If you just want to scale or rotate the bitmap (rotating a circle?), the best way to resize a bitmap is using createScaledBitmap, and rotating using a matrix.
For Scaling, you load any bitmap into memory like this
Bitmap circleBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.circle);
If you would like the circle (or any bitmap) rescaled you would do something like this:
Bitmap scaledCircle = Bitmap.createScaledBitmap(circleBitmap, dstWidth, dstHeight, filter);
Where dstWidth and dstHeight are the target destination width and height, which you can previously calculate by scaling the original width and height.
int scaledHeight = circleBitmap.getHeight()/2;
int scaledWidth = circleBitmap.getWidth()/2;
And finally you would normally draw this Bitmap using a canvas like this
canvas.drawBitmap(bitmap)
For rotating, create a Matrix
Matrix mat;
mat.postRotate(degrees); // Rotate the matrix
Bitmap rotatedBitmap = Bitmap.createBitmap(originalBitmap, x, y, width, height, mat, filter);
and finally
canvas.drawBitmap(rotatedBitmap);
Keep in mind Canvases are slow for games or anything real-time!
Hope it helps.

no, you can not animate the bitmap itself with the android animation framwork. You can directly animate Views or ViewGroups and all the classes that derives from View and ViewGroup.
Call view the ImageView that contains the bitmap.
TranslateAnimation slide = new TranslateAnimation(view.getX(), view.getX() + 100, view.getY(), view.getY() + 100 );
slide.setDuration(1000);
view.startAnimation(slide)
that should translate the ImageView by 100px from the current position

Related

Android 2D canvas game - draw background bitmap

I'm developing a simple 2D Android game and I want to draw the background of each level when the level begins. The background will be static for each level, it won't animate or move.
At first, I was drawing the background in a custom view using canvas and I was loading that view as the background of the level. That worked, however I noticed that if I draw a lot of lines and shapes, the UI begins to stutter. I solved the problem by drawing the background via canvas and saving it directly into a bitmap, which I then load into a background ImageView as you can see below:
CustomView bgView = new CustomView(this); //this view draws the background
Bitmap bitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
bgView.draw(canvas);
ImageView imageViewBg = (ImageView) findViewById(R.id.imageViewBg);
imageViewBg.setImageBitmap(bitmap);
The problem that I notice with this approach is that I'm creating a bitmap with a size of [screenWidth x screenHeight] which might cause an OutOfMemoryError.
So, what's the best approach for drawing the background of a full-screen game? The problem is that I want to draw it dynamically, I cannot load it directly from the assets. (I could use the Bitmap.Config.RGB_565 profile, but still it will just reduce the size of the bitmap in half, it's not the optimal solution).
I use Bitmap.createScaledBitmap():
Bitmap b = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.background),WIDTH,HEIGHT,false);
Get the width and height of the screen
Then draw it as usual:
canvas.drawBitmap(b, 0, 0, null);
EDIT:
Load the bitmap any way you would like. For the purposes of the example, the Bitmap-object will be called b. So first:
WIDTH = b.getWidth();
HEIGHT = b.getHeight();
Move on to rendering:
public void render(Canvas c){
final float scaleFactorX = getWidth()/(WIDTH*1.f);
final float scaleFactorY = getHeight()/(HEIGHT*1.f);
//check if the canvas is null first.
int savedState = c.getSaveCount();
c.scale(scaleFactorX, scaleFactorY);
//draw your bitmap.
c.restoreToCount();
//Do normal rendering
}
Explanation
What I do here is to scale the rendering only for the bitmap. This means anything else rendered will not be affected by this.
We need to get the scale factors to scale the screen to when rendering the Bitmap:
final float scaleFactorX = getWidth()/(WIDTH*1.f);
final float scaleFactorY = getHeight()/(HEIGHT*1.f);
Then save the state of the canvas to reload later.
int savedState = c.getSaveCount();
Now we scale the bitmap using the scaleFactors previously defined
c.scale(scaleFactorX, scaleFactorY);
And restore the bitmap to its original state to draw everything else in whatever type of scale you need. If you do not need to zoom the bitmap(if you have zoom) you can add that scaling after the background-scaling.
c.restoreToCount();

bitmap rotation causes an error

I am converting each frame retrieved from the camera into a bitmap and i display it on an ImageView, but i found that the imageView contains a rotated bitmap so i wanted to rotate the bitmap 90 degrees to set it right. to achieve this,
i wrote the below code to rotate the bitmap 90 degrees, but at run time i receive
bitmap size exceeds 32bits
i referred to some posts to solve this issue, and one of them suggested to recycle each bitmap used, but it did not solve the problem.
please let me know why i am getting this error and how to solve it?
code:
#Override
protected void onProgressUpdate(Bitmap... values) {
super.onProgressUpdate(values);
Bitmap b = values[0];
Matrix matrix = new Matrix();
matrix.postScale(b.getWidth()-10, b.getHeight()-10);
matrix.postRotate(90);
Bitmap resizedBitmap = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true);
mIVEdges.setImageBitmap(resizedBitmap);
b.recycle();
}
If you have 100x100 pixel bitmap, then
matrix.postScale(b.getWidth()-10, b.getHeight()-10);
will cause new bitmap to be scaled with 90 scale factor.
matrix.postScale(90, 90);
So output of new Bitmap is 9000x9000 pixel.
If you want to reduce size of new bitmap, you want to use scale factor > 0.0 and < 1.0
matrix.postScale(0.9f, 0.9f);

Avoid bitmap scaling with different canvas size

I am trying to implement overlay transformation for Picasso library.
So, I am loading image into image view and want to display overlay using bitmpap
First of all I am fill canvas with transparent color
Then I am trying to draw drawable over
#Override
public Bitmap transform(Bitmap source){
Bitmap workingBitmap=Bitmap.createBitmap(source);
Bitmap mutableBitmap=workingBitmap.copy(Bitmap.Config.ARGB_8888,true);
Canvas canvas=new Canvas(mutableBitmap);
canvas.drawColor(getResources().getColor(R.color.gray_transparent));
BitmapFactory.Options options=new BitmapFactory.Options();
options.inScaled=false;
Bitmap b=BitmapFactory.decodeResource(getResources(),R.drawable.ic_gif_white_24dp,options);
canvas.drawBitmap(b,source.getWidth()/2,source.getHeight()/2,paint);
source.recycle();
return mutableBitmap;
}
The problem is that I see different overlay image size when canvas size is different. How I can avaid bitmap scaling depends on canvas size? I want to see same GIF size with different canvases size.
On first image canvas has w = 1280, h = 854, second image w = 480, h = 270
UPDATE
I found solution to scale bitmap depends on canvas size, it works well, but I wish to find out better solution
BitmapDrawable drawable = (BitmapDrawable) getResources().getDrawable(R.drawable.ic_gif_white_24dp);
Bitmap drawableBitmap = drawable.getBitmap();
double size = source.getWidth() * 0.15;
Bitmap scaled = Bitmap.createScaledBitmap(drawableBitmap, (int) size, (int) size, true);

Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height) return wrong bitmap

I have to crop a bitmap image. For this, I am using
Bitmap bitmap = Bitmap.createBitmap(imgView.getWidth(),imgView.getHeight(), Bitmap.Config.RGB_565);
Bitmap result =Bitmap.createBitmap(bitmap,imgView.getLeft()+10, imgView.getTop()+50, imgView.getWidth()-20, imgView.getHeight()-100);
bitmap.recycle();
Canvas canvas = new Canvas(result);
imgView.draw(canvas);
But it cuts the bottom and right of the bitmap. Top and Left part of the bitmap exists in the output. That means x and y position has no effect.
I am searched for good documentation. But I couldn't.
Thanks in Advance
What is the problem here and how to solve?
Basically your problem arises form the fact that you create a bitmap. You don't put anything in it. You then create a smaller bitmap and then you render an imageView to that smaller bitmap.
This cuts off the bottom 100 pixels and right 20 pixels.
You need to Create the large bitmap. Add the imageview data to that bitmap. Then resize it.
The following code should work:
Bitmap bitmap = Bitmap.createBitmap(imgView.getWidth(),imgView.getHeight(), Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
imgView.draw(canvas);
Bitmap result =Bitmap.createBitmap(bitmap,imgView.getLeft()+10, imgView.getTop()+50, imgView.getWidth()-20, imgView.getHeight()-100);
bitmap.recycle();

Android : How to convert view to Bitmap, without capturing background screen

For my application, i have used pinch zoom feature by adapting from the tutorial and creating a custom view http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2-part-6-implementing-the-pinch-zoom-gesture/1847
Right now i'm working on capturing the zoomed image as bitmap.
Partially I was able to get the bitmap by making use of
setDrawingCacheEnabled(true);
Bitmap bm = Bitmap.createBitmap(finalView.getDrawingCache());
setDrawingCacheEnabled(false);
Using this approach, I'm getting both the zoomed image and the screen background.
Is there any way to capture only the zoomed image as a bitmap?
Try
setDrawingCacheEnabled(false)
finalView.setDrawingCacheEnabled(true);
Bitmap bm = Bitmap.createBitmap(finalView.getDrawingCache());
finalView.setDrawingCacheEnabled(false);
After having searched a lot, I found a 'Temporary' solution in the same Community & also thanks for the code from 'weakwire' provided in the same post.
Getting coordinates and width/height from a matrix
Idea is simple, all i have do is remove the background screen from the scaled image by cropping. Code is bit lengthy, but worked for me.
First get the Original Bitmap size
float imgWidth = imgBitmap.getWidth()
float imgHeight = imgBitmap.getHeight()
Obtain the matrix ( pinch zoom feature used in my application uses matrix 'trick') values, used to scale the image and get the scaledWidth & scaledHeight of the original image.
float[] values = new float[9];
matrix.getValues(values);
float globalX = values[2];
float globalY = values[5];
float scaledWidth = values[0]*imgWidth;
float scaledHeight = values[4]*imgHeight;
// If zoomed Image gets out of screen, I'm trying to crop the image available in the screen by considering image from (0,0)
if(globalX<0)
globalX = 0;
if(globalY<0)
globalY = 0;
Finally capture the View and crop the background
In my case ("finalView" is the custom View name, where pinch zooming happens)
setDrawingCacheEnabled(false);
destroyDrawingCache();
finalView.setDrawingCacheEnabled(true);
Bitmap bm = Bitmap.createBitmap(finalView.getDrawingCache());
finalView.setDrawingCacheEnabled(false);
//Final Image Width & Height
int finalWidth = Math.min((int)width,(int)finalView.getWidth());
int finalHeight = Math.min((int)height,(int)finalView.getHeight());
// crop to get the scaled image
Bitmap finalBitmap = Bitmap.createBitmap(bm, (int)globalX, (int)globalY, finalWidth ,finalHeight);
Though this is a temporary solution, it works for me. If there is any alternate solution, please post it.
This original answer here, just replace the setting background part. Hopefully it helps
public static Bitmap getBitmapFromView(View view) {
if (view == null) return null;
//Define a bitmap with the same size as the view
Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
//Bind a canvas to it
Canvas canvas = new Canvas(returnedBitmap);
// draw white background on the canvas
canvas.drawColor(Color.WHITE);
// draw the view on the canvas
view.draw(canvas);
//return the bitmap
return returnedBitmap;
}

Categories

Resources