LRUCache BitmapDrawable - android

I'm using an LruCache to cache a lot of small BitmapDrawables used throughout my app. The problem is that the sizes differ for the different places I use the images.
I set the bounds when I retrieve the drawable from the cache before setting it to the ImageView to have the correct size.
When I set the bounds, the drawable resizes on the other places as well.
How can I get around this issue without using drawable.getConstantState().newDrawable()? Creating a new drawable from the cached drawable is very slow when scrolling a listview.
The same images are used in DynamicDrawableSpans where I can't set the bounds on the span itself, only on the drawable directly.
Will it be wise to have the same drawable image cached for the different contexts in seperate Caches?

I got it to work correctly.
I changed the LruCache type from BitmapDrawable to Bitmap. This way the cache only stores the Bitmap image and not the drawable bounds as well.
When I want to set the bitmap I convert it to BitmapDrawable
Drawable d = new BitmapDrawable(getResources(), bitmap);
Then I set the bounds for the newly created drawable instance
d.setBounds(0, 0, sizex, sizey);
This way each instance of the Bitmap is a seperate Drawable with its own Bounds.

Related

Create a bitmap from drawable resource filepath

I would like to create an image chooser from my drawable resources. I think I have found an "easy" way to do this. I was going to create a listview that displays the drawables , and the user would be able to pick one. I would then pass back , the path to this drawable resource, the paths would be hard-coded in. I then would set a bitmap to this drawable path. I was trying to do a simple test of this with just hard coded values, (no listview yet) but I do not get a visible bitmap back. I think it "works" , but maybe the bitmap is to small or not set to visible?
bm2 = BitmapFactory.decodeFile("/gds2/res/drawable-hdpi/feel_like_a_sir.png");
foreground_imageview.setImageBitmap(bm2);
Try to load your drawable in this way
bm2 = BitmapFactory.decodeResource(getResources(), R.drawable.feel_like_a_sir);
foreground_imageview.setImageBitmap(bm2);

Set Picture into RemoteViews

