I've encountered totally bizarre behavior in the way Android loads bitmaps into ImageView. For example, I have a 500x313 image file called urimg_01.jpg. With this code:
img.setImageResource(R.drawable.urimg_01);
Bitmap bitmap = ((BitmapDrawable) img.getDrawable()).getBitmap();
Log.v(TAG,"---------------------> bitmap width = "+bitmap.getWidth());
Log.v(TAG,"---------------------> bitmap height = "+bitmap.getHeight());
the ImageView bitmap is 750x470. (I have a Nexus S with 480x800 display.)
With this code, which reads a copy of the same file located in getFilesDir():
Log.v(TAG,"image file is "+filelist[0].getAbsolutePath());
FileInputStream fis = new FileInputStream(filelist[0]);
FileDescriptor fd = fis.getFD();
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd);
if (bitmap != null) {
Log.v(TAG,"---------------------> bitmap width = "+bitmap.getWidth());
Log.v(TAG,"---------------------> bitmap height = "+bitmap.getHeight());
img.setImageBitmap(bitmap);
fis.close();
}
the ImageView bitmap is 500x313, as expected.
In the case of setImageResource(), where the devil is it getting 750x470 from?? And how do I get it to use the correct dimensions for resources in drawable?
Your resource is being scaled up because it's probably stored in a medium density folder and you're using a high density device. See Bitmap getWidth returns wrong value for details.
here you get your bitmap
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd);
now scale it according to device height and width
Display display=this.getWindowManager().getDefaultDisplay();
int w=display.getWidth();
int h=display.getHeight();
Bitmap newBitmap=Bitmap.createScaledBitmap(oldBitmap, w, h, false);
//now setImage to background with new Bitmap
One important thing "this" should be activity context
:) cheers
Related
I have a jpg image of size 1080*1080 in my drawable folder, when I am storing it in a Bitmap variable the size of the bitmap is not showing as 1080*1080, it is showing based on the device I am using, I want to draw the actual image with size 1080*1080 on a canvas, any idea how to get the bitmap with actual size
Bitmap bitmap = BitmapFactory.decodeResource(activity.getResources(), R.drawable.template_image);
int w = bitmap.getWidth();
int h = bitmap.getHeight();
The variable w and h are not showing 1080*1080, it's different on different devices
put your image file in drawable-nodpi This folder tells android to avoid scaling your image file on any pixel density:
More Info Medium Article
If you need to only retrieve image size without showing inside image view:
BitmapFactory.Options options = new BitmapFactory.Options();
//Just Retreive info about the bitmap without loading inside memory to avoid OutOfMemory.
options.inJustDecodeBounds(true)
Bitmap bitmap = BitmapFactory.decodeResource(activity.getResources(), R.drawable.template_image, options);
int w = options.outWidth;
int h = options.outHeight;
I am working on an Android app, And I put many pictures in Assets directory by categories. And I get a bitmap of a image using code below
InputStream in = getAssets().open(file);
Bitmap bm = BitmapFactory.decodeStream(in);
Bitmap board = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(board);
canvas.drawBitmap(bm,0,0,null);
And the width and height(pixel) of all my image files is 360x240, I want the Bitmap:board to be 960x720 when the images are read because I need convert the bitmap to a 960x720 Mat using OpenCV.
What can I do?
You can use createScaledBitmap :
Bitmap createScaledBitmap (Bitmap src,
int dstWidth,
int dstHeight,
boolean filter)
Creates a new bitmap, scaled from an existing bitmap, when possible.
If the specified width and height are the same as the current width
and height of the source bitmap, the source bitmap is returned and no
new bitmap is created.
I am trying to implement overlay transformation for Picasso library.
So, I am loading image into image view and want to display overlay using bitmpap
First of all I am fill canvas with transparent color
Then I am trying to draw drawable over
#Override
public Bitmap transform(Bitmap source){
Bitmap workingBitmap=Bitmap.createBitmap(source);
Bitmap mutableBitmap=workingBitmap.copy(Bitmap.Config.ARGB_8888,true);
Canvas canvas=new Canvas(mutableBitmap);
canvas.drawColor(getResources().getColor(R.color.gray_transparent));
BitmapFactory.Options options=new BitmapFactory.Options();
options.inScaled=false;
Bitmap b=BitmapFactory.decodeResource(getResources(),R.drawable.ic_gif_white_24dp,options);
canvas.drawBitmap(b,source.getWidth()/2,source.getHeight()/2,paint);
source.recycle();
return mutableBitmap;
}
The problem is that I see different overlay image size when canvas size is different. How I can avaid bitmap scaling depends on canvas size? I want to see same GIF size with different canvases size.
On first image canvas has w = 1280, h = 854, second image w = 480, h = 270
UPDATE
I found solution to scale bitmap depends on canvas size, it works well, but I wish to find out better solution
BitmapDrawable drawable = (BitmapDrawable) getResources().getDrawable(R.drawable.ic_gif_white_24dp);
Bitmap drawableBitmap = drawable.getBitmap();
double size = source.getWidth() * 0.15;
Bitmap scaled = Bitmap.createScaledBitmap(drawableBitmap, (int) size, (int) size, true);
I'm writing a custom printing app in Android and I'm looking for ways to save on memory. I have three basic rectangles I need to print on a full page. Currently I'm creating a base Bitmap the size of the page:
_baseBitmap = Bitmap.createBitmap(width/_scale, height/_scale, Bitmap.Config.ARGB_8888);
The print process requests a Rect portion of that page. I cannot predetermine the dimensions of this Rect.
newBitmap = Bitmap.createBitmap(fullPageBitmap, rect.left/_scale, rect.top/_scale, rect.width()/_scale, rect.height()/_scale);
return Bitmap.createScaledBitmap(newBitmap, rect.width(), rect.height(), true);
Using bitmap config ARGB_8888 _baseBitmap is about 28MB (8.5"x11" # 300dpi = 2250*3300*4bytes). Even at 50% scaling (used above), my image is over 7MB. Scaling any smaller than this and image quality is too poor.
I've attempted to create _baseBitmap using Bitmap.Config.RGB_565, which does greatly reduce the full image size, but then when I overlay an image (jpegs) I get funny results. The image is compressed in width, duplicated next to itself, and all the color is green.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDither = true;
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap myBitmap = BitmapFactory.decodeStream(input, null, options);
input.close();
return myBitmap;
....
private static Bitmap overlay(Bitmap bmp1, Bitmap bmp2, float left, float top) {
Canvas canvas = new Canvas(bmp1);
canvas.drawBitmap(bmp2, left, top, null);
return bmp1;
}
I know I can compress an image of these dimensions down to a reasonable size. I've looked into Bitmap.compress, but for some reason beyond my understanding I'm getting the same size image back:
ByteArrayOutputStream os = new ByteArrayOutputStream();
_baseBitmap.compress(Bitmap.CompressFormat.JPEG, 3, os);
byte[] array = os.toByteArray();
Bitmap newBitmap = BitmapFactory.decodeByteArray(array, 0, array.length);
_baseBitmap.getAllocationByteCount() == newBitmap.getAllocationByteCount()
It would be better to create it compressed than to create a large one and then compress it. Is there any way to create a compressed Bitmap? Any advice is greatly appreciated.
note: Not an Android expert. I'm not necessarily familiar with the platform specific terms you may use to respond. Please be gentle.
Try something like this, if you have a target size in mind.
private static final int MAX_BYTES_IMAGE = 4194304; // 4MB
//...
ByteArrayOutputStream out;
int quality = 90;
do
{
out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, out);
quality -= 10;
} while (out.size() > MAX_BYTES_IMAGE_FILESIZE);
out.close();
How to scale bitmaps at runtime to a very small size and then storing them in internal storage? how to call the scaled bitmaps into the program from the storage at runtime and if its not there, call it from drawable folder, scale it, write it to storage and then bind it to the view.
If you want to scale the bitmap you could use Bitmap.createScaledBitmap
To scale an arbitrary bitmap to 32x32 you could do it as follows:
Bitmap smallBitmap = Bitmap.createScaledBitmap( fullSizeBitmap, 32, 32, true );
You can use BitmapFactory.Options class to crop image to any size.
You can use following:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
options.inSampleSize = 8; // 1/8th of actual image.
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
Here, when you use a Bitmap, always call its bmp.recycle() method, since GC can't clear the memory held by Bitmap, if your bitmap is not getting garbage collected, then also you get the OME.