Scaling down Image for ImageButton programmatically - android

I have many icons in 512 x 512 resolution and i want to set them
on ImageButtons. Ofcourse i dont want the ImageButtons to be
512 x 512 big i want them to be as big as its optimal for the
screen size of the current device.
I create my buttons like this:
this.buttonMeasure = new ImageButton(this);
this.buttonMeasure.setImageResource(R.drawable.ic_measure);
this.buttonMeasure.setOnLongClickListener(this);
How can i scale down the images to an optimal size dependent
to the screen size of the device programmatically?
I tried this but that leads to an outOfMemoryError:
public static Bitmap getScaledBitMap(Context context, Drawable sourceDrawable) {
Bitmap sourceBitmap = ((BitmapDrawable)sourceDrawable).getBitmap();
DisplayMetrics metrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(metrics);
int width = sourceBitmap.getWidth();
int height = sourceBitmap.getHeight();
float scaleWidth = metrics.scaledDensity;
float scaleHeight = metrics.scaledDensity;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
return Bitmap.createBitmap(sourceBitmap, 0, 0, width, height, matrix, true);
}

I don't think you will be needing this at all. You specify the size of your ImageButton using properties like android:layout_width and android:layout_height for different layouts in folders, Similarly you need to place copy of images of various resolutions in respective folders with the same name.The appropriate image is automatically picked up by android itself at run time.

Related

How to Scale the bitmap to Support mulitscreen in canvas? [duplicate]

I am taking an image and drawing it to the screen using canvas. I want to scale it based on the screen size.
This is what I tried, but it cuts off a large chunk of the image:
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int width = metrics.widthPixels;
int height = metrics.heightPixels;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.myimage);
bitmap = Bitmap.createScaledBitmap(bitmap, width, height, false);
Rect frameToDraw = new Rect(0, 0, width, height);
RectF whereToDraw = new RectF(0, 0, width, height);
canvas.drawBitmap(bitmap,frameToDraw,whereToDraw, paint);
I know I am doing a few things wrong, but I'm not exactly sure what. This code causes the image to exceed the size of the screen. I want it to be scaled to the size of the screen. I'll be drawing smaller images in too that I also will need to scale according to the size of the screen, though not to the full screen.
Rect frameToDraw = new Rect(0, 0, width, height);
RectF whereToDraw = new RectF(0, 0, width, height);
Take a look at the above code. Your are not scaling the picture. You are simply taking a part of the picture (in this case the whole picture) and pasting it somewhere (in this case the size of the original picture).
The width and heigth of the frameToDraw rectangle should be the width and height of your picture.
dont need creat scale bitmap, instead:
Bitmap frameBuffer = Bitmap.createBitmap(frameBufferWidth,frameBufferHeight, Config.RGB_565);
frameBufferWidth and frameBufferHeight are the sizes that you want to make your app base on those(for example 480*800)
then simply add this code:
Rect dstRect = new Rect();
canvas.getClipBounds(dstRect); // get canvas size base screen size
canvas.drawBitmap(framebuffer, null, dstRect, null);
it draw your final bitmap according to screen size
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int width = metrics.widthPixels;
int height = metrics.heightPixels;
If you get your width and height like this, you aren't going to take the size of any toolbar/status bar/navigation bar into account.
If you are coding an app that has a View, inflate a layout with an ImageView that is full size (i.e. match_parent), then use the scaleType to scale/fit/crop the image how you want.

ImageView fit width crop bottom

I want to scale image to fit screen width and keep aspect ratio
if image height is smaller than screen height. I want to strength
it.
if image height is larger than screen height. I want to crop it.
I google for it but set scaleType to FitXY & AdjustViewInBounds doesn't work.
I test with 50x50 image and it's not working
// Use createScaledBitmap will cause OOM, so I set image to imageView first.
ImageView image= (ImageView) mPageView.findViewById(R.id.image);
// Set image to get IntrinsicWidth & IntrinsicHeight
image.setImageResource(imageDrawable);
// Change scale type to matrix
image.setScaleType(ImageView.ScaleType.MATRIX);
// Calculate bottom crop matrix
Matrix matrix = getBottomCropMatrix(mContext, image.getDrawable().getIntrinsicWidth(), image.getDrawable().getIntrinsicHeight());
// Set matrixx
image.setImageMatrix(matrix);
// Redraw image
image_image.invalidate();
And my matrix use following method
Matrix matrix = new Matrix();
// Get screen size
int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
int screenHeight = context.getResources().getDisplayMetrics().heightPixels;
// Get scale to match parent
float scaleWidthRatio = screenWidth / imageWidth;
float scaleHeightRatio = screenHeight / imageHeight;
// screenHeight multi by width scale to get scaled image height
float scaledImageHeight = imageHeight * scaleWidthRatio;
// If scaledImageHeight < screenHeight, set scale to scaleHeightRatio to fit screen
// If scaledImageHeight >= screenHeight, use width scale as height scale
if (scaledImageHeight >= screenHeight) {
scaleHeightRatio = scaleWidthRatio;
}
matrix.setScale(scaleWidthRatio, scaleHeightRatio);
I don't know where I am wrong. It just leave some blank at the bottom.
========
Update. I found out the problem. My matrix is right. The blank at the bottom is soft navigation bar. Use following method will get wrong value.
getResources().getDisplayMetrics()
Change it to
DisplayMetrics displaymetrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getRealMetrics(displaymetrics);
int screenWidth = displaymetrics.widthPixels;
int screenHeight = displaymetrics.heightPixels;
and it works!
Update. I found out the problem. My matrix is right. The blank at the bottom is soft navigation bar. Use following method will get wrong value.
getResources().getDisplayMetrics()
Change it to
DisplayMetrics displaymetrics = new DisplayMetrics();
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getRealMetrics(displaymetrics);
int screenWidth = displaymetrics.widthPixels;
int screenHeight = displaymetrics.heightPixels;
and it works!
Try this,
Use android:scaleType centerCrop instead of fitXY or matrix.
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />

