Search code examples
javaandroidimage-compression

Process to compress an image for uploading to a server in Android


I want to write my own code for compressing an image before I upload it to server.

I have seen many posts on SO like this and there are many other posts also but everywhere there are only code samples. It is not actually explained anywhere. I am not able to understand from the given code.

I just want to know about the overall approach to compress images so that I can start writing code by myself.

I am not looking for the code, only the steps that one person needs to follow to compress an image. (Like an algorithm is written before writing program i.e., pseudocode)


Solution

  • I think Chetan Joshi's answer is the closest so far. But to explain a bit further,

    "Compressing" an image and "scaling" (resizing) an image are different. Since you merely want to reduce the bandwidth (kb/Mb) over the network when you upload to the server, you are most likely talking about "scaling" since that will make the most difference to the size of the image.

    Note, as in other answers Android, you will need to work with Bitmaps. You need to use the API calls associated with Bitmaps to do what you want.

    Starting point:

    If you allow your app to take a photo using the camera or pick from the gallery, you get an Uri which allows you to open an InputStream like this:

    InputStream is = getContext().getContentResolver().openInputStream(photoUri);
    

    That's the first step. The next part is the pseudocode where you want something like this:

    1. Get an InputStream of the photo/selected picture. This is just a stream of bytes that represent the image.
    2. Decode the stream into a Bitmap using BitmapFactory.decodeStream(InputStream src)
    3. Scale (resize) the bitmap using Bitmap.createScaledBitmap(src, dstWidth, dstHeight, filter);. You'll have to decide on a destination width and destination height you want yourself. See the next set of pseudocode.
    4. Compress the Bitmap using imageFormat.getBitmapCompressFormat(), 100, output) where output is an instance of ByteArrayOutputStream
    5. You can now call output.toByteArray(); to get the bytes.
    6. The bytes are what you want to send to the server.

    Note about how to choose the destination width and height to scale to:

    1. Decide on a max height and max width, say 240 x 240. You will be comparing this with the actual height and actual width of the bitmap.
    2. If too high (actual height > max height), calculate a scaling factor that is max height / actual height
    3. If too wide (actual width > max width), calculate a scaling factor that is max width / actual width
    4. Your actual scaling factor is the minimum of these two scaling factors
    5. Return the actual height * scaling factor and the actual width * scaling factor

    Altogether the high level process is something like this:

    1. Open a stream of the bytes of the image
    2. Convert the bytes into a bitmap
    3. Scale the bitmap
    4. Compress the bitmap
    5. Convert the bitmap back to bytes