我有一个URI图像文件,我想减小其大小以上传它。初始图像文件大小取决于从移动设备到移动设备(可以是2MB,可以是500KB),但我希望最终大小约为200KB,以便我可以上传它。
从我读到的,我有(至少)2个选择:
什么是最佳选择?
我想最初调整图像宽度/高度,直到宽度或高度超过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");
}
有更好的方法吗?我应该尝试继续使用所有2种方法还是只使用一种方法?感谢
答案 0 :(得分:28)
使用Bitmap.compress()
,您只需指定压缩算法,并按压缩操作的方式花费相当多的时间。如果您需要使用大小来减少图像的内存分配,则需要使用Bitmap.Options
缩放图像,首先计算位图边界,然后将其解码为指定的大小。
我在StackOverflow上找到的最佳样本是this one。
答案 1 :(得分:1)
我发现的大部分答案都只是我必须整理好的一些内容才能得到正常工作的代码,该代码发布在
下面 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个参数sampleSize和quality起着重要作用
sampleSize 用于对原始图像进行二次采样并返回一个较小的图像,即
SampleSize == 4返回的图像是原始宽度/高度的1/4。
质量用于提示压缩器,输入范围在0-100之间。 0表示压缩 小尺寸,100意味着压缩以获得最高质量
答案 2 :(得分:0)
BitmapFactory.Options -减小图像大小(在内存中)
Bitmap.compress()-减小图像大小(在磁盘中)
有关使用它们的更多信息,请参考此链接: https://android.jlelse.eu/loading-large-bitmaps-efficiently-in-android-66826cd4ad53