PrintDocument default DPI value in C#? - c#

I created some graphics to be printed assuming that the PrintDocument class uses the standard 96 dpi (an inch of the drawing requires 96 pixels on the printout), but when I print those graphics on paper they appear smaller thus not having the appropiate dimensions.
So what is the default DPI value of the PrintDocument class?
Thanks in advance!

This answer is by Hans Passant:
In your PrintPage event handler, the e.Graphics.PageUnit property
is set to GraphicsUnit.Display. Which makes 100 "pixels" equal to
one inch on paper. Regardless of the printer DPI. Close to the default
DPI for the screen, not quite.

Related

Why this Bitmap Image changes its size after I load it?

Quick question:
I have this 1000 x 1000 bitmap image:
and I use this routine to load it:
private BitmapSource initialBitmap = new BitmapImage(new Uri("C:\\Users\\...\\Desktop\\Original.bmp"));
Why after I load it, and right after I step over the above line, I see it as 800 x 800?
P.S I want it to be 1000 x 1000 and without using any Resize functions. It was working and suddenly it is 800*800 !
The values returned by BitmapSource.Width and BitmapSource.Height are not in pixels, but rather WPF's device-independent units, which are always 96 dpi. E.g.:
Gets the width of the bitmap in device-independent units (1/96th inch per unit).
If you want to know the actual pixel width and height, you need to use the PixelWidth and PixelHeight properties.
Your question isn't very specific, but if what you are actually concerned about is having the bitmap display at the same size in which it was authored, then the easiest solution is to make sure you author it at 96 dpi. Whatever program you're using to author the bitmap likely has a place where you can set the bitmap resolution. Typically this can be set with or without changing the pixel dimensions of the image (i.e. scaling the image larger or smaller); you want to do it without scaling the image, so that the pixel dimensions remain the same but the dpi changes to match what WPF is using.
Note that this still won't guarantee the bitmap displays at a specific pixel size. The display resolution can be and often is different from 96 dpi, in which case WPF will scale images to ensure that the physical dimensions of the image (i.e. the dimensions in inches, millimeters, etc.) are correct according to the information in the bitmap. For example, 960 pixels wide at 96 dpi means 10" wide. On a 120 dpi display, this means displaying the bitmap large enough so that its width uses 1200 display pixels.
If you want or need the bitmap to display at exactly the same number of display pixels regardless of the display resolution, then you'll have to set a transform where you display the image to reverse the effect of the scaling that WPF would otherwise do. This requires knowing the display resolution, of course.
Here are some other related Stack Overflow questions which you might find useful:
RenderTargetBitmap renders image of a wrong size
WPF for LCD screen Full HD
Screen Resolution Problem In WPF?
This is by design. Note the MSDN documentation for BitmapSource.Width/Height:
Gets the width of the bitmap in device-independent units (1/96th inch
per unit). (Overrides ImageSource.Width.)
Instead you should use the PixelWidth / PixelHeight property:
Gets the width of the bitmap in pixels.
A rather confusing choice or terms, imo, but there you go..

Dealing with multiple DPI screens

Let's suppose that I have two screens, side by side:
1920x1080 100% DPI
1360x768 125% DPI
For my Window, this means:
1920x1080: Ok
1088x614: Not ok, it's divided by 1,25 because of the scaling factor.
Turning into this:
1920x1080 + 1088x614: 3008x1080
I want to use the CopyFromScreen/BitBlt methods.
These methods ignore all DPI info, making the Left and Top properties (of a window, for example) useless if inside a high dpi screen. Or left to a high dpi screen, since it behaves like 1 screen, example:
So whenever I need to get a screen point from within a set of screens with at least one having a high DPI, it will return a smaller point.
Is there any way to get the true (by true, ignoring the scaling factor) XY info from a set of screens with (at least one) high DPI?
I already tried the managed PointToScreen and the unmanaged ClientToScreen methods, both resulting the same "right" point.
Please, read
I want to take screenshots of the screen based of the position of my Window.
I have two monitors, one with 100% DPI, other with 125% DPI.
If my Window is inside the 1st monitor, the screenshot based on the Left/Top properties of my Window works.
If my Window is inside the second monitor, the screenshot won't take the right spot!
Because
The BitBlt API method ignores the scaling of the screens. Example:
Screenshot of the point 100;100 will be right, because it's inside the 1st screen.
Screenshot of the point 1950;100 won't be right, because it's inside the 2nd screen. Notice that it's 30 pixels to the right.
Why?
As said earlier, for my app, the 125% DPI reduces the screen resolution to 1088x614, but for the BitBlt method, it is still 1360x768.
So I can't convert the Left/Top properties, because it will be wrong, since there is a 100% DPI screen to the left.
Example of the Left property:
I believe this is the right way to convert:
1920px + 50px: 100% + 125%: 1920 + 62: 1982px
And this is the proposed version:
1920px + 50px: 100% + 125%: 2400 + 62: 2462px
See, if I simple convert the current Left property based on the DPI of the current Window, on this case my second screen, I'll also be converting the values of my first screen. This should not happen.

