android - java.lang.OutOfMemoryError when createBitmap

标签 android image bitmap out-of-memory

您好,我正在创建图像编辑应用程序,我正在为 Canvas 和 ImageView 创建位图

这里我在 imageView 中使用 385kb 尺寸为 2000x2000 的图像文件

这是图片 enter image description here

我的问题是,我第一次用其他小图像创建位图并编辑图像时它工作了一段时间,但第二次使用上述尺寸和尺寸时它会生成 java.lang.OutOfMemoryError :(

这是我的相关方法代码

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // initialize variable
        init();

        // initialize view
        initView();

        // initialize view's event listener
        initEventListener();

        setImageToImageView(ims);

    }  

private void init() {

        context = MainActivity.this;
        db_colorImage = new DB_ColorImage(context);

        AppUtils.setColorPreference(MainActivity.this, AppConstant.PREF_COLOR_PIC, "FF0000");
        AppUtils.setComboColorPreference(MainActivity.this, AppConstant.PREF_COMBO, 1);

        openCatId = getIntent().getIntExtra("open_cat_id", -1);
        openCat = getIntent().getStringExtra("image_categoryname");
        openImgName = getIntent().getStringExtra("img_name");

        db_colorImage.openDB();
        db_colorImage.startTransaction();
        assetsImgxx = db_colorImage.getXXX(openCatId);
        db_colorImage.successfullTransaction();
        db_colorImage.completeTransaction();
        db_colorImage.closeDB();


        assetsAndSdImage = new ArrayList<>(getIntent().getStringArrayListExtra("again"));           // aa list edit karelu with sdcard image

        try {

            ims = getAssets().open(openCat + "/" + openImgName);
        } catch (IOException e) {
            File getFromSd = new File(AppUtils.appFolder() + File.separator + openImgName);
            try {
                ims = new FileInputStream(getFromSd);
            } catch (FileNotFoundException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }

    }  

    public void setImageToImageView(InputStream ims) {
        Drawable d = Drawable.createFromStream(ims, null);

        BitmapDrawable drawable = (BitmapDrawable) d;

        Bitmap bmp = drawable.getBitmap();


        if (bmp != null) {
            _alteredBitmap = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888); // here i used ARGB_8888 because jnibitmap.cpp also use ARGB_8888. If we do not use this it wont color on image
        }

        Canvas canvas = new Canvas(_alteredBitmap);

        Paint paint = new Paint();

        Matrix matrix = new Matrix();

        canvas.drawBitmap(bmp, matrix, paint);

        imageView.setImageBitmap(_alteredBitmap);  // we can also use imageView.setImageResource(R.drawable.test_image);

        // ******* clear bitmap after use *******
        // check after done this step it will not produce any problem
        if (bmp != null) {
            bmp.recycle();
            bmp = null;
        }
    }  

_alteredBitmap = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);

在我得到异常的这一行,这是日志

01-27 19:12:33.590 27252-27252/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                   java.lang.OutOfMemoryError
                                                       at android.graphics.Bitmap.nativeCreate(Native Method)
                                                       at android.graphics.Bitmap.createBitmap(Bitmap.java:640)
                                                       at android.graphics.Bitmap.createBitmap(Bitmap.java:620)
                                                       at com.yptech.myfloodfilldemo.ui.MainActivity.setImageToImageView(MainActivity.java:387)
                                                       at com.yptech.myfloodfilldemo.ui.MainActivity.onCreate(MainActivity.java:96)
                                                       at android.app.Activity.performCreate(Activity.java:5008)
                                                       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
                                                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
                                                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
                                                       at android.app.ActivityThread.access$600(ActivityThread.java:130)
                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
                                                       at android.os.Handler.dispatchMessage(Handler.java:99)
                                                       at android.os.Looper.loop(Looper.java:137)
                                                       at android.app.ActivityThread.main(ActivityThread.java:4745)
                                                       at java.lang.reflect.Method.invokeNative(Native Method)
                                                       at java.lang.reflect.Method.invoke(Method.java:511)
                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
                                                       at dalvik.system.NativeStart.main(Native Method)  

编辑图像后,我正在保存此图像,因此我不想降低图像质量,所以我使用 Bitmap.Config.ARGB_8888。我尝试了很多解决方案,比如 android developer document在位图上,但它对我不起作用。

OutOfMemoryError 是否取决于图像大小和维度???以及如何在 createBitmap 时解决我的 OutOfMemoryError 问题??

当我使用 largHeap 时,它工作正常,但是使用 android:largeHeap="true" 是更好的方法吗??

提前致谢:)

最佳答案

在使用前优化位图。

Bitmap bitmap = MediaOptimize.reduceResolution(mediaPath, width, height);

函数:

public Bitmap reduceResolution(String filePath, int viewWidth, int viewHeight) {
    int reqHeight = viewHeight;
    int reqWidth = viewWidth;

    BitmapFactory.Options options = new BitmapFactory.Options();

    // First decode with inJustDecodeBounds=true to check dimensions
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(filePath, options);

    double viewAspectRatio = 1.0 * viewWidth/viewHeight;
    double bitmapAspectRatio = 1.0 * options.outWidth/options.outHeight;

    if (bitmapAspectRatio > viewAspectRatio)
        reqHeight = (int) (viewWidth/bitmapAspectRatio);
    else
        reqWidth = (int) (viewHeight * bitmapAspectRatio);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    System.gc();                                        // TODO - remove explicit gc calls
    return BitmapFactory.decodeFile(filePath, options);
}


private 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) {
        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    return inSampleSize;
}

关于android - java.lang.OutOfMemoryError when createBitmap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41895852/

相关文章:

Android 推特开源客户端

python - 枕头图像类型错误: an integer is required (got type tuple)

c# - 从 Canvas 保存的图像未正确呈现

image - 无法让图像在Qt中中心旋转

android - 如何在android中编辑大图像?

android - 如何从第一个 fragment 获取数据到最后一个 fragment ?

java - NoClassDefFoundError Amazon ADM 在 kindle 上的集成

android - 在表中显示来自数据库的数据。安卓

android - 将专门的 NV12 视频帧转换为 RGB

Android:可滚动(位图)屏幕