简体   繁体   English

画廊中的Android位图压缩导致Xiomi手机中的OutOfMemoryError

[英]Android Bitmap compress from gallery cause OutOfMemoryError in Xiomi phones

The below code gives OutOfMemoryError while compress method is executed in Xiomi, ASUS Zenfone2 and Samsung S5 devices alone. 以下代码仅在Xiomi,ASUS Zenfone2和Samsung S5设备中执行compress方法时给出OutOfMemoryError

  Bitmap bm = BitmapFactory.decodeFile(<sd_card_path_here>);
  bm.compress(Bitmap.CompressFormat.JPEG, 20, out);

Destination sd card path has a file created with 0 bytes 目标sd卡路径具有0字节创建的文件

Any help is highly appreciated and Thanks in Advance. 非常感谢您的任何帮助,并在此先感谢。

You should read loading bitmap efficiently to give you the basic understanding of why you might be experiencing OutOfMemory exception. 您应该有效地阅读加载位图,以基本了解为什么会遇到OutOfMemory异常。 Additionally, processing Bitmap should be done off the UI thread to avoid ANR error as well. 此外,应在UI线程之外完成位图处理,以避免ANR错误。

Ref: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html#load-bitmap 参考: http : //developer.android.com/training/displaying-bitmaps/load-bitmap.html#load-bitmap

what width/height does the bitmap have? 位图有什么宽度/高度?

Android's OpenGL version has a limit of 4096*4096 pixel (65 Megabyte uncompressed image) per Bitmap Android的OpenGL版本每个位图的限制为4096 * 4096像素(65 MB未压缩图像)

You can also try to increase apps memory in the AndroidManifest.xml 您还可以尝试在AndroidManifest.xml中增加应用程序的内存

 <application ...
    android:largeHeap="true"..></application>

If this does not help you have to scale down the image as described in http://developer.android.com/training/displaying-bitmaps/load-bitmap.html#load-bitmap 如果这样做没有帮助,您必须按照http://developer.android.com/training/displaying-bitmaps/load-bitmap.html#load-bitmap中所述缩小图像

I got working answer from here : 我从这里得到了工作答案:

    public String compressImage(String imageUri) {
 
        String filePath = getRealPathFromURI(imageUri);
        Bitmap scaledBitmap = null;
 
        BitmapFactory.Options options = new BitmapFactory.Options();
 
//      by setting this field as true, the actual bitmap pixels are not loaded in the memory. Just the bounds are loaded. If
//      you try the use the bitmap here, you will get null.
        options.inJustDecodeBounds = true;
        Bitmap bmp = BitmapFactory.decodeFile(filePath, options);
 
        int actualHeight = options.outHeight;
        int actualWidth = options.outWidth;
 
//      max Height and width values of the compressed image is taken as 816x612
 
        float maxHeight = 816.0f;
        float maxWidth = 612.0f;
        float imgRatio = actualWidth / actualHeight;
        float maxRatio = maxWidth / maxHeight;
 
//      width and height values are set maintaining the aspect ratio of the image
 
        if (actualHeight > maxHeight || actualWidth > maxWidth) {
            if (imgRatio < maxRatio) {               imgRatio = maxHeight / actualHeight;                actualWidth = (int) (imgRatio * actualWidth);               actualHeight = (int) maxHeight;             } else if (imgRatio > maxRatio) {
                imgRatio = maxWidth / actualWidth;
                actualHeight = (int) (imgRatio * actualHeight);
                actualWidth = (int) maxWidth;
            } else {
                actualHeight = (int) maxHeight;
                actualWidth = (int) maxWidth;
 
            }
        }
 
//      setting inSampleSize value allows to load a scaled down version of the original image
 
        options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
 
//      inJustDecodeBounds set to false to load the actual bitmap
        options.inJustDecodeBounds = false;
 
//      this options allow android to claim the bitmap memory if it runs low on memory
        options.inPurgeable = true;
        options.inInputShareable = true;
        options.inTempStorage = new byte[16 * 1024];
 
        try {
//          load the bitmap from its path
            bmp = BitmapFactory.decodeFile(filePath, options);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();
 
        }
        try {
            scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight,Bitmap.Config.ARGB_8888);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();
        }
 
        float ratioX = actualWidth / (float) options.outWidth;
        float ratioY = actualHeight / (float) options.outHeight;
        float middleX = actualWidth / 2.0f;
        float middleY = actualHeight / 2.0f;
 
        Matrix scaleMatrix = new Matrix();
        scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
 
        Canvas canvas = new Canvas(scaledBitmap);
        canvas.setMatrix(scaleMatrix);
        canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
 
//      check the rotation of the image and display it properly
        ExifInterface exif;
        try {
            exif = new ExifInterface(filePath);
 
            int orientation = exif.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION, 0);
            Log.d("EXIF", "Exif: " + orientation);
            Matrix matrix = new Matrix();
            if (orientation == 6) {
                matrix.postRotate(90);
                Log.d("EXIF", "Exif: " + orientation);
            } else if (orientation == 3) {
                matrix.postRotate(180);
                Log.d("EXIF", "Exif: " + orientation);
            } else if (orientation == 8) {
                matrix.postRotate(270);
                Log.d("EXIF", "Exif: " + orientation);
            }
            scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
                    scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix,
                    true);
        } catch (IOException e) {
            e.printStackTrace();
        }
 
        FileOutputStream out = null;
        String filename = getFilename();
        try {
            out = new FileOutputStream(filename);
 
//          write the compressed bitmap at the destination specified by filename.
            scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
 
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
 
        return filename;
 
    }


public String getFilename() {
    File file = new File(Environment.getExternalStorageDirectory().getPath(), "MyFolder/Images");
    if (!file.exists()) {
        file.mkdirs();
    }
    String uriSting = (file.getAbsolutePath() + "/" + System.currentTimeMillis() + ".jpg");
    return uriSting;
 
}


private String getRealPathFromURI(String contentURI) {
        Uri contentUri = Uri.parse(contentURI);
        Cursor cursor = getContentResolver().query(contentUri, null, null, null, null);
        if (cursor == null) {
            return contentUri.getPath();
        } else {
            cursor.moveToFirst();
            int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
            return cursor.getString(index);
        }
    }

public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;
 
    if (height > reqHeight || width > reqWidth) {
        final int heightRatio = Math.round((float) height/ (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;      }       final float totalPixels = width * height;       final float totalReqPixelsCap = reqWidth * reqHeight * 2;       while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
        inSampleSize++;
    }
 
    return inSampleSize;
}

reference link : LINK 参考链接: LINK

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM