Xamarin Android Bitmaps Part 4 – Efficient Loading of Bitmaps

The fourth and final part of the Xamarin Android bitmap series, where we take a look at loading bitmaps efficiently.

Advertisements

This is part four of the bitmaps mini-series of posts. 

In the previous posts I discussed what bitmaps are, how they interact with Xamarin, how bitmap memory works in Xamarin, and how to clean up that memory with some helper methods. That’s all good stuff, and you absolutely should have a good understanding of it, but bitmap memory management only gets you so far if you are loading massive images that are far bigger than you ever need them to be, and that’s what I want to cover in this post, how to efficiently load bitmaps.

Bitmaps are big

Nice heading huh? Well, it’s true. Bitmaps are huge, take a standard bitmap for example. In the case of a 32 bit bitmap, which would give the bitmap an rgba channel, there are 4 bytes per pixel, making up the bitmaps color depth. If this bitmap is 1000×1000 pixels, you can calculate how big that bitmap is by taking 1000×1000, which equals 1 million pixels on screen, then multiplying that by 4, which is the number of bytes per pixel. In this case, 4 bytes per pixel, 1 million pixels gives us 4 million bytes, or 4 megabytes. Obviously that adds up pretty quick if you’ve got 20 of these things being loaded in, that’s nearly 1/10th of a gig just in bitmaps (4mb x 20 = 80mb).

All that said, the first, and by far the easiest way to make bitmaps get loaded in more efficiently is to not make a bitmap bigger than it needs to be, so if you have a png, jpg, bmp, whatever format it may be, you want to make sure that you are only making it as big as it absolutely has to be, so if that same 1000×1000 image really only ever needs to be 100×100, you’ve cut your memory usage down by 1/10th, which is a pretty dramatic difference. This will not just make your heap smaller, it’ll also mean faster rendering, because the CPU or GPU doesn’t have to process as many pixels to render your bitmap.

Lazy Loading

Lazy loading is an awesome concept to understand, as it is used across all different types of applications for all kinds of different purposes. Lazy loading is the idea that you only load something when it absolutely has to be done, my wife can attest to the fact that I tend to use lazy loading in day to day life for all kinds of things, dishes, laundry, trash, etc. There’s not much to discuss on lazy loading, as the exact way to go about implementing it can vary quite a bit just based on what you’re trying to do, so I won’t give any specific examples. That said, there’s TONS of information on lazy loading out there for probably anything you need to do, so I advise you take a look on the old internet.

Lazy loading helps your runtime performance in that less work has to be done up front, in favor of doing more work as the app runs, basically it distributes the same amount of work across a longer amount of time. It also benefits your heap because for, lets say, a list of items in an app that has images in each row, you only end up loading images that the user is actually looking at, rather than loading everything up front, so in the best case, you dramatically reduce the amount of heap memory getting used, in the worst case, you end up using the exact same amount of memory you would have used without lazy loading.

Downscaling bitmaps at runtime

This is probably the most effective way to efficiently load bitmaps, downscaling is the idea that even in the case where you have a 1000×1000 image, you just simply create a copy of it that is smaller and use that, I have some code that does this, and if this code looks familiar, that’s because it’s basically the same as the code on Xamarin and Android’s website for downscaling bitmaps.

....public static Bitmap LoadAndResizeBitmap(this string fileName, int width, int height)
....{
........BitmapFactory.Options options = new BitmapFactory.Options { InJustDecodeBounds = true };
........BitmapFactory.DecodeFile(fileName, options);
........int outHeight = options.OutHeight;
........int outWidth = options.OutWidth;
........int inSampleSize = 1;
........if(outHeight > height || outWidth > width)
........{
............inSampleSize = outWidth > outHeight ? outHeight / height : outWidth / width;
........}
........options.InSampleSize = inSampleSize;
........options.InJustDecodeBounds = false;
........Bitmap resizedBitmap = BitmapFactory.DecodeFile(fileName, options);
........return resizedBitmap;
....}

Again, I apologize for the horrible way I have to format this code, blame WordPress for that. I won’t explain every line here, but essentially what happens is we use the BitmapFactory class, which is a class that creates bitmaps. We then do some calculations to determine how to downscale the image and fill out the bitmap options, then we use those options when we reload the bitmap as a downscaled bitmap, and finally we return it. It should be noted, this code will also upscale bitmaps that need to be upscaled. Suffice to say, if you throw this code in a helper class, it will handle resizing bitmaps perfectly.

Third Party Libraries

There is one more way to efficiently load bitmaps that I will mention. For image heavy projects, I like to use a library called Picasso, available as a NuGet package under Square.Picasso. I won’t go into how to use it, as frankly it’s pretty simple to use and there’s plenty of resources on using it out there already, but if you want to just be able to load bitmaps into image views from a file or url easily, this library is…well, it’s just freaking awesome. There are other libraries as well, but I’ve never used the others so I can’t recommend them with any confidence, and frankly probably wouldn’t anyway because Picasso is so good. I would say though that you should limit using this (or any) libraries until you absolutely have to use them, or there is a significant gain to be had from using one of these libraries, because they do bloat your app, add dependencies, and give you more fault points in general.

Conclusion

That concludes the fourth, and final part of the bitmap mini-series. In the future, I do want to do some more posts pertaining to bitmaps, but not purely to bitmaps. For example, I have planned some image editing posts, things like applying grayscale, brightness adjustment, edge finding, etc. but in terms of this series on Xamarin Android bitmaps, I think I’m going to call this good. I hope you’ve enjoyed reading and got something out of it, if you have any questions, please comment below or shoot me an email and I’ll get back with you asap. If I missed anything you felt should have been included, or made any mistakes, feel free to let me know as well. Until next time.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

Advertisements
Advertisements
%d bloggers like this: