![]() | |
![]() |
| | Thread Tools | Search this Thread | Display Modes |
#1
| |||
| |||
|
#2
| |||
| |||
|
|
My code calculates the size required to maintain the aspect ratio of an image when displaying it. I use a scale transformation to scale the image to the proper size. For some reason my scaling is always off unless I account for the vertical and horizontal resolution of the image being drawn, as well as the DpiX and DpiY of the graphics object. Why is this? My control consists of a main control which can be resized by the user, an inner control which is resized as the main control is resized, and an image which is drawn in the inner control. The inner control is sized to maintain the aspect ratio of the image when displayed in the main control. Here are the steps, I've include relevant code below 1. Calculate Scaling Ratio 2. Resize my control to be the exact size of the image 3. Perform a transformation on my image so it is drawn within the inner control In the function SetupTransform, if I take out the code to regarding the resolution of the Image and the Dpi of the graphics object my scaling is off, if I leave it in the scaling is perfect. I don't understand why? I've tried changing the PageUnits of my graphics object but that doesn't seem to make a difference. 1.Calculate Scaling Ratio public float CalculateScalingRatio(float width, float height) { float largestRatio=0; if (Image != null) { largestRatio = (Math.Max((float)Image.Width / width, (float)Image.Height / height)); } return largestRatio; } 2.Resize inner control so that aspect ratio will be maintained private void MarkedImageContainer_Paint(object sender, PaintEventArgs e) { double largestRatio; float posX, posY; if (m_markedImage != null) { //get the graphics object Graphics g = e.Graphics; if (m_maintainAspectRatio) { //calculate the largest scaling ratio required for the image to maintain //its' aspect ratio largestRatio = m_markedImage.CalculateScalingRatio(Parent.Width, Parent.Height); posX = (float)((Parent.Width - (m_markedImage.Image.Width / largestRatio)) / 2); posY = (float)((Parent.Height - (m_markedImage.Image.Height / largestRatio)) / 2); Width = (int)(m_markedImage.Image.Width / largestRatio); Height = (int)(m_markedImage.Image.Height / largestRatio); } Left = Convert.ToInt32(posX); Top = Convert.ToInt32(posY) + m_topPadding; //make sure the marked image is drawn entirely within this control m_markedImage.Limits = new Rectangle(0, 0, this.Width, this.Height); //render m_markedImage.Draw(g); } else { } } } 3.Tranform and draw image protected override void SetupTransform(Graphics g) { //Why do I need to do this?? float xDpiScale = (m_Image.VerticalResolution / g.DpiX); float yDpiScale = (m_Image.HorizontalResolution / g.DpiY); float trueLimitX = Limits.Width*xDpiScale; float trueLimitY = Limits.Height*yDpiScale; //calculate scaling ratio necessary to draw the image inside of its limits float largestRatio = CalculateScalingRatio(Limits.Width, Limits.Height); ScaleFactor = largestRatio; //create the matrix we'll use to perform the scaling Matrix mx = new Matrix(); mx.Scale(1.0f / largestRatio, 1.0f / largestRatio); g.Transform = mx; mx.Dispose(); } //now draw the image protected override void RenderObject(Graphics g) { //draw the ourTemplate on the surface that was scaled in SetupTransform g.DrawImageUnscaled(m_Image, 0, 0); //reset the graphics object } |
#3
| |||
| |||
|
|
The DrawImage variants that do not explicitly specify the source and destination rectangle and the Pixel GraphicsUnit will automatically make the size translation on the drawing surface. To control the output on the pixel level you need to either be aware of the exact image resolution of the drawing surface and the image or specify the three factors mentioned above. Thanks for the response Bob, |
#4
| |||
| |||
|
|
The DrawImage variants that do not explicitly specify the source and destination rectangle and the Pixel GraphicsUnit will automatically make the size translation on the drawing surface. To control the output on the pixel level you need to either be aware of the exact image resolution of the drawing surface and the image or specify the three factors mentioned above. Thanks for the response Bob, |
#5
| |||
| |||
|
|
DrawImageUnscaled draws the image _physically_ unscaled taking the actual size of the rectangle calculated by the resolution and the pixel dimensions of the picture. It uses the world coordinates and ties them to the resolution of the output device, most likely 96 DPI. If you just want to output the image according to its pixel dimensions and ignore the actual physical size you must use the DrawImage variant that specifies the source, destination and Pixel GraphicsUnit. |
)
#6
| |||
| |||
|
|
DrawImageUnscaled draws the image _physically_ unscaled taking the actual size of the rectangle calculated by the resolution and the pixel dimensions of the picture. It uses the world coordinates and ties them to the resolution of the output device, most likely 96 DPI. If you just want to output the image according to its pixel dimensions and ignore the actual physical size you must use the DrawImage variant that specifies the source, destination and Pixel GraphicsUnit. |
![]() |
| Thread Tools | Search this Thread |
| Display Modes | |
| |