Android bitmap - out of memory - java

I have a problem with a function that I implemented. On some phones I get a out of memory error.
private Bitmap getIconMarkerOfPlayer(Player p) {
Drawable drawable = getIconOfPlayer(p);
Bitmap img = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(img);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.draw(canvas);
final float scale = this.getResources().getDisplayMetrics().density;
int heigthPixels = (int) (24 * scale + 0.5f);
int widthPixels = (int) (24 * scale + 0.5f);
return Bitmap.createScaledBitmap(img, widthPixels, heigthPixels, false);
}
The getIconMarkerOfPlayer(Player p) function gives a "programmed" drawable depending on the player's status (dead, alive, offline, ...) and its color. Each player has a unique color assigned to it in the early games.
How can I resize my bitmap from a Drawable object without having a out of memory error?

I suggest you to use some ImageLibraries to load Bitmaps efficiently.
Some of them are Fresco, Glide, Piccasio.
I suggest you to go with Glide. Have a look at it here

Related

Android: How to make a percentage of a bitmap black and white, retaining color in the rest?

I've got a bitmap displayed in an ImageView, and I want to be able to make a certain percentage of the image black and white, and have the other part retain it's color. For example, if 60% is the target percentage, the image would look like this: . Thanks.
I've got a bitmap displayed in an ImageView, and I want to be able to
make a certain percentage of the image black and white, and have the
other part retain it's color. For example, if 60% is the target
percentage.
It seems (from your image) you mean monochrome (i.e. greyscale), not black and white.
Something like this should do it (tested o.k.):
void doIt(ImageView image)
{
//get bitmap from your ImageView (image)
Bitmap originalBitmap = ((BitmapDrawable)image.getDrawable()).getBitmap();
int height = originalBitmap.getHeight();
int fortyPercentHeight = (int) Math.floor(height * 40.0 / 100.0);
//create a bitmap of the top 40% of image height that we will make black and white
Bitmap croppedBitmap = Bitmap.createBitmap(originalBitmap, 0, 0, originalBitmap.getWidth() , fortyPercentHeight );
//make it monochrome
Bitmap blackAndWhiteBitmap = monoChrome(croppedBitmap);
//copy the monochrome bmp (blackAndWhiteBitmap) to the original bmp (originalBitmap)
originalBitmap = overlay(originalBitmap, blackAndWhiteBitmap);
//set imageview to new bitmap
image.setImageBitmap(originalBitmap );
}
Bitmap monoChrome(Bitmap bitmap)
{
Bitmap bmpMonochrome = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmpMonochrome);
ColorMatrix ma = new ColorMatrix();
ma.setSaturation(0);
Paint paint = new Paint();
paint.setColorFilter(new ColorMatrixColorFilter(ma));
canvas.drawBitmap(bitmap, 0, 0, paint);
return bmpMonochrome;
}
Bitmap overlay(Bitmap bmp1, Bitmap bmp2)
{
Bitmap bmp3 = bmp1.copy(Bitmap.Config.ARGB_8888,true);//mutable copy
Canvas canvas = new Canvas(bmp3 );
canvas.drawBitmap(bmp2, new Matrix(), null);
return bmp3 ;
}

Google Maps - memory leak with dynamic bitmap markers

