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.
Related
I'm drawing to a Canvas using Graphics through a BufferStrategy with lines such as
g.drawImage(bufferedImage, x, y, null);
I currently have this running undecorated in a JFrame, 1920x1080p as per the resolution of my laptop. I'm curious as to whether there is any way to alter the resolution of the Graphics rendered, particularly lowering resolution so as to increase efficiency/speed, or fitting to another differently sized screen. There are many objects being rendered with a camera and the game runs fairly well, but any usable alterations to the resolution would be useful as optional in my settings.
I've researched this and found no good answers. Thank you for your time.
(Resolution changes such as for printing.)
Best to use a drawImage with a smaller image, and scaled width and height.
Now, you could even render all in your own BufferedImage using a Graphics2D with BufferedImage.createGraphics and scale afterwards. Not so nice for text or printing.
Or use Graphics2D scaling:
For complex rendering:
g.scale(2.0, 2.0);
... // Draw smaller image
g.scale(0.5, 0.5);
As you might imagine this probably does not help in memory consumption, apart from needing smaller images. At one point all pixels of the image must be given in the devices color size. 256 colors gif, or 10KB jpg will not help.
The other way around, supporting high resolutions with tight memory also exists. There one might use tiled images, see ImageIO.
Important is to prepare the image outside the paintComponent/paint.
You might also go for device compatible bit maps if you make your own BufferedImage, but this seems circumstantial (GraphicsEnvironment).
I have some very small images (20 by 20 pixels) which I am drawing using matrices onto a canvas using Canvas.drawBitmap(Bitmap, Matrix, Paint). The problem is that I am scaling these up about 5-10 times larger when I am drawing them and it is automatically re-sampling these images with smoothness. What I want is nearest-neighbour style re-sampling (so it will look pixelated) not the smoothness. I cannot find a way to change this. Also creating another whole image that is larger to store a properly re-sampled picture is not an option since I am under memory constraints. Thanks for any help!
You need to set up the paint you pass to drawBitmap, like so:
paint.setFilterBitmap(false);
So I have no clue why this is happening. I am using Universal Image Loader to load these images. It seems like the last line of pixels is being streched for some weird reason. I want the image to just stretch out evenly. (I don't care that it will look weird. The images below are for demo purposes.)
Also, don't mind the first and last image. I purposely blurred that out because it had someone's face on it.
This is how I set up my Universal Image Loader:
//setup Image Loader for loading cruise line logos
displayImageOptions = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_launcher)//show this image when image is loading
.showImageForEmptyUri(R.drawable.ic_launcher)//show this image incase image doesn't exist
.showImageOnFail(R.drawable.ic_launcher)//show this image if fetching image from URL didn't work
.cacheInMemory(true)//cache image in RAM
.cacheOnDisc(true)//cache image in device for later use
.considerExifParams(true)
.displayer(new RoundedBitmapDisplayer(5))//super subtle rounded corners on images
.build();
This is caused by the way RoundedBitmapDisplayer draws the bitmap.
If you look at the source, you'll see that it uses a RoundedDrawable, which uses canvas.drawRoundRect() to draw a rounded rectangle of the desired size of the Drawable, using the downloaded image as the texture via a BitmapShader. BitmapShader does not support scaling (only clamping and tile modes). Try using a SimpleBitmapDisplayer instead which uses the normal ImageView.setImageBitmap() way of displaying the image.
If you need rounded corners, you'll have to find a different way to implement that, for example by scaling the Bitmap to the desired size first. Another option is to call Canvas.saveLayer() before delegating to BitmapDrawable for the scaling, and then applying the rounded corner masking effect using PorterDuff.Mode.DST_IN. Either way you'll end up writing a bit more low-level code, but you should be able to encapsulate everything nicely in a custom BitmapDisplayer.
I am making a grid-based game that resizes its grid as the window size changes. I also may apply color filters for lighting effects in the future. I am concerned about the performance of this code, which draws to the screen an image in one of the grid squares.
public void drawSquares(Graphics g){
ListIterator<Viewport> iterator = vp.listIterator();
while(iterator.hasNext()){
Viewport v = (Viewport)iterator.next();
BufferedImage img = v.getSqView().getImage();
Rectangle b = v.getPixRect();
g.drawImage(img, b.x, b.y, b.width, b.height, v.getSqView().getBackground(), null);
}
return;
}
What this code does is get the image (stored in img) and get the pixel rectangle it needs to fit in (stored in b), then draw it in the space alloted via drawImage.
drawImage says that it scales images on the fly - which means that all images are being rescaled every frame. But the window is only resized rarely, so this must waste lots of processor time doing the same thing over and over again.
Now I saw this and decided that I would just update all the images upon resizing once, then store the result and be able to draw normally.
Like this:
public void resizeImage(int width, int height){
BufferedImage resized = new BufferedImage(width, height, img.getType());
Graphics2D g = resized.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(img, 0, 0, width, height, 0, 0, img.getWidth(), img.getHeight(), null);
g.dispose();
img = resized;
}
This doesn't work - I think it has something to do with img = resized. I just lose all the images with this code.
I have a few questions then.
What is the performance cost of repeatedly scaling with drawImage? Is it any different even if the window has not been resized in between frames?
How should I get the second code snippet to work? What is going wrong?
If I apply a lighting filter to a tile, will that eat up tons of processor time as well if I run it each frame? (Think 225 or so small images on a 800x800 or so display)
What is best practice for applying lighting filters? I am planning on overlaying on the whole map a pitch black filter, then exposing the areas around light sources.
Thanks for any help with this!
Resize the frame of this Grid to get a subjective feel for the latency. Use the approach shown here to measure the latency. Verify your findings in a profiler.
There's no reason you shouldn't be able to resize the elements of a List<Image> as you propose, but add() the resized instances to a new list as they are created.
What is the performance cost of repeatedly scaling with drawImage? Is
it any different even if the window has not been resized in between
frames?
You should always measure, but there is definitely a performance cost here, even if the window is not resized, because as the Javadoc says, there is no caching behind this drawImage method. The cost also depends on the frame rate.
How should I get the second code snippet to work? What is going wrong?
The second code snippet should be OK, I think the problem is somewhere else. Try reproducing the problem in a "small but complete" program, and post another question if you still see the problem.
If I apply a lighting filter to a tile, will that eat up tons of processor time as well if I run it each frame? (Think 225 or so small images on a 800x800 or so display)
You should always measure :)
What is best practice for applying lighting filters? I am planning on overlaying on the whole map a pitch black filter, then exposing the areas around light sources.
You can use an AlphaComposite for this.
Alright, so I have an image that it's resolution is: 1054X1054.
I want to set that image so it fits exactly the screen size of the android devices. (I'll cut the image in some editor as nessacary).
So my question is: How can I know what resolution my image should be so it will cover the device background without needing to resize the image.(For the mdpi,hdpi,ldpi)
I'm asking that question because I keep missunderstanding how the "multiple screen resolutions" really work..
you can design your image to re-size with different screen sizes, you'll discover that each design requires a minimum amount of space. So, each generalized screen size above has an associated minimum resolution that's defined by the system.
android os count sizes in "dp" units—the same units you should use when defining your layouts—which allows the system to avoid worrying about changes in screen density.
xlarge screens image sizes are at least 960dp x 720dp
large screens image sizes are at least 640dp x 480dp
normal screens image sizes are at least 470dp x 320dp
small screens image sizes are at least 426dp x 320dp