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.
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).
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How to define DPi for a new JPG image?
Is there a way to get a resolution (pixels per inch) of an image in Java? Either with Native APIs or third party libraries. I don't just want the height and width of an image but actually the resolution that determines the output quality of an image.
An image has only pixels. it has not ppi.
a monitor, an image sensor and an printer have ppi because they all have dots/pixels related to a measurable distance in inch.
ppi is short for pixels per inch, and therefore a measure for pixel density.
for calculation of ppi / dpi see http://en.wikipedia.org/wiki/Dots_per_inch
You simply divide the number of pixels or points by the number of inch that the output device or photo paper has.
But be carefull if points or pixels is wanted.
When I first asked this, I included as much information as I could, since I never know what will help someone if they can give m a solution, but from the answers, it seems I didn't make my point clear.
I'm leaving the original text at the bottom and shortening this. I hope that makes it clear.
I am working with images returned to me from another program. I can get an image that's, for example, 8x10 at 72 DPI or the same image at 16x20, also at 72DPI.
I'm working in Java. What I'd like to do is take the 16x20 image and resize it. If possible, I'd like to just change the file so instead of being 16x20 at 72DPI, it's 8x10 at 144DPI.
I know that it's still the same number of pixels, but viewers will say how big an image is and what the DPI is and also some open an image to its full size, so I'd rather them treat the 16x20 as a smaller image with a higher resolution.
Can I do that in Java? Will I lose any data? How would I do it - can I just change the metadata in the png or jpg file?
-----(original question below here)-----
I've seen a few questions that come close to this, but this is a little different.
I know you can decrease image resolution with an image in Java (also here). Any searches I've done have been concerned with decreasing the resolution of an image.
I have the opposite problem. I'm working with an image that I'm getting back in 72DPI. The advantage is I can increase the size of the picture, so I could make the size 100%, 200%, 400% and so on. All images are at 72DPI, so if I use 200% for the zoom, then open the image in a viewer and make it the same size as the 100% image, I am seeing a better resolution.
For clarity - I am getting an image from someone else, it could be generate from a PDF or picture, but I am given the image from another program. No matter what I do, this image is at 72DPI. I can't change that, but I can specify the size at 200% and it still comes back at 72DPI, just twice as big and with more detail.
I'm no graphics expert and this is the first time I've done any programming that uses graphics. The output could be jpg or png, so the format isn't that important. (I could probably also use other formats if needed.)
Let's say the original image is a photo - 8" x 10", and at 72 DPI. If I ask for a 200% zoom, I get a 16" x 20" image at 72DPI.
Can I, within Java, change that larger 16" x 20" 72DPI image to a 144DPI image that's 8" x 10" without losing data? In other words, double the DPI, but cut the size in half?
And, most importantly, can I do it without losing resolution? (I would think that can be done.)
No, if you take an 8x10 72dpi image and ask for a 200% zoom you'll get a 16x20 at 36 dpi. You can't magically increase image resolution.
What counts is the total number of pixels in the image. The stated DPI is just what the DPI will be at a specific size. Take your 8x10 image at 72dpi. It has 576x720 pixels. If you zoom to 200% you still have the same number of pixels, but now they'll be spread out over twice the linear dimensions, meaning the individual pixels will be bigger. Some software will attempt to increase resolution by interpolating pixels, i.e. creating new pixels by averaging the nearest neighbors. This can give the impression of higher resolution but the image does not contain any more data. It always has the effect of softening the image, especially any sharp edges or lines.
If you reduce the size of an image without resampling, you do increase the printed or displayed resolution, but the image gets smaller. For the same image, increasing the DPI to 144 will reduce the image size to 4x5.
This is tricky because, like so much in Java, you can't just access something in a simple way. Java does not keep track of DPI, but it does use dots per millimeter. Also, another part that is confusing is that you cannot change this kind of information in an image, or in a BufferedImage. You can only change this information when you are writing a BufferedImage out through an ImageWriter.
I was able to do this. As I said, I could specify the zoom on the image that was returned to me. No matter what zoom level, the output was 72 DPI. My goal was 300DPI. I specified a zoom level of 400%. So, on an 8" wide image of 72 DPI, that returned to me a 32" image of 72 DPI. All I had to do was specify a DPI of 288 (72 x 4) to override the default 72 DPI I was dealing with and then when it was written out, the image had the same number of pixels, but was considered to be done at 288 DPI rather than 72 DPI.
Here's a code snippet:
//Assumed there's already an ImageWriter iw
ImageWriteParam writeParam = writer.getDefaultWriteParam();
ImageTypeSpecifier typeSpecifier =
ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);
if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported()) {
continue;
}
// Set Parameters and info
int DPI = 72 * scaling/100;
double dotsPerMilli = 1.0 * DPI / 10 / 2.54;
double checkDots = 1.0 * 144 / 10 / 2.54;
System.out.println("Dots per inch: " + DPI + ", DotsPerMilli: " + dotsPerMilli + ",
CheckDots = " + checkDots);
IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize");
horiz.setAttribute("value", Double.toString(dotsPerMilli));
IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize");
vert.setAttribute("value", Double.toString(dotsPerMilli));
IIOMetadataNode dim = new IIOMetadataNode("Dimension");
dim.appendChild(horiz);
dim.appendChild(vert);
root.appendChild(dim);
metadata.mergeTree("javax_imageio_1.0", root);
// From here, just write out file using an ImageOutputStream
final ImageOutputStream stream = ImageIO.createImageOutputStream(outFile);
System.out.println("Output file: " + outFile);
try {
writer.setOutput(ImageIO.createImageOutputStream(outFile));
writer.write(metadata, new IIOImage(image_to_save, null, metadata),
writeParam);
} catch (Exception e) {
System.out.println("Caught exception " + e + " when trying to write out
file.");
System.exit(0);
} finally {
stream.close();
}
how to convert
1 cm to ?px
this conversion used in html parser
% conversion is -> (allToPx[0]) * 16)/100) px
pt conversion is -> (allToPx[0]) * 16)/12) px
em conversion is -> (allToPx[0]) * 16)/1) px
but how to convert in cm ?
You have to figure out the pixel density for the display you work on. This might be drastically different. You have to get these data:
width of screen
height of screen
vertical pixels
horizontal pixels
Then you can calculate what the actual size of a given pixel vertically and horizontally...
But obtaining this kind of information is not always possible. You might have to use some platform dependant trickery to get these, if even possible... Also, you didn't specify what kind of UI library you use. That might be of help for us to be able give advice.
There is no cm conversion as the size of the elements in cm depends heavily on the screen density (pixels per inch or cm), which you can't access on most devices
It would not be impossible to convert cm to px since they are not of the same unit types.
cm is an absolute length unit while px is a relative length unit
Its just like saying, "Can I convert kilos to hours?"
Use this as reference: http://msdn.microsoft.com/en-us/library/ms537660(v=vs.85).aspx
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.