Why are ?Images Compressed when Displayed on Android Phones/Emulator? - android

Essentially I want an HD background on a layout, but instead of being a pristine image, it shows up extremely compressed.
Example:
Source Image:
Android Emulator version:
I thought maybe that it was just the emulator, but it looks that bad on the phone itself. I know these are high quality Samsung Galaxy S phones (these are the ones that came with Avatar preinstalled after all).
Does anyone know how to load images without compression? Source files are uncompressed pngs.
here's the code for what it's worth:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:weightSum="1" android:background="#drawable/background" android:id="#+id/blank">
</LinearLayout>

Figured it out: The problem is the image is automatically converted into RGB565 colorspace from AGB888. To prevent this, make sure the image has an alpha channel and is in a "raw" directory instead of the "drawable" directory.

The aapt may compress images when it builds the apk, but that compression is supposed to be lossless. The problem is probably somewhere else. Here are two possibilities.
If your image resource is being loaded from res/drawable on a device (or emulator) that is not mdpi, then it will be scaled as described here. One solution is to put the resource in the res/drawable-nodpi folder. Another is to provide several, density-specific images.
Another problem will arise if your background image does not match the size of the view. The view will automatically scale the image to fit the view size. You can prevent this by defining the background as an XML Bitmap with a gravity set to something that does not scale (such as center).

Related

"Canvas: trying to draw too large bitmap" when Android N Display Size set larger than Small

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.

How to prevent a drawable from becoming blurry?

When i copy-paste an image to the drawable file, i get one image with the original resolution. When i use the New--ImageAset way i get a lot of images for different screen densities but they are all blurry, even xxhdpi! How can i have the different densities inages without this problem?
Im surprise i didnt noticed it before!
I read this but it hasnt helped me
Android ImageView blurry?
http://developer.android.com/guide/practices/screens_support.html
Any advice am i doing it wrong?
EDIT
I tried the AndroidAssetStudio but it still happens
Before
After (xxhdpi)
Cant i get it to be the ldpi and then make it scale up from it or something?
You can create your image in different resolutions using Android Assets Studio. Then, copy paste the image to the respective folder. This will give you a proper image, without blur.
There is a plugin exactly made for the same purpose. You can use that plugin to make different sizes of the same image. You have to copy/paste a single image in drawable folder. Then right click drawable folder and select
NEW>Batch_Drawable_Import. Select the size for your image and it will itself make the other sized images for you.

Using vector images to scale for app platforms

Images in apps come in many shapes or sizes, but to save space and editing time is there a way to use scaleable vector images?
Ideally I would have one vector image at middle resolution, I could then detect the screen size and scale the vector how I need and add the background using some custom gradients.
I'm using titanium for this.
Titanium doesn't yet support vector graphics, though it is available in native Android code via Shape Drawables. There is a third-party SVG library available for Android SDK.
For Titanium, branch the code based on the device screen size (Titanium.Platform.DisplayCaps), and find an image that works with decent performance on the device.
You can use PNGs with transparency and apply a background color to your view object.
I've found away round making different sized drawable:
Basically just one have folder called drawable within the res folder.
Make your artwork in what ever you use but make it large (at least 1080p for future devices).
Save the image's as PNG within the drawable folder but save them large. (IE at least 1000x1000)
Write a function that loads in the PNG but scales it (according to screen size & percentage of what size you want the drawable to be. So 20% of 800px width is 120px). I've managed to do this bit with 30ish lines of code, can't paste my code since I'm not on my working machine.
For me this has worked across all my apps for all devices, I've not had a single crash yet (1000's of installs, including Live Wallpapers).

Confusing PNG banding solutions

I've run into issues with banding of my PNG files. Digging into the problem has yielded two solutions. Both make sense individually, but together they don't. The solutions I've discovered:
1) Move the PNG file into the "raw" folder. This prevents AAPT from "optimizing" the image which results in banding.
2) Change the pixel format of your Activity's window to RGBA_8888 (i.e. in onCreate add this line "getWindow().setFormat(PixelFormat.RGBA_8888)"). On Android 2.2 and lower the default pixel format is 16-bit (565).
I have tried both of these and they correct the banding effect in my images, however now I am even more confused as to what Android is doing.
On the one hand, if I leave my PNG in the drawable folder it is "optimized" which results in a banding effect in the image. It magically goes away when I change the pixel format to 32-bit. If the image was "optimized" though, I would have expected the banding to remain.
On the other hand, if I move the PNG to the raw folder it will retain the nice gradient and display nicely even though the pixelFormat is supposedly 16-bit.
If anyone has any insight into what is going on I would appreciate it.
Thanks,
-Dan
I believe its quite simple :
You have to think of the pixel format of your Activity(RGBA_8888) as a DEFAULT optimization for your bitmaps.
If it is not set, then prior to 2.2, by default it will compress your bitmap to RGB_565.
But if you were to create programmatically a bitmap and set it to RGBA_8888, then it would be used as such by the app.
Same applies when you put your bitmap in the raw folder : Even though the default PixelFormat is set to RGB_565, the activity will use it as it is without "optimizing" it.
When you put your bitmap in the raw folder it will not be compressed at all and used as is even though the default PixelFormat is still RGB_565.

Android Textures appear unclear/fuzzy

I'm having trouble making my texture rendered correctly in my applications.
the artwork I use is precise and already scaled and the right size but when I render it on phone suddenly my texture are not as clear/precise as the original artwork and I can't figure out why.
has anybody had this issue before?
This is because android will compress all resources that are not placed inside /res/raw/
http://developer.android.com/guide/topics/graphics/2d-graphics.html
Note: Image resources placed in res/drawable/ may be automatically optimized with lossless image compression by the aapt tool. For example, a true-color PNG that does not require more than 256 colors may be converted to an 8-bit PNG with a color palette. This will result in an image of equal quality but which requires less memory. So be aware that the image binaries placed in this directory can change during the build. If you plan on reading an image as a bit stream in order to convert it to a bitmap, put your images in the res/raw/ folder instead, where they will not be optimized.
This might also happen if you use linear filtering in your texture, make sure that texture filters are GL_NEAREST for GL_MIN_FILTER and GL_MAG_FILTER.
Ok I finally figured it out
the problem I was having was coming from the default compatibility mode of android
I had to add this to my manifest

Categories

Resources