Hi i am creating a Bitmap from an png image named image.png. The image has the dimension 75 (width) x 92 (height). When I run this code:
Bitmap bitmap = BitmapFactory.decodeResource(this.context.getResources(), R.drawable.image
Log.d("image", "height: " + bitmap.getHeight() + " width: " + bitmap.getWidth());
the logger logs:
DEBUG/image(3550): height: 138 width: 113
and the image on the screen is bigger than other images which have the dimension 75 x 92. What can I do to make android load the image with the right dimension?
My solution:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeResource(this.context.getResources(), R.drawable.image, options );
It sounds like your screen density on your device is different than the density where image.png was created.
If you really want to prevent the scaling, you could try one of the following:
Put the image in res/drawable-nodpi (http://developer.android.com/guide/practices/screens_support.html#qualifiers)
Use ImageView.ScaleType.CENTER (http://developer.android.com/reference/android/widget/ImageView.ScaleType.html)
Just found this related question on SO: Android: How to stop Android 1.6+ from scaling images
Beause loader in BitmapFactory applies screen density scaling during loading.
To override this, provide own desired inTargetDensity in BitmapFactory.Options in call to decodeResource.
Bitmap thumbImage =
Bitmap.createScaledBitmap(BitmapFactory.decodeResource(context.getResources(),
R.drawable.image), 640, 640, false);
Related
I am trying to display pdf document using following code
pdfRenderer = new PdfRenderer(parcelFileDescriptor);
PdfRenderer.Page page = pdfRenderer.openPage(position);
Bitmap bitmap = Bitmap.createBitmap(page.getWidth(), page.getHeight(),
Bitmap.Config.ARGB_8888);
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT);
imageView.setImageBitmap(bitmap);
The problem is that the pdf displayed is very blur. I show comparison with pdf shown by wps office application in following image.
How to improve the bitmap quality and performance as my app seems to work quite slow.
Answer by #Mangaldeep is correct. However, he does not address memory requirements.
Please follow this article https://developer.android.com/topic/performance/graphics/load-bitmap
In your case you can increase the size of bitmap by a factor, say
x = size.x/page.getWidth().
Where size.x is your screen size. Width. Now you can create new bitmap like
Bitmap b = Bitmap.create(x*page.getWidth(), page.getHeight(),....);
Hope this helps.
Try this:
pdfRenderer = new PdfRenderer(parcelFileDescriptor);
PdfRenderer.Page page = pdfRenderer.openPage(position);
Bitmap bitmap = Bitmap.createBitmap(
getResources().getDisplayMetrics().densityDpi * mCurrentPage.getWidth() / 72,
getResources().getDisplayMetrics().densityDpi * mCurrentPage.getHeight() / 72,
Bitmap.Config.ARGB_8888
);
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT);
imageView.setImageBitmap(bitmap);
where:
getResources().getDisplayMetrics().densityDpi is the target DPI resolution
mCurrentPage.getWidth() returns width in Postscript points, where each pt is 1/72 inch.
72 (DPI) is the default PDF resolution.
Hence, diving #2 by 72 we get inches and multiplying by DPI we get pixels. In other words to match the quality of the printing device of the display you should increase the size of the image rendered as default PDF resolution is 72 DPI. Please also check this post?
Credits: https://stackoverflow.com/a/32327174/10471480
I'm developing application for my android tablet that using many images.
in my activity, I use effect splash that show image (3840 x 2108 70 KB) for the opening theme.
I use another background image (3840 x 2108 69 KB).
but, when I test it on my tablet, this application's cache reached 80 MB!
For your information, I load the image from my xml file.
Can anyone help me to reduce it?
Is it wrong to load image from xml file?
Is it the size of my images that cause this problem?
//UPDATE
at the end, i didn't found a really good way to my question. I'm using xml (I put at dawable) file to replace my big size image, and this method really reduce the cache alot. My conclusion is avoid using big image, instead, just replace the color image using color.
The advantage to use color is "faste to load", it reduce lag of my application.
Android default color model is ARGB_8888. It takes 4 byte for 1 pixel. So splash and background bitmap images in memory takes 3840*2108*4*2 = 61.76MB. You could resize the images for different device dpi and put them in proper drawable folder. For example, drawable-hdpi is suitable for 240 dpi, drawable-xxhdpi is suitable for 480 dpi.
In addition, you could manually load the images with java code. The following is a method to resolve the image safely:
protected Bitmap getBitmapSafely(Resources res, int id, int sampleSize) {
// res = youractivity.getResources, id = R.drawable.yourimageid
Bitmap bitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
options.inSampleSize = sampleSize;
try {
bitmap = BitmapFactory.decodeResource(res,
id, options);
} catch (OutOfMemoryError oom) {
Log.w("ImageView", "OOM with sampleSize " + sampleSize, oom);
System.gc();
bitmap = getBitmapSafely(res, id, sampleSize + 1);
}
return bitmap;
}
Your could use this method with sampleSize = 1 at first time. If there is not enough memory, it will catch OOM and increase the sampleSize until the image can be resolved.
My app contains buttons with images on them, set by using setCompoundDrawablesWithIntrinsicBounds. I use images from the app's drawables folder, but also use images downloaded from the web and stored on SD card. I found that I needed to upscale the SD card images so they'd render as the same size as the images in drawables. I did this using:
Options opts = new BitmapFactory.Options();
opts.inDensity = 160;
Bitmap bm = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() +
context.getResources().getString(R.string.savefolder) + iconfile, opts);
myIcon = new BitmapDrawable(context.getResources(), bm);
btn.setCompoundDrawablesWithIntrinsicBounds(myIcon, null, null, null );
This has worked with no problems, until I updated my phone to Android 4.1.1 and noticed that the downloaded images were now appearing at a much smaller size than those from the drawable folder.
I messed around with the inDensity value to little effect, but had more success with scaling the bitmap based on a btnheight value (just the height of the button the image sits on):
int intoffset=bm.getHeight() - bm.getWidth();
myIcon = new BitmapDrawable(context.getResources(),
Bitmap.createScaledBitmap(bm, btnheight - (((btnheight/100)*10) +
intoffset) , btnheight - ((btnheight/100)*10), true));
This sort of works, but the image is still a little bigger than the button it sits on (which shouldn't be the case, based on the above, as it should scale the image height to 90% of the button height.) I did this as a test. I can't use this method in my app as the button height changes in accordance with the font size displayed on the buttons, and the user can change this font size in the app preferences.
As an aside, I found that, oddly(?), by scaling the bitmap to twice it's original height using
Bitmap.createScaledBitmap(bm, bm.getWidth() * 2
, bm.getHeight() * 2, true));
It rendered correctly, (well, it was displayed at the same size as the drawable icons) in 4.0.3 and 4.1.1, but behaved as you'd expect (rendered bigger than the button it sits on) in 2.1.
If anyone has any insights as to why this happens in 4.1.1, and what I can do so my decodeFile bitmaps render at the same size as my drawable bitmaps, without having to code for 4.1.1 separately, it would be much appreciated!
Modifying my original code to be as below works on 4.1.1 as well as the previous versions I tested it on...
Options opts = new BitmapFactory.Options();
DisplayMetrics dm = new DisplayMetrics();
context.getWindowManager().getDefaultDisplay().getMetrics(dm);
int dpiClassification = dm.densityDpi;
opts.inDensity = dm.DENSITY_MEDIUM;
opts.inTargetDensity = dpiClassification;
opts.inScaled =true;
Bitmap bm = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() +
context.getResources().getString(R.string.savefolder) + iconfile, opts);
myIcon = new BitmapDrawable(context.getResources(), bm);
btn.setCompoundDrawablesWithIntrinsicBounds(myIcon, null, null, null );
I'm getting an image (.png) from SQLiteDatabase and using this code to decode the bytearray into a bitmap:
Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inDither = true;
options.inScaled = true;
options.inDensity = 240;
options.inTargetDensity = metrics.densityDpi;
Bitmap bmp = BitmapFactory.decodeStream(new ByteArrayInputStream(imageAsBytes), null, options);
As you can see, image (3) should be like (2), but it doesn't.
1) = Image with no scale (metrics.densityDpi = 240);
2) = same .png above, but compiled in res/drawable;
3) = Image with down scale (with metrics.densityDpi = 120);
I also tried options.inDither = false;, but I see no difference.
So what's wrong with my code?
There a few other things I would try:
Load the png with no scale, when you come to draw the Image (either from within an ImageView or directly onto the canvas) set a Matrix to scale the image
Alternatively, load the image in the required density and try drawing the Bitmap directly to the canvas with a Paint object. After instantiating your Paint, enable Bitmap filtering (this will increase the image quality)
setFilterBitmap(true)
Finally, you could always load the Bitmap (density independent) and resize the Bitmap manually using Bitmap.createScaledBitmap, make sure you set the third paramenter to true (this enabled bitmap filtering for increased quality). Below is an example of scaling a bitmap where 100 is the desired size:
Bitmap.createScaledBitmap ( original_bitmap, 100, 100, true);
Briefly, the best quality downscaling algorithm consists of 2 steps:
downscale using BitmapFactory.Options::inSampleSize->BitmapFactory.decodeResource() as close as possible to the resolution that you need but not less than it
get to the exact resolution by downscaling a little bit using Canvas::drawBitmap()
Here is detailed explanation how SonyMobile resolved this task: http://developer.sonymobile.com/2011/06/27/how-to-scale-images-for-your-android-application/
Here is the source code of SonyMobile scale utils: http://developer.sonymobile.com/downloads/code-example-module/image-scaling-code-example-for-android/
I am downloading images from web and i use Gallery widget to display the images.
If the downloaded image size is huge, my application crashes with the below log.
"E/GraphicsJNI( 3378): VM won't let us allocate 5591040 bytes"
I want to scale down the downloaded image size only when the image size is more to an extent that it will crash the app. I have written the code to scale down the image size but i am not sure how to find the bitmap size so i can decide on whether to scale or not
BitmapFactory.Options o = new BitmapFactory.Options();
o.inSampleSize = 2;
Bitmap bit = BitmapFactory.decodeStream(inputStream,null,o);
Bitmap scaled = Bitmap.createScaledBitmap(bit, 200, 200, true);
bit.recycle();
return scaled;
To get bitmap dimensions, you can simply use:
To get height -> bitmap.getHeight()
To get width -> bitmap.getWidth()
Use inJustDecodeBounds field of BitmapFactory.Options to get bitmap dimensions.