您好,我正在创建图像编辑应用程序,我正在为 Canvas 和 ImageView 创建位图
这里我在 imageView 中使用 385kb 尺寸为 2000x2000 的图像文件
我的问题是,我第一次用其他小图像创建位图并编辑图像时它工作了一段时间,但第二次使用上述尺寸和尺寸时它会生成 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/