java Android - working with image scaling/cropping programmatically - java

Well, all this thing tortures me for long weeks, I set an Image 227 pixels high in scales it to 170 pixels even if I want it to be wrap_content whenever I do.
Ok. Here I take My Image which is 1950 pixels long (I put here a part of it so you can understand how it should look like).
First, I want to scale it back to 227 pixels high because that's how it was designed and how it should be
Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),R.drawable.ver_bottom_panel_tiled_long);
int width = bitmapOrg.getWidth();
int height = bitmapOrg.getHeight();
int newWidth = 200; //this should be parent's whdth later
int newHeight = 227;
// 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);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
width, height, matrix, true);
BitmapDrawable dmpDrwbl=new BitmapDrawable(resizedBitmap);
verbottompanelprayer.setBackgroundDrawable(dmpDrwbl);
so... it's not a cropped image at all - no, it's 1950 pixels pressed into 200 pixels.
But I want just cut anything besides this 200 pixels or whatever width I'll set - crop it and not press all this long image into 200 pixels area.
Also, BitmapDrawable(Bitmap bitmap); and imageView.setBackgroundDrawable(drawable); are deprecated - how can I change that?

according to what i see, you create a bitmap of the new size (200x227) , so i'm not sure what you expected. you've even written in the comments that you scale and no word on cropping...
what you can do is :
if the API is at least 10 (gingerbread) , you can use BitmapRegionDecoder , using decodeRegion :
if the API is too old, you need to decode the large bitmap, and then crop it into a new bitmap, using Bitmap.createBitmap
something like this:
final Rect rect =...
if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD_MR1)
{
BitmapRegionDecoder decoder=BitmapRegionDecoder.newInstance(imageFilePath, true);
croppedBitmap= decoder.decodeRegion(rect, null);
decoder.recycle();
}
else
{
Bitmap bitmapOriginal=BitmapFactory.decodeFile(imageFilePath, null);
croppedBitmap=Bitmap.createBitmap(bitmapOriginal,rect.left,rect.top,rect.width(),rect.height());
}

Related

Resize Bitmap to 512x512 Without changing original aspect ratio

I have a created bitmaps. Sizes are not specific. Sometimes 120x60 , 129x800 , 851x784. Its not have a specific value... I want to make these bitmaps resizing to 512x512 always but without changing original images aspect ratio. And without cropping. New image must have canvas 512x512 and original image must be center without any cropping.
I was resizing my bitmaps with this function but it makes images really bad because image fitting X and Y . I don't want image to fit x and y on same time fits one of it and keeps its aspect ratio.
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
int width = bm.getWidth();
int height = bm.getHeight();
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);
// "RECREATE" THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(
bm, 0, 0, width, height, matrix, false);
bm.recycle();
return resizedBitmap;
}
What I have;
What I want;
Ok, so you're really close. I can't test this right now, but basically what needs to be changed is
1) You need to apply the same scale to both X and Y, so you need to pick the smaller one (try the bigger one if that doesn't work).
matrix.postScale(Math.min(scaleWidth, scaleHeight), Math.min(scaleWidth, scaleHeight));
2) The result will be a bitmap where at least one side is 512px large, the other one will be smaller. So you need to add the padding to fit that side to 512px (equally left and right/top and bottom for centering). In order to do so, you need to create an new bitmap of the desired size:
Bitmap outputimage = Bitmap.createBitmap(512,512, Bitmap.Config.ARGB_8888);
3) and lastly depending on what side of the resizedBitmap is 512px you need to draw resizedBitmap to the correct position in outputImage
Canvas can = new Canvas(outputimage);
can.drawBitmap(resizedBitmap, (512 - resizedBitmap.getWidth()) / 2, (512 - resizedBitmap.getHeight()) / 2, null);
Note here, that 512 - resizedBitmap.getWidth() results in 0 and therefor no padding at the side with correct size.
4) Now return outputImage
Here's a simplification in Kotlin that does both the scale and the translation with the matrix, skipping the intermediate bitmap.
Note that it also sets the background color to white for new pixels, which I needed for my image pipeline. Feel free to remove that if you don't need it.
fun resizedBitmapWithPadding(bitmap: Bitmap, newWidth: Int, newHeight: Int) : Bitmap {
val scale = min(newWidth.toFloat() / bitmap.width, newHeight.toFloat() / bitmap.height)
val scaledWidth = scale * bitmap.width
val scaledHeight = scale * bitmap.height
val matrix = Matrix()
matrix.postScale(scale, scale)
matrix.postTranslate(
(newWidth - scaledWidth) / 2f,
(newHeight - scaledHeight) / 2f
)
val outputBitmap = Bitmap.createBitmap(newWidth, newHeight, bitmap.config)
outputBitmap.eraseColor(Color.WHITE)
Canvas(outputBitmap).drawBitmap(
bitmap,
matrix,
null
)
return outputBitmap
}

