首页 文章

Android - 减少图像文件大小

提问于
浏览
52

我有一个URI图像文件,我想减小它的大小上传它 . 初始图像文件大小取决于从移动设备到移动设备(可以是2MB,可以是500KB),但我希望最终大小约为200KB,以便我可以上传它 .
从我读到的,我有(至少)2个选择:

  • 使用BitmapFactory.Options.inSampleSize,对原始图像进行二次采样并获得较小的图像;

  • 使用Bitmap.compress压缩指定压缩质量的图像 .

什么是最好的选择?


我想最初调整图像宽度/高度,直到宽度或高度高于1000px(类似1024x768或其他),然后压缩图像质量下降,直到文件大小超过200KB . 这是一个例子:

int MAX_IMAGE_SIZE = 200 * 1024; // max final file size
Bitmap bmpPic = BitmapFactory.decodeFile(fileUri.getPath());
if ((bmpPic.getWidth() >= 1024) && (bmpPic.getHeight() >= 1024)) {
    BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
    bmpOptions.inSampleSize = 1;
    while ((bmpPic.getWidth() >= 1024) && (bmpPic.getHeight() >= 1024)) {
        bmpOptions.inSampleSize++;
        bmpPic = BitmapFactory.decodeFile(fileUri.getPath(), bmpOptions);
    }
    Log.d(TAG, "Resize: " + bmpOptions.inSampleSize);
}
int compressQuality = 104; // quality decreasing by 5 every loop. (start from 99)
int streamLength = MAX_IMAGE_SIZE;
while (streamLength >= MAX_IMAGE_SIZE) {
    ByteArrayOutputStream bmpStream = new ByteArrayOutputStream();
    compressQuality -= 5;
    Log.d(TAG, "Quality: " + compressQuality);
    bmpPic.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream);
    byte[] bmpPicByteArray = bmpStream.toByteArray();
    streamLength = bmpPicByteArray.length;
    Log.d(TAG, "Size: " + streamLength);
}
try {
    FileOutputStream bmpFile = new FileOutputStream(finalPath);
    bmpPic.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpFile);
    bmpFile.flush();
    bmpFile.close();
} catch (Exception e) {
    Log.e(TAG, "Error on saving file");
}

有没有更好的方法呢?我应该尝试继续使用所有2种方法还是只使用一种方法?谢谢

2 回答

  • 27

    使用 Bitmap.compress() ,您只需指定压缩算法,并且按压缩操作的方式需要相当长的时间 . 如果需要使用大小来减少图像的内存分配,则需要使用 Bitmap.Options 来缩放图像,首先计算位图边界,然后将其解码为指定的大小 .

    我在StackOverflow上找到的最佳样本是this one .

  • 1

    我发现的大部分答案都只是我必须拼凑起来才能获得的答案 working code, which is posted below

    public void compressBitmap(File file, int sampleSize, int quality) {
            try {
               BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = sampleSize;
                FileInputStream inputStream = new FileInputStream(file);
    
                Bitmap selectedBitmap = BitmapFactory.decodeStream(inputStream, null, options);
                inputStream.close();
    
                FileOutputStream outputStream = new FileOutputStream("location to save");
                selectedBitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
                outputStream.close();
                long lengthInKb = photo.length() / 1024; //in kb
                if (lengthInKb > SIZE_LIMIT) {
                   compressBitmap(file, (sampleSize*2), (quality/4));
                }
    
                selectedBitmap.recycle();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    2 parameters sampleSize and quality plays an important role

    sampleSize 用于 subsample the original image and return a smaller image ,即
    SampleSize == 4返回的图像是原始宽度/高度的1/4 .

    quality is used to hint the compressor ,输入范围在0-100之间 . 0表示压缩小尺寸,100表示压缩以获得最高质量

相关问题