仅在太大时才调整位图大小

时间:2016-04-25 16:15:51

标签: android android-bitmap

如果照片太大(例如宽度> 2048像素),我想调整每张用相机拍摄的照片。

我在官方文件中看到了

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
    int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
     options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

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;
}

但是这段代码涉及我知道最​​终的大小。 我想要做的是如果它真的太大则减少50%,或者如果位图不是太大则减少20%等等(取决于智能手机的相机......)

方法calculateInSampleSize()似乎做了我想做的事,文档说"例如,使用inSampleSize为4解码的分辨率为2048x1536的图像产生大约512x384"的位图。但我不想设置最终的宽度/高度。

然后,当我得到较小的位图时,我想制作一个

scaledBitmap.compress(CompressFormat.JPEG, 80, out);

再次优化。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

您可以将位图的宽度和高度设为bitmap.getWidth()bitmap.getHeight()。一旦你有宽度和高度,检查哪个值更小。如果width小于height,请将width存储在一个名为value的变量中,否则存储height

然后您可以通过检查值来压缩位图,如下所示。

Bitmap bitmap = your bitmap;

int width = bitmap.getWidth();
int height = bitmap.getHeight();

int value;
if (width < height) {
    value = width;
} else {
    value = height;
}

Bitmap scaledBitmap;

if (value > 5000) {
    scaledBitmap = bitmap.compress(CompressFormat.JPEG, 80, out);
} else if (value > 4000) {
    scaledBitmap = bitmap.compress(CompressFormat.JPEG, 60, out);
} else if (value > 3000) {
    scaledBitmap = bitmap.compress(CompressFormat.JPEG, 40, out);
} else if (value > 2048) {
    scaledBitmap = bitmap.compress(CompressFormat.JPEG, 20, out);
}

答案 1 :(得分:0)

最后我选择了另一种解决方案:

public static void resizeBitmapOnFileSystem(String originalPath, File photoCompressedFile) throws IOException {
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(originalPath, options);

    int minimalLengthSide = 300; //Minimal length of the shorter side of the picture. Used to calculate the best 'scale' value.
    int scale = calculateInSampleSize(options, minimalLengthSide, minimalLengthSide);

    ByteArrayOutputStream out = null;
    FileOutputStream fo = null;
    Bitmap scaledBitmap = null;
    try {
        out = new ByteArrayOutputStream();
        fo = new FileOutputStream(photoCompressedFile);

        scaledBitmap = loadScaledBitmap(originalPath, scale);
        if (scaledBitmap != null) {
            scaledBitmap.compress(CompressFormat.JPEG, 75, out);
            fo.write(out.toByteArray());
        }
    } finally {
        IOUtils.closeQuietly(out);
        IOUtils.closeQuietly(fo);
        recycleQuietly(scaledBitmap);
    }
}

/**
 * From offical Android documentation
 * @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;
}

即使resizeBitmapOnFileSystem()方法不是很“方便”,诀窍就是minimalLengthSide变量。我设置了我想要的短边的最小长度(这里是300px),方法calculateInSampleSize()将自动计算出适当的比例。

保持比率宽度/高度,我不使用 Bitmap.createScaledBitmap(realImage, width, height, filter) 这可能是“代价高昂”或效率低下。