C# user control scaling image wrongly - c#

I have a usercontrol with an Image property. The image is the resources.resx and has a size of 48x48.
When I draw the image on the control using:
e.Graphics.DrawImage(image, 0, 0);
//or
e.Graphics.DrawImageUnscaled(image, 0, 0);
The image is always scaled to about 1.5 times its size. The only way to keep the image the size I want it is to pass a Rectangle to the methods.
Why is the usercontrol/image behaving like this?

When you say the image is scaled I suppose you are referring to its number of pixels...
But DrawImage use the device resolution to maintain its "physical size".
See this from msdn:
The DrawImage method draws an image using its physical size, so the
image will have its correct size in inches regardless of the
resolution (dots per inch) of the display device. For example, suppose
an image has a pixel width of 216 and a horizontal resolution of 72
dots per inch. If you call DrawImage to draw that image on a device
that has a resolution of 96 dots per inch, the pixel width of the
rendered image will be (216/72)*96 = 288.
...so this is the reason of the function behavior.
The same applies to DrawImageUnscaled.

Related

Not getting exact result using the DrawImage function

Okay, so I have an Image which holds my tile set. Then I have my PictureBox used as my "game screen". All the code does is takes a snippet of my tile set (a tile) and place it on the game screen.
Here's my code.
private void picMap_Click(object sender, EventArgs e)
{
//screenMain = picMap.CreateGraphics();
// Create image.
//gfxTiles = Image.FromFile(#Program.resourceMapFilePath + "poatiles.png");
// Create coordinates for upper-left corner of image.
int x = 0;
int y = 0;
// Create rectangle for source image.
Rectangle srcRect = new Rectangle(16, 16, 16, 16);
GraphicsUnit units = GraphicsUnit.Pixel;
// Draw image to screen.
screenMain.DrawImage(gfxTiles, x, y, srcRect, units);
screenMain.DrawImage(gfxTiles, 16, 0, srcRect, units);
screenMain.DrawImage(gfxTiles, 32, 0, srcRect, units);
screenMain.DrawImage(gfxTiles, 16, 16, srcRect, units);
}
And here is my output:
Any reason why that space between each "tile" is there (it's a 2 pixels gap)? I could ghetto rig the code, but I plan to use algebra to programatically figure out where tiles need to go, etc etc, so a ghetto rig would work, but to do that throughout the entire game would be troublesome, and at the very least, sloppy.
I think the call to DrawImage is okay. In the image you posted it looks like 16x16 tiles next to each other. I'd check poatiles.png. I'm not sure what's at Rectangle(16, 16, 16, 16) in it. It may not be what you think.
EDIT: I don't know what to say. I made a png almost the size of poatiles and put a 16x16 square in it a 16,16, and it drew exactly like you'd expect.
The code looks fine and since it works on smaller images, the only thing I can think of is there's a problem with poatiles.
There's the following comment in MSDN about Graphics.DrawImage Method (Image, Int32, Int32, Rectangle, GraphicsUnit)
This method draws a portion of an image using its physical size, so
the image portion will have its correct size in inches regardless of
the resolution (dots per inch) of the display device. For example,
suppose an image portion has a pixel width of 216 and a horizontal
resolution of 72 dots per inch. If you call this method to draw that
image portion on a device that has a resolution of 96 dots per inch,
the pixel width of the rendered image portion will be (216/72)*96 =
288.
Since you're specifying pixels as the unit I'd expect it to ignore that. But in the absence of better ideas you might want to compare the dpi of poatiles versus the smaller images. (Image.HorizontalResolution & Image.VerticalResolution)
I'm not sure that all of the information is there to start with, but here's some suggestions I have from looking at what you've done so far.
1) Check poatiles.png to make sure that it's definitely a 16x16 pixel image with no black pixels around it.
2) It seems odd that your Rectangle has four int's in its constructor. A rectangle should usually only have a width and height (if any sides have different lengths, then it's not a true rectangle!)
3) You might want to determine your positions on screen by multiplying by width and height of the Rectangle that you're trying to draw and adding that value to the origin (0,0).

Extract size of the image embedded in a PDF

I have an image embedded in a PDF file. I was able to extract the resolution of the image. However, if i crop the PDF using iTextsharp and a part of the image is cropped in the process. The new image continues to have the same resolution. By resolution I mean the dimension in the form of Width x Height. The cropped image is supposed to have a smaller size. How can I extract the size of the image in inches, if possible, so that I can differentiate the original image from the cropped pdf?
Embedded images in PDFs are never "cropped" in the sense that the "cropped-away" parts are gone forever. They are only cropped in the sense that these parts are hidden or masked.
If the image data inside the PDF say /Height 216 and /Width 288 then this is the size in Pixels (not inches or any other length unit). And "resolution" is then secondary:
if the PDF environment commands that this image should be rendered onto a square of 3x4 inches, its resolution in this moment is 72x72 dpi.
if the PDF environment commands that this image should be rendered onto a square of 1.5x2 inches, its resolution in this moment is 144x144 dpi.
However it can well be that the image is only partially visible ("cropped"), maybe because half of it is rendering beyond the page borders...

The difference in image resolution (ppi) between C# and Photoshop

