What's the easy way to render a shape in Java to its "actual size". For example, I have a tube with a diameter of 1" and I want to depict it on screen as the outline of a 1" circle. The Graphics2D method drawOval(int x, int y, int width, int height) takes a height and width in pixels. What are the steps to translate a pixel size into the size rendered on screen?
Thanks in advance.
The getNormalizingTransform() method of the class GraphicsConfiguration looks like it has some potential
http://java.sun.com/javase/6/docs/api/java/awt/GraphicsConfiguration.html#getNormalizingTransform()
The java.awt.Toolkit will tell you the size of a pixel, and the pixel dimensions of the screen. This is based on information from the underlying system, however, which may sometimes be misconfigured.
So, to draw a 1" circle, you'd use a diameter of 1.0 * tk.getScreenResolution(), a 2.5" circle is 2.5 * tk.getScreenResolution(), etc.
You should be aware that, even though you might be able to find out about the screen size and resolution, you still can't be sure of the actual size of the displayed picture. If the user has a CRT screen, the screen is likely to be a bit smaller than the actual screen size.
Therefore, if you really need accurate results, the only way is to let the user adjust a ruler displayed on the screen interactively and compare it with an actual ruler.
In theory you can do it this way. The java.awt.Toolkit will tell you the size of a pixel, and the pixel dimensions of the screen. So, to draw a 1" circle, you'd use a diameter of 1.0 * tk.getScreenResolution(), a 2.5" circle is 2.5 * tk.getScreenResolution(), etc. Or you can use the GraphicsConfiguration.getNormalizingTransform() method which adjusts the resolution to a 'fixed' size.
Unfortunately both of these methods rely on the underlying system knowing (and telling you) the actual resolution of your screen. In practice this very rarely occurs. All sorts of things can affect the actual size of a pixel. The actual size and make of monitor is one, and some monitors even allow you to adjust the size of the image on the screen.
This article http://www.developer.com/java/other/print.php/626071 discusses this.
Printers are generally better at telling you their real resolution. If you absolutely must have a picture which is the correct size, send it there.
Acknowledgements to the various answers from which I synthesized this one.
The problem you're going to have is Pixels are not always the same size. For example a 100 x 100 pixel square is going to be different sizes on a 17" 1280 x 1024 monitor and a 19" 1280 x 1024 monitor.
I don't believe there is an API which tells you the physical size of a display.
Asking the user the size of their monitor might not help as a lot of people simply won't know.
You could display a number of lines on screen and get the user to click which one is closest to 1 inch and scale all your rendering to that, but it's a bit clumsy.
Well, you would need the size of the monitor and resolution. Let's say the monitor is 17" with a 1280:1024 aspect ratio.
The screen size is the hypotenuse, so you would need to find the number of pixels on the hypotenuse. Simple geometry later, you can get the pixels/inch calculation.
1280px^2 + 1024px^2 = c^2, c ~= 1639.2px. So it's 1639.2px/17inch = 96.4px/inch for a 17 inch monitor with 1280x1024 resolution. This would have to be entered by the user.
I was under the impression that simply getting the screen resolution from Toolkit was not enough. I think you need to do something more along the lines of
float scalingFactor = Toolkit.getDefaultToolkit().getScreenResolution() / 72f;
Making a 1" square
int width = 1.0 * scalingFactor;
and a 2.5" square
int width = 2.5 * scalingFactor;
All of this being that Java2D assumes a 72 dpi screen resolution, and if the system is set differently you need to scale up to correct for this.
This is a curious question, one I haven't thought of. Off the top of my head, you would probably need to know a combination of screen size (17", 21", etc.), screen resolution ("800x600, 1280x1024, etc.) and DPI of the screen (72, 96, 120, etc.).
Through various api's, you can determine the screen resolution, and maybe the dpi... but good luck with the screen size. And even with all that, you're still not guaranteed to produce the correct size on screen.
Related
I have a neural network (made in java) which classifies handwritten digits, trained using the mnist data set.
I have a GUI where the user will draw a number (number on the left) and when the user hits the "guess" button the drawing is converted into a 400 by 470 image and is down-scaled to a 20 by 20 image, then is centered to a 28 by 28 image to feed into the network where the output is given on the right.
Here is what the GUI looks like:
My problem however, is that when I have a number that doesn't take up the majority of the panel (such as the 3 in the image above) the down-scaled image that is used as the input for the network is too small which causes the network to guess incorrectly.
Here is the final input image when the number is drawn small:
Here is the final input image when the number is drawn large:
What I'm asking is: is there any way to make the number that is drawn small the same size as the number drawn large while still keeping the size of the image as 28 by 28?
You can either use another object-detection network just to find the bounding box, or just calculate where the leftmost, rightmost, upmost, and bottom-most drawn pixel is. If you fear there will be outliers (there should not unless the user purposefully clicks an area far from the figure), you can remove outliers fairly easily. There are a number of ways, but method is to compute the distance of each drawn pixel to the center of the image, putting them into a distribution (normal might be good enough), and then compute which are outliers, and get rid of them. (Or compute the distance beyond which pixels become outliers, and cropping the box to fit). Then you scale the rectangle up to the correct size.
This is just a general method. As for specifics, I do not know how exactly your images are represented, but you can iterate over every pixel and note their positions (the number of iterations is not overly expensive).
I made a little game for my android phone (1440x2960) and I used pixels to draw (without any layout):
canvas.drawBitmap(image, x, y, null);
The code is working fine with 1440x1960 screens but didn't pay attention to the different screen sizes (at 720p you can't see even half of the game). How can I solve this problem nicely? I know, that I can make different sizes for the image, but the real problem are the x and y coordinates. I thought about that maybe I can get the actual pixels of the screen, make a ratio, and multiply the coordinates with it, but it's harder than it looks (needs many changes) and should be a better solution for this.
To get a phone's resolution, use
DisplayMetrics metrics = new DisplayMetrics();
This object will contain the data you need to adjust the images accordingly, when used with the functions in this documentation.
Also, have a look at converting dp to pixels and vice versa for appropriate scaling when referencing sizes in Java and XML simultaneously.
I have a game developed natively for Android, and now my users also want an iOS version. I thought LibGDX would be the better choice because it'll let me reuse Java code from the game, and also I already have some experience with it.
In my game I have different image sizes for different device densities (in drawable-hdpi, drawable-xhdpi and so on).
So, my question is: how can I achieve the same, but using LibGDX (also taking care of the new densities required by iOS device resolutions, if any change is required)?
Thank you.
Yes you can achieve the same, but it wont be automatic like on Android unless you write some native code as well. I have found that the best way to manage it is simply to do it yourself:
1) When your app starts you can get the screen size and density using Gdx.graphics.getHeight(), getWidth(), Gdx.graphics.getDensity()
2) Depending on the size and density you can change the location path to the correct folder where your assets should be loaded from.
3) Now when any asset loading code is run make sure that it uses your pre-set path from the step above, so that you get the correct assets for that display size/density.
Most of the time you can use the largest image and use `Viewports' to handle resolution and aspect ratio for you. The larger images will be scaled down and this will result in some loss of detail of course.
Viewports will automatically scale the size you want to show of your game world to the screen it displays it. For example FitViewport(100, 100) will create a viewport that shows 100 x 100 "game units". If you would play this on a 1920 x 1080 device it will scale that 100 x 100 game world to a 1080 x 1080 area and leave an empty bar of 840 x 1080.
The size of the game world has nothing to do with pixels. You could create a enemy with the size of 0.5f x 0.5f world units and give that a texture of 256 x 256 pixels. Your viewport scales this for you to the correct size.
Unless you want a pixel perfect game this should be good enough. On some bigger screens but low resolutions devices you might get some minor artefacts due to filtering, setting the filtering for your textures Texture.setFilter(TextureFilter.Nearest, TextureFilter.Linear) might fix some.
All I ever think about when designing graphics are the pixels in my art should represent roughly or at least 1 screen pixel. Usually I just draw pixel perfect for HD and it looks fine on a 800 x 480 screen. If you want to squeeze out a bit more performance you could use MipMaps, I think TexturePacker generates them automatically with the right Filter settings but I have no experience with them.
This can be done using
com.badlogic.gdx.assets.loaders.resolvers.ResolutionFileResolver.
Here is javadoc for it.
When using int resolution = Toolkit.getDefaultToolkit().getScreenResolution(); to get my monitor's resolution, the integer resolution returns 96. What does this mean, how could it be used, and, if possible, could I get the resolution in a 4:3, 16:9, etc. format?
getScreenResolution() return dots-per-inch (DPI). If you want the size of the screen, just use getScreenSize().
Here's a quote that gets you the basic idea of DPI vs. pixels:
So, if you have a 600 pixel x 600 pixel image at 300DPI, it will output at 2 inches square. If you change this images DPI to 150, this will mean it will output at 4 inches square. So, as you can see, changing the DPI of an image changes it output size.
You can find rest of the explanation here.
This isn't directly a programing problem but I feel it still can fall under the catagory, I am sorry if this is the wrong place. I am making a game in flash using box2d and I decided to draw the levels in flash as the level design would look better, The levels are very large ( this level is 10,000 pixels long) and the canvas in flash just won't display anything.
The preview in the library seems to be able to display the drawing longer than the one on the stage. How do I go about making the canvas longer? Should I try upgrading to a newer version of flash, does that version allow this?
You just don't put everything at once over your canvas, instead draw only those level primitives or parts that are visible right now. Or, if your level is basically a pretty simple shape, you can just change its X and Y so that the relevant part of the level is displayed on stage.
Don't use giant bitmaps - they use a lot of memory, and even if not all of the content is visible, they will degrade performance considerably. For this reason, Flash imposes a size limit of 4095x4095 pixels (or an equal amount of pixels in rectangular formats).
The way to deal with this is to tile your graphics into parts of equal size, preferably smaller than the stage (1/2 or 1/3 side length is a good measure). You then place them all as a grid into a larger Sprite or MovieClip and set visible=false; on each tile. Then, at runtime, your game loop must check for each frame, which of the tiles should actually appear on the stage - and only those should then be set to visible=true;. That way, you reduce the amount of pixels drawn to what is absolutely necessary, and keep screen memory usage to a minimum.