How to reduce image size into 1MB

前端 未结 3 1343
情话喂你
情话喂你 2021-01-13 00:03

I want my application to upload image with no size limit, but in the code, I want to resize the image into 1MB if the image size exceeds. I have tried many ways but I could

3条回答
  •  有刺的猬
    2021-01-13 00:37

    I've tried to comment it but the comment become too big. So, I've tested many solutions and it seems like there are only TWO solutions for this problem, which give some results.

    Lets discuss Koen solution first. What it actually does is creates a scaled JPG

    Bitmap.createScaledBitmap(input, newWidthPx, newHeightPx, true)
    

    Seems like it does not compress it at all but just cuts off the resolution.

    I've tested this code and when I pass MAX_IMAGE_SIZE = 1024000 it gives me 350kb compressed image out of 2.33Mb original image. Bug? Also it lacks quality. I was unable to recognize a text on A4 sheet of paper photo made by Google Pixel.

    There is another solution to this problem, which gives good quality, but lacks in speed. A WHILE LOOP! Basically you just loop through image size, until you get the desired size

    private fun scaleBitmap() {
        if (originalFile.length() > MAX_IMAGE_SIZE) {
            var streamLength = MAX_IMAGE_SIZE
            var compressQuality = 100
            val bmpStream = ByteArrayOutputStream()
            while (streamLength >= MAX_IMAGE_SIZE) {
                bmpStream.use {
                    it.flush()
                    it.reset()
                }
    
                compressQuality -= 8
                val bitmap = BitmapFactory.decodeFile(originalFile.absolutePath, BitmapFactory.Options())
                bitmap.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream)
                streamLength = bmpStream.toByteArray().size
            }
    
            FileOutputStream(compressedFile).use {
                it.write(bmpStream.toByteArray())
            }
        }
    }
    

    I think that this approach will consume exponential time depending on image resolution. 9mb image takes up to 12 seconds to compress down to 1mb. Quality is good. You can tweak this by reducing the original bitmap resolution(which seems like a constant operation), by doing:

    options.inSampleSize = 2;

    What we need to do is to somehow calculate compressQuality for any image. There should be a math around this, so we can determinate compressQuality from original image size or width + height.

提交回复
热议问题