Android - масштабирование и сжатие растрового изображения

Я работаю над приложением для Android, которое имеет функцию захвата камеры и загрузки фотографий. Если устройство оснащено камерой высокого разрешения, размер получаемого изображения будет очень большим (1–3 МБ или более).
Поскольку приложение должно будет загрузить это изображение на сервер, мне нужно будет сжать изображение перед загрузкой. Если камера, например, сделала снимок в полном разрешении 1920x1080, идеальным выходом будет сохранить соотношение изображения 16: 9, сжать его до размера 640x360, чтобы уменьшить качество изображения и уменьшить его размер в байтах.

Вот мой код (по ссылке из Google):

/**
 * this class provide methods that can help compress the image size.
 *
 */
public class ImageCompressHelper {

/**
 * Calcuate how much to compress the image
 * @param options
 * @param reqWidth
 * @param reqHeight
 * @return
 */
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {

    final int halfHeight = height / 2;
    final int halfWidth = width / 2;

    // Calculate the largest inSampleSize value that is a power of 2 and keeps both
    // height and width larger than the requested height and width.
    while ((halfHeight / inSampleSize) > reqHeight
            && (halfWidth / inSampleSize) > reqWidth) {
        inSampleSize *= 2;
    }
}

return inSampleSize;
}

/**
 * resize image to 480x800
 * @param filePath
 * @return
 */
public static Bitmap getSmallBitmap(String filePath) {

    File file = new File(filePath);
    long originalSize = file.length();

    MyLogger.Verbose("Original image size is: " + originalSize + " bytes.");

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(filePath, options);

    // Calculate inSampleSize based on a preset ratio
    options.inSampleSize = calculateInSampleSize(options, 480, 800);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;

    Bitmap compressedImage = BitmapFactory.decodeFile(filePath, options);

    MyLogger.Verbose("Compressed image size is " + sizeOf(compressedImage) + " bytes");

    return compressedImage;
}

Проблема с приведенным выше кодом:

Он не может сохранить соотношение, код заставляет изображение изменять размер до 480x800. если пользователь захватил изображение в другом соотношении, изображение не будет хорошо выглядеть после сжатия.

Это не работает хорошо. Код всегда будет изменять размер изображения до 7990272 байт независимо от исходного размера файла. Если исходный размер изображения уже достаточно мал, он станет большим (мой результат теста - сделать фотографию моей стены, которая в значительной степени одноцветная):

Original image size is: 990092 bytes.
Compressed image size is 7990272 bytes

Я спрашиваю, есть ли предложение лучшего способа сжатия фотографии, чтобы она могла быть загружена гладко?

Ответы на вопрос(2)

Ваш ответ на вопрос