在没有OutOfMemoryError或缩减的情况下在Android中旋转图像

时间:2012-06-21 19:45:48

标签: android bitmap rotation out-of-memory

基本上我正在尝试在Android应用中旋转位图(来自图像)。我想这样做的原因是,即使垂直拍摄,从相机拍摄的照片(通过意图)也会水平显示,并且方向在图像上保留为元数据。如果错了,请纠正我。然而问题是,如果在装有相当好的相机的手机上拍摄时,图像将占用大量内存,而且我没有找到旋转和保存它的方法而没有获得OutOfMemoryError的风险。下面的代码是i:

  1. 加载图片
  2. 检查是否需要旋转
  3. 加载缩小版本以在ImageView中显示
  4. 根据需要旋转小图片
  5. 在一个单独的线程中;加载,旋转和保存图像,以便将来不需要
  6. 对于应用程序而言,保持图像的分辨率非常重要,但欢迎任何带编码的技巧。我已经在互联网上搜索了几天,找不到比我已经实现的更多的内容。这里有另一个主题,但似乎没有任何解决方案。希望你能帮忙。

        public Bitmap getBitmap(final Context c) {
        if (bitmap != null)
            return bitmap;
    
        final int rotate = necessaryRotation(c, file);
        // if(rotate != 0) rotateImageFile(c, rotate);
    
        try {
            // Get scaled version
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(file, options);
            options.inSampleSize = calcInSampleSize(options, 1024, 1024);
            options.inJustDecodeBounds = false;
            bitmap = BitmapFactory.decodeFile(file, options);
    
            // rotate?
            bitmap = rotateImage(c,bitmap,rotate);
    
            System.out.println("Bitmap loaded from file: size="
                    + bitmap.getWidth() + "," + bitmap.getHeight());
    
            System.gc();
        } catch (Exception e) {
            System.err.println("Unable to load image file: "
                    + this.getFilename());
        }
    
        // if rotation is needed, do it in worker thread for next time
        if(rotate != 0){
            Thread t = new Thread(new Runnable(){
    
                public void run() {
                    // load entire image
                    try{
                        File imageFile = new File(getFilename());
                        Bitmap huge = Media.getBitmap(c.getContentResolver(),
                        Uri.fromFile(imageFile));
    
                        huge = rotateImage(c,huge,rotate);
    
                        // save bitmap properly
                        FileOutputStream out = new FileOutputStream(imageFile);
                        huge.compress(Bitmap.CompressFormat.PNG, 100, out);
    
                        out.flush();
                        out.close();
                        huge.recycle();
                        huge = null;
                        out = null;
                        System.gc();
    
                    }catch(IOException e){
                        e.printStackTrace();
                    }
                }
    
            });
            t.start();
        }
    
        return bitmap;
    }
    
    private Bitmap rotateImage(Context c, Bitmap bitmap, int rotate) {
        if (rotate != 0) {
            // rotate
            Matrix m = new Matrix();
            m.postRotate(rotate);
            Bitmap rotImage = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                    bitmap.getHeight(), m, true);
            bitmap.recycle();
    
            System.out.println("Image (id=" + getId()
                    + ") rotated successfully");
    
            System.gc();
    
            return rotImage;
        }
        return bitmap;
    }
    
    private int necessaryRotation(Context c, String imageFile) {
        int rotate = 0;
        ExifInterface exif;
        try {
            exif = new ExifInterface(imageFile);
            int orientation = exif.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
    
            switch (orientation) {
            case ExifInterface.ORIENTATION_ROTATE_270:
                rotate = 270;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                rotate = 180;
                break;
            case ExifInterface.ORIENTATION_ROTATE_90:
                rotate = 90;
                break;
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
        return rotate;
    }
    
    private int calcInSampleSize(BitmapFactory.Options options, int reqWidth,
            int reqHeight) {
        int height = options.outHeight;
        int width = options.outWidth;
        int inSampleSize = 1;
        while (height > reqHeight || width > reqWidth) {
            height /= 2;
            width /= 2;
            inSampleSize *= 2;
        }
    
        return inSampleSize;
    }
    

    如果你需要了解或有任何优化我可能会用来减少内存使用量,请写:)谢谢

1 个答案:

答案 0 :(得分:0)

试试这个代码段:

private Bitmap rotateImage(Context c, Bitmap bitmap, int rotate) {
    ....

    // reduce byte per pixel
    bitmap = bitmap.copy(Bitmap.Config.RGB_565, false);

    Bitmap.createBitmap(bitmap,...
}