Raster images performance issue - android

We started using vector drawables in our Android application.
I have read about performance issues faced while using raster images in android applications.
Can anyone explain the reason why there is a performance issue ?
Is it okay to use plenty of vector drawables in an application ?
Thanks in advance !!

This isn't really android specific. It's more to do with different image formats. A raster image has a "fixed" size, in the sense that it is always comprised of the same number of pixels, which is one of the major factors in file size (and memory footprint once it's loaded). This also affects your ability to transform the image.
If you want to shrink a raster image, you have to drop pixels, which is necessarily a lossy transform (even though the smaller size makes it difficult or impossible to notice the lost data). To enlarge the image, you have to interpolate pixels: add data that wasn't there in the original image, which means the image will start to pixelate.
With a vector image, on the other hand, the data stored is not in terms of pixels. Instead it stores "paths" that instruct the computer on how to draw the image. These paths are size-independent, which means that its size can be increased or decreased with no loss of data or image quality. Since the size doesn't matter, only the data necessary to hold the paths (and other data) is stored in a vector image file. This means that the file is (generally) much smaller than the equivalent raster image and so takes up less memory when loaded.
Using a vector will mean your app takes less memory and is more easily adaptable to different screen sizes because android can shrink/expand your graphics to fit without losing any quality.

Raster graphics have more complexity to support images that cant be easily convert vectors like shapes. The technique behind raster graphics are uses pixels unlike vectors uses lines as we know path in Android.
So that raster images have more path elements that represents pixels. Android generates images by using these elements. Complex vectors are takes more time when trying to be generated instead loading a given bitmap.
As i know, You shouldnt be able to use raster in Android. It only supports vectors.
Good luck
Emre

Related

Do I Need Multiple Image Sizes (xxhdpi vs. xxxhdpi)?

Apologies in advance for such a basic question, but this is my first app and I can't quite find a clear answer for my situation. All the images in my app are stored in the drawable folder, I'm NOT downloading any images from the internet. All the information I come across when it comes to multiple image sizes seems to refer to the occasion when the app is fetching images from the internet.
So currently most the images in my app are one size, customized for the largest size - xxxhdpi. However, I understand the app is doing some work to "shrink down" those images for the xxhdpi size screens.
I'm having second thoughts about this one size fits all approach. I'm thinking that perhaps the app doing the work to shrink the image down might take up extra memory and negatively impact performance. I've been looking at the Android Studio Profiler and I've been trying to understand the Graphics Process when I look at the Memory Graph.
More generally speaking, is there a benefit to having the smallest size images possible, even for the xxxhdpi? For example, does it hurt (memory wise or in some other aspect) to use a .png image when I could use a lower quality jpg? Again, just to super clear, this is just in the scenario when the app has all of its images in the drawable folder. My app has options where players can change the game background and other images so I want to be sure I'm optimizing how the images for best performance. Thanks.
Memory. If you load a bitmap of x by y pixels, in memory that takes 4*x*y bytes. For a full screen image, you can expext that to be 4000*1000*4 or 16 MB. That's a good chunk of memory to a small device, which also tends to have less RAM. If instead it needed one at half the resolution, you would have 2000*500*4, or 4 MB.
Obviously this scales with size. The smaller your images, the less memory wasted. I wouldn't argue that you need to provide every size, but if you're using large images I'd provide more than one. Also, for anything that isn't incredibly complex (like icons) I'd consider vector images instead (although that's a CPU time vs memory tradeoff).
You mentioned png vs jpg. There's two things to consider there: apk size and image quality. JPG is smaller, so it will lead to a smaller apk size. PNG is lossless, so it will have higher quality (although whether that matters requires a human visual check- it matters less than you'd think on a lot of things). Interestingly it doesn't effect the amount of memory used at runtime, because both are held in the Bitmap object uncompressed.

Using fontawesome (icons) in game, in theory

The font-awesome icons are vector based, and from my understanding vector iamges are bad in apps since they are very big (in bytes), is this true
for fontawesome icons? In theory, could I use these icons in my game, not only for menu buttons and such, but also for actual game graphics?
I'm planning on doing a very simple game, and I'd hate to get stuck on the design part, not only the drawing of them, but I've had trouble with scaling of
images (according to screen size) in the past, vector images would solve this.
I realize icons are not optimal for game graphics, but would it be usable?
Vector based images are usually smaller than bitmap based images, because they just contain an abstract description of the image content, that can be scaled to virtually any size.
Your graphics card does not understand these kind of image formats though. You would have to convert them to a bitmap based format first, which means you have to set a specific size for the resulting image.
LibGDX offers the FreeType extension, to convert TrueType font files (.ttf) at runtime to a BitmapFont with a specific size, which can then be rendered.
That way you will be able to generate icons on the fly for the correct display size, without having to ship many different versions of them, for different resolutions.

How to find out maximum bitmap size to be loaded into an ImageView? [duplicate]

