I am trying to place an image as background in my TextView. I want the image to get changed by pressing a button. At the first image gets loaded but when I try for next time it says OutOfMemoryError.
My Code:
int [] Quo = {R.drawable.wallpaper10,R.drawable.wallpaper2,R.drawable.wallpaper3,R.drawable.wallpaper4};
txtView.setBackgroundResource(Quo[j] );
It works perfectly if i give
txtView.setBackgroundResource(Quo[0]);
I am new to android development please help me resolve issue.
image memory usage is based on multiple things:
resolution of the image.
where the image file is located (the density qualifier of the drawable folder) compared to on which screen density the app is running on.
which bitmap format you used .
whether or not the image is 9-patch image.
so , for example, if you have a 100x100 image, and the file is in "drawable-mdpi" yet it runs on an xhdpi device , and the bitmap format is the default one, and it's not a 9-patch image, the bitmap would take:
100*100 * 4 *4 = 160,000 bytes.
the 100*100 is because of the number of pixels for width and height.
the first 4 is because on the default bitmap format, each pixel takes 4 bytes.
the second 4 is because the density is 2 times larger in both width and height (2*2=4).
so, if this is the only code you show, i think you use too much memory because of your images.
one thing that you could do is to downsample them.
Related
I am saving three imageviews to one bitmap after the user edits the image(s). The problem is that once the final result is saved, the resulting saved image doesn't always look the same on different screen resolutions.
On my phone, which is a Asus Padfone X, the saved image comes out perfectly. On my partners phone, Note 6, the positioning of the saved images on the resulting bitmap are off. (See example below)
I am using the following code to save the imageviews to a single image:
Bitmap mainBmp = backImage.getDrawingCache();
Bitmap centerBmp = centerImage.getDrawingCache();
Bitmap handleBmp = handleImage.getDrawingCache();
Canvas canvas = new Canvas(mainBmp);
canvas.drawBitmap(centerBmp, 17, 95, null);
canvas.drawBitmap(handleBmp, 17, 85, null);
Which saves properly on my phone but not one with a bigger screen/higher resolution. How do I ensure the resulting saved image looks the same regardless of the device it is saved on?
EXAMPLE OF DIFFERENCE
You need to scale. For example, lets say that device 1 is 500x1000 pixels and device 2 is 600x1200. Lets say the bitmap is 300x400 and starts at an offset of 30 pixels in x and 100 in y.
The bitmap needs to grow in size by the ratio of the two screens sizes. So it would need to be 300*(600/500) pixels wide and 400*(1200/1000) pixels big. The offset would need to scale as well- to 30*(600/500) and 100*(1200/1000).
Please note that when scaling you may get stretching, pixelation, and other image defects. The more you stretch the worse it will be. Shrinking can also give defects, but these tend to be more minor.
This is the simple case- the two screens I gave have the same aspect ratio (ratio of width:height). In the case of different aspect ratios, you need to choose:
1)Keep the aspect ratio of the image the same. This will mean you'll have blank space in 1 direction, but the image won't be effected.
2)Allow the aspect ratio of the image to change. This will leave no blank space, but will skew the image.
For #2, use the same code as above. For #1, figure out which dimension needs to scale the least, and use that to scale x and y.
It is not possible to scale from any size phone to any size phone without any defects on a generic image. You'll have to choose between the two options above.
I also found that if I instead use imageview.getWidth() and imageview.getHeight(), I can position each "layer" where I need it to be no matter the screen size. I tested this method on a small android device all the way up to a tablet and the saved image came out perfect across all devices.
What I did was determine the pixel size of each image("layer") using Photoshop. I then used an online px to dp calculator/converter to determine the correct dp size of each layer. I set specific dp width and height for each layer in the layout. For each layer I needed to save to the main image, I calculated the x and y dimensions by taking the mainimageviews height and width and subtracting the pixels needed from the edge to the respective edge of that layer. Through trial and error, I ran the app a few times to get the exact positioning of each layer I wanted. The result of the saved image was exactly the way it looked to the user. Hope this helps someone else in the future.
I have 270 x 2693 pixel image in drawable folder . When i try to set that image in imagview i got Bitmap too large to be uploaded into a texture warning.
Image sets perfectly in android device < 4.0 but not sets > 4.0 device.
Please help me to resolve this issue.
Code
<ImageView
android:id="#+id/imageView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:contentDescription="#string/name"
android:src="#drawable/hindi" />
Here hindi is a image in drawable folder and its size is 270 x 2693 pixel.
Problem
This problem is usually related either to OpenGL maximum texture size or the Device Memory. The full error you are getting is probably something like
W/OpenGLRenderer(12681): Bitmap too large to be uploaded into a texture (270x2693, max=2048x2048)
Memory is generally the problem with a large scale image but in your case 270x2693 is 727110 pixels. If you are in RGBA, it's 4 bytes per pixel so 727110 * 4 = 2908440 bytes, which is approximately 2,7 megabytes. That should fit on any devices.
Thus, your problem is probably related to OpenGL. What might happen is that the Android device > 4.0 you are testing on detect that your image is too large for OpenGL and resize it for you, while older devices don't.
Edit:
In my case, the problem is that my 640x1136 splash image seems to get rezised automatically to a 1280x2272 image size to fit my device huge screen. Which also triggers the error message you are having.
If you get this error further on, it is related to the dpi that is used to load the image. As you will find on Android reference, device will load image regarding their dpi which can alter the size of image that is loaded in memory.
Solution
You don't have much choice other than detecting the device size to
load the image properly.
See how to load large bitmap in memory.
You can also use different image size for different device dpi which
can be automatically selected from the Drawable folder by Android.
See the How to support screens which tells you how to setup your
folder.
As other stated, use a smaller image or reduce its size.
Related informations
I suggest you have a look there if you need to support multiples screens.
Android also collect data which are updated every 7 days on Screens size among their users.
Also have a look to this interesting answer which points out a good website to understand Image Size in memory.
Finally, if you are already using OpenGL in your app, have a look to this answer which shows how to detect the max OpenGL texture size.
Why not reduce the size of the image? If you don't want to do that, then rather than specify the bitmap in the XML, load it from program code, and scale it to fit the display. See this guide for more information on loading large bitmaps.
try use this code
int[] maxTextureSize = new int[1];
GLES10.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, 0);
maxTextureSize stores the size limit for decoded image such as 4096x4096, 8192x8192 . Remember to run this piece of code in the MainThread or you will get Zero.
I have a ListView, with about 50 rows. Each item has an image. Sometimes, the images are downloaded, but sometimes, I just show a specific image from app resources.
Issues:
Sometimes I just show about 20 images from resources for my items
that all of the are the same image .it means I just show an image
for 20 rows that all the same. is it loading a bitmap an take the
amount of ram for each item ? or it just load an image and show it
for other items ?
The imageview's size for each item is 100*70 dp . so I want to do
something , like re sizing or reducing the image dp before I bitmap
them and show them in my app, so I can reduce the amount of ram they
takes . Is it possible ?
Thanks
Showing same image multiple times
If you set all the image as same Drawable (variable), you got from resources, Only 1 bitmap Drawable resides in RAM. Also, ListView recycles its rows, it does not really create 20 rows with all 20 Bitmaps loaded in RAM.
Setting DPI of images
BitmapDrawable class can automatically decide DPI for rendering, that's why it asks for Resources in its constructor. Or you can call setTargetDensity(int) later. NOTE: Changing DPI is not exactly same thing as Scaling an Image.
Loading scaled down images
This will definitely save RAM, Read Answers on how to load scaled down images.
I have an activity that set a background image. And it causes OutOfMemory in some devices when I keep enter and leave this activity.
Suppose I am using x-hdpi device. Is that I would use up more memory if I put a image in hdpi bucket than put in x-hdpi bucket because the image need to be scaled up if I put in hdpi bucket? Actually, how to determine which bucket should I put the image to?
And Is there any way to avoid OutOfMemory of this case?
I try to call recycle and setImageResource(null) in OnDestroy. But when I enter that activity again, I would have exception "cannot draw recycled bitmap".
Answer to Second Question.
Before Decoding image and setting to background you should resize image to Avoid Memory Overflow Error. This Error generally comes when we load image inside Memory. See how to Display Images Efficiently
Answer to First Question.
Putting same image to different folder will not cost memory as if you show LDPI image to HDPI device it will stretch but will take the same memory(All though it will look weired). But if your designer make Image differently for each density then image size will differ then it will take some more or less memory
Actually i am developing one application, where my requirement is like i have to scale large size images to some predefined size as per user selection. eg,Suppose i have an image which is of 1Mb and user select it to convert it into an image of size 100kb then i have to resize that image to 100kb.
last one day i am trying to achevive this with Bitmap APIs but i am not able to achieve the exact size what user want. Sometimes its very large sometimes very small. So please if anyone knows how to resize image in android to exact size(which is changing as per user selection).
Please help me out in this.
If only the file size matters, you will want to use an image file format that does not use compression. You should be able to take an image with attributes such as width, height, bit-depth, and so on and calculate the expected file size for such an image.
So, using such a file format you start with your original image and you have
File size = width x height x bit depth + metadata/overhead.
I assume you want to maintain the original aspect ratio also. In that case, you can probably just figure out the % reduction in file size from the current file size, and multiply the width and height by the same %. Scale your image using a bitmap image manipulation API and then save it. It should be close to the file size you are looking for.
Specific to the Android Bitmap api you can use getByteCount() to determine how many bytes the image currently takes up. You can also use getConfig() to determine how many bytes per pixel.
So, your final goal file size converted to bytes divided by the number of bytes per pixel, gives you the number of pixels you are allowed. Number of pixels allowed divided by the number of pixels in your current image will give you the scaling factor. Use the scaling factor and scale the image keeping the current aspect ratio and you should have a bitmap with a number of pixels close to your goal. Then save in a file format that does not use compression.