Reusing a bitmap

ukimiku

Active Member
Licensed User
Longtime User
I draw, through canvas c, into a (mutable) bitmap b. It gets displayed in image view i.

Now what I am trying to achieve is to resize bitmap b to get smaller or larger (user choice).

Any combination of commands I have tried has just resulted in another bitmap being created and drawn on top of the existing one. I can't have that as there may be many bitmaps created, which would use up too much device memory.

I have the feeling that the solution may have something to do with "recycling" bitmap b, but the post(s) I read on that topic have been eluding me. Do I have to remove the image view i from the activity? Do I have to set the reference to c, b, or i to "null"?

Thank you.

Regards,
 

ukimiku

Active Member
Licensed User
Longtime User
No, you can also use the ABExtDrawing library to load the bitmap right into the RGB565 format. But most of the transformations you're going to apply on it will convert it to ARGB_8888 again (there's probably a way to avoid this but I don't know it).

I see. My bitmap is a mutable one anyway, my code draws into it, it is not one loaded from an assets folder.

Thank you. Regards,
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
@thedesolatesoul: I need to determine the memory at runtime, as I have no way of knowing how large the user wants the picture to be. If s/he's got a powerful device, a couple of thousands pixels in each dimension would be quite feasible.

Thank you for the link. I will explore.

Regards,

The size can be roughly computed like this: width * height * color depth. The exact computation is done by my function BitmapSize in the Cache library, but it needs the bitmap to be loaded into memory.

Example:
1024 * 768 * 24 (typical color depth for a jpeg file) = 18 874 368 bytes
 
Upvote 0

thedesolatesoul

Expert
Licensed User
Longtime User
The size can be roughly computed like this: width * height * color depth. The exact computation is done by my function BitmapSize in the Cache library, but it needs the bitmap to be loaded into memory.

Example:
1024 * 768 * 24 (typical color depth for a jpeg file) = 18 874 368 bytes
Yes, but generally in Android most functions use ARGB_8888, so generally I just say:
Width x Height x 4 bytes/pixel

Unless you change the settings manually, then you know what you are doing.
 
Upvote 0

ukimiku

Active Member
Licensed User
Longtime User
Thank you both for your estimates/calculations for the picture size.

Over several dozens of resize operations, the app seems to have resized the globally allocated bitmap properly every time. Not a single crash or out-of-memory situation has occured.

Regards,
 
Upvote 0

ukimiku

Active Member
Licensed User
Longtime User
I did not load any picture. I created an empty mutable bitmap into which the B4A code drew mathematical pictures (programatically). After the picture has been drawn, the user can enter new parameters and have another picture drawn. Two of the parameters are the new_width and new_height of the new picture. The app then saves the picture to a file, and is ready to draw another one. The idea was to offer the user to create pictures that have a high enough resolution for subsequent offset printing.

In Globals I declare:
B4X:
Dim tb As Bitmap
Dim tc As Canvas
Dim tv As ImageView: triangle_view.Initialize("tv")    ' set to "tv" so the user's clicks on the picture can be intercepted
Activity.AddView(tv, 0dip, 0dip, 10dip, 10dip)   ' just a dummy position and size

Later, in my drawing routine, I have the following code (uses the Reflection library for recycling the bitmap-to-be-resized. "old_bitmap" is a Reflector):
B4X:
If tb.IsInitialized = True Then
   tv.Bitmap = Null
   tc = Null
   old_bitmap.Target = tb
   old_bitmap.RunMethod("recycle")
   Dim tc As Canvas
End If
   
tv.RemoveView
tb.InitializeMutable(new_width, new_height)
tc.Initialize2(tb)
tv.Initialize("tv")
tv.Gravity = Gravity.NO_GRAVITY
tv.Bitmap = tb
Activity.AddView(tv, 0dip, 0dip, new_width, new_height)

I am not sure anymore whether/why the tv.RemoveView and Activity.AddView(tv...) is necessary, but it works.

Regards,
 
Last edited:
Upvote 0

ukimiku

Active Member
Licensed User
Longtime User
Thanks for the idea for improvement. I have never used .SetLayout, but it's worth a shot.

I declare tv as canvas because before, I set the reference to "null". I remember having to deal with a null pointer exception, and put in the dim tc as canvas again. Can I get around that somehow?

Regards,
 
Upvote 0

ukimiku

Active Member
Licensed User
Longtime User
When I set canvas.bitmap = null, the app complained at runtime that I had to initialize the canvas or the bitmap first.

What to do?

Thanks & regards,
 
Upvote 0

ukimiku

Active Member
Licensed User
Longtime User
Yes, thank you. I cannot trace the dozends of code line variants anymore, and with them the order in which objects were declared... In-between it was a bit of a mess, and now I am happy with the results. I have even time now again to actually continue developing and prepare a nice animated intro, learning to use the Animation library for the first time... :)

Regards,
 
Upvote 0

ukimiku

Active Member
Licensed User
Longtime User
Hm, thanks for that pointer. This approach seems to be ok then.

I wonder, why do you have these lines:
__________________
_________
__________________
___________________________
in your signature?

Regards,
 
Upvote 0

thedesolatesoul

Expert
Licensed User
Longtime User

VB that is not what I understood. Erel said to re-initialize the canvas, not to to re-dim it. Those are two different things. Or am I missing something?
Although in this case it matters less whether you Re-Dim the canvas or re-initialize it, you just want to lose the bitmap.

For reference, read this thread where he says to only use one canvas object: http://www.b4x.com/forum/basic4android-updates-questions/18663-memory-impact-canvas.html#post107111
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
I'm currently writing a tutorial for beginners on how to conceive an application for B4A (I didn't find anything on this subject), with a very simple method and the pitfalls to avoid. There's a section in this tutorial dedicated to the common enemies (Application not responding, Out of Memory, Loading Time) and another dedicated to optimization. I will insist on bitmaps, because they are the main cause of Out of Memory and there are some misconceptions about them (it's obvious in this thread where there was a confusion between resizing a bitmap and resizing an ImageView). If one of you wants to say something on this matter for my tutorial, I'm listening.
 
Upvote 0

ukimiku

Active Member
Licensed User
Longtime User
I think it would be good to have a short working code sample in the tutorial. With simple variable names, and not much achieved, but to show how it works. Maybe some lines from the discussion here can be inserted.

Regards,
 
Upvote 0
Top