I implemented a RecyclerView in one of my Activities.
I use a customized RecyclerView adapter to load data from a SQLite Database (using Room and LiveData-structure) and display it in the view.
All of the rows have a large ImageView where I want to show a Drawable (just a .png). To do that I first tried to use the approach written on the official Android Developers site but it did not work well for me.
Therefore I am trying to use Glide as a library recommended by Google.
I have 16 drawables in my project. They all have a scaling between 800x800 and 1920x1080 pixels.
In my adapter I load the data from my database and based on the drawable id, the image as well (so there is no image data stored in the database; I did this previously).
Unfortunately my App cannot handle that amount of image cache which leads to an OutOfMemoryError exception. That's why I used
android:largeHeap = "true"
in my Android Manifest.
I know this is not a good solution and I also know that there has to be a way to use less memory for such a small amount of pictures.
In Glide I use
GlideApp
.load(R.drawable.my_drawable)
.fitcenter()
.into(myImageView);
But unfortunately the image does not get shrinked or smaller. I thought that Glide can scale the image based on the size of the ImageView, screen size and so on.
What am I doing wrong? Is there a better way to use less memory without fixed scaling so that my pictures not become ugly?
EDIT:
I first stored my images in the basic "drawable" folder in my project structure (copy and paste).
My second approach was the gimp-android-xdpi addon which exports images or icons for any android density (mdpi, hdpi, xhdpi etc.). But this did not help either.
call override(horizontalSize, verticalSize).
This will resize the image before displaying it in the ImageView.
I've been having problems with large images being resized for UI use in Android.
Look at this image, it's an ImageView:
The original image (That arc is a progressbar) is around 10 times bigger than what you see here. In UWP (Windows Platform) we had no problem using a very large image, but here in Android, I beleive it's the Nearest Neighbour method used for fitting images into UI elements, which as you see, causes sharp edges.
Is there any way to switch it into another method? Like Bicubic? It happens in all Android versions I've tested (4.1, 5.0, 6.0).
Just to mention, I'm using Xamarin 4, which I don't beleive as a contributing factor here.
No luck searching through the internet, I'm afraid I'm the only one having this problem.
Thanks.
As mentioned above, you should prefer to use vector image instead of pixel image.
But if you have to use pixel image, maybe you could use BitmapRegionDecoder to decode lines of image and write your own resample algorithm(like Bilinear Interpolation, it's much better than the Near Neighbor) to resize the image, typically in JNI side.
Another possible way is to use "filter" parameter while calling Bitmap.createBitmap method as your original image would not cause OOM issue, just set it to true, it works to reduce the artifacts.
You should use Vector Images instead of Bitmap Images.
Bitmap x Vector
A bitmap represents an image by a series of colored pixels. Whereas a vector image is represented by geometric shapes (lines, curves) using colors.
The main utility of a vector image is allowing to scale without losing definition.
I have a published app that is crashing at startup on Android N when the newly introduced Display size OS setting is set to too large a value.
When I look in logcat, I see the following message:
java.lang.RuntimeException: Canvas: trying to draw too large(106,975,232 bytes) bitmap.
I've traced the issue to an ImageView in my first Activity that shows a nice big background image. The image in question is 2048x1066 and is in my generic drawables directory, so no matter the density, this image will be used.
Everything works okay when the Display size setting is Small. But when I go up to Default, it stops working. If I then swap the image out with a smaller one, it works at Default, but if I go up to Large, it stops working again.
My guess is that adjusting Display size up causes your device to behave like a physically smaller device with a higher pixel density. But I don't understand what I'm supposed to do here. If I put in progressively smaller images for progressively higher resolutions, it won't look good on actually large displays. Or am I not understanding something?
Any pointers would be greatly appreciated.
I my case, moving the (hi-res) splash bitmap from drawable to drawable-xxhdpi was the solution.
I had the same problem. I didn't suspect my splash screen to be the problem, since it is displayed when the app is started, but it turned out the splash screen is the problem.
The splash screen in my case has xxhdpi resolution, and it was mistakenly placed in the drawable folder, instead of drawable-xxhdpi. This made Android assume the splash screen had mdpi resolution and scale the image to 3*3 times it's required size and trying to create a bitmap.
I solved the problem after adding the below code into the Manifest file's application tag in between android: lines.
android:hardwareAccelerated="false"
I don't know would it help some one, but I'll just leave it here.
In my case - problem was only on Sumsung devices with Android 7, and problem was in splash screen proportions. after changing height to 1024 px - everything works fine
Move your image in the drawable to mipmap-xxhdpi.Your image is in bitmap format so you should put your image in mipmap folder,then it will work
There are some scenarios where Original Bitmap needs be Drawn into ImageViews, Photo Editing apps etc...,
as bay mentioned above setting
android:hardwareAccelerated="false"
will Cause bad UI experince, You can set hardwareAccelerated Only one selected Activity where high res image to be drawn
<application android:hardwareAccelerated="true">
<activity ... />
<activity android:hardwareAccelerated="false" />
</application>
Try to use Bitmap.Factory class, this link will help you
Loading Large Bitmaps Efficiently
if you use Picasso change to Glide like this.
Remove picasso
Picasso.get().load(Uri.parse("url")).into(imageView)
Change Glide
Glide.with(context).load("url").into(imageView)
More efficient
The icon files are too large for Android to efficiently and smoothly load. Android recognizes this with its smart algorithms.
You can resize the icon files using Final Android Resizer by asystat. Resize them to "xhdpi" or lower.
Place the resized photos in drawable or overwrite over the existing large icon files.
Then, you're done.
if you are using glide and you are loading 1k of images at a time or some images then it is issue of glide or whatever you are doing to use to set the image view. you can resolve it just by applying scale type in glide.
In my case, I just changed the canvas of image which is used in the background using Paint3d(or you can use any other). Here I am sharing a screenshot just go through it.
it is solved by resizing the images to a lower size.
Need to add Manifest file's application tag in between android: add below lines.
android:hardwareAccelerated="false"
Just an addition to the Johan Franzén's answer, maybe it's a good idea to not only add drawable-xxhdpi density folder, but also add another density folder.
So whatever the android version and size, your app can prepare the image source with the right size :
Change your folder view on the top left from Android to Project
Go to YourProjectFolder folder > app > src > main > res
Prepare the original image with your best resolution, and split it into each folder size automatically. You can do it in Baker
Then create a folder with another density, namely:
drawable-hdpi, drawable-ldpi, drawable-mdpi, drawable-xhdpi, drawable-xxhdpi, drawable-xxxhdpi
Put each image into the appropriate folder
i solved the problem by simply changing the image extension to .png extension, and it worked just fine with me.
I have a custom view where normally I was using .png files to draw onto in a canvas and that worked fine but now my requirements are to use .gif files and for some reason the same code will not work. Is there something specific about .gif files that doesnt allow android canvas objects to draw on bitmaps made from them?
Apparently you cannot draw on a canvas created from a .gif file. Once I was able to convert the .gif to .png I was able to draw on the canvas again.
Actually, I can draw GIF files on canvas, but all transparent colours turn into white! I assume it is just a bug, related to the new parameter inPremultiplied in Bitfactory.Options which probably was not tested properly.
I am really frustrated with that, since now I have to replace GIFs by PNG in all my previous applications. (Fixing the bug in the following version doesn't make any difference, since there will still be models, not supporting GIF transparency.)
Indeed GIF file has it own advantage. It doesn't support alpha or true colour, but it has transparent index which in many cases is what actually needed. If you want PNG files to be not crucially bigger in size than GIF (I assume this is the main reason for using GIF instead of PNG), convert PNG files from true color to index (colormap) format (most of graphic editor, including GIMP and Photoshop support that), which works OK with KitKat. You will still lose size, but no mare than 1%.
My Problem: Only one image will actually load from the assets folder. I have all the images there and when I try to access any of them I don't get an error. By actually load I mean it shows the image on the screen. When I load the other images the whole screen comes up white.
In every instance I am loading the whole image to the whole screen.
If I were to put the image as a fourth its size in the middle of the screen then there is a white rectangle there. The image is supposedly in the .apk because I don't get an error for the game trying to find it. However if I were to load this one image then everything words fine.
The one image that works find is a .png image and I tried to load the others as a .png but it does not work.
Any advice on where to start?
I load the images through the AssetManager.readAsset() as an input stream and then use the bitmap factory to get the image as a bitmap. Afterwards I load the bitmap into open gl and draw the region I want. However, the problem is only my first image I ever started using works at the moment. Could there be something wrong with a file that eclipse generates?
Some png bug android.
Just try to open them and save them with gimp. Sometimes it solves the problem.
Finally found the solution.
Turns out that one image that worked had a bit depth of 32 and the other ones only had a 24 bit depth.
The solution is to open up the image in gimp, add an alpha channel (makes it 32 bit), and save it as a .png file. Then read the details and it should say it is 32 bit.
Thanks guy! :)
Also note that images have to be by power of 2. For example it needs to be 1024 by 1024.