How to resize bimpat size? - android

In my application I need to resize the bitmap to imageview size. I tried the following code and I am getting exception.
Bitmap bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), aMatrix, false);
Bitmap.createScaledBitmap(bmp, MyImageview_wt, MyImageview_ht, false);
MyImageview.setImageBitmap(bmp);
Pls help
Thanks
Monali

Try with the following code
public static Bitmap resizeBitMapImage1(String filePath, int targetWidth,
int targetHeight) {
Bitmap bitMapImage = null;
// First, get the dimensions of the image
Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
double sampleSize = 0;
// Only scale if we need to
// (16384 buffer for img processing)
Boolean scaleByHeight = Math.abs(options.outHeight - targetHeight) >= Math
.abs(options.outWidth - targetWidth);
if (options.outHeight * options.outWidth * 2 >= 1638) {
// Load, scaling to smallest power of 2 that'll get it <= desired
// dimensions
sampleSize = scaleByHeight ? options.outHeight / targetHeight
: options.outWidth / targetWidth;
sampleSize = (int) Math.pow(2d,
Math.floor(Math.log(sampleSize) / Math.log(2d)));
}
// Do the actual decoding
options.inJustDecodeBounds = false;
options.inTempStorage = new byte[128];
while (true) {
try {
options.inSampleSize = (int) sampleSize;
bitMapImage = BitmapFactory.decodeFile(filePath, options);
break;
} catch (Exception ex) {
try {
sampleSize = sampleSize * 2;
} catch (Exception ex1) {
}
}
}
return bitMapImage;
}

I think you are trying to get the width and height of the Bitmap itself, but instead you want to get the Height and Width of your ImageView and resize your Bitmap acordingly.

Try this:
Bitmap bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), aMatrix, false);
bmp = Bitmap.createScaledBitmap(bmp, MyImageview_wt, MyImageview_ht, false);
MyImageview.setImageBitmap(bmp);

Related

How do you deal with insanely high MP cameras (and images) on Android? - "Canvas: trying to draw too large bitmap"

