Android - 缩放和压缩位图

All*_*ang 7 java android image bitmap image-processing

我正在开发一款Android应用程序,它具有摄像头捕捉和照片上传功能.如果设备具有高分辨率相机,则捕获的图像尺寸将非常大(1~3MB或更多).
由于应用程序需要将此图像上传到服务器,因此我需要在上传之前压缩图像.例如,如果相机捕获了1920x1080全分辨率照片,则理想输出是保持图像的16:9比例,将其压缩为640x360图像以降低某些图像质量并使其以字节为单位缩小.

这是我的代码(从谷歌引用):

/**
 * 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;
}
Run Code Online (Sandbox Code Playgroud)

上面代码的问题是:

  1. 它无法保持比例,代码强制图像调整为480x800.如果用户以另一个比例捕获图像,压缩后图像看起来不会很好.
  2. 它运作不正常.无论原始文件大小是多少,代码都会始终将图像大小更改为7990272byte.如果原始图像尺寸已经非常小,它会变大(我的测试结果是拍摄我的墙,这是非常单色):

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

我问是否有更好的方法压缩照片,以便可以顺利上传?

Sz.*_*Sz. 12

  1. 您需要决定宽度或高度的限制(显然不是两者).然后用计算的图像替换那些固定的图像尺寸,例如:

    int targetWidth = 640; // your arbitrary fixed limit
    int targetHeight = (int) (originalHeight * targetWidth / (double) originalWidth); // casts to avoid truncating
    
    Run Code Online (Sandbox Code Playgroud)

    (根据需要添加横向/纵向方向的检查和计算备选方案.)

  2. 正如@harism所评论的那样:你提到的大尺寸是480x800位图的原始尺寸,而不是文件大小,在你的情况下应该是JPEG.你是如何保存该位图的?BTW?您的代码似乎不包含保存部分.

    在这里看到这个问题的帮助,关键是:

    OutputStream imagefile = new FileOutputStream("/your/file/name.jpg");
    // Write 'bitmap' to file using JPEG and 80% quality hint for JPEG:
    bitmap.compress(CompressFormat.JPEG, 80, imagefile);
    
    Run Code Online (Sandbox Code Playgroud)