How to reduce an Image file size before uploading to a server

AndroidImageUpload

Android 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:

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)

enter image description here

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() + " }";
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1537779View Question on Stackoverflow
Solution 1 - AndroidMBHView Answer on Stackoverflow
Solution 2 - AndroidBiraj ZalavadiaView Answer on Stackoverflow
Solution 3 - AndroidGene BoView Answer on Stackoverflow
Solution 4 - Androidemad pirayeshView Answer on Stackoverflow
Solution 5 - AndroidGk Mohammad EmonView Answer on Stackoverflow
Solution 6 - AndroidSan JuanView Answer on Stackoverflow
Solution 7 - AndroidMahmoud AymanView Answer on Stackoverflow
Solution 8 - AndroidMichael PlischkeView Answer on Stackoverflow
Solution 9 - AndroidFalchioView Answer on Stackoverflow
Solution 10 - AndroidVishal KumarView Answer on Stackoverflow
Solution 11 - AndroidPERAM BRAHMA REDDYView Answer on Stackoverflow