My app uses geojson to draw features on map. To draw feature:
for (GeoJsonFeature f : new GeoJsonLayer(googleMap, new JSONObject(geojson)).getFeatures())
{
f.setPointStyle(getPointStyle(text,status);
layer.addFeature(f);
}
layer.addLayerToMap();
To generate point (marker) style and set icon:
GeoJsonPointStyle markerStyle = new GeoJsonPointStyle();
int[] markers = {R.drawable.marker0,R.drawable.marker1,R.drawable.marker2,R.drawable.marker3,R.drawable.marker4};
bmp = Utils.drawTextToBitmap(getContext(), markers[status], icon);
markerStyle.setIcon(highlighted ? BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN):BitmapDescriptorFactory.fromBitmap(bmp));
drawTextToBitmap just generates bitmap with text on it:
public static Bitmap drawTextToBitmap(Context gContext, int gResId, String gText)
{
Resources resources = gContext.getResources();
float scale = resources.getDisplayMetrics().density;
Bitmap bitmap = BitmapFactory.decodeResource(resources, gResId);
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
if (bitmapConfig == null)
{
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
paint.setTextSize((int) (18 * scale));
Typeface tf = Typeface.createFromAsset(gContext.getAssets(), "fonts/fontawesome.ttf");
paint.setTypeface(Typeface.create(tf, Typeface.BOLD));
paint.setShadowLayer(1f, 0f, 1f, Color.WHITE);
Rect bounds = new Rect();
paint.getTextBounds(gText, 0, gText.length(), bounds);
int x = (bitmap.getWidth() - bounds.width()) / 2;
int y = (bitmap.getHeight() + bounds.height()) / 2 -8;
canvas.drawText(gText, x, y, paint);
return bitmap;
}
My problem is that on some phones (not on every phone) this approach causes huge memory leak if there is big amount of markes to draw on map. Problem does not exists if I use static marker drawable from resources, but I need dynamic bitmap to add text on it.
Do you have any idea about memory leak cause? It seems map holds bitmap reference so it prevents garbage from disposing it. Even if map fragment is destroyed, map resources will be never released, so after displaying map few times, app stops working due to OutOfMemory exception.

Draw in a canvas and save it to a larger image

I have a requirement, like drawing something in canvas and saving it to a larger image. As of now whatever I draw inside onDraw() method and save, it gives device provided image/canvas size, say something around 538(w)/852(h). I need image of almost double size, around 1000(w)/1500(h) without losing resolution. Any sample code, reference link would help definitely. Thanks in advance.
One way is to create Bitmap of desired size and draw on it using canvas:
int w = 1000, h = 1500;
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
Bitmap bmp = Bitmap.createBitmap(w, h, conf);
Canvas canvas = new Canvas(bmp);
Finally you will have you bmp with your drawing and necessary dimentions.
EDIT::
#Override
protected void onDraw(Canvas canvas) {
int w = 1000, h = 1500;
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
Bitmap bmp = Bitmap.createBitmap(w, h, conf);
Canvas mycanvas = new Canvas(bmp);
super.onDraw(mycanvas);
...
}
First get bitmap of your view using the function getDrawingCache(), then scale the bitmap as per your requirements.
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
//bitmap = bitmap.createScaledBitmap(..as your requirements..);
EDIT
You are saying that you want image in higher quality. You can't simply get a higher quality image from a lower quality image. However you can apply bitmap filtering to get slightly better quality.
Bitmap bitmap = getDrawingCache();
Bitmap output = Bitmap.createBitmap(/*width, height, bla bla bla*/);
Canvas canvas = new Canvas(output);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
Rect srcRect = new Rect(0,0,bitmap.getWidth(), bitmap.getHeight());
Rect destRect = new Rect(0,0,output.getWidth(), output.getHeight());
canvas.drawBitmap(bitmap, srcRect, destRect, paint);

How to blur the edges of bitmap to fit the square like blur square or iphone inbuilt feature

I want to implement the type of blurring shown in the picture below. I have my bitmap, and I want to implement this blurring on the sides of to make it a square like iPhone's inbuilt feature to fit WhatsApp or Instagram display picture. Till now I have been able to fill color in those edges using Color.Blue etc.
For more info: How to create a square bitmap from a rectangular bitmap in Android
I want to fill those white sides in that question's image with blurred part.
Its the blurred version of same image shown in the background. Following code gives you a blurred effect of same image. Adjust BLUR_RADIUS for amplitude of effect.
public class BlurBuilder {
private static final float BITMAP_SCALE = 0.4f;
private static final float BLUR_RADIUS = 20f;
public static Bitmap blur(Context context, Bitmap image) {
int width = Math.round(image.getWidth() * BITMAP_SCALE);
int height = Math.round(image.getHeight() * BITMAP_SCALE);
Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
RenderScript rs = RenderScript.create(context);
ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
theIntrinsic.setRadius(BLUR_RADIUS);
theIntrinsic.setInput(tmpIn);
theIntrinsic.forEach(tmpOut);
tmpOut.copyTo(outputBitmap);
return outputBitmap;
}
}
Source

Image masking with another resizable android

I have a requirement where I will be having a background Image and one mask Image. Lets say the background Image is of Motorcycle and the mask will be used to hide the registration number. So the mask will be movable and also resize-able. Finally the combined Image will be generated with background image and Image mask. How we can achieve this ?
public Bitmap drawFacesOnBitmap(Context gContext, Bitmap bitmap) {
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
// set default bitmap config if none
if(bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
// resource bitmaps are imutable,
// so we need to convert it to mutable one
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
// new antialised Paint
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// text color - #3D3D3D
paint.setColor(Color.GREEN);
// draw text to the Canvas center
Log.d("BITMAP DIMENS****", "bitmapWidth:"+bitmap.getWidth()+" & bitmapHeight:"+bitmap.getHeight());
android.graphics.Rect r = new android.graphics.Rect();
r.left = 200;
r.top = 200;
r.right = 400;
r.bottom = 400;
canvas.drawRect(r, paint);
return bitmap;
}
You can use this code to draw a rectangle on a bitmap. Edit it to meet your needs.

Categories