I have an activity where the user can open the camera like so
getPictureUri(createImageFromFile = true)?.let {
photoUri = it
openCameraActivity(REQUEST_IMAGE_CAPTURE, it)
} ?: photoViewModel.onRequestUriError()
openCamera is an Activity Extension that looks like this
fun Activity.openCameraActivity(requestCode: Int, pictureUri: Uri) {
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
takePictureIntent.resolveActivity(packageManager)?.also {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri)
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
startActivityForResult(takePictureIntent, requestCode)
}
}
}
We write the image to a file when we get it back, and store the photoUri in the app somewhere. It works great! The issue is that some users have super high megapixel cameras, like 64mp, and when they take a picture it tries to display in the UI and it crashes.
FATAL EXCEPTION: main
Process: co.app.staging, PID: 27859
java.lang.RuntimeException: Canvas: trying to draw too large(256576512bytes) bitmap.
Is there a way I can limit the camera resolution on this? I could turn the quality down but that seems like a bandaid at best. What are some decent solutions for this?
I tried this way to draw bitmap on canvas from URI, try this:
(Explanation given below code)
private void drawBitmapUriOnCanvas(Uri selectedImage) {
if (selectedImage != null) {
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
try {
BitmapFactory.decodeStream(getContentResolver().openInputStream(
selectedImage), null, bmpFactoryOptions);
bmpFactoryOptions.inSampleSize = 2;
bmpFactoryOptions.inJustDecodeBounds = false;
Bitmap bmp = BitmapFactory
.decodeStream(getContentResolver().openInputStream(
selectedImage), null, bmpFactoryOptions);
Bitmap alteredBitmap;
if (bmp != null) {
if (getDeviceRam(this) <= 1024) {
bmp = getResizedBitmap(bmp, displayWidth);
}
bmp = checkAndRotateBitmap(bmp);
alteredBitmap = Bitmap.createBitmap(bmp.getWidth(), bmp
.getHeight(), bmp.getConfig());
Canvas canvas = new Canvas(alteredBitmap);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setStrokeWidth(5);
paint.setAntiAlias(true);
Matrix matrix = new Matrix();
canvas.drawBitmap(bmp, matrix, paint);
(now alteredBitmap is processed bitmap and you can use it)
}
} catch (FileNotFoundException e) {
Toast.makeText(this, "Error reading Image Metadata", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
}
Other included methods:
public static long getDeviceRam(Context context) {
ActivityManager actManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
actManager.getMemoryInfo(memInfo);
long totalMemory = memInfo.totalMem;
long fileSizeInKB = totalMemory / 1024;
// Convert the KB to MegaBytes (1 MB = 1024 KBytes)
return fileSizeInKB / 1024;
}
public static Bitmap getResizedBitmap(Bitmap image, int maxSize) {
int width = image.getWidth();
int height = image.getHeight();
float bitmapRatio = (float) width / (float) height;
if (bitmapRatio > 1) {
width = maxSize;
height = (int) (width / bitmapRatio);
} else {
height = maxSize;
width = (int) (height * bitmapRatio);
}
return Bitmap.createScaledBitmap(image, width, height, true);
}
Here, first of all i decoded image uri using BitmapFactory, then i checked device ram and it it was of 1GB then i resize the bitmap other wise original bitmap will be ok for next step,
And next was simply drawing bitmap on canvas and you will get alteredBitmap will is processed bitmap and it will be easy to use.
If this will not work then there is another option for completing your requirement and it was given below:
Bitmap bitmap = getBitmapFromGallery(selectedImage.getPath(), 800, 800);
private Bitmap getBitmapFromGallery(String path, int width, int height) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, width, height);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(path, options);
// if you use image from camera then in some cases it will rotated automatically like it was captured landscape but displays portrait then you have to use method `checkAndRotateBitmap()` which was also given below
// bitmap = checkAndRotateBitmap(bitmap);
return bitmap;
}
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
private Bitmap checkAndRotateBitmap(Bitmap bmp) {
try {
ExifInterface ei = new ExifInterface(imgPath);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
Bitmap rotatedBitmap;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotatedBitmap = Helper.rotateImage(bmp, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotatedBitmap = Helper.rotateImage(bmp, 180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotatedBitmap = Helper.rotateImage(bmp, 270);
break;
case ExifInterface.ORIENTATION_NORMAL:
default:
rotatedBitmap = bmp;
}
return rotatedBitmap;
} catch (IOException e) {
e.printStackTrace();
return bmp;
}
}
EDIT
for more information on how getBitmapFromGallery() method works, you should have look at https://medium.com/android-news/loading-large-bitmaps-efficiently-in-android-66826cd4ad53
That's all my friend, now try one of the methods for your requirement and let me know if this will work or not, also help me improve my answer if anything was wrong..Thank you!!

How to display Bitmap correctly?

I'm coping with two issues trying to display a photo from the Gallery in my Android application. What I want to do is simple: get a photo from the gallery and put it in a ImageView (which is 100dp*100dp) in my MainActivity.
The first issue is that on some phones, such as Sony Xperia, the photo is rotated when it is set on the ImageView. To address the problem, I found that piece of code in a SO answer:
public Bitmap decodeFile(String path)
{
int orientation;
try {
if (path == null) {
return null;
}
// decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 0;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale++;
}
// decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap bm = BitmapFactory.decodeFile(path, o2);
Bitmap bitmap = bm;
ExifInterface exif = new ExifInterface(path);
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
Log.e("ExifInteface .........", "rotation =" + orientation);
// exif.setAttribute(ExifInterface.ORIENTATION_ROTATE_90, 90);
Log.e("orientation", "" + orientation);
Matrix m = new Matrix();
if ((orientation == ExifInterface.ORIENTATION_ROTATE_180)) {
m.postRotate(180);
// m.postScale((float) bm.getWidth(), (float) bm.getHeight());
// if(m.preRotate(90)){
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
m.postRotate(90);
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
m.postRotate(270);
Log.e("in orientation", "" + orientation);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
bm.getHeight(), m, true);
return bitmap;
}
return bitmap;
} catch (Exception e) {
return null;
}
}
That works perfectly, but I also want the image to be a square, which is not the case for now.
To do that, after I used the first method on my bitmap, I also called that one:
public static Bitmap cropToSquare(Bitmap bitmap)
{
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int newWidth = (height > width) ? width : height;
int newHeight = (height > width)? height - ( height - width) : height;
int crop = (width - height) / 2;
crop = (crop < 0)? 0: crop;
Bitmap cropImg = Bitmap.createBitmap(bitmap, crop, 0, newWidth, newHeight);
return cropImg;
}
It does turns the bitmap into a square, but the problem is it cuts the photo instead of rescaling it. (basically half of the image is lost)
I am pretty sure what I want to do is simple, how can I do that?
Instead of using,
Bitmap.createBitmap(bitmap, crop, 0, newWidth, newHeight);
Use this below line,
Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, false);
Anyway, the official document is the best teacher, check here

