Detect Original Picture From Scanned Image - c#

When I scan a small picture, the scanner output is a big picture. How can I detect original picture from scanned image?

I think you are confusing physical size with resolution. The photograph you are scanning obviously has a physical size — you can measure this with a ruler. When you scan however, you end up with a picture that has a resolution (pixel size) rather than a physical size and this is controlled by the DPI setting in your scanning software. DPI means dots-per-inch and controls how many dots (pixels) will be created for each inch of your photograph — 300 dpi would result in 300 pixels across for each inch width of your photograph and 300 pixels down for each inch of height. As an example, a photograph 10 inches square would produce a 10 * 300 * 10 * 300 = 9 million pixel (or approximately 9 mega-pixel) image.
Physical size will not actually have much meaning on the computer until you come to print your image again*. Then, you can specify the output DPI — how many pixels make up each inch of your printed document. So if you were to scan at 300 dpi and print at 150 dpi, you would end up with an image that is twice the size of your original (as less pixels are making up each inch so those scanned pixels go twice as far). For example, the 9 million pixels of the above example would be printed 150 for every inch across and down (150² per square inch) thus would produce an image that is 20 inches square.
Physical size and resolution are intertwined, however. The more dpi you scan at, the more information about the original document you preserve which means you can print at much larger sizes without the image appearing pixelated. As an extreme example, if you were to print at 1 dpi, you could make those scanned pixels spread over a huge number of inches but each square inch would be a block of solid colour.
* The web mixes things up in that images are usually handled in pixel form thus their size on screen is dependent upon the user's monitor and page zoom settings.

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..

PrintDocument - Scale or something else not right?

I'm using a C# printdocument class. My printer's driver is set to print at 1000 DPI. I am placing strings down the page at various intervals. I am using a PageUnit of Pixel (so 1,000 pixels = 1 inch?) to place these DrawString()s down the paper. Higher in the paper, they appear fine; however as you get lower, they aren't quite as far down as they should be. By the bottom of the paper, it's off a quarter of an inch.
Any ideas where I should start to resolve this issue?
For example: the DrawString() that should be Y coordinates 4147 (pixles) down (at 1000 DPI, should be about 4.147 inchs down) is actually only about 4.010 inches down~.

What is the relationship between ScaleTransform and Pixel

I am new to the concepts of pixels, dpi, resolution and stuffs. So let me put out this simple question for which I am finding hard to get a simple answer
What is the default measuring unit in wpf
When I apply a scale transform to a button, how is it getting bigger (whats really happening)
What is the unit of the zoom factor in wpf
How is the zoom factor related to pixel (or location of a control that is scaled)
That subjet is quite complex actually.
Unit
In WPF, all sizes are expressed in Device Independent Unit (DIU).
1 DIU = 1/96th of an inch.
1 DIU = 1 pixel on a 96 DPI display.
1 DIU = 2.083333 pixels on a 200 DPI display.
Scale and Zoom
You look confused here. A scale/zoom of 1.0 means 100%, 2.0 means 200%, 0.5 means 50%. There is not unit, it's a factor.

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.

How do I determine the true pixel size of my Monitor in .NET?

