How to reduce an Image file size before uploading to a server
AndroidImageUploadAndroid Problem Overview
Lot of application allow sharing an image, which is picked from the gallery.
Do they upload the original image file? Which is like 1-3 mb? Or do they process?
In any case, how can I take the image from a filepath, reduce its size by lowering the resolution and save it some where else and the try to upload?
I tried:
Bitmap photo = decodeSampledBitmapFromFile(filePath, DESIRED_WIDTH,
DESIRED_HEIGHT);
FileOutputStream out = new FileOutputStream(filePath);
photo.compress(Bitmap.CompressFormat.JPEG, 100, out);
public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth,
int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
final int height = options.outHeight;
final int width = options.outWidth;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
int inSampleSize = 1;
if (height > reqHeight) {
inSampleSize = Math.round((float) height / (float) reqHeight);
}
int expectedWidth = width / inSampleSize;
if (expectedWidth > reqWidth) {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
options.inSampleSize = inSampleSize;
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
}
But is this they right way to do? Because I have seen answers suggesting compression operation takes rather big amount of time
here
Android Solutions
Solution 1 - Android
I use this function to reduce the size of image before uploading it, it reduces the image size to nearly 200 KB and keep the quality relatively good, u may modify it to fulfill your purpose by changing the REQUIRED_SIZE and inSampleSize:
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=75;
// 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.createNewFile();
FileOutputStream outputStream = new FileOutputStream(file);
selectedBitmap.compress(Bitmap.CompressFormat.JPEG, 100 , outputStream);
return file;
} catch (Exception e) {
return null;
}
}
NOTE: I resize and override the original file image in this function, u may write it to another file as well.
I hope it may help you.
Solution 2 - Android
This is working great Try this
private String decodeFile(String path,int DESIREDWIDTH, int DESIREDHEIGHT) {
String strMyImagePath = null;
Bitmap scaledBitmap = 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
String extr = Environment.getExternalStorageDirectory().toString();
File mFolder = new File(extr + "/TMMFOLDER");
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.JPEG, 75, 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;
}
ScalingUtilities.java
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
/**
* Class containing static utility methods for bitmap decoding and scaling
*
* @author
*/
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);
}
}
}
Solution 3 - Android
Here's a solution that's handled in memory and doesn't require actually generating a file on the file system.
From some Fragment, after user selects an image file:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
if (imageReturnedIntent == null
|| imageReturnedIntent.getData() == null) {
return;
}
// aiming for ~500kb max. assumes typical device image size is around 2megs
int scaleDivider = 4;
try {
// 1. Convert uri to bitmap
Uri imageUri = imageReturnedIntent.getData();
Bitmap fullBitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), imageUri);
// 2. Get the downsized image content as a byte[]
int scaleWidth = fullBitmap.getWidth() / scaleDivider;
int scaleHeight = fullBitmap.getHeight() / scaleDivider;
byte[] downsizedImageBytes =
getDownsizedImageBytes(fullBitmap, scaleWidth, scaleHeight);
// 3. Upload the byte[]; Eg, if you are using Firebase
StorageReference storageReference =
FirebaseStorage.getInstance().getReference("/somepath");
storageReference.putBytes(downsizedImageBytes);
}
catch (IOException ioEx) {
ioEx.printStackTrace();
}
}
public byte[] getDownsizedImageBytes(Bitmap fullBitmap, int scaleWidth, int scaleHeight) throws IOException {
Bitmap scaledBitmap = Bitmap.createScaledBitmap(fullBitmap, scaleWidth, scaleHeight, true);
// 2. Instantiate the downsized image content as a byte[]
ByteArrayOutputStream baos = new ByteArrayOutputStream();
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] downsizedImageBytes = baos.toByteArray();
return downsizedImageBytes;
}
Thanks to:
- Convert uri to bitmap: https://stackoverflow.com/a/4717740/2162226
- Scaling/resize step (from this thread): https://stackoverflow.com/a/50192169/2162226
- Save byte[] to Firebase : https://stackoverflow.com/a/40886397/2162226
Solution 4 - Android
this code reduce size image
private Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//Compression quality, here 100 means no compression, the storage of compressed data to baos
int options = 90;
while (baos.toByteArray().length / 1024 > 400) { //Loop if compressed picture is greater than 400kb, than to compression
baos.reset();//Reset baos is empty baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);//The compression options%, storing the compressed data to the baos
options -= 10;//Every time reduced by 10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//The storage of compressed data in the baos to ByteArrayInputStream
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//The ByteArrayInputStream data generation
return bitmap;
}
Solution 5 - Android
You can use this library named Compressor.
Compress Image File
val compressedImageFile = Compressor.compress(context, actualImageFile)
Compress Image File to specific destination
val compressedImageFile = Compressor.compress(context, actualImageFile) {
default()
destination(myFile)
}
Custom Compressor
Using default constraint and custom partial of it
val compressedImageFile =
Compressor.compress(context, actualImageFile) {
default(width = 640, format = Bitmap.CompressFormat.WEBP)
}
Full custom constraint
val compressedImageFile = Compressor.compress(context, actualImageFile) {
resolution(1280, 720)
quality(80)
format(Bitmap.CompressFormat.WEBP)
size(2_097_152) // 2 MB
}
Using own custom constraint
class MyLowerCaseNameConstraint: Constraint {
override fun isSatisfied(imageFile: File): Boolean {
return imageFile.name.all { it.isLowerCase() }
}
override fun satisfy(imageFile: File): File {
val destination = File(imageFile.parent, imageFile.name.toLowerCase())
imageFile.renameTo(destination)
return destination
}
}
val compressedImageFile = Compressor.compress(context, actualImageFile) {
constraint(MyLowerCaseNameConstraint()) // your own constraint
quality(80) // combine with compressor constraint
format(Bitmap.CompressFormat.WEBP)
}
Create Kotlin extension -
fun Compression.lowerCaseName() {
constraint(MyLowerCaseNameConstraint())
}
val compressedImageFile = Compressor.compress(context, actualImageFile) {
lowerCaseName() // your own extension
quality(80) // combine with compressor constraint
format(Bitmap.CompressFormat.WEBP)
}
Compress image with Kotlin coroutines -
// e.g calling from activity lifecycle scope
lifecycleScope.launch {
val compressedImageFile = Compressor.compress(context, actualImageFile)
}
// calling from global scope
GlobalScope.launch {
val compressedImageFile = Compressor.compress(context, actualImageFile)
}
Run Compressor in main thread -
val compressedImageFile = Compressor.compress(context, actualImageFile, Dispatchers.Main)
Solution 6 - Android
Here is my solution
/*
* This procedure will replace the original image
* So you need to do a tmp copy to send before reduce
*/
public static boolean reduceImage(String path, long maxSize) {
File img = new File(path);
boolean result = false;
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap bitmap = null;
options.inSampleSize=1;
while (img.length()>maxSize) {
options.inSampleSize = options.inSampleSize+1;
bitmap = BitmapFactory.decodeFile(path, options);
img.delete();
try
{
FileOutputStream fos = new FileOutputStream(path);
img.compress(path.toLowerCase().endsWith("png")?
Bitmap.CompressFormat.PNG:
Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
result = true;
}catch (Exception errVar) {
errVar.printStackTrace();
}
};
return result;
}
EDIT Removed other procedures calls
Solution 7 - Android
here's the method iam using in kotlin:
Note: i tried it with 3 images each of them was 6 mb and in one call
private fun Bitmap.compress(cacheDir: File, f_name: String): File? {
val f = File(cacheDir, "user$f_name.jpg")
f.createNewFile()
ByteArrayOutputStream().use { stream ->
compress(Bitmap.CompressFormat.JPEG, 70, stream)
val bArray = stream.toByteArray()
FileOutputStream(f).use { os -> os.write(bArray) }
}//stream
return f
}
Solution 8 - Android
@MBH's answer has a strange and unnecessary way of getting a result that can cause the while loop to be bypassed if the file has a greater number of pixels than 6X REQUIRED_SIZE = 75;
. o.inSampleSize = 6;
is the cause of this, and only succeeds in convoluting what the allowed number of axial pixels (6*75 = 450) is. Below is a refurbished version of MBH's answer that also includes an option to not only adjust by pixels, but by storage size:
//This is the number of pixels that the width and height of the image will be allotted
//Note that the number of pixels implies (but does not exclusively determine) the file size of the image
private int REQUIRED_SIZE = 720;
//Method allows image files to be compressed to a standard maximum size
public void saveBitmapToFile(){
try {
//Initialize BitmapFactory options to downsize the image
BitmapFactory.Options o = new BitmapFactory.Options();
//Image dimensions do not change with change in pixel density
o.inJustDecodeBounds = true;
//Retrieve file and decode into bitmap, then close the stream when decode complete
FileInputStream inputStream = new FileInputStream(imageFile);
BitmapFactory.decodeStream(inputStream, null, o);
inputStream.close();
//Start with 1:1 scale size
int scale = 1;
while (o.outWidth / scale / 2 >= REQUIRED_SIZE && o.outHeight / scale / 2 >= REQUIRED_SIZE) {
//Find the correct scale value. It should be the power of 2.
scale *= 2;
}
//Create new Bitmap options instance to adjust the image scale...(1/2)
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
//...then apply with new input stream
inputStream = new FileInputStream(imageFile);
Bitmap selectedBitmap = BitmapFactory.decodeStream(inputStream, null, o2);
inputStream.close();
//Overwrite original file (type 'File') then compress the output file
imageFile.createNewFile();
FileOutputStream outputStream = new FileOutputStream(imageFile);
selectedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
//maxImageSize is arbitrary file size (byte) limit
if(imageFile.length() < maxImageSize) {
//Set image in place and get the uri
imagePost.setImageURI(imageUri);
//Reset in case decreased previously
REQUIRED_SIZE = 720;
} else {
Toast.makeText(PostActivity.this, "Your image is " + (imageFile.length() - maxImageSize) / 1000 + "kb too large to upload. Reattempting...", Toast.LENGTH_LONG).show();
REQUIRED_SIZE = REQUIRED_SIZE - 240;
//Loop method until goal file size achieved
saveBitmapToFile();
}
} catch (Exception ignored) {
}
}
Solution 9 - Android
Fix image resolution and file size. Applies a watermark. Encode to Base64
private const val TAG = "Compressor"
private const val START_QUALITY = 100
private const val QUALITY_DECREASE_STEP = 10
private const val DEFAULT_SIZE_LIMIT = 512_000
private const val MARGIN = 30
//image resolution 1024*768
private const val LONG_SIZE = 1024
private const val SHORT_SIZE = 768
object Compressor {
private val FORMAT = Bitmap.CompressFormat.JPEG
fun compressImage(
imageFile: File,
limitSize: Int = DEFAULT_SIZE_LIMIT,
watermark: String? = null
): String {
val originalBitmap = BitmapFactory.decodeFile(imageFile.absolutePath)
val bitmapWithWaterMark = mark(originalBitmap, watermark)
val (newWidth, newHeight) = calculateNewWidthAndHeight(bitmapWithWaterMark)
val resizedBitmap = getResizedBitmap(bitmapWithWaterMark, newWidth, newHeight)
val stream = ByteArrayOutputStream()
var quality = START_QUALITY
//compressed Bitmap write to ByteArrayOutputStream
resizedBitmap.compress(FORMAT, quality, stream)
while (stream.size() > limitSize && quality > QUALITY_DECREASE_STEP) {
stream.reset()
quality -= QUALITY_DECREASE_STEP
resizedBitmap.compress(FORMAT, quality, stream)
}
val base64String = Base64.encodeToString(stream.toByteArray(), Base64.DEFAULT)
return base64String
}
private fun calculateNewWidthAndHeight(waterMarkBitmap: Bitmap): Pair<Int, Int> {
val newWidth = if (isPortrait(waterMarkBitmap)) SHORT_SIZE else LONG_SIZE
val newHeight = if (isPortrait(waterMarkBitmap)) LONG_SIZE else SHORT_SIZE
return Pair(newWidth, newHeight)
}
private fun isPortrait(bitmap: Bitmap) = bitmap.height > bitmap.width
private fun mark(source: Bitmap, watermark: String? = null): Bitmap {
if (watermark == null) return source
val width = source.width
val height = source.height
val result = Bitmap.createBitmap(width, height, source.config)
val canvas = Canvas(result)
canvas.drawBitmap(source, 0f, 0f, null)
val paint = getPaint(18)
val (widthPaint, heightPaint) = paint.getTextWidthAndHeight(watermark)
//watermark background
val backgroundPaint = getBackgroundPaint()
canvas.drawRect(
width - widthPaint - MARGIN,
height - heightPaint * 2,
width.toFloat(),
height.toFloat() - heightPaint + MARGIN,
backgroundPaint
)
//watermark text
canvas.drawText(
watermark,
width - widthPaint,
height - heightPaint,
paint
)
return result
}
private fun getBackgroundPaint(): Paint {
return Paint().apply {
style = Paint.Style.FILL
color = Color.BLACK
}
}
private fun dpToPx(dp: Int): Float {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp.toFloat(),
App.resources.displayMetrics
)
}
private fun getPaint(textSize: Int, isShadowEnable: Boolean = false): Paint {
return Paint(Paint.ANTI_ALIAS_FLAG).apply {
setTextSize(dpToPx(textSize))
typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
if (isShadowEnable) {
setShadowLayer(2f, 2f, 2f, Color.BLACK)
}
color = Color.WHITE
textAlign = Paint.Align.LEFT
}
}
private fun Paint.getTextWidthAndHeight(text: String): Pair<Float, Float> {
val baseline = -this.ascent() // ascent() is negative
val width: Float = this.measureText(text) + dpToPx(8)
val height: Float = baseline + this.descent() + dpToPx(4)
return Pair(width, height)
}
private fun getResizedBitmap(bitmap: Bitmap, newWidth: Int, newHeight: Int): Bitmap {
val width = bitmap.width
val height = bitmap.height
val scaleWidth = newWidth.toFloat() / width
val scaleHeight = newHeight.toFloat() / height
// CREATE A MATRIX FOR THE MANIPULATION
val matrix = Matrix()
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight)
// "RECREATE" THE NEW BITMAP
val resizedBitmap = Bitmap.createBitmap(
bitmap, 0, 0, width, height, matrix, false
)
bitmap.recycle()
return resizedBitmap
}
}
Solution 10 - Android
Use this method that returns a bitmap image compressed to around 200 KB. You can configure it to get a bitmap image of whatever size you want.
public static Bitmap scaleImage(Context context, Uri photoUri) throws IOException {
InputStream is = context.getContentResolver().openInputStream(photoUri);
BitmapFactory.Options dbo = new BitmapFactory.Options();
dbo.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, dbo);
is.close();
int rotatedWidth, rotatedHeight;
int orientation = getOrientation(context, photoUri);
if (orientation == 90 || orientation == 270) {
rotatedWidth = dbo.outHeight;
rotatedHeight = dbo.outWidth;
} else {
rotatedWidth = dbo.outWidth;
rotatedHeight = dbo.outHeight;
}
Bitmap srcBitmap;
is = context.getContentResolver().openInputStream(photoUri);
if (rotatedWidth > MAX_IMAGE_DIMENSION || rotatedHeight > MAX_IMAGE_DIMENSION) {
float widthRatio = ((float) rotatedWidth) / ((float) MAX_IMAGE_DIMENSION);
float heightRatio = ((float) rotatedHeight) / ((float) MAX_IMAGE_DIMENSION);
float maxRatio = Math.max(widthRatio, heightRatio);
// Create the bitmap from file
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = (int) maxRatio;
srcBitmap = BitmapFactory.decodeStream(is, null, options);
} else {
srcBitmap = BitmapFactory.decodeStream(is);
}
is.close();
/*
* if the orientation is not 0 (or -1, which means we don't know), we
* have to do a rotation.
*/
if (orientation > 0) {
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
srcBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(),
srcBitmap.getHeight(), matrix, true);
}
String type = context.getContentResolver().getType(photoUri);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (type.equals("image/png")) {
srcBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
} else if (type.equals("image/jpg") || type.equals("image/jpeg")) {
srcBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
}
byte[] bMapArray = baos.toByteArray();
baos.close();
return BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);
}
Solution 11 - Android
protected void Page_Load(object sender, EventArgs e)
{
//BR**
string filePath = "";//Source file path with image name
int CompressLevel = 50;//Image compression leve as per our requirement
string DestintionPath = "";//Destination file path
string Filename = "";//Output image name to save in destination path
Stream bmpStream = System.IO.File.Open(filePath, System.IO.FileMode.Open);
Bitmap bmp1 = new Bitmap(bmpStream);
ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg);
System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
EncoderParameters myEncoderParameters = new EncoderParameters(1);
EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, CompressLevel);
myEncoderParameters.Param[0] = myEncoderParameter;
bmp1.Save(DestintionPath + "\\" + Filename, jpgEncoder, myEncoderParameters);
//BR**
bmpStream.Close();
string lblmsg = "Compressed Sucessfully with Compression Level { " + CompressLevel.ToString() + " }";
}