How to show a large image completely on a canvas?

I want to load an image from gallery as a bitmap an show it on a custom view(not an imageview).Here is the code for loading bitmap.
private Bitmap loadBitmap(String filePath, int orientation, int width, int height) {
Bitmap bitmap = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
int scale = 1;
if ((options.outWidth > width) || (options.outHeight > height)) {
if (options.outWidth < options.outHeight) {
scale = Math.round((float) options.outWidth / width);
} else {
scale = Math.round((float) options.outHeight/ height);
}
}
options.inSampleSize = scale;
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(filePath, options);
if (orientation > 0) {
// rotate the image w.r.to orientation
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
bitmap = Bitmap.createBitmap(bitmap, 0, 0,width,height, matrix, true);
}
} catch (Exception e) {
bitmap = null;
}
return bitmap;
}
Now my problem is that the canvas does not show the bitmap completely.Only a part o it.How can i adjust the image (without losing its clarity,not stretching) with screen size?
Thanks in Advance
May be you can try the ScaleType options and use the one whihc suits you the best. Follow the link below for details:
http://developer.android.com/reference/android/widget/ImageView.ScaleType.html

How to resize Image in Android?

I am creating an application and want to setup a gallery view. I do not want the images in the gallery view to be full size. How do I resize images in Android?
Try:
Bitmap yourBitmap;
Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true);
or:
resized = Bitmap.createScaledBitmap(yourBitmap,(int)(yourBitmap.getWidth()*0.8), (int)(yourBitmap.getHeight()*0.8), true);
public Bitmap resizeBitmap(String photoPath, int targetW, int targetH) {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(photoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
int scaleFactor = 1;
if ((targetW > 0) || (targetH > 0)) {
scaleFactor = Math.min(photoW/targetW, photoH/targetH);
}
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true; //Deprecated API 21
return BitmapFactory.decodeFile(photoPath, bmOptions);
}
Capture the image and resize it.
Bitmap image2 = (Bitmap) data.getExtras().get("data");
img.setImageBitmap(image2);
String incident_ID = IncidentFormActivity.incident_id;
imagepath="/sdcard/RDMS/"+incident_ID+ x + ".PNG";
File file = new File(imagepath);
try {
double xFactor = 0;
double width = Double.valueOf(image2.getWidth());
Log.v("WIDTH", String.valueOf(width));
double height = Double.valueOf(image2.getHeight());
Log.v("height", String.valueOf(height));
if(width>height){
xFactor = 841/width;
}
else{
xFactor = 595/width;
}
Log.v("Nheight", String.valueOf(width*xFactor));
Log.v("Nweight", String.valueOf(height*xFactor));
int Nheight = (int) ((xFactor*height));
int NWidth =(int) (xFactor * width) ;
bm = Bitmap.createScaledBitmap( image2,NWidth, Nheight, true);
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bm.compress(CompressFormat.PNG, 100, ostream);
ostream.close();
You can use Matrix to resize your camera image ....
BitmapFactory.Options options=new BitmapFactory.Options();
InputStream is = getContentResolver().openInputStream(currImageURI);
bm = BitmapFactory.decodeStream(is,null,options);
int Height = bm.getHeight();
int Width = bm.getWidth();
int newHeight = 300;
int newWidth = 300;
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, true);
BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
//photo is bitmap image
Bitmap btm00 = Utils.getResizedBitmap(photo, 200, 200);
setimage.setImageBitmap(btm00);
And in Utils class :
public static 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();
// 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;
}
bm = Bitmap.createScaledBitmap(bitmapSource, width, height, true);
:)
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize=2; //try to decrease decoded image
Bitmap bitmap=BitmapFactory.decodeStream(is, null, options);
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos); //compressed bitmap to file
Following is the function to resize bitmap by keeping the same Aspect Ratio. Here I have also written a detailed blog post on the topic to explain this method. Resize a Bitmap by Keeping the Same Aspect Ratio.
public static Bitmap resizeBitmap(Bitmap source, int maxLength) {
try {
if (source.getHeight() >= source.getWidth()) {
int targetHeight = maxLength;
if (source.getHeight() <= targetHeight) { // if image already smaller than the required height
return source;
}
double aspectRatio = (double) source.getWidth() / (double) source.getHeight();
int targetWidth = (int) (targetHeight * aspectRatio);
Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
if (result != source) {
}
return result;
} else {
int targetWidth = maxLength;
if (source.getWidth() <= targetWidth) { // if image already smaller than the required height
return source;
}
double aspectRatio = ((double) source.getHeight()) / ((double) source.getWidth());
int targetHeight = (int) (targetWidth * aspectRatio);
Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
if (result != source) {
}
return result;
}
}
catch (Exception e)
{
return source;
}
}
resized = Bitmap.createScaledBitmap(yourImageBitmap,(int)(yourImageBitmap.getWidth()*0.9), (int)(yourBitmap.getHeight()*0.9), true);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 10;
FixBitmap = BitmapFactory.decodeFile(ImagePath, options);
//FixBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.gv);
byteArrayOutputStream = new ByteArrayOutputStream();
FixBitmap.compress(Bitmap.CompressFormat.JPEG, 80, byteArrayOutputStream); //compress to 50% of original image quality
byteArray = byteArrayOutputStream.toByteArray();
ConvertImage = Base64.encodeToString(byteArray, Base64.DEFAULT);

