Android - 在不损失质量的情况下缩放、旋转位图并将其保存到 SD 卡

标签 android matrix bitmap rotation

我正在做一个应用程序,它用相机拍照,然后旋转和缩放它。 我需要旋转图像,因为相机返回错误的旋转图像,我需要缩放它以减小其尺寸。 我首先将相机返回的原始图像保存在一个临时目录中,然后读取它并进行修改,将新图像保存到一个新文件中。 我尝试使用矩阵来旋转和缩放图片,但它会降低质量。 然后我尝试先用 Bitmap.createScaledBitmap 缩放它,然后用矩阵旋转它,但结果比只使用矩阵的更难看。 然后我尝试先旋转它,然后始终使用 Bitmap.createScaledBitmap 调整它的大小。图像没有失去质量,但在旋转图像后缩放它时它被拉伸(stretch)了,宽度和高度倒置了。还尝试根据所做的旋转反转高度和宽度,但它再次失去质量。 这是我写的最后一段代码:

in= new FileInputStream(tempDir+"/"+photo1_path);
            out = new FileOutputStream(file+"/picture.png");
            Bitmap src = BitmapFactory.decodeStream(in);
            int iwidth = src.getWidth();
            int iheight = src.getHeight();
            int newWidth = 0;
            int newHeight = 0;

                newWidth = 800;
                newHeight = 600;

              // calculate the scale - in this case = 0.4f
              float scaleWidth = ((float) newWidth) / iwidth;
              float scaleHeight = ((float) newHeight) / iheight;

              // createa matrix for the manipulation
              Matrix matrix = new Matrix();
              // resize the bit map
              //matrix.postScale(scaleWidth, scaleHeight);
              int orientation = getOrientation(MyActivity.this,Uri.parse(tempDir+"/"+photo1_path));
              switch(orientation) {
                case 3:
                    orientation = 180;
                    break;
                case 6:
                    orientation = 90;
                   break;
                case 8:
                    orientation = 270;
                    break;
              }
              int rotate = 0;
              switch(orientation) {
                case 90:
                    rotate=90;
                    break;
                case 180:
                    rotate=180;
                    break;
                case 270:
                    rotate=270;
                    break;

              }
              // rotate the Bitmap
              matrix.postRotate(rotate);

              src =Bitmap.createScaledBitmap(src , newWidth, newHeight, false);
              // recreate the new Bitmap
              Bitmap new_bit = Bitmap.createBitmap(src, 0, 0,
                                src.getWidth(), src.getHeight(), matrix, true);
                      new_bit.compress(Bitmap.CompressFormat.PNG, 100, out);

有什么建议吗?

编辑:如果我只旋转或缩放图像,它不会降低质量。当我同时执行这两项操作时,图像质量就会下降。此外,如果我在调整图像大小和缩放后将其放入 ImageView 中,它不会降低质量,只是当我将其保存到文件时质量会降低。

最佳答案

解决了! 我使用 BitmapFactory inSampleSize 选项调整图像大小,图像质量丝毫没有下降。 代码:

BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
Bitmap bm = BitmapFactory.decodeFile(tempDir+"/"+photo1_path , bmpFactoryOptions);


int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)600);
int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)800);

if (heightRatio > 1 || widthRatio > 1)
{
    if (heightRatio > widthRatio){
        bmpFactoryOptions.inSampleSize = heightRatio;
    } else {
        bmpFactoryOptions.inSampleSize = widthRatio; 
    } 
}

bmpFactoryOptions.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(tempDir+"/"+photo1_path, bmpFactoryOptions);
//bm.compress(Bitmap.CompressFormat.PNG, 100, out);
/*Bitmap new_bit = Bitmap.createScaledBitmap(src , newWidth, newHeight, true);
            new_bit.compress(Bitmap.CompressFormat.PNG, 100, out);*/


// recreate the new Bitmap
src = Bitmap.createBitmap(bm, 0, 0,bm.getWidth(), bm.getHeight(), matrix, true);


//Bitmap dest = Bitmap.createScaledBitmap(new_bit , newWidth, newHeight, true);
src.compress(Bitmap.CompressFormat.PNG, 100, out);

关于Android - 在不损失质量的情况下缩放、旋转位图并将其保存到 SD 卡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17472788/

相关文章:

android - 如何在mapbox android中将缩放级别设置为(> 18)?

Java (Android) 线程,访问同一列表

arrays - 将矩阵的坐标转换为相应数组的坐标

c# - Bitmap.Save 参数无效

android - CannyEdgeDetector 使用位图给出堆栈溢出

android - 在 Android O 预览中将 AdaptiveIconDrawable 转换为位图

java - 删除 fragment View 并返回到 Cordova Webview

java - Java中两个矩阵相乘

matlab - 在矩阵中保存不同大小的向量

android - 显示质量图像 - 位图大小超出 VM 预算错误