Reputation: 325
Hi i am creating image editing app wher i am create bitmap for canvas and imageview
here i am using 385kb image file with 2000x2000 dimension in imageView
my problem is that first time i create bitmap with other small image and edit image it work some time but for second time with above size and dimension it generate java.lang.OutOfMemoryError :(
this is my related methods code
@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);
at this line where i get EXCEPTION, here is the log
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)
After edit image I am saving this image so I don't want to reduce image quality so I use Bitmap.Config.ARGB_8888. I tried so many solution like android developer document on bitmap but it not work for me.
is OutOfMemoryError depends upon image size and dimension ??? and how to solve my problem for OutOfMemoryError while createBitmap ??
when I am using largHeap it work fine but is that better approach to use android:largeHeap="true" ??
thanks in advance :)
Upvotes: 4
Views: 5213
Reputation: 231
I'm using Glide (https://bumptech.github.io/glide/) to loading large bitmaps efficiently. In case of loading photos from your device Glide also handle the correct rotation for you.
val myUri = ...
val neededHeight = 600
val neededWidth = 800
val bitmap = GlideApp
.with(context)
.asBitmap()
.load(myUri)
.override(neededWidth, neededHeight)
.submit()
.get()
Upvotes: 1
Reputation: 1812
Optimize the bitmap before using it.
Bitmap bitmap = MediaOptimize.reduceResolution(mediaPath, width, height);
Functions:
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;
}
Upvotes: 2
Reputation: 336
The image is way to big. I recommend shrinking the image or using picasso library to make better use of memory issues and image caching.
Upvotes: -1
Reputation: 1190
Try this out, just add it to AndroidManifest.xml
<application
...
android:largeHeap="true">
<activity
android:name=".MainActivity"
...
Upvotes: -1