How to scale bitmap with high quality and without crash in android

I am downloading image using url, but after scaling it's crashing and scaling is not proper.
This is the code I have used,
//Code to fetch bitmap
Bitmap bmp=HttpFetch.fetchBitmap(imageUrl);
//Scale bitmap
Bitmap myBitmap = getResizedBitmap(bmp, viewWidth, viewHeight);
public static Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
int srcWidth = bm.getWidth();
int srcHeight = bm.getHeight();
int desiredWidth = newWidth;
int desiredHeight = newHeight;
int inSampleSize = 1;
while(srcWidth / 2 > desiredWidth){
srcWidth /= 2;
srcHeight /= 2;
inSampleSize *= 2;
}
float desiredWidthScale = (float) desiredWidth / srcWidth;
float desiredHeightScale = (float) desiredHeight / srcHeight;
// Decode with inSampleSize
options.inJustDecodeBounds = false;
options.inDither = false;
options.inSampleSize = inSampleSize;
options.inScaled = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Matrix matrix = new Matrix();
matrix.postScale(desiredWidthScale, desiredHeightScale);
original = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
return original;
}
Could not find code to get BitmapFactory.Option using bitmap and most of the places it is using filename, is it possible to get BitmapFactory.Options using bitmap?
Kindly suggest better solution to scale bitmap when we download from network.
original = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
This line returns an immutable Bitmap, after calling getResizedBitmap(), if you are trying to modify this Bitmap, it might result in a crash.
Android#createBitmap()
Please look up LogCat for details.

Categories

Resources