I would like to know if there is any kind of limitation on the texture size that can be used in any Android Opengl Es 2.0 projects. I understand that having a huge texture of size 4096x4096 is a bit meaning less as it is rendered on a small screen. But What if the requirement is to switch between many textures at run time? And If I want to have a texture atlas to do a quick single upload instead of multiple smaller texture upload. Please let me know your ideas in this regards.
Also I am sure there has to be a limitation on the size of image that can be processed by a device, as the memory on the device is limited. But I would like to know if it is resolution based or is it size based. I mean if a device has a limitation of 1024x1024 image size can it handle a compressed texture of size 2048x2048 that would be of same size approx as uncompressed 1024x1024.
Also please let me know on an general basis usually how much the limitation on texture size or resolution normal devices running android 2.2 and above would be.
Also please let me know if there are any best practices when handling high resolution images in opengles 2.0 to get best performance in both load time and also run time.
There is a hardware limitation on the texture sizes. To manually look them up, you can go to a site such as glbenchmark.com (Here displaying details about google galaxy nexus).
To automatically find the maximum size from your code, you can use something like:
int[] max = new int[1];
gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, max, 0); //put the maximum texture size in the array.
(For GL10, but the same method exists for GLES20)
When it comes to the processing or editing of an image you usually use an instance of Bitmap when working in android. This holds the uncompressed values of your image and is thus resolution dependant. However, it is recommended that you use compressed textures for your openGL applications as this improves the memory-use efficiency (note that you cannot modify these compressed textures).
From the previous link:
Texture compression can significantly increase the performance of your
OpenGL application by reducing memory requirements and making more
efficient use of memory bandwidth. The Android framework provides
support for the ETC1 compression format as a standard feature [...]
You should take a look at this document which contains many good practices and hints about texture loading and usage. The author explicitly writes:
Best practice: Use ETC for texture compression.
Best practice: Make sure your geometry and texture resolutions are
appropriate for the size they're displayed at. Don't use a 1k x 1k
texture for something that's at most 500 pixels wide on screen. The
same for geometry.

In what format should I keep the resource images for my app?

I am building a simple wallpaper app. I store the wallpaper images(.jpg) as resources in the res folder. I show the user a grid of thumbnails, which I store separately as resources(.jpg) too in res. I want the scrolling through this grid to be smooth and fast. My question is that when I load the gridview using the adapter, In the getView method I convert the resource to a bitmap and then load it in each imageView in the Grid. Would it be faster if I stored the thumbnails as .bmp in the res folder in the first place? Also I've manually created the thumbnails, rather than manipulating the large wallpapers making them at run-time. Each thumbnail is made to scale to width of 120pixels and the grid consists of 120x120 imageviews. So I was wondering how I could load these images quickly and effectively?
Im setting the adapter to the gridview inside Asyntask, but I dont notice an improvement.
Jpeg, which is lossy image compression, usually provides the best quality to size trade-off.
If you're trying to store high quality images then you're almost certainly going to want to use Jpeg.
PNG does has useful features such as allowing you to work with transparency, and, for simple block colour images outputs really small file sizes.
However, the moment you start to create photo quality images, such as wallpapers, as PNG, you're going to see monster file sizes, which on a mobile device is not going to be much fun or much appreciated by the end user.
Also larger files tend to require more system resources (CPU time and RAM), and on a mobile devices these resources are at a premium.
I would suggest that perhaps for thumbnails you might use PNG, and for the full size image use JPEG, but you might do well to see which creates the smallest file, because that is likely to give an good indication of the rendering efficiency i.e. it takes little resources to render a 800b PNG.
Changing your images to the bmp file format could make a little improvement in performance (because JPG is a compressed bitmap image that needs to be decompressed when rendered), but it's usually not worth the major increase in filesize.
I would recommend using the PNG bitmap format because it's light in both rendering and filesize.
As for the rendering in the ListView, you might want to take a look at this question and this code project.

Android high resolution image processing

From experiments and from reading other posts like this one it seems that it's hard to process high resolution images on Android because there is a limit on how much memory the VM will allow to allocate.
Loading a 8MP camera pictures takes around 20 MB of memory.
I understand that the easy solution is to downsample the image when loading it (BitmapFactory offers such an option) but I still would like to process the image in full resolution: the camera shoots 8MP, why would I only use 4MP and reduce the quality.
Does anyone know good workarounds for that?
In a resource-constrained environment I think that your only solution is to divide and conquer: e.g. caching/tiling (as in: tiles)
Instead of loading and processing the image all at once you load/save manageable chunks of the image from a raw data file to do your processing. This is not trivial and could get really complex depending on the type of processing you want to do, but it's the only way if you don't want to comprise on image quality.
Indeed, this is hard. But in case image is in some continuous raster format, you can mmap it
( see java.nio.ByteBuffer ) - this way you get byte buffer without allocating it.
2 things:
Checkout the gallery in Honeycomb. It does this tiled based rendering. You can zoom in on an image and you see then that the current part is higher res then the other parts. If you pan around you see it rendering.
When using native code (NDK) there is not a resource limit. So you could try to load all the data native and somehow get parts of it using JNI, but I doubt it's better then the gallery of honeycom.

Categories

Resources