How to resize image with custom size - android

I need to resize my image with custom size. The image is taken from device camera or gallery, i tired the below code, but the image is stretched, i need the image in square shape with out any stretch.
public Bitmap decodeSampledBitmapFromFile(Bitmap bm, int boundBoxInDp) {
boundBoxInDp=300;
int height = bm.getHeight();
int width = bm.getWidth();
float scaleWidth = ((float) boundBoxInDp) / width;
float scaleHeight = ((float) boundBoxInDp) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
return resizedBitmap;
}

If you already have a bitmap, you could use the following code to resize:
Bitmap originalBitmap = <original initialization>;
Bitmap resizedBitmap = Bitmap.createScaledBitmap(originalBitmap, newWidth, newHeight, false);
Or you can use following library for resize image
https://github.com/biokys/cropimage

This won't fit your image in a bounding box (the failure of which is presumably what you're calling "stretch"). It will not handle rectangular bitmaps in your square bounding box, nor will it handle images smaller than the bounding box particularly well. You probably want something like:
public Bitmap decodeSampledBitmapFromFile(Bitmap bm, int boundBoxInDp) {
boundSquareInPx=convertToPixels(300);
int maxDimen = Math.max(bm.getHeight(), bm.getWidth())
float scale = (maxDimen <= boundSquareInPx) ? 1 : boundSquareInPx / (float) maxDimen;
float scaleWidth = scale * bm.getWidth();
float scaleHeight = scale * bm.getHeight();
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, true);
return resizedBitmap;
}
Few notes: if you image is smaller than your bound it won't fit it- obvious modifications do that.
Secondly, dp != px; the Bitmap object returns px, so you're going to have to convert to px from dp (which is well documented elsewhere).
Use postTranslate(...) if you need to center the correspondingly cropped bitmap.
The documentation is here; this is allready the best library I know for resizing in Android- I've never needed anything else, and I've been in the game a while and work with this frequently.
If you need, in my opinion, the best introduction to working with the API efficiently: read the source code to ImageView and Drawable instances; a really worthwhile personal development exercise would be to use the SDK to implement a fading transition drawable that is center cropped, as that's rather annoyingly one of the only things missing from the Android library, and would involve a heck of a lot of the kind of coding you're trying to do above.
NB:
As you'll note, another answerer has pointed out the existence of createScaledBitmap, which is probably much clearer code; I just wanted to point out how what you were doing was basically right and how it could be improved.
Best.

Take a look at https://github.com/coomar2841/image-chooser-library/blob/d27b542d2487132b0150be382f39e9ef95aafe68/src/com/kbeanie/imagechooser/threads/MediaProcessorThread.java.
The method called compressAndSaveImage.

Related

How to pixelize a bitmap in android

I have been searching but i did not find a question about how to pixelize a bitmap in android
Example
Note that i dont mean blur
You could just try and resize that image to a smaller version (and then back up if you need it at the same size as the original for some reason)
{
Bitmap original = ...;
//Calculate proportional size, or make the method accept just a factor of scale.
Bitmap small = getResigetResizedBitmap(original, smallWidth, smallHeight);
Bitmap pixelated = getResigetResizedBitmap(small, normalWidth, normalHeight);
//Recycle small, recycle original if no longer needed.
}
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);
return resizedBitmap;
}
The code is from here
The simplest way to pixelate the image would be to scale image down using "nearest neighbour" algorithm, and then scale up, using the same algorithm.
Filtering over the image trying to find an average takes much more time, but does not actually give any improvements in result quality, after all you do intentionally want your image distorted.

Should I recycle my bitmaps after a resize?

