I have a custom ImageView that covers the whole screen. The image is sourced from one of the drawable folders, drawable-hdpi, drawable-xhdpi, drawable-sw600dp etc. and there are separate images for each density bucket.
So far, the application works fine on xhdpi and hdpi devices, the problem occurs when I test it on a Nexus 7. The image stored in the sw600dp folder has a size of 1600x1600 and should be enough to directly draw on the screen (without scaling), however when I run the app, the screen turns out to be completely blank and I get the following warning:
03-04 16:25:46.338: W/OpenGLRenderer(25457): Bitmap too large to be
uploaded into a texture (2130x2130, max=2048x2048)
For some reason the 1600x1600 bitmap is scaled to 2130x2130 although I have not manually scaled it anywhere (no matrix postscale or scaleX/scaleY applied)
Any thoughts on why this might be happening? Please provide a solution along with the explanation of why this might be happening.
Since Nexus 7 is tvdpi, it scales every image to 1.33 of the original value. So 1600 becomes (1600*1.33)= ~2130. It wont display it from the sw600dp folder.
More Info:-http://developer.android.com/guide/practices/screens_support.html
You can use the same image which you are using for every other 7 inch tablet ( i.e. of resolution 1024*600 ).
I want to share some info about error you are getting..
According to Romain Guy (Android framework engineer):
When using hardware acceleration, there is a limit to the size of a
texture. When you render a bitmap, it has to be uploaded to an OpenGL
texture first. Your bitmap happens to be bigger than the maximum
texture size on Xoom (2048x2048.) You need to use a smaller bitmap or
split it into several bitmaps.
Other SO Links may be helpful to you : click here1, click here2
Git: click here
Update: This answer only tells why error is happening (becauseof texture size limit) sorry it's not a full answer for why 1600x1600 bitmap is scaled to 2130x2130!!
Related
I'm trying to make an activity with an image that is the same height as the screen. I tried going to easy route, and just using a really big image and then scaling it down within the app, but when I run it on a device with a smaller screen, I get an error saying the device ran out of memory. I was hoping to make several drawable folders for each dpi (drawable-mdpi, drawable-hdpi, etc.). I looked up the pixel dimensions for splash screens, but when I resize my image to fit those dimensions (https://stackoverflow.com/a/15744389/5909429), the image only fills about half the screen on my smaller device.
What dimensions should I actually use, or am I using the drawable folders wrong?
[...]or am I using the drawable folders wrong?
Yes and no. I don't know about any "perfect" values for your picture dimensions, and I doubt that there are any, due to the fact that there are too many different phones to support.
The usage of dpi ensures that everything has the same size. If you were to put a ruler on your screens on a xxxhdpi and a ldpi device, both pictures would be the same size. This is dpi.
What you are trying to do is filling a phone screen. This has not much to do with dpi, but is about the actual pixel size of the screen. If you have a 1920x1080 phone display, you want an image with the same resolution. This does not say anything about dpi or screen density, and it has frankly nothing to do with it.
To properly scale down your image—and not running into OOM—you can either use a designated image loading library, like Glide, or Picasso, or you can take a look at BitmapFactory which lets you supply a inSampleSize to load the image in the size needed yourself. The official documentation can be found here at Loading large bitmaps efficiently.
I calculate inSampleSize to use Bitmap decode method to resize large png files.
When creating a this new bitmap and Log info it's width and height with .getWidth() and .getHeight(), its pixels count has grown by 3 relative to its original size.
code: from line 121-204
https://github.com/abisai1221/android-bitmaps/blob/master/png%20to%20bmp
all help is greatly appreciated.
I would bet on screen density being applied. When you load bitmaps from resources, you have to put them in right drawable folders, because Android will automatically scale them to match your phone's screen density. Each folder should contain only images for one specific density. For example, if you have a high density screen in your phone, you should put images in drawable-hdpi folder to get them without scaling. If you're getting 3 times larger images, you probably have a very dense screen, like Nexus 5 or recent Galaxy S phone. To disable scaling, put images in drawable-nodpi folder.
I saw another post of resizing issues and came across the ".inScaled" field of BitmapFactory.options.
This executes by default to scale bitmap to target density.
I set this field to false to prevent it from executing and the images come out perfectly, tho Im still confused as to why it scales the image by a factor of 3.
I'm making a game on Android in Eclipse, and when I run it through the emulator, it appears fine. The emulator I set up has the resolution at 800x480 (sideways). When I run the game on my phone, with resolution 1920x1200, it screws up the bitmaps by only drawing a fourth of them. I've made test code and two screenshots to show what I mean.
Small screen, emulator, running 2.3.3
http://i.stack.imgur.com/2WstK.png
Large screen, Galaxy S4, running 4.2.2
http://i.stack.imgur.com/8wtAD.png
It's the same code on each. The top has the dimensions correctly in the emulator (frame size of the bear, which is 64x64), but on the larger resolution it's halved the width and doubled the height for some reason.
The bear at the bottom is set to be near the bottom coordinates whatever the screen size, which is why it's different in each screenshot. The rectangles and top bear is set from the top coordinates.
I can post code but I'm just wondering if it's some type of setting that I'm unaware of because of the difference in resolution.
One more thing, I have the rectangles flipped horizontally from their original bitmap, so the fact that it appears to have taken the top right part of the bitmap to draw is not part of this, as far as I know. Again, just wondering if it's some setting that auto-scales things if the resolution is huge. I have a feeling it's something like that, OR that it's running on such a newer version of Android. Could be lots of things I guess.
Android usually scales up / scales down the image if it cannot find the right image assets for the device resolution. I believe this could be the reason for the behaviour you are observing. You can read more about providing the proper assets for different device configurations here,
http://developer.android.com/guide/practices/screens_support.html
Alternatively, if you don't want android to scale your images you can also place the image resources under drawable-nodpi folder.
I know that the title makes it sound like it is a duplicate, but I think I have a very specific situation here that I can't solve from all of my searches.
First, I have images that are specifically sized based off of a specific monitor (Yes, monitor. Not handheld device's screen). The images are based off of these specific settings:
1600x900 20" monitor at 96ppi
Now, all of the images must be sized in millimeters (they are square images btw, so Height=Width). Using these specific settings as a determining factor, 1mm = 3.78px. So, my images are sized using this. For example, for an image to appear as 65mm, I size the images to 246px. I tested this in Photoshop using these settings, and measuring the image on the screen did in fact come out correct.
So now in my Android application, I load up these images into ImageViews to be displayed. This is where I am stuck. The device is an MDPI device. If I load the images into the MDPI drawables folder, the images appear too large on the monitor. Using my above example, I convert the Drawable to a Bitmap and dump the Height of the image to my log. This is correct and shows 246px, but for some reason it is measuring well over 85mm instead of 65mm.
If I load all of my images into the HDPI (yes, I know it is an mdpi device so it will be sized by the Android OS), the height of the image (using my example) dumps as 164px and appears at roughly 50mm. This is more explainable, but still I am still confused on how to get these images to appear as they did in Photoshop.
So my question is, what is the best way to programmatically size the ImageView to be the exact size of the image? For my example, I need to find out why my 246px square image (at 96ppi) is not showing up as 65mm like it should.
Because these ImageViews are generated programmatically, I have tried the following two things:
Set the ImageView Height and Width (using LayoutParams) to the height of the image (246px). I did this thinking WRAP_CONTENT was not acting as it should.
Used ImageView.ScaleType.CENTER to try and make sure the ImageView is sized exactly to the image.
Neither of these things seem to have effected the output.
UPDATES:
I have verified that my device is a MDPI device. This means that there is not DPI to PX conversion (or vice versa) necessary because of the 1:1 relationship. Somewhere, the sizes are being increased and I cannot determine where. As I indicated in the comments for the answer below, when I pull my Drawable and convert it to Bitmap, it pulls the EXACT pixel Height that I made it. I am starting to figure out the percentage of size difference from what it should be (65mm vs 85mm) and it works out to be 23.529%. I am scaling my bitmaps subtracting this value, but it ruins the quality of my image.
I am beginning to give up.
The device I am utilizing is an MK802III Rockchip Device (Amazon Link)
Android modifies all images for display with the following formula:
px = dp * (dpi / 160)
Where "dpi" is the screen density in dots-per-inch of a device's display.
Additionally, Android looks through a hierarchy of drawable folders when deciding which image to display. As we all know, an HDPI device will use an image from the drawale-hdpi folder while an MDPI device will display the same named image from the drawable-mdpi directory.
However, when an MDPI device cannot find an image in the drawable-mdpi directory, it will eventually choose from the drawable-hdpi folder, but it will down-scale the image for display on the MDPI screen.
This explains why your image appears smaller when you saved it in the drawable-hdpi folder.
But, it does not explain why the image appears too large when correctly placed in the drawable-mdpi folder.
It so happens that:
65mm ~= 85mm * (120 / 160)
50mm ~= 85mm * (120 / 240)
This is the scaling that I would expect for your images if your device were LDPI (120dpi) instead of MDPI (160dpi) as reported.
I hate answering my own question, but I am just going to update everyone what I did. If someone comes up with a better solution, I am all ears. I had to force this along because I am on a tight deadline.
I created a dummy application that dumped boxes that I could measure. Using these, I determined that 1 millimeter is 3 density pixels. Let me repeat that, 1mm = 3dp.
Using this value, I resized all of my images (utilizing a PHP script) to this constraint. All of my images are appearing as normal. 195dp = 65mm, and it appears as such.
Like I said, any explanation as to why I had to do this and you get an upvote and answer.
i just released my app on android and have problems with customers with high density displays.
i added a debug thing to see what's going in, here is one sample output
Device: Nexus 10 Android version: 4.2.2
DisplayMetrics{density=2.0, width=2560, height=1504, scaledDensity=2.0, xdpi=298.275, ydpi=298.823}
MainView w=1900 h=1342
mDrumKitMode=BIG
KitView w=640 h=1266 x=1920.0 y=0.0
the main view is the music notation area on the left of the screen shot, its 1900 wide (MainView w=1900 h=1342) the drum kit is a bitmap that is 640w and 640 high. somehow, the display is scaling it to be full height of the parent, (KitView w=640 h=1266 x=1920.0 y=0.0). this doesn't happen on displays where density=1.0.
i have no way to test this since i can't get the emulator work on big displays for some reason and i don't have a high density tablet.
does anyone have an idea what could be going on? thanks
and here's another customer with a similar problem
Device: A700 Android version: 4.1.1
DisplayMetrics{density=1.5, width=1920, height=1128, scaledDensity=1.5, xdpi=224.73732, ydpi=224.11765}
MainView w=1260 h=1044
mDrumKitMode=BIG
KitView w=640 h=968 x=1280.0 y=0.0
i think its the scaledDensity=1.5 parameter, maybe i need to do something to disable automatic image scaling, i.e. set scaledDensity=1?
i should add that the entire application is based on exact pixel positions, both for the music notation display and the drum kit display which overlays images on top of the base drum kit image (you can see the drum pedals are in the wrong place on this image too). i don't want automatic scaling as i handle scaling inside the app for different display sizes and user preferences.
i should also add that all my drum kit images are in drawable-mdpi and all the other dpis are empty. this is because i scale images programmatically based on screen size and user preference BUT i think maybe the problem is a need to put some images in xhdpi? i guess i can do that but it will be a lot of work.
PS, i guess i found my answer here http://developer.android.com/guide/practices/screens_support.html
Provide different bitmap drawables for different screen densities
By default, Android scales your bitmap drawables (.png, .jpg, and .gif files) and Nine-Patch drawables (.9.png files) so that they render at the appropriate physical size on each device. For example, if your application provides bitmap drawables only for the baseline, medium screen density (mdpi), then the system scales them up when on a high-density screen, and scales them down when on a low-density screen. This scaling can cause artifacts in the bitmaps. To ensure your bitmaps look their best, you should include alternative versions at different resolutions for different screen densities.
i wonder if simply copying all the -mdpi images to -xhdpi will work?
If you intend for this app to be used across devices you have no choice but to put in images for all the various density folders that exist (xhdpi,xxhdpi, hdpi, mdpi). It's also worth considering that you may want to change the actual layouts you include, to offer different ones for different devices.
Consult the documentation for how to handle this.
http://developer.android.com/guide/practices/screens_support.html
If that creates an apk that's too heavy (I have no idea how many images you have) then you can go the other way and specify a no scaling drawable folder which will just use the images in their native density across devices. It's definitely wrong to use ONLY mdpi unless you intend to support only mdpi devices.