Android-减少图像尺寸不会以相同的比例减少大小
我有一个小方法,可以调整图像大小(存储为文件),以生成具有预定义文件大小(在我的示例中为512 KB)的新图像。该方法如下所示:Android-减少图像尺寸不会以相同的比例减少大小,android,bitmap,image-resizing,android-bitmap,Android,Bitmap,Image Resizing,Android Bitmap,我有一个小方法,可以调整图像大小(存储为文件),以生成具有预定义文件大小(在我的示例中为512 KB)的新图像。该方法如下所示: private static final int maximumFileSizeInKBs = 512; public static Uri resizeImage(Context context, Uri imageUri) { // get image width and height BitmapFactory.Options options
private static final int maximumFileSizeInKBs = 512;
public static Uri resizeImage(Context context, Uri imageUri) {
// get image width and height
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap imageBitmap = BitmapFactory.decodeFile(new File(imageUri.getPath()).getAbsolutePath(), options);
int imageWidth = options.outWidth;
int imageHeight = options.outHeight;
// get image file size (in KBs)
File file = new File(imageUri.getPath());
int fileSizeInKBs = Integer.parseInt(String.valueOf(file.length()/1024));
// get the scaling factor
// (square root because when we scale both the width and height by the
// square root of the scaling factor, then the size of the final image
// will be scaled by the scaling factor)
double scalingFactor = Math.sqrt(fileSizeInKBs / maximumFileSizeInKBs);
// no need to scale if file already within maximum file size limit
if(scalingFactor <= 1) {
return imageUri;
}
// get scaled dimensions
int scaledImageWidth = (int) Math.floor(imageWidth / scalingFactor);
int scaledImageHeight = (int) Math.floor(imageHeight / scalingFactor);
// load original bitmap (load a scaled copy to avoid OutOfMemory errors)
options = new BitmapFactory.Options();
options.inSampleSize = Math.max(imageHeight/scaledImageWidth, imageHeight/scaledImageHeight);
imageBitmap = BitmapFactory.decodeFile(new File(imageUri.getPath()).getAbsolutePath(), options);
// the scaled image above will be scaled by a value equal to the
// nearest power of 2, hence it wont be scaled to the exact value
// that we want. So, we need to calculate new scaling factors
// based on the scaled loaded bitmap
Matrix m = new Matrix();
RectF inRect = new RectF(0, 0, imageWidth, imageHeight);
RectF outRect = new RectF(0, 0, scaledImageWidth, scaledImageHeight);
m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
float[] values = new float[9];
m.getValues(values);
// create a scaled bitmap with required file size
Bitmap scaledBitmap = Bitmap.createScaledBitmap(imageBitmap, (int) (imageWidth*values[0]), (int) (imageHeight*values[4]), true);
// delete original image
new File(imageUri.getPath()).delete();
// write bitmap to file
File newImageFile = BaseResourceClass.makeTempResourceFile(Slide.ResourceType.IMAGE, context);
try {
newImageFile.createNewFile();
FileOutputStream fos = new FileOutputStream(newImageFile);
scaledBitmap.compress(Bitmap.CompressFormat.PNG, 1, fos);
fos.close();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(context, "Something went wrong", Toast.LENGTH_SHORT).show();
}
// recycle bitmaps to reallocate memory
Storage.recycleBitmap(imageBitmap);
Storage.recycleBitmap(scaledBitmap);
// scaling done, return new Image
return Uri.fromFile(newImageFile);
}
我不明白,在从图像中删除这么多像素后,是什么占据了这么多空间,从而使图像文件保持这么大。试图查看其他StackOverflow问题以及android BitmapFactory和位图类文档,但没有提到这个问题。任何帮助都将不胜感激 出现这种情况的原因有很多,这取决于您正在读取的图像类型(JPG、GIF、PNG、BMP)、压缩质量(如果是JPG)以及缩小图像尺寸后如何保存 在您的示例中,您没有显示您使用的图像或图像使用的压缩类型。但从代码中,我看到您正在将其保存为PNG图像 如果你拍摄了一幅高质量的2MB jpg图像,并且像以前一样缩小了尺寸,但将其保存为PNG(无损质量),那么你可能会得到一个比以前更大的文件 JPG图像使用压缩算法来存储与原始图像尽可能相似的图像,但占用的空间要小得多。根据质量的不同,您可以得到一个看起来几乎与原始图像一样大的文件大小的图像,或者一个只需要几千字节的可怕图像 当您将图像保存为PNG时,您会得到与原始图像完全相同的图像(这就是为什么它被称为loseless),这样,您就无法通过压缩保存太多的文件大小 如果您使用PNG作为输入,并将简化后的版本保存为PNG,您可能会更接近您的“比例文件大小”想法。虽然减小大小可以通过抗锯齿在生成的图像中创建新的颜色,并稍微降低压缩性能
使用JPG图像会使其更不可预测,因为原始图像中使用的质量和用于压缩结果的质量都会影响结果的文件大小。如果图像未压缩,您可以预期图像文件大小与图像宽度x高度成比例。这仅适用于BMP格式 您正在处理以PNG格式存储的图像。PNG使用压缩来存储图像。这就是为什么图像大小更多地取决于图像的细节,而较少地取决于图像的宽度和高度 在您的情况下,图像大小主要取决于第二个参数,质量 scaled位图.compress(Bitmap.CompressFormat.PNG,1,fos) 您可以将其更改为0以获得较小的文件
before resizing
imageWidth : 3120, imageHeight : 4160, fileSize : 2960 KB
after resizing
imageWidth : 1395, imageHeight : 1860, fileSize : 2491 KB