3

I'm doing an app which takes a photo with the camera and then rotates it and scales it. I need to rotate the image because the camera returns a wrong rotated image and I need to scale it to reduce its size. I first save in a temp directory the original image returned by camera, then I read it and make modifications, saving the new image to a new file. I tried using matrix to rotate and scale the picture, but it loses quality. Then I tried to scale it first with Bitmap.createScaledBitmap and then rotate it with matrix, but the result is even uglier than the one using only matrix. Then I tried to rotate it first and then resize it using always Bitmap.createScaledBitmap. The image doesn't lose quality, but it's stretched as I scaled it after rotating it and width and height are inverted. Tried also to invert height and width according to the rotation made, but it loses quality again. This is the last code I've written:

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);

Any advice?

EDIT: If I only rotate or only scale the image, it doesn't lose quality. It's when I do both that the image loses quality. Also, if I put the image in an ImageView after resizing it and scaling it, it doesn't lose quality, it's just when I save it to file that loses quality.

4

3 回答 3

4

Solved! I resize the image using BitmapFactory inSampleSize option and the image doesn't lose quality at all. Code:

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);
于 2013-07-05T07:48:43.070 回答
0

不要让新的位图只是覆盖

角度=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");
            }

        }
于 2013-07-04T15:04:39.937 回答
0

use this method to rotate the bitmap...

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;
}
于 2013-07-04T14:35:25.927 回答