For example, C # says that the selected image contains 96 ppi, while that same image in Photoshop contains 72 ppi.
Why is there a difference?
I’m inclined to trust Photoshop in this case, and how to test image resolution if C# returns false results?
We need to build some sort of validator control that rejects all images with ppi != 300.
Control should support the following formats: jpg, jpeg, gif, png, bmp.
Code is listed below:
Image i = Image.FromFile(FileName);
Console.Write(i.VerticalResolution);
Console.Write(i.HorizontalResolution);
DPI means dots (pixels) per inch. The physical size in inches is subjective, based on the current monitor's size and resolution. Unless you're relying on metadata (which gif and bmp don't contain) you cannot reliably calculate this.
Photoshop simply has a prescribed value for DPI, which it uses when translating images for print. This value is stored in the PSD file and may be copied to JPEG metadata, but if you save the image in a format without DPI metadata, the information is not stored.
Update:
The reason your code gets a different value is that C# fetches its VerticalResolution and HorizontalResolution values from the current DPI setting on the computer. Photoshop's DPI is for use with print, so it knows the physical dimensions if you want to send your image to a printer. It has a default value of 72dpi, but you can change this. The value has no meaning on a screen, though, since screens deal in pixels only.
DPI means dots per inch. A bitmap image does not have an inherent DPI, it merely has a size which is the number of pixels in the horizontal and the number of pixels in the vertical (width and height). An image only gains a resolution (in DPI) when you say how many pixels you want to squeeze into each inch.
So if I have an image that is 100 pixels wide and 100 pixels high (100px × 100px), it will be 100 DPI if I print it (or convert it into a format that dictates the print size) such that it fits exactly in a one square inch (1" × 1"). It will be 50 DPI if I print it to fit in a square that is two inches by two inches, &c.

Scaling and printing a Bitmap object

I have a Bitmap object created by drawing several controls with the DrawToBitmap method. I would now like to print the bitmap. However, the bitmap is too large to fit on a single page and so it must be scaled down. I'm trying to do that using the following overload of DrawImage:
public void PrintPageHandler(object sender, PrintPageEventArgs e)
{
Bitmap bitmap = GetBitmap();
Rectangle destRect = new Rectangle(
e.MarginBounds.X,
e.MarginBounds.Y,
e.MarginBounds.Width,
e.MarginBounds.Width * bitmap.Height / bitmap.Width);
e.Graphics.DrawImage(
bitmap,
destRect,
0,
0,
bitmap.Width,
bitmap.Height,
System.Drawing.GraphicsUnit.Pixel);
}
Note that the destRect width and height are constructed like this because the bitmap is much wider than it is tall (i.e. width is always the limiting dimension).
My problem is that the image ends up being very blurry when it's printed. Am I scaling this incorrectly? I have a feeling there may be some issue with a GraphicsUnit mismatch between e.MarginBounds and the image dimensions. Any help would be appreciated.
[UPDATE]
I tried resizing the bitmap using the method given in the comment below, but the image still prints blurry. For testing, I saved both the original and resized bitmap to files, opened them in Windows Photo Viewer, and tried to print them from there. The resized image prints blurry like it does from within my c# application, but the original image prints beautifully; whatever algorithm Windows Photo Viewer uses to resize to a single page did not cause the image to get blurred.
I wonder, could Windows Photo Viewer be increasing the pixel density when it resizes for printing? Maybe that's why resizing it in code is causing it to get blurred; the origin pixel density is insufficient to display the scaled down image clearly.
It doesn't look like you are preserving the aspect ratio. You need to calculate the ratio of the width to height of the original image and make sure to scale the output image so that it's dimensions have the same ratio.
Basically:
1 - Calculate the aspect ratio.
2 - Find the largest dimension of the target size.
3 - Resize the output so that the largest dimensions matches, and set the smaller dimension to the larger one multiplied by the ratio.
EDIT
Check the graphics.dpiX and .DpiY proeprties to see if your printer has a different DPI going horizontally from vertically. If they are different you will have to apply some additional adjustments to the dimensions.

How can I crop image without changing its resolution in C#.Net?

I made small program to divide large pictures and take part of them.
When i import image that made by "Microsoft Paint" this image is "96 dpi" so my program doing well.
But I've pictures that made by Photoshop its resolution is 71.6 dpi when i crop these pictures the new cropped picture take 96 dpi resolution so the size is deference between them.
I want to crop the picture with keeping its resolution as it.
.
thank you very much
Bitmap.clone lets you create a cropped copy of an image, which you can then save. It shouldn't change resolution or anything (the image will look bigger if you open it in a program that zooms in more when images are smaller). It cannot be used to expand the canvas (you'll get out of memory errors). So, just grab an Image from file, cast to Bitmap, (system.drawing namespace) and clone it to be smaller, then save it.
Example:
using System.Drawing;
//...
Bitmap x = (Bitmap) Image.FromFile(#"c:\tmp\food.png");
Image x2 = x.Clone(new Rectangle(25, 25, 50, 50), x.PixelFormat);
x2.Save(#"c:\tmp\food2.png");
DPI (dots per inch) is just a relationship between pixel size and the size on a medium. If you have an image which is 1024 x 768 pixels, it is 1024 x 768. There is no inherent DPI attached to a bitmap/binary file.
If you want to print that image on a printer which prints at 300 dpi, then you can calculate the size on the paper, for example.
The SetResolution() method of the Bitmap class allows you to specify the resolution of an image.
See http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.setresolution.aspx

Categories

Resources