Scale image to fit to A4 page - Migradoc - c#

I am really struggling to get this right, any help would be appreciated.
I have a series of images that I want to build in to a PDF using MigraDoc (1 image = 1 page)
Each image must be displayed on a separate page but may not extend over the page it must fit on to the page perfectly.
So, how do I scale an image (of any size) to fit to a page using MigraDoc?

You call AddImage() to add the image - and in return you get an Image object that allows you to set width and/or height of the image.
What you have to do: check the dimensions of the image, calculate which is the limiting factor (width or height), then set this limiting factor on the Image object and also set LockAspectRatio.
Or set both Width and Height and leave LockAspectRatio off.
For DIN A4, you may allow e.g. 19 cm x 27.7 cm as maximum image size.
For an image with 1000x1000 pixel you would set the width to 19 cm (assuming LockAspectRatio is on). Height will then also be 19 cm automatically.
For an image with 1000x2000 pixel you would set the height to 27.7 cm. Width will then be 50% of the height.

Related

WPF Image control decimates large bitmaps

I'm writing an image viewer application that loads large still images. I must be able to zoom in to 1:1 to measure exact pixel coordinates of features in the image. I'm using the Viewport control posted here that works great for zoom and panning. I can load a 150 MP tiff image with BitmapDecoder and its pixel count is correct 14000 x 10000. However, when I assign this bitmap to the Image.Source property it gets decimated to roughly 15MP:
sourceBitmap.PixelWidth = 14204
sourceBitmap.PixelHeight = 10652
After assigning this bitmap to image1.Source we get
image1.Source.Width = 4545.27...
image1.Source.Height = 3408.64...
I'm aware of the unitless context of WPF graphics, and can work back the scale factors to read original coordinates, but there is a risk of rounding errors, and I'm working on a scaled copy that degrades the original image resolution.
According to the Microsoft documentation, a WPF bitmap can be up to 64GB in size, but the Image control seems not to be designed to work with bitmaps larger than 15MP. Setting Stretch to "None" makes things worst. It trims the image to the top left 4545 x 3408 pixels of the source and it displays it very small, almost as a thumbnail instead of 1:1.
Is there any way around this limitation?
In contrast to a BitmapSource's PixelWidth and PixelHeight, the Widthand Height values depend on its DPI (dots per inch), which is a TIFF or EXIF tag in the image file.
The values are identical when the resolution is 96 DPI, otherwise calculated as
Width = PixelWidth * 96 / DpiX
Height = PixelHeight * 96 / DpiY
Apparently, your images are tagged with 300 DPI.
This does in no way affect the pixel count, but just determines the native, unstretched size of the bitmap when it is shown in an Image element or ImageBrush.
Instead of using Width and Height, just keep using PixelWidth and PixelHeight:
var bitmap = (BitmapSource)image1.Source;
var width = bitmap.PixelWidth;
var height = bitmap.PixelHeight;

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

Why Image size is NaN (wpf) and how to resize via mouse wheel?

I want to load an image and put it into a viewbox. The image is displayed correctly, but, when I'm going to get it's width and height, it's both NaN.
This is my image load code :
Image img = new Image();
img.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("1.png");
Viewbox vb = new Viewbox();
vb.Width = img.Width;
vb.Height = img.Height;
vb.Child = img;
cnv.Children.Add(vb);
The reason I want to get the image width and height is so I could resize it (via viewbox resize) later inside the application.
Any idea how to get the image dimension?
And this is how I'm going to resize it (via mouse wheel)
private void cnv_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (vb != null)
{
vb.Width += Mouse.MouseWheelDeltaForOneLine;
vb.Height += Mouse.MouseWheelDeltaForOneLine;
}
}
And it returns error and said that vb.Width is not a valid value.
Questions to sum this up :
How to get the image width / height in wpf?
How to resize the viewbox (which will also result in image resize) via mouse wheel? For example, if I scroll up the wheel, the width and height is added by 1, and if I scroll down the wheel, the width and height is reduced by 1.
Thank you
P.S. Viewbox vb; and Image img; is a global variable, I just shorten the script down.
P.S.S. I know if the Viewbox width and height initialized by a number, lets say 100 and 100, it will work, I just wanna know how to get the image original size.
EDIT :
The resize can be achieved by detecting whether it's scrolled up or down by detecting e.Delta > 0 or e.Delta < 0
(Source : http://social.msdn.microsoft.com/Forums/vstudio/en-US/170c4fd0-1441-4d83-903d-594af75f8fb4/detect-mouse-scroll)
It seems as though the Image object is not fully loaded at that stage. I believe that you can use the Width and Height properties of the ImageSource class instead. That should be fully loaded at this stage.
ImageSource.Width Property
ImageSource.Height Property
For other users, you can also possibly find the values that you want from the ActualWidth and ActualHeight properties of the Image class (inherited from the FrameworkElement class) instead of the more usual Width and Height properties.
FrameworkElement.ActualHeight Property
FrameworkElement.ActualWidth Property
The image original size can only be obtained in Pixels while your WPF controls are measured in Device Independent Pixels so you're going to have to make a translation from Pixels to Device Independent Pixels and back wherever necessary.
That said, to obtain the width and height for a png file, you can load it into a BitmapImage instead of Image and query the PixelWidth and PixelHeight properties for the BitmapImage.
Again, be aware that this is the only place in your code where you're going to be dealing with Pixels, all Width and Height properties (including ActualWidth and ActualHeight, only set after the control is fully rendered) are measured in Device Independent Pixels. This can be misleading because in a lot of situations this happens to be a 1:1 conversion but this is not guaranteed to be the case.
More info can be found here: http://msdn.microsoft.com/en-us/library/windows/desktop/ff684173%28v=vs.85%29.aspx

Setting Image Width/Height in codebehind - ASP.NET, C#

I am trying to set the width and height of images in a datalist in the codebehind.
The plan is to do something more complex than this based on the width/height, so setting width and height in the aspx file to 50% is not an option.
For some reason I always get 0 for width and height. Image1.ImageUrl is what i would expect though. Any ideas? Image is the System.Web.UI.Webcontrols.Image, not a System.Drawing.Image.
protected void DataList9_ItemDataBound(object sender, DataListItemEventArgs e)
{
Image Image1 = (Image)e.Item.FindControl("Image1");
double height = Image1.Height.Value;
double width = Image1.Width.Value;
height = height * 0.5;
width = width * 0.5;
Image1.Height = new Unit(height);
Image1.Width = new Unit(width);
}
Your code above is referencing a image control that more then likely does not specify a width and or height.
To do what you want I believe you would need to get the source of the image and load it in memory using GDI. Then you could determine the width and height. Then you would be able to do your adjustments to the height and width and apply to the properties of the image tag.
Remember with an img tag, you don't set width and height by default. In this case, unless you set Width and Height, they will be 0 (or undefined). If you need the actual (image, pixels) width and height, you'll need to discover that for yourself by loading the image into memory.
Depending on the filetype, .NET probably has a decoder or the ability to load it already. Load it into a Bitmap then query the width and height there.
I am not sure about c# but I can code it this way in VB.net, so I am sure there is something equivelant and it looks like it will solve your intent if not your actual coding problem.
With dImage
.Width = 50%
.Height = 50%
End With
I tried it both with setting the image height in my xaml as well as leaving it out.
--edited for layout purposes.
Have you tried declaring/defining an OnLoad handler for the image and setting the height/width in there?

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