Resizing Bitmap maintaining aspect ratio and without distortion and cropping - android

Is there any way to resize a Bitmap without distortion so that it does not exceed 720*1280 ? Smaller height and width is completely fine (blank canvas in case of smaller width or height is fine) I tried this https://stackoverflow.com/a/15441311/6848469 but it gives distorted image. Can anybody suggest a better solution?

Here is the method for downscaling bitmap not to exceed MAX_ALLOWED_RESOLUTION. In you case MAX_ALLOWED_RESOLUTION = 1280. It will downscale without any distortion and losing quality:
private static Bitmap downscaleToMaxAllowedDimension(String photoPath) {
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(photoPath, bitmapOptions);
int srcWidth = bitmapOptions.outWidth;
int srcHeight = bitmapOptions.outHeight;
int dstWidth = srcWidth;
float scale = (float) srcWidth / srcHeight;
if (srcWidth > srcHeight && srcWidth > MAX_ALLOWED_RESOLUTION) {
dstWidth = MAX_ALLOWED_RESOLUTION;
} else if (srcHeight > srcWidth && srcHeight > MAX_ALLOWED_RESOLUTION) {
dstWidth = (int) (MAX_ALLOWED_RESOLUTION * scale);
}
bitmapOptions.inJustDecodeBounds = false;
bitmapOptions.inDensity = bitmapOptions.outWidth;
bitmapOptions.inTargetDensity = dstWidth;
return BitmapFactory.decodeFile(photoPath, bitmapOptions);
}
In case if you already have BITMAP object and not path use this:
private static Bitmap downscaleToMaxAllowedDimension(Bitmap bitmap) {
int MAX_ALLOWED_RESOLUTION = 1024;
int outWidth;
int outHeight;
int inWidth = bitmap.getWidth();
int inHeight = bitmap.getHeight();
if(inWidth > inHeight){
outWidth = MAX_ALLOWED_RESOLUTION;
outHeight = (inHeight * MAX_ALLOWED_RESOLUTION) / inWidth;
} else {
outHeight = MAX_ALLOWED_RESOLUTION;
outWidth = (inWidth * MAX_ALLOWED_RESOLUTION) / inHeight;
}
Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, outWidth, outHeight, false);
return resizedBitmap;
}

Related

Bitmap.createScaledBitmap not resizing the image twice the original size

I am trying to resize an image twice its original size.
Say, a width of 623 and height of 415.
So i tried this code:
Bitmap resized_captured_image_bm =
Bitmap.createScaledBitmap(ogBitmap,(int)(ogBitmap.getWidth() * 2),
(int)(ogBitmap.getHeight() * 2), false);
But the above code does nothing to the image, the displayed image is still the same dimension size.
Try to use next method:
public static final int MAX_FILE_ONE_SIZE = 200 * 1024;
public static final int MAX_SIZE_1 = 1280;
public static final int MAX_SIZE_2 = 960;
public static Bitmap resizeBitmap(Context context, Bitmap bitmap) {
Bitmap result = null;
if(bitmap != null){
int cnt = 0;
int width = bitmap.getWidth();
int height = bitmap.getHeight();
result = bitmap.copy(bitmap.getConfig(), true);
while(getImageSize(result) >= MAX_FILE_ONE_SIZE || !canSendBitmapResolution(result)){
result.recycle();
width = width/2;
height = height/2;
result = Bitmap.createScaledBitmap(bitmap, width, height, true);
if(cnt++ > 10) {
result = null;
break;
}
}
bitmap.recycle();
}
return result;
}
public static boolean canSendBitmapResolution(Bitmap bitmap){
boolean result = false;
if((bitmap.getWidth() <= MAX_SIZE_1 && bitmap.getHeight() <= MAX_SIZE_2)
|| (bitmap.getWidth() <= MAX_SIZE_2 && bitmap.getHeight() <= MAX_SIZE_1)){
result = true;
}
return result;
}
The problem is that the scale ratio doesn't match.
you just need to figure out what ratio to use and scale accordingly.
Ex:
final int maxSize = 960;
int outWidth;
int outHeight;
int inWidth = myBitmap.getWidth();
int inHeight = myBitmap.getHeight();
if(inWidth > inHeight){
outWidth = maxSize;
outHeight = (inHeight * maxSize) / inWidth;
} else {
outHeight = maxSize;
outWidth = (inWidth * maxSize) / inHeight;
}
Bitmap resizedBitmap = Bitmap.createScaledBitmap(myBitmap, outWidth, outHeight, false);
or, follow by google docs: Loading large bitmaps

Why image rotates after downsampling?

I am downsampling image with following code
private static Bitmap downsample(String path) {
final BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inTargetDensity = 1;
bitmapOptions.inSampleSize = 1;
bitmapOptions.inDensity = 1;
bitmapOptions.inTargetDensity = 1;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
int reqWidth = 800, reqHeight = 800;
final int newWidth = imageWidth / bitmapOptions.inSampleSize, newHeight =
imageHeight / bitmapOptions.inSampleSize;
if (newWidth > reqWidth || newHeight > reqHeight) {
if (newWidth * reqHeight > newHeight * reqWidth) {
// prefer width, as the width ratio is larger
bitmapOptions.inTargetDensity = reqWidth;
bitmapOptions.inDensity = newWidth;
} else {
// prefer height
bitmapOptions.inTargetDensity = reqHeight;
bitmapOptions.inDensity = newHeight;
}
}
final Bitmap scaledBitmap = BitmapFactory.decodeFile(path, bitmapOptions);
scaledBitmap.setDensity(Bitmap.DENSITY_NONE);
return scaledBitmap;
}
and load with glide
Glide.with(getActivity())
.load(MainActivity.mProfile.getImg())
.override(avatarSize, avatarSize)
.centerCrop()
.error(R.drawable.placeholder_photo)
.into(imAvatar);
However resulting bitmap i rotated 90 degree if original height bigger then width.