Set Bitmap to specific size inside imageview

Trying to resize a bitmap and set to a specific part of an imageview. The imageview is square and I wish to have the bitmap in the bottom right corner. Width to be 10% of imageview and height to be 30%.
int w = imageview.getWidth();
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.vertical_bar_green);
imageview.setImageBitmap(Bitmap.createScaledBitmap(bm, w/10, w*30/100, false));
imageview.setScaleType(ScaleType.FIT_END);
The result is the bitmap is the full height of the imageview and the width is much larger.
How can I set specific points to place the bitmap?
From the documentation for END (the matrix used by FIT_END).
Compute a scale that will maintain the original src aspect ratio, but
will also ensure that src fits entirely inside dst. At least one axis
(X or Y) will fit exactly. END aligns the result to the right and
bottom edges of dst.
You will probable want to use a custom matrix for this, probably built with setRectToRect().
For example:
Matrix matrix = new Matrix();
RectF from = new RectF(0, 0, bm.getIntrinsicWidth(), bm.getIntrinsicHeight());
RectF to = new RectF(view.getWidth() * 0.9, view.getHeight() * 0.7, view.getWidth(), view.getHeight());
matrix.setRectToRect(from, to, Matrix.ScaleToFit.FILL);
view.setScaleType(ScaleType.MATRIX);
view.setImageMatrix(matrix);
(I'm not sure if you wanted to keep the original proportions or not, if you want it then use FIT_END for setRectToRect()).

How can I scale my bitmap in Android based on the width and height pixels?

I want to be able to scale my image based on the screen size. In a normal java applet I would do something like the following....
int windowWidth = 1280;
int windowHeight = 720;
Image image;
public void paint(Graphics g)
{
g.drawImage(image, x, y, windowWidth / 4, windowHeight / 16, null);
}
I've been searching for an answer for a while and everything I find seems to turn up some weird result. From what I read I might need to do something with Resolution Independent Pixels but I'm not %100 sure.
The thing I am trying to avoid is having to create a whole new set of images and icons just for different screen densities. The method I showed above works for resizing desktop apps without a problem.
Edit:
This is what I have been using to draw an image in android.
Matrix matrix = new Matrix();
Bitmap image;
Constuctor....()
{
image = BitmapFactory.decodeResource(context.getResources(), R.drawable.play);
}
public void render(Canvas c)
{
c.drawBitmap(image, matrix, null);
}
Hi see thsi question I have posted scale bitmap
If you are using canvas get the width and height of the canvas. or if you want to have it formal normal layouts then get the width and height by using
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
dispWidth=metrics.widthPixels;
dispheight=metrics.heightPixels;
and then scale our bitmap according to your requirement like this. In this I Have to have 8 bricks so I have taken the width by dividing with the Number of columns
String strwidth=String.valueOf(((float)(bmp.getWidth())/NO_COLUMNS));
if(strwidth.contains("."))
{
scalebit=Bitmap.createScaledBitmap(bmp, (int)(Math.ceil(((float)bmp.getWidth())/NO_COLUMNS))*NO_COLUMNS, bmp.getHeight(), true);
}
else
{
scalebit=bmp;
}

Android, Java: Resized Bitmap ignores bitmap options

I am creating this Android game with Java. However, I load the bitmaps and then resize them to fit screens and such (dpi isn't really exact). BUT my thought is also to load the bitmaps in 16b (mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_4444) for devices with a small amount of ram. But when I resize the bitmaps they seem to go back to 32b (Bitmap.Config.ARGB_8888).
This is how I declare the options:
mBitmapOptions = new BitmapFactory.Options();
mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_4444;
This is how I load the bitmaps:
mBitmaps.add(getResizedBitmap(BitmapFactory.decodeResource(mResources, imagePath, mBitmapOptions)));
And this is the getResizeBitmap method:
public Bitmap getResizedBitmap(Bitmap bm)
{
//Original size
int width = bm.getWidth();
int height = bm.getHeight();
//New size (percent)
float newWidth = 1 * mScaleWidth;
float newHeight = 1 * mScaleHeight;
//Create the matrix
Matrix matrix = new Matrix();
matrix.postScale(newWidth, newHeight);
//Recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
//Recycle the old Bitmap
bm.recycle();
return resizedBitmap;
}
Any ideas why the new Bitmap ignores the options?
Why don't you use the createScaledBitmap method? It should preserve the options. In your case, you are creating a completely new Bitmap and it probably applies a default config.
EDIT: Another option would be to use your code and add a call to the copy method like this:
Bitmap smallerBitmap = resizedBitmap.copy (Bitmap.Config.ARGB_4444, false);
resizedBitmap.recycle ();
However, I don't think this will have a nice performance...

Android Rotatable ImageView

I am trying to create a Rotatable an ImageView to which I will specify certain angle and pivot point and see it rotated around that pivot point. I tried something like this:
Matrix matrix = new Matrix();
matrix.postRotate(45, imageView.getWidth(), imageView.getHeight());
imageView.setScaleType(ScaleType.MATRIX);
imageView.setImageMatrix(matrix);
but the parameters of postRotate method (the second and third - the pivot points) make NO CHANGE at all. even if they are 0, 0 - it's the same thing.
So I wanna create a ImageView that would be rotated by certain angle when initialized. In this example 45 degrees. I tried setting the bounds and staff.. no help.
How do I do that? :/
You can rotate a ImageView by using setRotation(int);
// rotate imageView 45 around center pivot point
imageView.setPivotX(imageView.getWidth()/2);
imageView.setPivotY(imageView.getHeight()/2);
imageView.setRotation(45);
Reference: http://goo.gl/WhhGM
Edit: I had to shorten the link because of a ) in the url, some browsers don't like that.
This is how I use view.setRotation(float angle) in my apps, hope it will be helpful:
//to make rotation use next code
imageView.setPivotX(imageView.getWidth() / 2);
imageView.setPivotY(imageView.getHeight() / 2);
imageView.setRotation(45);
//to reset rotate state to initial position
imageView.setPivotX(imageView.getWidth() / 2);
imageView.setPivotY(imageView.getHeight() / 2);
imageView.setRotation(0);
Based on answer from Spencer
This function works for me.
public static Bitmap rotateImage (Bitmap srcBitmap, int width, int height, int rotation)
{
// create rotated image
Matrix matrix = new Matrix();
rotation = (rotation +1 ) % 3;
rotation = rotation * 90;
matrix.postRotate( rotation,
width,
height );
Bitmap rotatedBmp = Bitmap.createBitmap( srcBitmap,
0,
0,
srcBitmap.getWidth(),
srcBitmap.getHeight(),
matrix,
false );
return rotatedBmp;
}

Categories