I want to display an image at 'true size' in my application. For that I need to know the pixel size of the display.
I know windows display resolution is nominally 96dpi, but for my purposes I want a better guess. I understand this information may not always be available or accurate (e.g. older CRT displays), but I imagine with the prevelance of LCD displays that this should be possible!
Is there a way to get the pixel size of my display?
Is there a way to determine if the pixel size is accurate?
.NET API's preferred (I couldn't find them), but Win32 is OK too, I'm happy to P/Invoke.
For the display size you'll want Screen.PrimaryScreen.Bounds.Size (or Screen.GetBounds(myform)).
If you want the DPI, use the DpiX and DpiY properties of Graphics:
PointF dpi = PointF.Empty;
using(Graphics g = this.CreateGraphics()){
dpi.X = g.DpiX;
dpi.Y = g.DpiY;
}
Oh, wait! You wanted actual, hold a ruler up to the monitor and measure, size?! No. Not possible using any OS services. The OS doesn't know the actual dimensions of the monitor, or how the user has it calibrated. Some of this information is theoretically detectable, but it's not deterministic enough for the OS to use it reliably, so it doesn't.
As a work around, you can try a couple of things.
You can try to query the display string of the installed monitor device (I'm not sure how to do that) and see if you can parse out a sensible size out of that. For example, the monitor might be a "ValueBin E17p", and you might deduce that it's a 17" monitor from that. Of course, this display string is likely to be "Plug and Play Monitor". This scheme is pretty sketchy at best.
You could ask the user what size monitor they have. Maybe they'll know.
Once you know (or think you know) the monitor's diagonal size, you need to find its physical aspect ratio. Again, a couple of things:
Assume the current pixel aspect ratio matches the monitor's physical aspect ratio. This assumes that (A) the user has chosen a resolution that is ideal for their monitor, and that (B) the monitor has square pixels. I don't know of a current consumer-oriented computer monitor that doesn't have square pixels, but older ones did and newer ones might.
Ask the user. Maybe they'll know.
Once you know (or think you know) what the monitor's diagonal size and physical aspect ratio are, then you you can calculate it's physical width and height. A2 + B2 = C2, so a few calculations will give it to you good:
If you found out that it's a 17" monitor, and its current resolution is 1280 x 1024:
12802 + 10242 = 2686976
Sqrt(2686976) = 1639.1998047828092637409837247032
17" * 1280 / 1639.2 = 13.274768179599804782820888238165"
17" * 1024 / 1639.2 = 10.619814543679843826256710590532"
This puts the physical width at 13.27" and the physical height at 10.62". This makes the pixels 13.27" / 1280 = 10.62" / 1024 = 0.01037" or about 0.263 mm.
Of course, all of this is invalid if the user doesn't have a suitable resolution, the monitor has wacky non-square pixels, or it's an older analog monitor and the controls aren't adjusted properly for the display to fill the entire physical screen. Or worse, it could be a projector.
In the end, you may be best off performing a calibration step where you have the user actually hold a ruler up to the screen, and measure the size of something for you. You could:
Have the user click the mouse on any two points an inch (or a centimeter) apart.
Draw a box on the screen and have the user press the up and down arrows to adjust its height, and the left and right arrows to adjust its width, until the box is exactly one inch (or centimeter) square according to their ruler.
Draw a box on the screen and have the user tell you how many inches/centimeters it is in each dimension.
No matter what you do, don't expect your results to be 100% accurate. There are way too many factors at play for you (or the user) to get this exactly correct, every time.
Be aware that 96 dpi is usually pretty close to accurate. Modern pixels on non-projected screens all tend to be about 0.25 mm, give or take, so you usually end up with about 100 physical pixels per inch, give or take, if the monitor is set to its native resolution. (Of course, this is a huge generalization and does not apply to all monitors. Eee PCs, for example, have pixels about 0.19 mm in size, if I remember the specs correctly.)
sorry, you've got to P/Invoke for this information.
Here's the link that I utilized for it a while ago:
http://www.davidthielen.info/programming/2007/05/get_screen_dpi_.html
You can check by just manually calculating from your screen size
cos(45)*LCD_SCREEN_DIAGONAL_IN_INCHES/sqrt(HORZ_RES^2 + VERT_RES^2)
That would give you the pixel width in inches
GetDeviceCaps can be P/Invoke'd to get some figures, but I've never known the figures to be that trustworthy...
You may obtain the physical dimensions of the display using the EDID information stored in the registry. You can obtain the appropriate monitor's registry key using the EnumDisplayDevices windows API call.
Physical Dimensions to the Screen object:
TL;DR
WPF's True Size = Pixels * DPI Magnification
DPI Magnification:
Matrix dpiMagnification
= PresentationSource.FromVisual(MyUserControl).CompositionTarget.TransformToDevice;
double magnificationX = dpiMagnification.M11;
double magnificationY = dpiMagnification.M22;
Discussion
I had trouble solving this question still in 2020. Back when this question was asked/answered in 2009, .NET C# probably meant Windows Forms. But WPF is the de facto standard of the day...
By asking about "true size" you have probably already figured out that the operating system does some calculation with actual pixels (say 1366x768, which I understand is usual laptop resolutions) and the DPI (hard to find) in order to give a control's true size. And you are trying to make an app that scales to different monitors.
This DPI actual number seems to be hidden, but it has been normalized (converted to a percentage). Assume 100% = 96 DPI, just because the actual number does not matter anymore. People can easily increase the system-wide text size by going to Desktop on Windows 10 > right click > Display settings > section Scale and layout > change the percentage to magnify text and other elements.
You can find the pixels another way, and multiple/divide the pixel by the DPI percentage in order to get true size. For instance, I want to drag a UserControl around a canvas element of a WPF window with the mouse. The user control's pixel count and the mouse xy-coordinates were off by the normalized DPI. In order to keep the mouse moving at the same rate as the user control, I use:
double newXCoord = System.Windows.Forms.Cursor.Position.X;
double newYCoord = System.Windows.Forms.Cursor.Position.Y;
double deltaX = newXCoord - oldXCoord;
double deltaY = newYCoord - oldYCoord;
double magnificationX = 1;
double magnificationY = 1;
Matrix dpiMagnification
= PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice;
if (magnificationMatrix != null)
{
magnificationX = dpiMagnification.M11;
magnificationY = dpiMagnification.M22;
}
PixelsFromLeft += deltaX / m_magnificationX;
PixelsFromTop += deltaY / m_magnificationY;

Categories