Android - 减小图像文件大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11061280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android - Reduce image file size
提问by KitKat
I have an URI image file, and I want to reduce its size to upload it. Initial image file size depends from mobile to mobile (can be 2MB as can be 500KB), but I want final size to be about 200KB, so that I can upload it.
From what I read, I have (at least) 2 choices:
我有一个 URI 图像文件,我想减小它的大小以上传它。初始图像文件大小取决于移动设备(可以是 2MB 也可以是 500KB),但我希望最终大小约为 200KB,以便我可以上传它。
从我读到的内容来看,我(至少)有 2 个选择:
- Using BitmapFactory.Options.inSampleSize, to subsample original image and get a smaller image;
- Using Bitmap.compressto compress the image specifying compression quality.
- 使用BitmapFactory.Options.inSampleSize,对原始图像进行二次采样并获得较小的图像;
- 使用Bitmap.compress压缩指定压缩质量的图像。
What's the best choice?
最好的选择是什么?
I was thinking to initially resize image width/height until width or height is above 1000px (something like 1024x768 or others), then compress image with decreasing quality until file size is above 200KB. Here's an example:
我想最初调整图像宽度/高度的大小,直到宽度或高度超过 1000 像素(例如 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");
}
Is there a better way to do it? Should I try to keep using all 2 methods or only one? Thanks
有没有更好的方法来做到这一点?我应该尝试继续使用所有 2 种方法还是只使用一种?谢谢
采纳答案by teoREtik
Using Bitmap.compress()
you just specify compression algorithm and by the way compression operation takes rather big amount of time. If you need to play with sizes for reducing memory allocation for your image, you exactly need to use scaling of your image using Bitmap.Options
, computing bitmap bounds at first and then decoding it to your specified size.
使用Bitmap.compress()
您只需指定压缩算法,顺便说一下压缩操作需要相当长的时间。如果您需要调整大小以减少图像的内存分配,则您Bitmap.Options
确实需要使用 缩放图像,首先计算位图边界,然后将其解码为您指定的大小。
The best sample that I found on StackOverflow is this one.
我在 StackOverflow 上找到的最好的示例是这个。
回答by Mightian
Most of the answers i found were just pieces that i had to put together to get a 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
2 参数sampleSize和质量起重要作用
sampleSizeis used to subsample the original image and return a smaller image, ie
SampleSize == 4 returns an image that is 1/4 the width/height of the original.
sampleSize用于对原始图像进行二次采样并返回较小的图像,即
SampleSize == 4 返回的图像是原始图像宽度/高度的 1/4。
quality is used to hint the compressor, input range is between 0-100. 0 meaning compress for small size, 100 meaning compress for max quality
quality 用于提示压缩器,输入范围在 0-100 之间。0 表示压缩小尺寸,100 表示压缩以获得最大质量
回答by Ziad H.
BitmapFactory.Options- Reduces Image Size (In Memory)
BitmapFactory.Options- 减小图像大小(在内存中)
Bitmap.compress()- Reduces Image Size (In Disk)
Bitmap.compress()- 减小图像大小(在磁盘中)
Refer to this link for more information about using both of them:https://android.jlelse.eu/loading-large-bitmaps-efficiently-in-android-66826cd4ad53
有关使用它们的更多信息,请参阅此链接:https : //android.jlelse.eu/loading-large-bitmaps-efficiently-in-android-66826cd4ad53