In my chat-app I want to send image message. How can I upload images between 100kb, without loosing so much quality? I am new in android, please help me to do this.
ActivityResultLauncher<String> launcher = registerForActivityResult(new ActivityResultContracts.GetContent(), new ActivityResultCallback<Uri>() {
#Override
public void onActivityResult(Uri result) {
StorageReference reference = FirebaseStorage.getInstance().getReference("MESSAGE").child(mMsgPath).child("file_name");
reference.putFile(mImgUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
reference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
String url = uri.toString();
}
});
}
});
}
});
launcher.launch("image/*");
use bellow code for compress image
Bitmap bitmapImage = BitmapFactory.decodeFile("Your path");
int nh = (int) ( bitmapImage.getHeight() * (512.0 / bitmapImage.getWidth()) );
Bitmap scaled = Bitmap.createScaledBitmap(bitmapImage, 512, nh, true);
your_imageview.setImageBitmap(scaled);
Compress your image without losing quality
public String compressImage(String imageUri) {
String filePath = getRealPathFromURI(imageUri);
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
// by setting this field as true, the actual bitmap pixels are not loaded in the memory. Just the bounds are loaded. If
// you try the use the bitmap here, you will get null.
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(filePath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
// max Height and width values of the compressed image is taken as 816x612
float maxHeight = 816.0f;
float maxWidth = 612.0f;
float imgRatio = actualWidth / actualHeight;
float 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 = (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;
}
}
// 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 = new byte[16 * 1024];
try {
// load the bitmap from its path
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 = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
// check the rotation of the image and display it properly
ExifInterface exif;
try {
exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, 0);
Log.d("EXIF", "Exif: " + orientation);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 3) {
matrix.postRotate(180);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 8) {
matrix.postRotate(270);
Log.d("EXIF", "Exif: " + orientation);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix,
true);
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream out = null;
String filename = getFilename();
try {
out = new FileOutputStream(filename);
// write the compressed bitmap at the destination specified by filename.
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return filename;
}
public String getFilename() {
File file = new File(Environment.getExternalStorageDirectory().getPath(), "MyFolder/Images");
if (!file.exists()) {
file.mkdirs();
}
String uriSting = (file.getAbsolutePath() + "/" + System.currentTimeMillis() + ".jpg");
return uriSting;
}
private String getRealPathFromURI(String contentURI) {
Uri contentUri = Uri.parse(contentURI);
Cursor cursor = getContentResolver().query(contentUri, null, null, null, null);
if (cursor == null) {
return contentUri.getPath();
} else {
cursor.moveToFirst();
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(index);
}
}
public 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;
}
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
I have been searching image compression and i found this useful link a whatsapp like compression example http://grishma102.blogspot.ug/2016/03/image-compression-in-android.html and also read different posts such as How whatsapp/Instagram or other compresses the image before uploading it to server? on this same issue , but i have failed to achieve what i want .
My achievemnet is :-
I want when i select an image from the gallery, it attaches it's self on an ImageView when it's already compressed.
This is how i was doing it
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK) {
if (data == null) {
//showError("Failed to open picture!");
return;
}
try {
imageUri = data.getData();
compressImage(imageUri.toString());
Picasso.with(c).load(imageUri).fit().into(imageSelect);
} catch (Exception e) {
e.printStackTrace();
}
}
}
And of course the compressImage() method , is as below i got it from the links i have posted,
public static String compressImage(String imagePath) {
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(imagePath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
float imgRatio = (float) actualWidth / (float) 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(imagePath, options);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
try {
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.RGB_565);
} 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 = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
if (bmp != null) {
bmp.recycle();
}
ExifInterface exif;
try {
exif = new ExifInterface(imagePath);
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);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream out = null;
String filepath = getFilename();
try {
//new File(imageFilePath).delete();
out = new FileOutputStream(filepath);
//write the compressed bitmap at the destination specified by filename.
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return filepath;
}
public static String getFilename() {
File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
+ "/ImageCompApp/Images");
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
mediaStorageDir.mkdirs();
}
String mImageName = "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg";
String uriString = (mediaStorageDir.getAbsolutePath() + "/" + mImageName);
return uriString;
}
public static void hideKeyboard(Activity context) {
try {
if (context == null) return;
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(context.getWindow().getCurrentFocus().getWindowToken(), 0);
} catch (Exception e) {
}
}
But its not working the way am expecting it , where am i wrong please
try this code:
public String compressImage(String imageUri) {
String filePath = getRealPathFromURI(imageUri);
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
// by setting this field as true, the actual bitmap pixels are not loaded in the memory. Just the bounds are loaded. If
// you try the use the bitmap here, you will get null.
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(filePath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
// max Height and width values of the compressed image is taken as 816x612
float maxHeight = 500.0f;
float maxWidth = 500.0f;
float imgRatio = actualWidth / actualHeight;
float 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 = (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;
}
}
// 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 = new byte[16 * 1024];
try {
// load the bitmap from its path
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 = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
// check the rotation of the image and display it properly
ExifInterface exif;
try {
exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, 0);
Log.d("EXIF", "Exif: " + orientation);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 3) {
matrix.postRotate(180);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 8) {
matrix.postRotate(270);
Log.d("EXIF", "Exif: " + orientation);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix,
true);
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream out = null;
String filename = getFilename();
try {
out = new FileOutputStream(filename);
// write the compressed bitmap at the destination specified by filename.
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return filename;
}
public String getFilename() {
File file = new File(Environment.getExternalStorageDirectory().getPath(), "MyFolder/Images");
if (!file.exists()) {
file.mkdirs();
}
String uriSting = (file.getAbsolutePath() + "/" + System.currentTimeMillis() + ".jpg");
return uriSting;
}
private String getRealPathFromURI(String contentURI) {
Uri contentUri = Uri.parse(contentURI);
Cursor cursor = getContentResolver().query(contentUri, null, null, null, null);
if (cursor == null) {
return contentUri.getPath();
} else {
cursor.moveToFirst();
int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(index);
}
}
public 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;
}
the above code is used to reduce the size of images with maintaining the aspect ratio.
source
hope it helps u..
I just discovered a bug in my app, but don't know how to fix it. It is a simple Camera/Photo app but the problem is that when the user takes a picture with the front camera, the picture in the editor is rendered upside-down. If the user takes a picture with the rear (main) camera, everything is OK.
This is code from my CameraBitmapUtils.java class.
package com.example.myapp.common;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
public class CameraBitmapUtils {
private static final String TAG = "CameraBitmapUtils";
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 heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
#SuppressLint("NewApi")
public static Bitmap decodeSampledBitmap(Uri uri, int reqWidth, int reqHeight, Activity act) {
// First decode with inJustDecodeBounds=true to check dimensions
InputStream is;
try {
is = act.getApplicationContext().getContentResolver().openInputStream(uri);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, options);
is.close(); // consider use is.mark and is.reset instead [TODO]
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
// open input stream again
is = act.getApplicationContext().getContentResolver().openInputStream(uri);
options.inJustDecodeBounds = false;
Bitmap ret = BitmapFactory.decodeStream(is, null, options);
is.close();
return ret;
} catch (FileNotFoundException e) {
Log.v(TAG, "File not found:" + uri.toString());
e.printStackTrace();
} catch (IOException e) {
Log.v(TAG, "I/O exception with file:" + uri.toString());
e.printStackTrace();
}
return null;
}
public static Bitmap downSampleBitmap(Uri uri, Activity act, Boolean needRotate) {
DisplayMetrics displaymetrics = new DisplayMetrics();
act.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
Resources r = act.getResources();
int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, r.getDisplayMetrics()); // 50:
// magic
// num
int targetWidth = displaymetrics.heightPixels;
int targetHeight = displaymetrics.widthPixels - px;
Bitmap resizedBitmap = decodeSampledBitmap(uri, targetWidth, targetHeight, act);
Bitmap returnBitmap = null;
ExifInterface exif;
try {
float degree = 0;
exif = new ExifInterface(uri.toString());
if (uri.getScheme().equals("content")) {
/*
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = act.getContentResolver().query(uri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();
*/
String filePath = ImageFilePath.getPath(act, uri);
// /new 27/9
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 1024;
// Find the correct scale value. It should be the power of
// 2.
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp < REQUIRED_SIZE && height_tmp < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
Bitmap b1 = BitmapFactory.decodeFile(filePath, o2);
returnBitmap = ExifUtils.rotateBitmap(filePath, b1);
} else {
int orient = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
if (resizedBitmap != null && needRotate) {
degree = getDegree(orient);
if (degree != 0) {
returnBitmap = createRotatedBitmap(resizedBitmap, degree);
}
returnBitmap = returnBitmap == null ? resizedBitmap : returnBitmap;
}
}
} catch (IOException e) {
Log.v(TAG, "not found file at downsample");
e.printStackTrace();
}
return returnBitmap;
}
public static float getDegree(int exifOrientation) {
if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90)
return 180;
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180)
return 270;
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270)
return 0;
return 90;
}
public static Bitmap createRotatedBitmap(Bitmap bm, float degree) {
Bitmap bitmap = null;
if (degree != 0) {
Matrix matrix = new Matrix();
matrix.preRotate(degree);
bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
}
return bitmap;
}
}
If I set return 90; on return 270; the front camera is fixed, but then the back camera's photo is upside-down. This code is not mine, so I really don't know how to fix it.
After resizing the image size is greater than the original
original image detail
Dimension 1680 x 1050
Size 553 KB
Resized image
Dimension 720 x 1280
Size 1.83 MB
Method i am using
bitmap = Bitmap.createBitmap (bitmap, bitmapGapX, bitmapGapY,
deviceWidth, deviceHeight);
Is there any way to get compressed resized image. Right now iamge size is lot larger than the original image
See the documentation for Bitmap.Compress(), especially the second parameter (quality):
quality Hint to the compressor, 0-100. 0 meaning compress for small size, 100 meaning compress for max quality. Some formats, like PNG which is lossless, will ignore the quality setting
Just use a lower quality setting to get a smaller file. It is quite possible for a resized image of a lower resolution to end up with a larger filesize than the original if the quality setting passed to Bitmap.compress() is large, and the original file was saved with a low quality setting.
So just try using a lower quality value e.g:
bitmap.compress(Bitmap.CompressFormat.JPEG, 75 /*quality setting*/, outputStream);
Experiment with different quality settings until you find a good trade off between quality and file size.
I don't know how you are resize image, but you can try with this method to reduce size. Run this method in background thread.
public String compressImage(String imageUri) {
Log.i(TAG, "qq imageUri = " + imageUri);
String filePath = getRealPathFromURI(imageUri);
Log.i(TAG, "qq filePath = " + filePath);
// getAxiomData( filePath);
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 = utils.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 = 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);
Log.d("EXIF", "Exif: " + orientation);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 3) {
matrix.postRotate(180);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 8) {
matrix.postRotate(270);
Log.d("EXIF", "Exif: " + orientation);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(),
matrix, true);
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream fOut = null;
ByteArrayOutputStream uploadStream = new ByteArrayOutputStream();
String filename = getFilename();
try {
// Store in folder
fOut = new FileOutputStream(filename);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
// Store in variable to upload
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100,
uploadStream);
byte[] byteArray = uploadStream.toByteArray();
strBase64Img[imgCount] = Base64.encodeToString(byteArray,
Base64.DEFAULT);
// Show in layout
finalBtmpImg[imgCount] = scaledBitmap;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return filename;
}