How to reduce image without losing quality and preserving the aspect ratio?
本问题已经有最佳答案,请猛点这里访问。
我有图像
我将它加载到位图
问题是它非常大(
这张图片工作得很慢。
我想将图像缩小到更小的尺寸。 但要保持质量和比例。 如何才能做到这一点?
您应该阅读有效加载大位图。
基本上,首先计算样本量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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; } |
然后使用样本大小加载图像:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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); } |
如果你在这里阅读教程,你会看到谷歌为你提供了一个非常全面的指南,指导如何在没有过多内存使用的情况下缩放位图。
特别是,这两种方法(来自教程):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | public static Bitmap decodeSampledBitmapFromResource(File file, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(file, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(file, 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; } |
在保持纵横比的同时完成缩放。
这两种方法的技巧是第一个解码操作设置为仅解码图像的属性(维度和其他信息),如下所示:
1 | options.inJustDecodeBounds = true; |
其中新的比例因子通过calculateInSampleSize()方法按比例计算。
然后再次解码图像,这次是
1 | options.inJustDecodeBounds = false; |
以及比例因子设置,因此位图工厂在解码时自动缩放,减少了内存占用。
关于图像需要解码的分辨率,这实际上取决于您的用例。但是,如果特定图像不需要稍后放大,则只需要设备的物理屏幕尺寸,可以通过以下方式获得:
1 2 3 |
其中object
我用它来调整我的位图的大小。也许对你有用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public Bitmap resizeBitmap(Bitmap bitmap, int newWidth, int newHeight) { //bitmap it's the bitmap you want to resize //newWidth and newHeight are the with and height that you want to the new bitmap int width = bitmap.getWidth(); int height = bitmap.getHeight(); float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) /height; Matrix matrix = new Matrix(); matrix.postScale(scaleWidth, scaleHeight); Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false); return resizedBitmap; } |
我希望这对你有帮助。