仅在太大时才调整位图大小
Resize Bitmap only if too large
只有当照片太大(例如,宽度 > 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() 方法似乎做我想做的事,文档说“例如,分辨率为 2048x1536 的图像用 4 的 inSampleSize 解码产生大约 512x384 的位图”但我不想设置最终 width/height.
然后,当我得到较小的位图时,我想制作一个
scaledBitmap.compress(CompressFormat.JPEG, 80, out);
再次优化。
请问我该如何解决?
您可以获得位图的宽度和高度,如bitmap.getWidth()
和bitmap.getHeight()
。获得宽度和高度后,检查哪个值较小。如果宽度小于高度,将 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);
}
最后我选择了另一个解决方案:
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()
方法不是很 "handy",技巧是 minimalLengthSide
变量。我设置了我想要的短边的最小长度(这里是 300px),方法 calculateInSampleSize()
会自动计算出合适的比例。
比率 width/height 保持不变,我不使用
Bitmap.createScaledBitmap(realImage, width, height, filter)
效率可能 "costly" 或更低。
只有当照片太大(例如,宽度 > 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() 方法似乎做我想做的事,文档说“例如,分辨率为 2048x1536 的图像用 4 的 inSampleSize 解码产生大约 512x384 的位图”但我不想设置最终 width/height.
然后,当我得到较小的位图时,我想制作一个
scaledBitmap.compress(CompressFormat.JPEG, 80, out);
再次优化。
请问我该如何解决?
您可以获得位图的宽度和高度,如bitmap.getWidth()
和bitmap.getHeight()
。获得宽度和高度后,检查哪个值较小。如果宽度小于高度,将 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);
}
最后我选择了另一个解决方案:
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()
方法不是很 "handy",技巧是 minimalLengthSide
变量。我设置了我想要的短边的最小长度(这里是 300px),方法 calculateInSampleSize()
会自动计算出合适的比例。
比率 width/height 保持不变,我不使用
Bitmap.createScaledBitmap(realImage, width, height, filter)
效率可能 "costly" 或更低。