【问题标题】:Android - scale, rotate and save a bitmap to sdcard without losing qualityAndroid - 缩放、旋转位图并将其保存到 SD 卡而不损失质量
【发布时间】:2013-07-04 14:27:07
【问题描述】:

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

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 中,它不会丢失质量,只是当我将其保存到文件时会丢失质量。

【问题讨论】:

    标签: android matrix bitmap rotation


    【解决方案1】:

    解决了! 我使用 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);
    

    【讨论】:

    • Bitmap.CompressFormat.PNG的问题是文件每次旋转都会变大。
    【解决方案2】:

    使用此方法旋转位图...

    private Bitmap checkifImageRotated() {
        ExifInterface exif;
        try {
            exif = new ExifInterface(file.getAbsolutePath());
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            int rotate = 0;
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_270 :
                    rotate = -90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180 :
                    rotate = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_90 :
                    rotate = 90;
                    break;
            }
            if (rotate != 0) {
                Bitmap bitmap = BitmapFactory.decodeFile(getTempFile().getPath());
                Matrix matrix = new Matrix();
                matrix.setRotate(rotate);
                Bitmap bmpRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
                recycle(bitmap);
                return bmpRotated;
            }
        }
        catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    

    【讨论】:

    • 谢谢,我刚试过,但没有任何变化,总是质量下降。无论如何,您也使用矩阵来旋转图像,因此即使使用 ExifInterface 获取方向也没有任何变化是合理的:(
    【解决方案3】:

    不要让新的位图只是覆盖

    int 角度=0;整数值角度=0;位图位图;

            @Override
            public void onClick(View v) {
    
                System.out.println("valueeeeeee  " + angle);
                if (bitmap != null) {
    
                    angle = valueangle + 90;
    
    
    
                    Matrix matrix = new Matrix();
                    matrix.postRotate(angle);
    
                    bitmap = Bitmap.createBitmap(
                            bitmap , 0, 0,
                            bitmap .getWidth(),
                            bitmap .getHeight(), matrix, true);
    
    
    
                    main_img.setImageBitmap(bitmap );
    
                } else {
    
                    System.out.println(" bitmap is null");
                }
    
            }
    

    【讨论】:

    • 谢谢,我刚刚尝试覆盖,但结果是一样的,图像质量下降。我没有像你那样把我的位图放在 ImageView 中,这能改变什么吗?
    • 表示更改正确解释的内容,如果此代码有助于完全接受和支持
    • 一旦不要一次又一次地缩放位图,然后你用那个位图做任何事情你旋转了很多次它并没有损失质量,只有当你缩放位图时,如果你这样做它就会丢失质量
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-04
    • 2012-08-04
    相关资源
    最近更新 更多