Android drawing scaled Bitmap without OutOfMemory error

I need scale my bitmap to screenSizeAverage / 3. When I do it like this, I have sometimes OutOfMemory error.
screenWidth = size.x;
screenHeight = size.y;
screenSizeAverage = (screenWidth + screenHeight) / 2;
Bitmap b2 = BitmapFactory.decodeResource(getResources(), R.drawable.logoqrtz);
logoqrtz = Bitmap.createScaledBitmap(b2, screenSizeAverage / 3,screenSizeAverage / 3, true);
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(logoqrtz, (int) (screenWidth / 2, (int) (screenHeight /2), p);
}
What is the best way to do this without OutOfMemory error?
From developer.android.com
private Bitmap setPic() {
// Get the dimensions of the View
int targetW = size.x;
int targetH = size.y;
int size = ((screenWidth + screenHeight) / 2) / 3;
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/size, photoH/size);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
return BitmapFactory.decodeResource(getResources(), R.drawable.logoqrtz, bmOptions);
}
Modified for your case.

How to compress image size?

I want to capture image in low resolution using android camera api but when I captured image it will take default resolution of device camera.So I want to capture image in low resolution or small size at time of capture or how can I compress big image into small size in android?
You can create bitmap with captured image as below:
Bitmap bitmap = Bitmap.createScaledBitmap(capturedImage, width, height, true);
Here you can specify width and height of the bitmap that you want to set to your ImageView. The height and width you can set according to the screen dpi of the device also, by reading the screen dpi of different devices programmatically.
Use Compressor (Image compression library).
Visit zetbaitsu/Compressor for code and documentation.
add dependency in gradle (app level)
dependencies {
implementation 'id.zelory:compressor:3.0.0'
}
To Compress Image use one of these approaches:
Compress Image File:
val compressedImageFile = Compressor.compress(context, actualImageFile)
Compress Image File to Bitmap:
val compressedImageFile = Compressor.compress(context, actualImageFile)
val bitmap = BitmapFactory.decodeFile(compressedImageFile.path)
Try this is working great with me.
private String decodeFile(String path) {
String strMyImagePath = null;
Bitmap scaledBitmap = null;
try {
// Part 1: Decode image
Bitmap unscaledBitmap = ScalingUtilities.decodeFile(path, DESIREDWIDTH, DESIREDHEIGHT, ScalingLogic.FIT);
if (!(unscaledBitmap.getWidth() <= 800 && unscaledBitmap.getHeight() <= 800)) {
// Part 2: Scale image
scaledBitmap = ScalingUtilities.createScaledBitmap(unscaledBitmap, DESIREDWIDTH, DESIREDHEIGHT, ScalingLogic.FIT);
} else {
unscaledBitmap.recycle();
return path;
}
// Store to tmp file
String extr = Environment.getExternalStorageDirectory().toString();
File mFolder = new File(extr + "/myTmpDir");
if (!mFolder.exists()) {
mFolder.mkdir();
}
String s = "tmp.png";
File f = new File(mFolder.getAbsolutePath(), s);
strMyImagePath = f.getAbsolutePath();
FileOutputStream fos = null;
try {
fos = new FileOutputStream(f);
scaledBitmap.compress(Bitmap.CompressFormat.PNG, 70, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
scaledBitmap.recycle();
} catch (Throwable e) {
}
if (strMyImagePath == null) {
return path;
}
return strMyImagePath;
}
Utility Class
public class ScalingUtilities {
/**
* Utility function for decoding an image resource. The decoded bitmap will
* be optimized for further scaling to the requested destination dimensions
* and scaling logic.
*
* #param res The resources object containing the image data
* #param resId The resource id of the image data
* #param dstWidth Width of destination area
* #param dstHeight Height of destination area
* #param scalingLogic Logic to use to avoid image stretching
* #return Decoded bitmap
*/
public static Bitmap decodeResource(Resources res, int resId, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
options.inJustDecodeBounds = false;
options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
dstHeight, scalingLogic);
Bitmap unscaledBitmap = BitmapFactory.decodeResource(res, resId, options);
return unscaledBitmap;
}
public static Bitmap decodeFile(String path, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
options.inJustDecodeBounds = false;
options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
dstHeight, scalingLogic);
Bitmap unscaledBitmap = BitmapFactory.decodeFile(path, options);
return unscaledBitmap;
}
/**
* Utility function for creating a scaled version of an existing bitmap
*
* #param unscaledBitmap Bitmap to scale
* #param dstWidth Wanted width of destination bitmap
* #param dstHeight Wanted height of destination bitmap
* #param scalingLogic Logic to use to avoid image stretching
* #return New scaled bitmap object
*/
public static Bitmap createScaledBitmap(Bitmap unscaledBitmap, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
Rect srcRect = calculateSrcRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),
dstWidth, dstHeight, scalingLogic);
Rect dstRect = calculateDstRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),
dstWidth, dstHeight, scalingLogic);
Bitmap scaledBitmap = Bitmap.createBitmap(dstRect.width(), dstRect.height(),
Config.ARGB_8888);
Canvas canvas = new Canvas(scaledBitmap);
canvas.drawBitmap(unscaledBitmap, srcRect, dstRect, new Paint(Paint.FILTER_BITMAP_FLAG));
return scaledBitmap;
}
/**
* ScalingLogic defines how scaling should be carried out if source and
* destination image has different aspect ratio.
*
* CROP: Scales the image the minimum amount while making sure that at least
* one of the two dimensions fit inside the requested destination area.
* Parts of the source image will be cropped to realize this.
*
* FIT: Scales the image the minimum amount while making sure both
* dimensions fit inside the requested destination area. The resulting
* destination dimensions might be adjusted to a smaller size than
* requested.
*/
public static enum ScalingLogic {
CROP, FIT
}
/**
* Calculate optimal down-sampling factor given the dimensions of a source
* image, the dimensions of a destination area and a scaling logic.
*
* #param srcWidth Width of source image
* #param srcHeight Height of source image
* #param dstWidth Width of destination area
* #param dstHeight Height of destination area
* #param scalingLogic Logic to use to avoid image stretching
* #return Optimal down scaling sample size for decoding
*/
public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
if (scalingLogic == ScalingLogic.FIT) {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
if (srcAspect > dstAspect) {
return srcWidth / dstWidth;
} else {
return srcHeight / dstHeight;
}
} else {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
if (srcAspect > dstAspect) {
return srcHeight / dstHeight;
} else {
return srcWidth / dstWidth;
}
}
}
/**
* Calculates source rectangle for scaling bitmap
*
* #param srcWidth Width of source image
* #param srcHeight Height of source image
* #param dstWidth Width of destination area
* #param dstHeight Height of destination area
* #param scalingLogic Logic to use to avoid image stretching
* #return Optimal source rectangle
*/
public static Rect calculateSrcRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
if (scalingLogic == ScalingLogic.CROP) {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
if (srcAspect > dstAspect) {
final int srcRectWidth = (int)(srcHeight * dstAspect);
final int srcRectLeft = (srcWidth - srcRectWidth) / 2;
return new Rect(srcRectLeft, 0, srcRectLeft + srcRectWidth, srcHeight);
} else {
final int srcRectHeight = (int)(srcWidth / dstAspect);
final int scrRectTop = (int)(srcHeight - srcRectHeight) / 2;
return new Rect(0, scrRectTop, srcWidth, scrRectTop + srcRectHeight);
}
} else {
return new Rect(0, 0, srcWidth, srcHeight);
}
}
/**
* Calculates destination rectangle for scaling bitmap
*
* #param srcWidth Width of source image
* #param srcHeight Height of source image
* #param dstWidth Width of destination area
* #param dstHeight Height of destination area
* #param scalingLogic Logic to use to avoid image stretching
* #return Optimal destination rectangle
*/
public static Rect calculateDstRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
if (scalingLogic == ScalingLogic.FIT) {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
if (srcAspect > dstAspect) {
return new Rect(0, 0, dstWidth, (int)(dstWidth / srcAspect));
} else {
return new Rect(0, 0, (int)(dstHeight * srcAspect), dstHeight);
}
} else {
return new Rect(0, 0, dstWidth, dstHeight);
}
}
}
You can compress image bitmap like this way.
ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
Here 100 is quality of image and you can change format of image to get low resolution image.
I think you are asking about Shrinking image size:
public Bitmap ShrinkBitmap(String file, int width, int height)
{
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(file, bmpFactoryOptions);
int heightRatio = (int) Math.ceil(bmpFactoryOptions.outHeight / (float) height);
int widthRatio = (int) Math.ceil(bmpFactoryOptions.outWidth / (float) width);
if(heightRatio > 1 || widthRatio > 1)
{
if(heightRatio > widthRatio)
{
bmpFactoryOptions.inSampleSize = heightRatio;
}
else
{
bmpFactoryOptions.inSampleSize = widthRatio;
}
}
bmpFactoryOptions.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(file, bmpFactoryOptions);
return bitmap;
}
please have look at compressImage method i have used for compressing image.
public static String compressImage(String imageUri, Activity activity) {
String filename = "";
try {
String filePath = getRealPathFromURI(imageUri, activity);
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(filePath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
float maxHeight = 816.0f;
float maxWidth = 612.0f;
float imgRatio = actualWidth / actualHeight;
float maxRatio = maxWidth / maxHeight;
if (actualHeight > maxHeight || actualWidth > maxWidth) {
if (imgRatio < maxRatio) {
imgRatio = maxHeight / actualHeight;
actualWidth = (int) (imgRatio * actualWidth);
actualHeight = (int) maxHeight;
} else if (imgRatio > maxRatio) {
imgRatio = maxWidth / actualWidth;
actualHeight = (int) (imgRatio * actualHeight);
actualWidth = (int) maxWidth;
} else {
actualHeight = (int) maxHeight;
actualWidth = (int) maxWidth;
}
}
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
options.inJustDecodeBounds = false;
options.inDither = false;
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
try {
bmp = BitmapFactory.decodeFile(filePath, options);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
try {
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float) options.outHeight;
float middleX = actualWidth / 2.0f;
float middleY = actualHeight / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas;
if (scaledBitmap != null) {
canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
}
ExifInterface exif;
try {
exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
} else if (orientation == 3) {
matrix.postRotate(180);
} else if (orientation == 8) {
matrix.postRotate(270);
}
if (scaledBitmap != null) {
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
}
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream out;
filename = getFilename(activity);
try {
out = new FileOutputStream(filename);
if (scaledBitmap != null) {
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
return filename;
}
private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
final float totalPixels = width * height;
final float totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
inSampleSize++;
}
return inSampleSize;
}
private static String getRealPathFromURI(String contentURI, Activity activity) {
Uri contentUri = Uri.parse(contentURI);
Cursor cursor = activity.getContentResolver().query(contentUri, null, null, null, null);
if (cursor == null) {
return contentUri.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx);
}
}
You can use this awesome library to compress.
Add dependency in app-level gradel:
dependencies {
implementation 'id.zelory:compressor:3.0.0'
}
And then just compress the actual image file like this:
val compressedImageFile = Compressor.compress(context, actualImageFile)
You should use Googles native image format WebP, it will shrink the image without losing quality. You can compress 80% of the picture without losing quality.
You can use CompressFormat.WEBP to encode any bitmap in WEBP format.
Example from file:
const int quality = 100;
FileOutputStream out = new FileOutputStream(path);
bitmap.compress(Bitmap.CompressFormat.WEBP, quality, out);
out.close();
Try this one:
byte[] data = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bi.compress(Bitmap.CompressFormat.JPEG, 100, baos);
data = baos.toByteArray();
i resolve this problem in this way, later i will improve the code
protected Void doInBackground(byte[]... data) {
FileOutputStream outStream = null;
// Write to Internal Storage
try {
File dir = new File (context.getFilesDir());
dir.mkdirs();
String fileName ="image.jpg";
File outFile = new File(dir, fileName);
outFile.setExecutable(true, false);
outFile.setWritable(true, false);
outStream = new FileOutputStream(outFile);
outStream.write(data[0]);
outStream.flush();
outStream.close();
InputStream in = new FileInputStream(context.getFilesDir()+"image.jpg");
Bitmap bm2 = BitmapFactory.decodeStream(in);
OutputStream stream = new FileOutputStream(String.valueOf(context.getFilesDir()+pathImage+"/"+idPicture+".jpg"));
bm2.compress(Bitmap.CompressFormat.JPEG, 50, stream);
stream.close();
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
return null;
}
use this class to compress image
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Matrix
import android.graphics.Paint
import android.net.Uri
import android.os.Environment
import java.io.*
class ImageFile(val uri: Uri, name: String) {
val filename: String
init {
val file = File(Environment.getExternalStorageDirectory().toString() + "/Documents")
if (!file.exists()) {
file.mkdirs()
}
val fileNoMedia = File(file.absolutePath + "/.nomedia")
if (!fileNoMedia.exists())
fileNoMedia.createNewFile()
if (name.toLowerCase().endsWith(".pdf")) {
filename = file.absolutePath + "/" + System.currentTimeMillis() + ".pdf"
} else {
filename = file.absolutePath + "/" + System.currentTimeMillis() + ".jpg"
}
}
#Throws(IOException::class)
fun copyFileStream(context: Context, uri: Uri): String {
if (filename.endsWith(".pdf") || filename.endsWith(".PDF")) {
var ins: InputStream? = null
var os: OutputStream? = null
try {
ins = context.getContentResolver().openInputStream(uri)
os = FileOutputStream(filename)
val buffer = ByteArray(1024)
var length: Int = ins.read(buffer)
while (length > 0) {
os.write(buffer, 0, length);
length = ins.read(buffer)
}
} catch (e: Exception) {
e.printStackTrace();
} finally {
ins?.close()
os?.close()
}
} else {
var ins: InputStream? = null
var os: OutputStream? = null
try {
ins = context.getContentResolver().openInputStream(uri)
var scaledBitmap: Bitmap? = null
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
var bmp = BitmapFactory.decodeStream(ins, null, options)
var actualHeight = options.outHeight
var actualWidth = options.outWidth
// max Height and width values of the compressed image is taken as 816x612
val maxHeight = 816.0f
val maxWidth = 612.0f
var imgRatio = (actualWidth / actualHeight).toFloat()
val maxRatio = maxWidth / maxHeight
// width and height values are set maintaining the aspect ratio of the image
if (actualHeight > maxHeight || actualWidth > maxWidth) {
if (imgRatio < maxRatio) {
imgRatio = maxHeight / actualHeight
actualWidth = (imgRatio * actualWidth).toInt()
actualHeight = maxHeight.toInt()
} else if (imgRatio > maxRatio) {
imgRatio = maxWidth / actualWidth
actualHeight = (imgRatio * actualHeight).toInt()
actualWidth = maxWidth.toInt()
} else {
actualHeight = maxHeight.toInt()
actualWidth = maxWidth.toInt()
}
}
// setting inSampleSize value allows to load a scaled down version of the original image
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight)
// inJustDecodeBounds set to false to load the actual bitmap
options.inJustDecodeBounds = false
// this options allow android to claim the bitmap memory if it runs low on memory
options.inPurgeable = true
options.inInputShareable = true
options.inTempStorage = ByteArray(16 * 1024)
try {
// load the bitmap from its path
ins.close()
ins = context.getContentResolver().openInputStream(uri)
bmp = BitmapFactory.decodeStream(ins, null, options)
} catch (exception: OutOfMemoryError) {
exception.printStackTrace()
}
try {
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888)
} catch (exception: OutOfMemoryError) {
exception.printStackTrace()
}
val ratioX = actualWidth / options.outWidth.toFloat()
val ratioY = actualHeight / options.outHeight.toFloat()
val middleX = actualWidth / 2.0f
val middleY = actualHeight / 2.0f
val scaleMatrix = Matrix()
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY)
val canvas = Canvas(scaledBitmap!!)
canvas.matrix = scaleMatrix
canvas.drawBitmap(bmp, middleX - bmp.width / 2, middleY - bmp.height / 2, Paint(Paint.FILTER_BITMAP_FLAG))
os = FileOutputStream(filename)
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, os)
val buffer = ByteArray(1024)
var length: Int = ins.read(buffer)
while (length > 0) {
os.write(buffer, 0, length);
length = ins.read(buffer)
}
} catch (e: Exception) {
e.printStackTrace();
} finally {
ins?.close()
os?.close()
}
}
return filename
}
fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
val height = options.outHeight
val width = options.outWidth
var inSampleSize = 1
if (height > reqHeight || width > reqWidth) {
val heightRatio = Math.round(height.toFloat() / reqHeight.toFloat())
val widthRatio = Math.round(width.toFloat() / reqWidth.toFloat())
inSampleSize = if (heightRatio < widthRatio) heightRatio else widthRatio
}
val totalPixels = (width * height).toFloat()
val totalReqPixelsCap = (reqWidth * reqHeight * 2).toFloat()
while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
inSampleSize++
}
return inSampleSize
}
}
https://lalitjadav007.blogspot.in/2017/08/compress-image-in-android.html
You can try this code
public class ScalingUtilities {
/**
* Utility function for decoding an image resource. The decoded bitmap will
* be optimized for further scaling to the requested destination dimensions
* and scaling logic.
*
* #param res The resources object containing the image data
* #param resId The resource id of the image data
* #param dstWidth Width of destination area
* #param dstHeight Height of destination area
* #param scalingLogic Logic to use to avoid image stretching
* #return Decoded bitmap
*/
public static Bitmap decodeResource(Resources res, int resId, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
options.inJustDecodeBounds = false;
options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
dstHeight, scalingLogic);
Bitmap unscaledBitmap = BitmapFactory.decodeResource(res, resId, options);
return unscaledBitmap;
}
public static Bitmap decodeFile(String path, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
options.inJustDecodeBounds = false;
options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
dstHeight, scalingLogic);
Bitmap unscaledBitmap = BitmapFactory.decodeFile(path, options);
return unscaledBitmap;
}
/**
* Utility function for creating a scaled version of an existing bitmap
*
* #param unscaledBitmap Bitmap to scale
* #param dstWidth Wanted width of destination bitmap
* #param dstHeight Wanted height of destination bitmap
* #param scalingLogic Logic to use to avoid image stretching
* #return New scaled bitmap object
*/
public static Bitmap createScaledBitmap(Bitmap unscaledBitmap, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
Rect srcRect = calculateSrcRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),
dstWidth, dstHeight, scalingLogic);
Rect dstRect = calculateDstRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),
dstWidth, dstHeight, scalingLogic);
Bitmap scaledBitmap = Bitmap.createBitmap(dstRect.width(), dstRect.height(),
Config.ARGB_8888);
Canvas canvas = new Canvas(scaledBitmap);
canvas.drawBitmap(unscaledBitmap, srcRect, dstRect, new Paint(Paint.FILTER_BITMAP_FLAG));
return scaledBitmap;
}
/**
* ScalingLogic defines how scaling should be carried out if source and
* destination image has different aspect ratio.
*
* CROP: Scales the image the minimum amount while making sure that at least
* one of the two dimensions fit inside the requested destination area.
* Parts of the source image will be cropped to realize this.
*
* FIT: Scales the image the minimum amount while making sure both
* dimensions fit inside the requested destination area. The resulting
* destination dimensions might be adjusted to a smaller size than
* requested.
*/
public static enum ScalingLogic {
CROP, FIT
}
/**
* Calculate optimal down-sampling factor given the dimensions of a source
* image, the dimensions of a destination area and a scaling logic.
*
* #param srcWidth Width of source image
* #param srcHeight Height of source image
* #param dstWidth Width of destination area
* #param dstHeight Height of destination area
* #param scalingLogic Logic to use to avoid image stretching
* #return Optimal down scaling sample size for decoding
*/
public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
if (scalingLogic == ScalingLogic.FIT) {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
if (srcAspect > dstAspect) {
return srcWidth / dstWidth;
} else {
return srcHeight / dstHeight;
}
} else {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
if (srcAspect > dstAspect) {
return srcHeight / dstHeight;
} else {
return srcWidth / dstWidth;
}
}
}
/**
* Calculates source rectangle for scaling bitmap
*
* #param srcWidth Width of source image
* #param srcHeight Height of source image
* #param dstWidth Width of destination area
* #param dstHeight Height of destination area
* #param scalingLogic Logic to use to avoid image stretching
* #return Optimal source rectangle
*/
public static Rect calculateSrcRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
if (scalingLogic == ScalingLogic.CROP) {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
if (srcAspect > dstAspect) {
final int srcRectWidth = (int)(srcHeight * dstAspect);
final int srcRectLeft = (srcWidth - srcRectWidth) / 2;
return new Rect(srcRectLeft, 0, srcRectLeft + srcRectWidth, srcHeight);
} else {
final int srcRectHeight = (int)(srcWidth / dstAspect);
final int scrRectTop = (int)(srcHeight - srcRectHeight) / 2;
return new Rect(0, scrRectTop, srcWidth, scrRectTop + srcRectHeight);
}
} else {
return new Rect(0, 0, srcWidth, srcHeight);
}
}
/**
* Calculates destination rectangle for scaling bitmap
*
* #param srcWidth Width of source image
* #param srcHeight Height of source image
* #param dstWidth Width of destination area
* #param dstHeight Height of destination area
* #param scalingLogic Logic to use to avoid image stretching
* #return Optimal destination rectangle
*/
public static Rect calculateDstRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
ScalingLogic scalingLogic) {
if (scalingLogic == ScalingLogic.FIT) {
final float srcAspect = (float)srcWidth / (float)srcHeight;
final float dstAspect = (float)dstWidth / (float)dstHeight;
if (srcAspect > dstAspect) {
return new Rect(0, 0, dstWidth, (int)(dstWidth / srcAspect));
} else {
return new Rect(0, 0, (int)(dstHeight * srcAspect), dstHeight);
}
} else {
return new Rect(0, 0, dstWidth, dstHeight);
}
}
public static String decodeFile(String path,int DESIREDWIDTH, int DESIREDHEIGHT, int type) {
String strMyImagePath = null;
Bitmap scaledBitmap = null;
Bitmap rotated = null;
try {
// Part 1: Decode image
Bitmap unscaledBitmap = ScalingUtilities.decodeFile(path, DESIREDWIDTH, DESIREDHEIGHT, ScalingLogic.FIT);
// if (!(unscaledBitmap.getWidth() <= DESIREDWIDTH && unscaledBitmap.getHeight() <= DESIREDHEIGHT)) {
// // Part 2: Scale image
// scaledBitmap = ScalingUtilities.createScaledBitmap(unscaledBitmap, DESIREDWIDTH, DESIREDHEIGHT, ScalingLogic.FIT);
// } else {
// unscaledBitmap.recycle();
// return path;
// }
// Store to tmp file
scaledBitmap = ScalingUtilities.createScaledBitmap(unscaledBitmap, DESIREDWIDTH, DESIREDHEIGHT, ScalingLogic.FIT);
String extr = Environment.getExternalStorageDirectory().toString();
File mFolder = new File(extr + com.vt.vsmart.utils.Config.SD_PATH+"/image");
if (!mFolder.exists()) {
mFolder.mkdir();
}
String s = type+"temp.jpg";
File f = new File(mFolder.getAbsolutePath(), s);
strMyImagePath = f.getAbsolutePath();
FileOutputStream fos = null;
try {
fos = new FileOutputStream(f);
// scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 95, fos);
// quay anh 90 do
Matrix matrix = new Matrix();
matrix.postRotate(90);
rotated = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
rotated.compress(Bitmap.CompressFormat.JPEG, 95, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
// scaledBitmap.recycle();
rotated.recycle();
} catch (Throwable e) {
}
if (strMyImagePath == null) {
return path;
}
return strMyImagePath;
}
// check anh bi quay
public int getCameraPhotoOrientation(Context context, Uri imageUri, String imagePath){
int rotate = 0;
try {
context.getContentResolver().notifyChange(imageUri, null);
File imageFile = new File(imagePath);
ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
// Log.i("RotateImage", "Exif orientation: " + orientation);
// Log.i("RotateImage", "Rotate value: " + rotate);
} catch (Exception e) {
e.printStackTrace();
}
return rotate;
}
}
It work for me. I hope it can hepl you!
Try this Method,this will convert your Image file to compressed format,and you can customized the compress level by varrying the value of x & y in the code(Indicated in comment line)
File mImageFile = saveBitmapToFile(ImageFile);
public File saveBitmapToFile(File file){
try {
// BitmapFactory options to downsize the image
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
o.inSampleSize = 6;
// factor of downsizing the image
FileInputStream inputStream = new FileInputStream(file);
//Bitmap selectedBitmap = null;
BitmapFactory.decodeStream(inputStream, null, o);
inputStream.close();
// The new size we want to scale to
final int REQUIRED_SIZE=200; // x............
// Find the correct scale value. It should be the power of 2.
int scale = 1;
while(o.outWidth / scale / 2 >= REQUIRED_SIZE &&
o.outHeight / scale / 2 >= REQUIRED_SIZE) {
scale *= 2;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
inputStream = new FileInputStream(file);
Bitmap selectedBitmap = BitmapFactory.decodeStream(inputStream, null, o2);
inputStream.close();
// here i override the original image file
File outPutFile = File.createTempFile("abc","image");
FileOutputStream outputStream = new FileOutputStream(outPutFile);
// y.......
selectedBitmap.compress(Bitmap.CompressFormat.JPEG, 95 , outputStream);
return outPutFile;
} catch (Exception e) {
return null;
}
}
Thanks

How to Resize a Bitmap in Android?

I have a bitmap taken of a Base64 String from my remote database, (encodedImage is the string representing the image with Base64):
profileImage = (ImageView)findViewById(R.id.profileImage);
byte[] imageAsBytes=null;
try {
imageAsBytes = Base64.decode(encodedImage.getBytes());
} catch (IOException e) {e.printStackTrace();}
profileImage.setImageBitmap(
BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)
);
profileImage is my ImageView
Ok, but I have to resize this image before showing it on my ImageView of my layout. I have to resize it to 120x120.
Can someone tell me the code to resize it?
The examples I found could not be applied to a base64 string obtained bitmap.
Change:
profileImage.setImageBitmap(
BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)
To:
Bitmap b = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length)
profileImage.setImageBitmap(Bitmap.createScaledBitmap(b, 120, 120, false));
import android.graphics.Matrix
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;
}
EDIT: as suggested by by #aveschini, I have added bm.recycle(); in order to avoid the memory leaks. Please note that in case if you are using the previous object for some other purposes, then handle accordingly.
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);
Scale based on aspect ratio:
float aspectRatio = yourSelectedImage.getWidth() /
(float) yourSelectedImage.getHeight();
int width = 480;
int height = Math.round(width / aspectRatio);
yourSelectedImage = Bitmap.createScaledBitmap(
yourSelectedImage, width, height, false);
To use height as base intead of width change to:
int height = 480;
int width = Math.round(height * aspectRatio);
Scale a bitmap with a target maximum size and width, while maintaining aspect ratio:
int maxHeight = 2000;
int maxWidth = 2000;
float scale = Math.min(((float)maxHeight / bitmap.getWidth()), ((float)maxWidth / bitmap.getHeight()));
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
try this this code :
BitmapDrawable drawable = (BitmapDrawable) imgview.getDrawable();
Bitmap bmp = drawable.getBitmap();
Bitmap b = Bitmap.createScaledBitmap(bmp, 120, 120, false);
I hope it's useful.
Someone asked how to keep aspect ratio in this situation:
Calculate the factor you are using for scaling and use it for both dimensions.
Let´s say you want an image to be 20% of the screen in height
int scaleToUse = 20; // this will be our percentage
Bitmap bmp = BitmapFactory.decodeResource(
context.getResources(), R.drawable.mypng);
int sizeY = screenResolution.y * scaleToUse / 100;
int sizeX = bmp.getWidth() * sizeY / bmp.getHeight();
Bitmap scaled = Bitmap.createScaledBitmap(bmp, sizeX, sizeY, false);
for getting the screen resolution you have this solution:
Get screen dimensions in pixels
Although the accepted answer is correct, it doesn't resize Bitmap by keeping the same Aspect Ratio. If you are looking for a method to resize Bitmap by keeping the same aspect ratio you can use the following utility function. The usage details and explanation of the function are present at this link.
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;
}
}
public Bitmap scaleBitmap(Bitmap mBitmap) {
int ScaleSize = 250;//max Height or width to Scale
int width = mBitmap.getWidth();
int height = mBitmap.getHeight();
float excessSizeRatio = width > height ? width / ScaleSize : height / ScaleSize;
Bitmap bitmap = Bitmap.createBitmap(
mBitmap, 0, 0,(int) (width/excessSizeRatio),(int) (height/excessSizeRatio));
//mBitmap.recycle(); if you are not using mBitmap Obj
return bitmap;
}
public static Bitmap resizeBitmapByScale(
Bitmap bitmap, float scale, boolean recycle) {
int width = Math.round(bitmap.getWidth() * scale);
int height = Math.round(bitmap.getHeight() * scale);
if (width == bitmap.getWidth()
&& height == bitmap.getHeight()) return bitmap;
Bitmap target = Bitmap.createBitmap(width, height, getConfig(bitmap));
Canvas canvas = new Canvas(target);
canvas.scale(scale, scale);
Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
canvas.drawBitmap(bitmap, 0, 0, paint);
if (recycle) bitmap.recycle();
return target;
}
private static Bitmap.Config getConfig(Bitmap bitmap) {
Bitmap.Config config = bitmap.getConfig();
if (config == null) {
config = Bitmap.Config.ARGB_8888;
}
return config;
}
Try this:
This function resizes a bitmap proportionally. When the last parameter is set to "X" the newDimensionXorY is treated as s new width and when set to "Y" a new height.
public Bitmap getProportionalBitmap(Bitmap bitmap,
int newDimensionXorY,
String XorY) {
if (bitmap == null) {
return null;
}
float xyRatio = 0;
int newWidth = 0;
int newHeight = 0;
if (XorY.toLowerCase().equals("x")) {
xyRatio = (float) newDimensionXorY / bitmap.getWidth();
newHeight = (int) (bitmap.getHeight() * xyRatio);
bitmap = Bitmap.createScaledBitmap(
bitmap, newDimensionXorY, newHeight, true);
} else if (XorY.toLowerCase().equals("y")) {
xyRatio = (float) newDimensionXorY / bitmap.getHeight();
newWidth = (int) (bitmap.getWidth() * xyRatio);
bitmap = Bitmap.createScaledBitmap(
bitmap, newWidth, newDimensionXorY, true);
}
return bitmap;
}
profileImage.setImageBitmap(
Bitmap.createScaledBitmap(
BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length),
80, 80, false
)
);
Bitmap Resize based on Any Display size
public Bitmap bitmapResize(Bitmap imageBitmap) {
Bitmap bitmap = imageBitmap;
float heightbmp = bitmap.getHeight();
float widthbmp = bitmap.getWidth();
// Get Screen width
DisplayMetrics displaymetrics = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
float height = displaymetrics.heightPixels / 3;
float width = displaymetrics.widthPixels / 3;
int convertHeight = (int) hight, convertWidth = (int) width;
// higher
if (heightbmp > height) {
convertHeight = (int) height - 20;
bitmap = Bitmap.createScaledBitmap(bitmap, convertWidth,
convertHighet, true);
}
// wider
if (widthbmp > width) {
convertWidth = (int) width - 20;
bitmap = Bitmap.createScaledBitmap(bitmap, convertWidth,
convertHeight, true);
}
return bitmap;
}
Try this kotlin code for resize....Where Max size any size you
want
fun getResizedBitmap(image: Bitmap?, maxSize: Int): Bitmap {
var width = image!!.width
var height = image.height
val bitmapRatio = width.toFloat() / height.toFloat()
if (bitmapRatio > 0) {
width = maxSize
height = (width / bitmapRatio).toInt()
} else {
height = maxSize
width = (height * bitmapRatio).toInt()
}
return Bitmap.createScaledBitmap(image, width, height, true)
}
As of API 19, Bitmap setWidth(int width) and setHeight(int height) exist.
http://developer.android.com/reference/android/graphics/Bitmap.html
/**
* Kotlin method for Bitmap scaling
* #param bitmap the bitmap to be scaled
* #param pixel the target pixel size
* #param width the width
* #param height the height
* #param max the max(height, width)
* #return the scaled bitmap
*/
fun scaleBitmap(bitmap:Bitmap, pixel:Float, width:Int, height:Int, max:Int):Bitmap {
val scale = px / max
val h = Math.round(scale * height)
val w = Math.round(scale * width)
return Bitmap.createScaledBitmap(bitmap, w, h, true)
}
Keeping the aspect ratio,
public Bitmap resizeBitmap(Bitmap source, int width,int height) {
if(source.getHeight() == height && source.getWidth() == width) return source;
int maxLength=Math.min(width,height);
try {
source=source.copy(source.getConfig(),true);
if (source.getHeight() <= source.getWidth()) {
if (source.getHeight() <= maxLength) { // if image already smaller than the required height
return source;
}
double aspectRatio = (double) source.getWidth() / (double) source.getHeight();
int targetWidth = (int) (maxLength * aspectRatio);
return Bitmap.createScaledBitmap(source, targetWidth, maxLength, false);
} else {
if (source.getWidth() <= maxLength) { // if image already smaller than the required height
return source;
}
double aspectRatio = ((double) source.getHeight()) / ((double) source.getWidth());
int targetHeight = (int) (maxLength * aspectRatio);
return Bitmap.createScaledBitmap(source, maxLength, targetHeight, false);
}
}
catch (Exception e)
{
return source;
}
}
While the previous answers do scale the image and take care of the aspect ratio, the resampling itself should be done so that there is no aliasing. Taking care of scale is a matter of fixing arguments correctly. There are many comments about the quality of the output images from standard scaling call. to maintain quality of the image one should use the standard call:
Bitmap resizedBitmap = Bitmap.createScaledBitmap(originalBitmap, newWidth, newHeight, true);
with the last argument set to true because it will do the bilinear filtering for resampling to prevent aliasing. Read more about aliasing here: https://en.wikipedia.org/wiki/Aliasing
From android documentation:
https://developer.android.com/reference/android/graphics/Bitmap#createScaledBitmap(android.graphics.Bitmap,%20int,%20int,%20boolean)
public static Bitmap createScaledBitmap (Bitmap src,
int dstWidth,
int dstHeight,
boolean filter)
filter : boolean, Whether or not bilinear filtering should be used when scaling the bitmap. If this is true then bilinear filtering will be used when scaling which has better image quality at the cost of worse performance. If this is false then nearest-neighbor scaling is used instead which will have worse image quality but is faster. Recommended default is to set filter to 'true' as the cost of bilinear filtering is typically minimal and the improved image quality is significant.
* For resize bitmap with width and height ratio.
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);
}
apply Matrix.ScaleToFit.CENTER) for getting a new bitmap keeps aspect ratio.
public static Bitmap getScaledwonBitmap(Bitmap srcBmp, int deisredWidth, int desiredHeight) {
Matrix matrix = new Matrix();
matrix.setRectToRect(new RectF(0, 0, srcBmp.getWidth(), srcBmp.getHeight()),
new RectF(0, 0, deisredWidth, desiredHeight),
Matrix.ScaleToFit.CENTER);
return Bitmap.createBitmap(srcBmp, 0, 0, srcBmp.getWidth(), srcBmp.getHeight(), matrix, true);
}

Categories

Resources