MeasureString() gives different size for different screen resolutions

We are using Measurestring() to calculate size based on the length of text. For different screen resolution, MeasureString() gives different size.
Graphics g;
Size size = g.MeasureString(GetItemText(this.Items[n]), this.Font).ToSize();
width=size.width;
For Screen resolution 125%, size.width=76 and
For Screen resolution 100% and 150%, size.width=61.
How can i get same width in this code, please suggest me some ideas to measure size using measurestring().
Waiting for suggestions........
It's because the 125% behaves differently by default. For example, in Windows 7, if you change the DPI setting, because of the Windows XP style mode, the applications will aware of the current DPI setting. However, if you set 150%, this checkbox is not set by default, so the applications will work in DPI unaware mode, which means, that the MeasureString will return the same result as in case of 96 DPI, and the resizing will be performed automatically by Windows.
Normally you can ignore the result, because the sizes will be upscaled in your application anyway. If you still want to obtain the actual DPI value of Windows, see my answer here: https://stackoverflow.com/a/33412669/5114784
And then you can upscale your drawing like this (but as I said, normally this is not needed):
// See GetSystemDpi in the referenced post
float zoomFactor = (float)GetSystemDpi() / 96f;
size.Width = (int)(size.Width * zoomFactor);
size.Height = (int)(size.Height * zoomFactor);

How to give a textbox a fixed width of 17,5 cm?

I have an application with a textbox, and the width of the textbox on the screen must always be 17,5 centimeters on the screen of the user.
This is what I tried so far:
const double centimeter = 17.5; // the width I need
const double inches = centimeter * 0.393700787; // convert centimeter to inches
float dpi = GetDpiX(); // get the dpi. 96 in my case.
var pixels = dpi*inches; // this should give me the amount of pixels
textbox1.Width = Convert.ToInt32(pixels); // set it. Done.
private float GetDpiX()
{
floar returnValue;
Graphics graphics = CreateGraphics();
returnValue = graphics.DpiX;
graphics.Dispose(); // don’t forget to release the unnecessary resources
return returnValue;
}
But this gives me different sizes with different resolutions.
It gives me 13 cm with 1680 x 1050 and 21,5 cm with 1024 x 768.
What am I doing wrong?
The method graphics.DpiX does not give the real dots per inch of the monitor. It returns the DPI set in Windows Display properties, mostly either 96 or 120 DPI.
It is not possible to read the real DPI of the monitor. Microsoft did research this for Windows Vista/7 but as long as manufactures of monitors do not provide a standard way to read the value from the monitor hardware it will not be possible.
Yes, unfortunately Xenan is right.
To workaround the problem you could allow a sort of by hand calibration, done by the user.
e.g. draw a line of 400 pixel on the screen, ask the user to measure it on the screen and set the result. Now is really simple to calculate the PPI (pixels per inch) that is your calibration.
Width property of the Size structure depend on PageUnit and PageScale settings of the Graphics class. Try playing around with these settings to get your desired effect. Since you most likely need to modify these settings on the Paint event of the control, I suggest you create your own custom TextBox control instead.

Setting image DPI in relation to height/width C#

I'm writing an application to send some images to a third party, and the images must be 200x200 DPI. The image is a Bitmap and is sized at 500 width and 250 height.
The first time I tested the images with the third party, my resolution was incorrect. I merely used image.SetResolution(200,200) to correctly set it to 200x200. This, however, only changed the resolution tag for the image and did not properly, according to my third party technical contact, adjust the image height and width.
Is there a ratio that I can use so that for each X units I increment the resolution, I merely increment the corresponding height or width Y units? I thought that I could just increment resolution without having to increment height or width.
Thank you,
Aaron.
An image stored digitally has no meaningful concept of DPI. DPI comes into play when reproducing an image on a physical device.
You need to adjust the image size with regard to the DPI of the physical device, and the desired size of the output on that device.
For example, if a printer tells you they need an image at 300dpi to fill a space of 4in x 4in then you would provide them a bitmap with a size of 1200x1200 pixels. This image would end up with a physical size of 4in x 4in on a 300dpi output device. On a 600dpi device the same image would have an output size of 2in x 2in.
When dealing with digital images, you usually refer to PPI, which is pixels per inch. DPI is not directly related to digital image resolution.
So, if you look at a image that is 200px by 200px # 200PPI, you will have an image that is 1 inch by 1 inch.

Categories