Android: How do I scale a bitmap to fit the screen size using canvas/draw bitmap?

I am taking an image and drawing it to the screen using canvas. I want to scale it based on the screen size.
This is what I tried, but it cuts off a large chunk of the image:
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int width = metrics.widthPixels;
int height = metrics.heightPixels;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.myimage);
bitmap = Bitmap.createScaledBitmap(bitmap, width, height, false);
Rect frameToDraw = new Rect(0, 0, width, height);
RectF whereToDraw = new RectF(0, 0, width, height);
canvas.drawBitmap(bitmap,frameToDraw,whereToDraw, paint);
I know I am doing a few things wrong, but I'm not exactly sure what. This code causes the image to exceed the size of the screen. I want it to be scaled to the size of the screen. I'll be drawing smaller images in too that I also will need to scale according to the size of the screen, though not to the full screen.
Rect frameToDraw = new Rect(0, 0, width, height);
RectF whereToDraw = new RectF(0, 0, width, height);
Take a look at the above code. Your are not scaling the picture. You are simply taking a part of the picture (in this case the whole picture) and pasting it somewhere (in this case the size of the original picture).
The width and heigth of the frameToDraw rectangle should be the width and height of your picture.
dont need creat scale bitmap, instead:
Bitmap frameBuffer = Bitmap.createBitmap(frameBufferWidth,frameBufferHeight, Config.RGB_565);
frameBufferWidth and frameBufferHeight are the sizes that you want to make your app base on those(for example 480*800)
then simply add this code:
Rect dstRect = new Rect();
canvas.getClipBounds(dstRect); // get canvas size base screen size
canvas.drawBitmap(framebuffer, null, dstRect, null);
it draw your final bitmap according to screen size
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int width = metrics.widthPixels;
int height = metrics.heightPixels;
If you get your width and height like this, you aren't going to take the size of any toolbar/status bar/navigation bar into account.
If you are coding an app that has a View, inflate a layout with an ImageView that is full size (i.e. match_parent), then use the scaleType to scale/fit/crop the image how you want.

rotate bitmap and maintain size

I am creating a tile board game.
I want to rotate a bitmap tile piece by a few pre-determined degrees.
When I rotate my bitmap, the size changes.
For example, if I want a 75x75 triangle tile piece, on rotation I get a 68x68 back from this code. How can I keep things the same size so everything remains the size for the board?
Here's what I'm using to rotate:
public class RotatebitmapActivity 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.t123);
int width = bitmapOrg.getWidth();
int height = bitmapOrg.getHeight();
int newWidth = 75;
int newHeight = 75;
// 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(120);
// 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);
}
What is happening in your code, is that the bitmap that is created is the correct size. However, all Bitmaps are automatically scaled to fit the density of the screen that is currently in use.
There are two ways (that I know of) to get the result you desire.
You can set the density of a bitmap after creating it and before wrapping it in a drawable. To do this, add code similar to:
resizedBitmap.setDensity(DisplayMetric.DENSITY_HIGH);
This code sets the density that the bitmap is designed for, and can prevent Android from auto-scaling the image.
The second solution is more of a methodology than a specific solution to this particular problem. I won't go into detail, for that see Supporting Multiple Screens | Android Developers
Hopefully someone will happen along that can answer your question better than I can.

android drawable changes sizes on screen when reading image from file

I have an image on a private file.
I read the file, create the drawable, and assign it to an ImageView.
The ImageView has WRAP_CONTENT so the size is automatic.
On 320x480 screens, the image looks good
But on screens with more resolution and high density 480x800 or 480x854 (N1, droid) , when the image is for example 150x150, I see the image as 100x100.
Of course it has something to do with the density but not sure how should I resolve this.
This is my code:
FileInputStream fis = this.openFileInput("icon.png");
icon = Drawable.createFromStream(fis, "icon");
fis.close();
imageView.setImageDrawable(icon);
thanks
================================================================
update:
with the following code:
FileInputStream fis = this.openFileInput("icon.png");
icon = Drawable.createFromStream(fis, "icon");
if I then inspect the size of the icon, android thinks the size is 100x100, when really is 150x150.
Looks like its reducing the image by the density.
Can anybody explain this and how to avoid this.
Thanks
I am working on a similar issue, try this:
TypedValue typedValue = new TypedValue();
//density none divides by the density, density default keeps the original size
typedValue.density = TypedValue.DENSITY_DEFAULT;
Drawable d = Drawable.createFromResourceStream(null, typedValue, fis, "icon");
I am still working through how to develop a general solution to pick resolution/resize images from a generic stream instead of the drawable-* directories.
Rescale the image to desired dimension:
d = Drawable.createFromPath(filePath);
if (d != null) {
Bitmap bitmapOrg = ((BitmapDrawable) d).getBitmap();
int width = bitmapOrg.getWidth();
int height = bitmapOrg.getHeight();
int newWidth = 170;
int newHeight = 170;
// calculate the scale
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
width, height, matrix, true);
// make a Drawable from Bitmap to allow to set the BitMap
d = new BitmapDrawable(resizedBitmap);
}
Try BitmapDrawable#setTargetDensity:
Bitmap b = BitmapFactory.decodeFile(path)
BitmapDrawable bmd = new BitmapDrawable(b);
bmd.setTargetDensity(getResources().getDisplayMetrics());
Set some dimensions in device independent pixels (or DIPs).

Categories

Resources