I've got a utility method (below) that resizes a bitmap and gives me back a new version. Since I am doing this with quite a few images & I wanted to reduce the chance of running out of memory, I've recycled the bitmap after usage.
This works fine on almost all devices. However, I've notice on the samsung galaxy tab 3 (10 inch) and the note 10.1 (2014) I'm getting the below stack traces:
java.lang.IllegalArgumentException: Cannot draw recycled bitmaps
at android.view.GLES20Canvas.drawBitmap(GLES20Canvas.java:756)
at android.view.GLES20RecordingCanvas.drawBitmap(GLES20RecordingCanvas.java:104)
Below is my resize code:
private static Bitmap resizeBitmap(int newWidth, int newHeight, Bitmap bitmapResize) {
if (bitmapResize == null) {
return null;
}
int width = bitmapResize.getWidth();
int height = bitmapResize.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmapResize,
newWidth, newHeight, true);
//SHOULD I DO THIS???
bitmapResize.recycle();
return resizedBitmap;
}
I have not figured out why almost all devices work, except those 2 (there may be more). The emulator shows no issues either.
It might be worth noting, not all images give me a "Cannot draw recycled bitmaps" error. Only some. But its consistently the same images.
(In case its of use, my app runs on 2.2 upwards)
I've managed to find the solution to my issue. It turns out the original image may be passed back as an optimisation, if the width/height of the resize match the original image.
I imagine on some devices my computations resulted in me trying to resize an image to its existing size. When i recycled the "old" bitmap, i was recyling the resized one too.
The solution is to change my code to say
if (bitmapResize!=resizedBitmap )
bitmapResize.recycle();
I found my issue covered in this conversation ( which i didn't find in my initial searching for the issue)
https://groups.google.com/forum/#!topic/android-developers/M6njPbo3U0c
I had a similar issue with on of ma games and from my experience you are doing the right thing. its the right place to recycle the old bitmap and will prevent OutOfMemoryExceptions, keep in mind that this instance of Bitmap will not be usable anymore.
You may simply use input bitmap reference as output. This way your input bitmap will be overwritten and you won't need to recycle it.
Kind of:
private static Bitmap resizeBitmap(int newWidth, int newHeight, Bitmap bitmapResize) {
if (bitmapResize == null) {
return null;
}
int width = bitmapResize.getWidth();
int height = bitmapResize.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
return Bitmap.createScaledBitmap(bitmapResize,
newWidth, newHeight, true);
}

Zooming the Bitmap on Surfaceview in Android

I want to resize the bitmap slowly (like zooming in the bitmap )on surface view. When I set some standard increased values for width and height, it will displays the bigger image.As I give below in onDraw method
can.drawBitmap(gball, lastVisitedX, lastVisitedY, paint);
gball = getResizedBitmap(gball, bitmapInitHeight
+ bitmapInitHeight, bitmapInitHeight + bitmapInitHeight);
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
return resizedBitmap;
}
But when I try to resize by increasing the height and width like
can.drawBitmap(gball, lastVisitedX, lastVisitedY, paint);
gball = getResizedBitmap(gball, bitmapInitHeight
+ zoomXValue, bitmapInitHeight + zoomYValue);
zoomXValue= zoomXValue+5;
zoomYValue= zoomYValue+5;
In onDraw method but the bitmap is resize with bad quality.
Finally my question is how to scale like zooming out with out damaging the quality.
Thanks in Advance.
You are always going to have scaling problems especially if you scale up and you have same hard edges on your image, only way you can avoid this (in some manner) is to use larger image and always scale down (Still not going to help with hard edges).
Try setting Filter to true it might help a little :)
Hope this helps and enjoy your work.

Setting wallpaper

Im trying to set my bitmap image as a wallpaper!
Im currently using this code to get it done.
WallpaperManager wpm = WallpaperManager.getInstance(this);
float minH = wpm.getDesiredMinimumHeight();
float minW = wpm.getDesiredMinimumWidth();
Log.d("seb", minH + " = Min Height");
Log.d("seb", minW + " = Min Width");
targetBitmap = Bitmap.createScaledBitmap(targetBitmap,(int)minW, (int)minH, false);
wpm.setBitmap(targetBitmap);
It works! The phone automatically resizes the bitmap to fit the screen, but no mather how small my bitmap is, it's always cropped horizontally and scaled up.
Does anyone know how to fix this?
(One fix would be to put a black border around and have them cropped instead of the actual picture, though Im guessing there is a better alternative )
EDIT
this is original picture in code.
The following picture is what I mean with cropped when set to wallpaper:
And this will be in the same way even if i resize the image since the system automatically enlarges the picture to fit the whole screen
Ok, so after our discussion in "comments", here is a solution which can work.
Try that:
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
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);
return resizedBitmap;
}
Try it and if you have the same (or another) problem, let me know and we will try to fix it.

How to make an image small rather than its original size?

I am developing an animation app in the android.
i have one big image in application.
The image should start from the center of screen. The image size will be bigger at the initial stage. While moving to the left of the screen, its size should decrease(i.e. scaling should take place). Image should not go back to its original position. It should be placed at the leftside of the screen itself after the animation.
Can anyone please help.
Thanking you.
If I understand conrrectly you want to display an image and then animate it so that it appers to be reducing in size giving an affect that is going into the background.
You need to use ScaleAnimation
http://developer.android.com/reference/android/view/animation/ScaleAnimation.html
A good tutorial regarding android animation can be found at:
http://www.hascode.com/2010/09/playing-around-with-the-android-animation-framework/#Scale_Animations
this function resize the bitmap
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
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);
matrix.postRotate(90);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
resizedBitmap.compress(Bitmap.CompressFormat.PNG, 70, bytes);
return resizedBitmap;
}

Categories

Resources