I want to paint a Bitmap scaled in a canvas (based on the Bitmap and the View size). The problem is that if I scale the canvas before painting the bitmap:
canvas.scale(1.5f,1.5f);
canvas.drawBitmap(mBitmap, 0, 0, paint);
This is the result:
But if instead of scaling the canvas I scale the bitmap:
Bitmap scaled = Bitmap.createScaledBitmap(
mBitmap, bitmapWidth, bitmapHeight,
true);
canvas.drawBitmap(scaledBitmap, 0, 0, paint);
The result is much better:
The problem is that the Bitmap is pretty big and having in memory both the original and the scaled bitmap may be problematic.
Is there any way to obtain the second result without creating a scaled Bitmap every time the Bitmap or the View bounds changes?
Use a matrix that contains the scaling info when drawing to canvas
canvas.drawBitmap(x,y,..., matrix...)
Use inSampleSize in BitmapOptions when reading the bitmap from your source to scale it accordingly (it is passed as an extra parameter).
This is androids preferred way of loading images in nearly all cases to avoid memory overflow, as the full image is Never loaded into memory.
The android docs on Loading BItmaps efficiently can be found here.
With example code on how to retrieve an image of desired size from your source. (resource, file, etc etc)
The two methods in Loading Large Bitmaps Efficiently are the ones you are looking for.
The solution to my problem was that the Paint hasn't enabled the FILTER_BITMAP_FLAG flag.
Related
I am using Pax A920 device.
I have an issue when printing a bitmap, there is no option to center the bitmap(image) documentation
Methods reference:
The issue is when the bitmap's width is short, its left-aligned on the printed receipt.
I can scale the bitmap using:
Bitmap.createScaledBitmap(receiptLogo, 512, receiptLogo.getHeight(), false);
But it looks bad, I'm thinking of creating a new Bitmap with width of 512 & height of receipt.Logo.getHeight() then put the receipt logo in the middle so it wont look stretch.
Is this doable?
How to resize image without losing its quality using java code ?
I have tried below code.
BufferedImage thumbnail =
Scalr.resize(inputImage,150, 100);
String formatName = outputImagePath.substring(outputImagePath
.lastIndexOf(".") + 1);
ImageIO.write(thumbnail, formatName, new File(outputImagePath));
It is not possible to resize an image without either throwing pixels away (when making it smaller) or interpolating/duplicating pixels (when making it larger). Thus, it is impossible to "resize" an image without sacrificing quality.
I have used this code, Short and works fine.
Bitmap yourBitmap;
Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true);
I have a lot of images with xhdpi resolution. Now I need the same images but in mdpi, ldpi, hdpi resoulution. I think this process could be automated. So, what is the best way to generate images with different resolution?
Try using:
http://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html
This helps a lot in generating resources. Hope it helps!
The process is already automated. If you provide just one size - hdpi works for me - then the Android system will resize or rescale it as needed for other screen resolutions and sizes.
The drawback of not providing images in different sizes is that the automatic resizing algorithm might not do as good a job as a graphic designer. However, if you are looking for a non Android algorithm to do the resizing, who's to say it will be any better than the built-in algorithm?
I suggest trying just one size on various devices and see how your graphics looks. Some images will scale better than others, so you may only need to provide multiples for a few.
Not too long ago I needed to resize a Image in java and I found a very good method for that, it returns a type of bufferedimage and you will have to use that new instance. You can specicify your width and height. Here is the code:
public BufferedImage resizeImage(final Image image, int width, int height) {
final BufferedImage bufferedImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
final Graphics2D graphics2D = bufferedImage.createGraphics();
graphics2D.setComposite(AlphaComposite.Src);
graphics2D.drawImage(image, 0, 0, width, height, null);
graphics2D.dispose();
return bufferedImage;
}
Just putting in 1 image at a higher resolution (like xhdpi or hdpi) and using that for all scales is not efficient as while android does resize it to fit, it still is loading the image in its original size into memory, thus this would cause some lag or outOfMemory errors if you have lot of them in 1 activity.
I would use the bitmap Image loader that google recommends.
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html#decodeSampledBitmapFromResource
This lets you take an image, and it will resize it, while only loading the new image size into memory. This is also the method you would want to do if you want a "lazy load".
The solution I chose to handle all my drawables is the following:
1- Have all drawables in high resolution in a /etc folder in your app project.
For the high resolution I chose 10 times the default resolution (mdpi). So for instance the launcher icon drawables (48dip x 48dip which is 48 x 48 pixels in mdpi) would be 480 x 480 pixels.
I have all my drawables in high res in the /etc folder.
2- At build time, my ant script would take all drawables from /etc, and resize them to fill all /res/drawables-* folders.
From the highres drawable at 100% size, the various resolutions sizes will be: ldpi: 7.5%, mdpi: 10%, hdpi: 15%, xhdpi: 20%, xxhdpi: 30%
I use an external program launched by ant to actually do the resizing.
What is the best way of resizing a bitmap?
Using
options.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.mandy_moore, options);
or
Bitmap resizedbitmap = Bitmap.createScaledBitmap(bitmap, 200, 200, true);
What is the best way of resizing a bitmap?
It depends the flexibility you need:
options.inSampleSize = N; means that you will obtain an image which is N times smaller than the original. Basically, the decoder will read 1 pixel every N pixel.
Use that option if you don't need a particular size for your bitmap but you need to make it smaller in order to use less memory. This is particularly useful for reading big images.
Bitmap.createScaledBitmap on the other hand give you more control: you can indicate precisely the final dimension of the bitmap, ...
The best is to use a combination of both method:
Determine the maximal value of inSampleSize you can use to decode the source image efficiently (such that the decoded image is still bigger than the final size you need)
Use Bitmap.createScaledBitmap to precisely control the resulting size
Use this to create sampled image maintaining same aspect ration as orignal image was.
This is best way to resize.
options.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.mandy_moore, options);
Bitmap resizedbitmap = Bitmap.createScaledBitmap(bitmap, 200, 200, true);
This will scale the bitmap in provided w and h.
This may distort the bitmap.
Use according to your need.
the method createScaledBitmap produce low quality images
take suggestion from this post bitmap image quality
I am displaying a Bitmap on an ImageView. When the ImageView is tapped, I would like to get the pixel x/y coordinates for the Bitmap where it was tapped. I have registered the ImageView's onTouchListener, and within the onTouch method, I use getX and getY to get the location of the touch. The problem is that the image within the ImageView may be larger than the view itself, so it is scaled down to fit the screen. The x and y coordinates returned, then, are the coordinates of the view, but not necessarily the coordinates of the corresponding pixel on the Bitmap.
Can I get some sort of scale factor to know how much it was resized? Or if not, could someone suggest how I could go about getting the information I need? What's most important is that I can get the pixel coordinates - if I have to change the view type, that's alright.
Also, sometimes the bitmap is smaller than the screen, so it scales it up. In this scenario, it is possible that the x and y received from the MotionEvent are outside the bounds of the actual Bitmap.
Check into the ScaleType property. You'll have to do the math on the original image, based on the results of getScaleType(), but it's worth checking out.
I can across the same case. The thread is more than a year old, but thought it might be useful for someone. I had to scale the bitmap before setting to the ImageView.
Here is the code:
//Convert Uri to Bitmap
inputBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImage);
//Scale the bitmap to fit in the ImageView
Bitmap bmpScaled = Bitmap.createScaledBitmap(inputBitmap, img.getWidth(), img.getHeight(),true);
//Set the scaled bitmap to the ImageView
img.setImageBitmap(bmpScaled);
After this, the touched coordinates are the same as the coordinates of the bitmap.