I have some SVGs in my assets folder and I need to dynamically set them in my widget (on an ImageView).
I am using this library: http://code.google.com/p/svg-android/
This library returns a Picture or a PictureDrawable.
The only methods I can see to use on RemoteViews are setImageViewBitmap which obviously takes a bitmap.
I tried looking for code to convert a Drawable to a Bitmap like this:
PictureDrawable pictureDrawable = svg.createPictureDrawable();
Bitmap bitmap = Bitmap.createBitmap(pictureDrawable.getIntrinsicWidth(), pictureDrawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawPicture(pictureDrawable.getPicture());
currentBitmap = bitmap;
But the bitmap is too small. When I create the bitmap in Illustrator I set the artboard size to 65 which is what comes through on the intrinsic width/height.
My widgets can be resized so the ImageView sizes are variable. Even if I set the width and height statically to some large number like this...
Bitmap bitmap = Bitmap.createBitmap(300, 300, Config.ARGB_8888);
then the resulting bitmap just has a bunch of whitespace below and to the right of a tiny image.
I guess I need to somehow draw the picture at a scaled up value as well as creating the Bitmap at size 300. Ideally I could figure out the size of the ImageView at runtime and set the proper sized Bitmap if I knew that. Is this the best approach and how would I do this? Perhaps there is a better approach I don't even know about?
I've not used android-svg but if it's using vanilla PictureDrawables, then it should be just a matter of not using the intrinsic bounds.
Try the following:
PictureDrawable pictureDrawable = svg.createPictureDrawable();
Bitmap bitmap = Bitmap.createBitmap(300, 300, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
pictureDrawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
pictureDrawable.draw(canvas); // do not access the Picture directly, that defeats the purpose
currentBitmap = bitmap;
In short, use the Drawable, not its Picture and set the Drawable's bounds to be the full canvas.
Have you tried createScaledBitmap?
createScaledBitmap()
I have tried svg-android and it has not worked for me for this very reason. Not to mention its severely limited feature set.
The point of using vector graphics is that I can generate images of any appropriate size to fit the UI View size. Which means the generation method must accept the size requirements at run-time, and not always use width,height declared in <svg> tag.
Hence I used the native implementation: libsvg-android, which exactly does that.
It directly renders to a canvas with given size:
long objId = SvgRaster.svgAndroidCreate();
SvgRaster.svgAndroidParseBuffer(objId, readString(mInputStream, "UTF-8"));
SvgRaster.svgAndroidSetAntialiasing(objId, true);
SvgRaster.svgAndroidRenderToArea(objId, mCanvas, 0, 0, mWidth, mHeight);
I ended up modifying the underlying Artboard size to be 300. None of the scaling up methods worked. So the final code I used was that which I originally posted:
PictureDrawable pictureDrawable = svg.createPictureDrawable();
Bitmap bitmap = Bitmap.createBitmap(pictureDrawable.getIntrinsicWidth(), pictureDrawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawPicture(pictureDrawable.getPicture());
currentBitmap = bitmap;
Once I had a 300x300 Bitmap I was able to set it into the RemoteViews using setImageViewBitmap .
This kind of defeated the purpose of using SVGs in the first place (at least as far as using them in widgets was concerned).
My problem was not the same as User117. Perhaps he did not name the outer layer 'bounds' as was required in the library. Either way, I managed to get the library working, albeit by having to modify the SVG Artboard size.
Hopefully with the increase in screen resolution Android will introduce SVGs as part of the platform soon.

Android BitmapDrawable recycling/re-use

In the code below I've got two bitmaps (I omitted the code for creating them as that's not relevant to my question) and I also have an ImageView in my layout. I make the ImageView display the first bitmap as a drawable, and then make it display the second bitmap, again as a drawable.
I'm aware that bitmaps can be recycled, my question is related to the "new BitmapDrawable" part, as I can't figure out exactly what a BitmapDrawable is. Is it just a reference or does it use up memory each time one is created? In other words, does the BitmapDrawable I create for bitmap1 need to be deleted/recycled before I create another BitmapDrawable for bitmap2?
Thanks.
Bitmap bitmap1,bitmap2;
...assume bitmap1 and bitmap2 contain valid bitmaps...
// get imageview
ImageView iv = (ImageView)findViewById(R.id.my_imageview);
// make the imageview display bitmap1
iv.setImageDrawable(new BitmapDrawable(getResources(),bitmap1));
// now make the imageview display bitmap2
iv.setImageDrawable(new BitmapDrawable(getResources(),bitmap2));
You should keep bitmaps as long as you need them. It is costly to create new bitmaps. GC will fire if enough memory not available and your app will stall for that time.
See this for efficiently displaying bitmaps
http://developer.android.com/training/displaying-bitmaps/index.html

Best way to animate programatically created bitmaps in android

I have a board game app that creates a lot (hundreds) of bitmaps, and constantly changes them as the game progresses. These bitmaps are created, not loaded from a resource... so they have no R.id to refer to.
I would like to animate some of them, e.g. a bitmap moving from one loction to another when a player taps to move it. What is the best way to do this?
Note, this is 2.1 and the bitmaps are drawn on a canvas via a matrix translate.
Make this function to get image from drawable folder
private Bitmap getImageBitmap(){
int resID = getResources().getIdentifier(uri, "drawable",
"a.b.c");
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), resID);
return mBitmap;
}
For set the image , where do you you want>
ImageView imageview01.setImageBitmap(getImageBitmap("name of bitmap");
if you want more about bitmap. then you may try this links.
http://developer.android.com/reference/android/widget/ImageView.html
drawable getResources().getIdentifier problem
setImageURI / setimagebitmap to fetch image from net and display in image view

Android: how to simply draw a bitmap on another bitmap

I'm new to Android dev and I'm having a hard time trying to do something which seems obvious to me: drawing little images on top of a bigger image.
Let's say that I have a 500x500 image and I want to draw icons at different locations. Icons are png files that I load with:
Bitmap img =
BitmapFactory.decodeResource(getResources(),
R.drawable.idIcon1)
My "background image" is a LayerDrawable.
Then, I am totally lost... Do I have to create a canvas ? How to draw on my "background image" my icons at different positions?
int positionLeft=0;
int positionTop=0;
Bitmap newBitmap =Bitmap.createBitmap(backgroundBitmap.getWidth(),bitmap.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
canvas.drawBitmap(backgroundBitmap, positionLeft, positionTop,null);
positionLeft=100;
positionTop=100;
canvas.drawBitmap(iconBitmap,positionLeft,positionTop,null);
imageView.setImageBitmap(newBitmap);
You're making simple things difficult. Just use a layout with android:background attribute, and then add ImageViews dynamically with the necessary bitmaps inside.

Categories

Resources