jeudi 16 juin 2016

How to improve JPG Compression on Android

In my app a user can share pictures that he has taken and upload them to a website. Therefore I scale the image down to max 1200px and then upload them via an api.

Here is the code I've created so far and the code works without problems:

Bitmap image = null;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

//LoadImage from URI/Stream
try (InputStream inputStream = context.getContentResolver().openInputStream(photoUri)) {
   IOUtils.copy(inputStream, outputStream);
   byte[] bytes = outputStream.toByteArray();
   BitmapFactory.Options options = new BitmapFactory.Options();
   options.inScaled = false;
   image = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
}

//Calculte sizes to scale down by given maxImageSize (1200px)
int outWidth;
int outHeight;
int inWidth = image.getWidth();
int inHeight = image.getHeight();
if(inWidth > inHeight){
     outWidth = maxImageSize;
     outHeight = (inHeight * maxImageSize) / inWidth;
} else {
     outHeight = maxImageSize;
     outWidth = (inWidth * maxImageSize) / inHeight;
}


// Scale image down image
Bitmap result = Bitmap.createScaledBitmap(image, outWidth, outHeight, false); 

// Compress to JPEG by given ImageQuality (90%)
result.compress(Bitmap.CompressFormat.JPEG, imageQuality, dataOutputStream);

As I mentioned before, the code works without problems, but even though I set the quality to 90%, the edges are very grained / noisy and the image size is rather high (see zoomed in pictures).

On my web application, running C# I am doing the same, but the result is way better. When I scale down and compress in C# the result is 189KB and the pixels are somehow smoother: Image scaled down with C#

Compared to the same image scaled down and compressed version in Java with 238KB using the code shown above: Image Scaled down with Java

I can cut down a lot of bytes by reducing the quality of the compression of course, but the image quality gets even worse.

I'm not an expert when it comes to image compression/sizing, so I am not sure, if the compression itself is the problem or the resizing before. I checked out stackoverflow and found this solution that was posted two years ago:

How to compress Bitmap as JPEG with least quality loss on Android?

Regarding to the documentation, YuvImage is used only to compress a region to a JPEG. so probably not what i need: https://developer.android.com/reference/android/graphics/YuvImage.html

Further down the post, the author is mentioning the LibJPEG but this does not seem to be a Java-Lib?

Is there a better way to improve the quality of the picture with some options I have to set in my code or with another android library?

Aucun commentaire:

Enregistrer un commentaire