I am trying to scale up a bitmap from its center point in Android to achieve a zoom effect, but without success. The code I have is:
float scaleWidth = ((float) width + (i * 5)) / width;
float scaleHeight = ((float) height + (i * 5)) / height;
Matrix matrix = new Matrix();
matrix.setScale(scaleWidth, scaleHeight, scaleWidth / 2, scaleHeight / 2);
Bitmap rescaledBitmap = Bitmap.createBitmap(src, 0, 0, width, height, matrix, true);
result.add(rescaledBitmap);
I am setting the pivot point by dividing the dimensions by 2, but the effect is just that the image is scaled from 0, 0 as coordinates instead of from the center. What I want is for the image to be a fixed size, but scaled up from its center point (thus cropping the image).
I'm going to offer an alternative solution using a property animator since that is a cleaner solution I think.
SomeLayout.xml (The key here is that the ViewGroup is the same size as the View, so it will clip as you requested (like google maps zoom in))
<FrameLayout
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center">
<View
android:id="#+id/zoom"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#drawable/myCoolImage"
/>
</FrameLayout>
Code: (the 1,2,1 will start at a scale of 1x then 2x then back to 1x, it takes a list of values)
final View view = findViewById(R.id.zoom);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.SCALE_X, 1, 2, 1)
.ofFloat(view, View.SCALE_Y, 1, 2, 1)
.setDuration(5000);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.start();
}
});
So with this version image if you had a zoom +, and zoom - views with onClickListeners, you could basically simulate the controlled zooming as long as you know what values you want to zoom with.
Also as previously noted the ViewGroup being the same size as the internal view will force the animation to clip to it's parent bounds instead of being completely visible.
References:
Google Android ObjectAnimator
Sure this will come late, but for all looking after me:
double scaleFactor = 0.75; // Set this to the zoom factor
int widthOffset = (int) ((1 - scaleFactor)/2 * bmp.getWidth());
int heightOffset = (int) ((1 - scaleFactor)/2 * bmp.getHeight());
int numWidthPixels = bmp.getWidth() - 2 * widthOffset;
int numHeightPixels = bmp.getHeight() - 2 * heightOffset;
Bitmap rescaledBitmap = Bitmap.createBitmap(bmp, widthOffset, heightOffset, numWidthPixels, numHeightPixels, null, true);
This example will zoom in on the center of a bitmap and with a factor of 25%.
The second and third arguments in createBitmap take the x/y coordinates of the top left corner. You're sending 0,0, so if I understand correctly...
The image is correctly scaled, but the image is not centered, right?
To center it, you need to find the correct (x,y) point for the top left corner. This should be 1/4th the original width/height.
So...
Bitmap rescaledBitmap = Bitmap.createBitmap(src, (width/2), (height/2), width, height, matrix, true);
should work.
Related
For an android 2D-game, I want to create a image scale animation on surfaceview canvas. Following is my working code, I am not sure about the approach is correct or not.
Please suggest me, if I am wrong.
public void drawScaledImage(Canvas canvas, Bitmap bitmap, float scale) {
width = bitmap.getWidth();
height = bitmap.getHeight();
Bitmap tempBitmap = Bitmap.createScaledBitmap(bitmap, (int) (width * scale), (int) (height * scale), false);
canvas.drawBitmap(tempBitmap, getX(), getActualY(), paint);
}
Following code will be executing on every 16ms (FPS 60) with a new scale value.
Please suggest the correct approach to create a image scale animation in android canvas.
I want to create the animation memory and process optimised way.
Thanks.
I am developing an application in which I need to fit an Bitmap into Imageview with specific dimensions(let's suppose 350dpx50dp - height*width).
I wanted to do something similar like this: http://gyazo.com/d739d03684e46411feb58d66acea1002
I have looked here for solutions. I found this code for scale the bitmap and fit it into imageview, but the problem is that imageview becomes greater when I add the bitmap into him:
private void scaleImage(Bitmap bitmap, ImageView view)
{
// Get current dimensions AND the desired bounding box
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int bounding = dpToPx(350);
// Determine how much to scale: the dimension requiring less scaling is
// closer to the its side. This way the image always stays inside your
// bounding box AND either x/y axis touches it.
float xScale = ((float) bounding) / width;
float yScale = ((float) bounding) / height;
float scale = (xScale <= yScale) ? xScale : yScale;
// Create a matrix for the scaling and add the scaling data
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
// Create a new bitmap and convert it to a format understood by the ImageView
Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
// Apply the scaled bitmap
view.setImageBitmap(scaledBitmap);
}
Using this code I can get this : http://gyazo.com/e9871db2130ac33668156fc0cf773594
But that's not what I wanted, I want to keep the dimensions of imageview and add the bitmap into imageview without modifying the dimensions of imageview and occupying all the imageview's surface. Like the first image.
Why don't you just add android:scaleType="fitXY" to your ImageView in xml?
I have two images that don't always completely fit onto the screen. Therefore I want to crop them (like CENTER_CROP does) but in a way, so that the bottom area of the image is always visible. Both images fill the entire screen width and each 1/2 of the screen height.
I found a similar solution here:
ImageView scaling TOP_CROP
The accepted solution works perfectly, but I can't figure out how to change the matrix to make it BOTTOM_CROP instead.
Working Code for TOP_CROP:
setScaleType(ScaleType.MATRIX);
Matrix matrix = getImageMatrix();
float scaleFactor = (getWidth() - Data.getImgPadding(c)) / (float) getDrawable().getIntrinsicWidth();
matrix.setScale(scaleFactor, scaleFactor, 0, 0);
setImageMatrix(matrix);
Note: A padding to the right is set programmatically, therefore it needs to be included in the calculation (the value is read by Data.getImgPadding(c)).
For BOTTOM_CROP I thought I'd use:
matrix.setScale(scaleFactor, scaleFactor, 0, getHeight());
But it's not really working, for the first image the bottom part is displayed more or less correctly, but there is some sort of margin below it - the bottom image border should be exactly at the bottom ImageView border. I assume I have to use the padding somehow but I don't know how to caculate the "new" image height after the horizontal padding value is set.
The bigger problem however is that (for whatever reason) when I set the value py in setScale() the second ImageView is suddenly empty... both views use the same layout xml, but that can't be the reason as the original code works perfectly on both.
I know this is a long time gone, but I've modified the answer in the post to suit your need.
#Override
protected boolean setFrame(int l, int t, int r, int b) {
boolean hasChanged = super.setFrame(l, t, r, b);
Matrix matrix = getImageMatrix();
float scaleFactor = getWidth() / (float) getDrawable().getIntrinsicWidth();
matrix.setScale(scaleFactor, scaleFactor, 0, 0);
// The Important Bit
Drawable drawable = getDrawable();
float heightD = drawable.getIntrinsicHeight();
float height = getHeight();
matrix.setTranslate(0, height - heightD);
setImageMatrix(matrix);
return hasChanged;
}
Hope it helps!
Starting point: in my app I let the user pick an image that will be used as the app's background. In case the image's width/height is larger than the device's screen width/height, I want to crop the image so it matches the device dimensions (see picture below).
I tried the method below, but with no luck at all, the resulting image is messed up.
private Bitmap crop(Bitmap bmp) {
int centerW = bmp.getWidth() / 2;
int centerH = bmp.getHeight() / 2;
int startX = centerW
//returns screen width
- GetSettings.getScreenDimensions(getActivity())[0] / 2;
int startY = centerH
//returns screen height
- GetSettings.getScreenDimensions(getActivity())[1] / 2;
return Bitmap.createBitmap(bmp, startX, startY,
GetSettings.getScreenDimensions(getActivity())[0],
GetSettings.getScreenDimensions(getActivity())[1]);
}
I guess I'm misunderstanding the parameters I need to pass to the createBitmap() method to get a proper result.
So how can I crop a Bitmap to make it's width/height to match the screen's width/height?
I'm not an android developer, but I would imagine your startX and startY variables are incorrect.
I would think you would want something like this:
startX = (bmp.getWidth() - screenWidth) / 2;
startY = (bmp.getHeight() - screenHeight) / 2;
Then your draw X and Y lengths would just be the screen width and height.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to crop the parsed image in android?
How does one crop the same way as Androids ImageView is doing
android:scaleType="centerCrop"
Your question is a bit short of information on what you want to accomplish, but I guess you have a Bitmap and want to scale that to a new size and that the scaling should be done as "centerCrop" works for ImageViews.
From Docs
Scale the image uniformly (maintain the image's aspect ratio) so that
both dimensions (width and height) of the image will be equal to or
larger than the corresponding dimension of the view (minus padding).
As far as I know, there is no one-liner to do this (please correct me, if I'm wrong), but you could write your own method to do it. The following method calculates how to scale the original bitmap to the new size and draw it centered in the resulting Bitmap.
Hope it helps!
public Bitmap scaleCenterCrop(Bitmap source, int newHeight, int newWidth) {
int sourceWidth = source.getWidth();
int sourceHeight = source.getHeight();
// Compute the scaling factors to fit the new height and width, respectively.
// To cover the final image, the final scaling will be the bigger
// of these two.
float xScale = (float) newWidth / sourceWidth;
float yScale = (float) newHeight / sourceHeight;
float scale = Math.max(xScale, yScale);
// Now get the size of the source bitmap when scaled
float scaledWidth = scale * sourceWidth;
float scaledHeight = scale * sourceHeight;
// Let's find out the upper left coordinates if the scaled bitmap
// should be centered in the new size give by the parameters
float left = (newWidth - scaledWidth) / 2;
float top = (newHeight - scaledHeight) / 2;
// The target rectangle for the new, scaled version of the source bitmap will now
// be
RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight);
// Finally, we create a new bitmap of the specified size and draw our new,
// scaled bitmap onto it.
Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, source.getConfig());
Canvas canvas = new Canvas(dest);
canvas.drawBitmap(source, null, targetRect, null);
return dest;
}