android get bitmap width and height after scaled by matrix - android

I use matrix to scale a bitmap and draw it on canvas, after it's scaled, is there a way to get the scale with of the bitmap? and it's scale height?
sx += 0.5f;
matrix.setScale(sx, sx);
matrix.postTranslate(left, top);
canvas.drawBitmap(bitmap, matrix, paint);
// here how to get the scaled width of bitmap?
This is part of my current project - a simple meme maker, so another question is that is there any good tutorials or resource (open source app) I can learn? I googled a lot, just get some pieces no complete tutorials.
Thanks.

I believe
Bitmap#getScaledHeight (Canvas canvas)
should do the job. If not try with
final int scaledHeight = bitmap.getHeight() * sx;
but the first one should work.

Related

Android - Set Drawable to Canvas but keep Aspect Ratio

I'm having a small issue with my android code . This is the first time i'm using canvas and i want to set an image to it but keep some type of aspect ratio.
This is what i'm doing right now and this maps the image onto the canvas completely . It sets the image width-height to canvas width-height.
Drawable drawable = image; // gets the image
drawable.SetBounds(0, 0, canvasWidth, canvasHeight);
drawable.Draw(canvas);
This works well on certain devices but when the device is large , the stretching is really bad . I want to set the bounds in such a way that it keeps an aspect ratio . If the canvas width-height is not the same aspect ratio , it will try to fill the canvas with an aspect ratio but might leave some space off in x or y axis .
int imgWidth = 500;
int imgHeight = 800;
I want to map the image on the canvas based on these values and stretch as necessary but keeping this aspect ratio even if part of the canvas is not filled .
What is the best way to do this ?
Thanks
I've already answered a similar question here.
To preserve the aspect ratio I did this:
val drawable = resources.getDrawable(R.drawable.my_vector, null)
val aspectRatio = drawable.intrinsicWidth.toFloat() / drawable.intrinsicHeight
val desiredWidthInPx = 100 // could be your view size or canvas size
val derivedHeightInPx = (desiredWidthInPx / aspectRatio).toInt()
drawable.setBounds(0, 0, desiredWidthInPx, derivedHeightInPx)
drawable.draw(canvas)
The above is for when the drawable width is smaller than its height.
If the drawable height is larger than its width, then first set the height to your desired size and then calculate the width.
Provide correct images in each resource folder. Correct images means correct resolution and screen density. Refer to this link http://developer.android.com/guide/topics/resources/providing-resources.html

Set opacity to PictureDrawable

I need a piece of advice with setting opacity to a PictureDrawable object since usual setAlpha() is not implemented in PictureDrawable.
My case is pretty similar to this one (I also get my drawables from SVGs in raw resources using a library). But I cannot use the solution because I would like to change the opacity dynamically (not by applying color filter at creation).
The context is animating multiple drawables when drawing on a SurfaceView.
What could be a good workaround in this situation?
Thank you.
Credit goes to #pskink, I'll just elaborate it a little for further references.
This is what I do in onDraw(Canvas canvas) method (in my case int opacity changes iteratively from 0 to 255):
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
canvas.saveLayerAlpha(x, y, x + width, y + height, opacity,
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
drawable.setBounds(x, y, x + width, y + height);
drawable.draw(canvas);
canvas.restore();
This answer also provides good guidance on saveLayerAlpha() usage.

How should I deal with an Live wallpaper so it supports multiple aspect ratios?

I have a live wallpaper all set up (for simplicity's sake, assume it consists of two rotating bitmaps positioned side by side, each rotating at different speeds; also note that the bitmaps' edges (not the invisible box around the image, but rather the actual pixels of the drawing) are touching.)
I described the translate for each as a percentage of the canvas size (a value between 0 and 1 multiplied by c.getHeight(), and c.getWidth() (where c is a canvas).)
Anyways, everything works fine as long the aspect ratio is maintained. So xxhdpi and xhdpi # 1080x1920 and 720x1280 is all good, but then when i run it on a nexus s # 480x800, the two bitmaps are no longer positioned properly.
I do not want to distort my images (they are circles and must remain circles), so I was thinking the best way would be the limit the size of the canvas and center it.
So for the nexus s # 480x800, i would actually want to only draw in a 450x800 area which i would center on my screen.
In fact, I would always want to have my 2 bitmaps in an area respecting the height = width * 0.5625.
How should I go about doing this?
NB: I based my live wallpaper around the cube sample.
Please let me know if I left any important details out,
Thank you!
Werner
inside your Engine, implement following to capture the screen's height and width
int screenHeight, screenWidth;
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
screenHeight = height; screenWidth = width;
}
and wherever you decode your bitmap, do it like this:-
//get bitmap
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bitmap);
//scale bitmap
bitmap = Bitmap.createScaledBitmap(bitmap, screenWidth, screenWidth * 0.5625, true);
This will fill your entire screen with a circle of correct aspect ratio (width * 0.5625).
And then make it centred by:-
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
final SurfaceHolder holder = getSurfaceHolder();
Canvas canvas = holder.lockCanvas();
int x = ( screenHeight - screenWidth*0.5625 ) / 2;
canvas.drawBitmap(bitmap, 0, x, paint);

Expanding the drawing on canvas for android

So the scenario is that I have a surfaceView of size 640 x 480 on which I am showing on camera preview. Now I draw a something vertically on the screen. After that I am rotating the canvas using
canvas.rotate(90, getWidth()/2, getHeight/2);
Once I do that, I am expecting my drawing to be scaled and drawn horizontally. It does draw it horizontally but it is not scaling it according the width and height.
Here is the pictorial example explanation to help you understand better.
https://lh4.googleusercontent.com/-2wlImCt0m88/UcHzhKUSGBI/AAAAAAAAB9Y/bGNMOTu9DqM/s1440/canvas_rotation.png
Is there a way or an algorithm by which I can rotate the canvas and then scale it accordingly?
let me know if you need any further explanation.
Thanks in advance.
Well so I figured out the solution to it. What we can do is that we can use
canvas.scale( newX, newY, pivotX, pivotY);
/*
* Where
* newX = oldX * (newWidth/oldWidth);
* newY = oldY * (newHeight/oldHeight);
* pivotX = same as before;
* pivotY = same as before;
*/

Scaling canvas and keeping center

I'm want to scale a canvas with a bitmap drawn on it. I'm able to scale the canvas but the bitmap drawn on it moves to the upper left respectively lower right.
#Override
protected void onDraw(Canvas canvas) {
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
//draw bitmap
}
For the last few days I tried many different approaches from manipulating translation coordinates to pivot points for scaling. But nothing did work for me. I'm pretty sure there must be an easy solution for my problem.
Thanks in advance
Like you mentioned, the pivot point is the correct way to do this:
canvas.scale(2,2, redCircle.x, redCircle.y);
will work. There is no need for extra translation.
var widthNew = ctx.canvas.width / 2;
var heightNew = ctx.canvas.height / 2;
ctx.setTransform(scale,0,0,scale,-(scale-1)*widthNew,-(scale-1)*heightNew);
This will help you scale the canvas horizontally and vertically with the horizontal and vertical translation.

Categories

Resources