我希望我的应用程序上传没有大小限制的图像,但在代码中,如果图像大小超过,我想将图像大小调整为1MB。我尝试了很多方法,但是我找不到上面提到的要求的任何代码。
有一次,我试过这个:
public void scaleDown() {
int width = stdImageBmp.getWidth();
int height = stdImageBmp.getHeight();
Matrix matrix = new Matrix();
float scaleWidth = ((float) MAX_WIDTH) / width;
float scaleHeight = ((float) MAX_HEIGHT) / height;
matrix.postScale(scaleWidth, scaleHeight);
stdImageBmp = Bitmap.createBitmap(stdImageBmp, 0, 0, width, height, matrix, true);
File Image = new File("path");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//compress bmp
stdImageBmp.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
imgViewStd.setImageBitmap(stdImageBmp);
Log.d("resizedBitmap", stdImageBmp.toString());
width = stdImageBmp.getWidth();
height = stdImageBmp.getHeight();
System.out.println("imgWidth" + width);
System.out.println("imgHeight" + height);
}
答案 0 :(得分:4)
您可以使用此代码调整位图大小和图像大小< 1MB我建议使用480x640
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// "RECREATE" THE NEW BITMAP
return Bitmap.createBitmap(
bm, 0, 0, width, height, matrix, false);
}
答案 1 :(得分:0)
如果您真的想将位图缩小到最接近给定字节数的位图,请使用以下方法。
/**
* Method to scale the Bitmap to respect the max bytes
*
* @param input the Bitmap to scale if too large
* @param maxBytes the amount of bytes the Image may be
* @return The scaled bitmap or the input if already valid
* @Note: The caller of this function is responsible for recycling once the input is no longer needed
*/
public static Bitmap scaleBitmap(final Bitmap input, final long maxBytes) {
final int currentWidth = input.getWidth();
final int currentHeight = input.getHeight();
final int currentPixels = currentWidth * currentHeight;
// Get the amount of max pixels:
// 1 pixel = 4 bytes (R, G, B, A)
final long maxPixels = maxBytes / 4; // Floored
if (currentPixels <= maxPixels) {
// Already correct size:
return input;
}
// Scaling factor when maintaining aspect ratio is the square root since x and y have a relation:
final double scaleFactor = Math.sqrt(maxPixels / (double) currentPixels);
final int newWidthPx = (int) Math.floor(currentWidth * scaleFactor);
final int newHeightPx = (int) Math.floor(currentHeight * scaleFactor);
Timber.i("Scaled bitmap sizes are %1$s x %2$s when original sizes are %3$s x %4$s and currentPixels %5$s and maxPixels %6$s and scaled total pixels are: %7$s",
newWidthPx, newHeightPx, currentWidth, currentHeight, currentPixels, maxPixels, (newWidthPx * newHeightPx));
final Bitmap output = Bitmap.createScaledBitmap(input, newWidthPx, newHeightPx, true);
return output;
}
“示例”用法如下所示:
// (1 MB)
final long maxBytes = 1024 * 1024;
// Scale it
final Bitmap scaledBitmap = BitmapUtils.scaleBitmap(yourBitmap, maxBytes);
if(scaledBitmap != yourBitmap){
// Recycle the bitmap since we can use the scaled variant:
yourBitmap.recycle();
}
// ... do something with the scaled bitmap
答案 2 :(得分:0)
我试图对此发表评论,但评论变得太大了。 因此,我测试了许多解决方案,似乎只有两个解决方案可以给出一些结果。
让我们首先讨论Koen解决方案。它实际上是创建一个缩放的JPG
Bitmap.createScaledBitmap(input, newWidthPx, newHeightPx, true)
似乎它根本不压缩它,只是降低了分辨率。
我已经测试了这段代码,当我通过MAX_IMAGE_SIZE = 1024000时,它为我提供了来自2.33Mb原始图像的350kb压缩图像。虫子? 也缺乏质量。我无法识别Google Pixel制作的A4纸质照片上的文本。
对此问题还有另一种解决方案,该解决方案虽然质量不错,但速度却很慢。
一个WHILE LOOP!
基本上,您只需遍历图像大小,直到获得所需的大小
private fun scaleBitmap() {
if (originalFile.length() > MAX_IMAGE_SIZE) {
var streamLength = MAX_IMAGE_SIZE
var compressQuality = 100
val bmpStream = ByteArrayOutputStream()
while (streamLength >= MAX_IMAGE_SIZE) {
bmpStream.use {
it.flush()
it.reset()
}
compressQuality -= 8
val bitmap = BitmapFactory.decodeFile(originalFile.absolutePath, BitmapFactory.Options())
bitmap.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream)
streamLength = bmpStream.toByteArray().size
}
FileOutputStream(compressedFile).use {
it.write(bmpStream.toByteArray())
}
}
}
我认为这种方法将消耗指数时间,具体取决于图像分辨率。 9mb的图像最多需要12秒才能压缩到1mb。 质量很好。 您可以通过执行以下操作来降低原始位图分辨率(这似乎是一个恒定的操作)来进行调整:
options.inSampleSize = 2;
我们需要做的是以某种方式计算任何图像的compressQuality。 应当对此进行数学计算,以便我们可以根据原始图像的大小或宽度+高度确定compressQuality。