I am drawing a bitmap on a window and I need to emulate ImageLayout.Zoom functionality.
This is what I am using right now:
if (_bitmap.Width > _bitmap.Height)
{
ZoomPercent = (int)(((double)ClientRectangle.Width) / ((double)_bitmap.Width) * 100);
}
else
{
ZoomPercent = (int)(((double)ClientRectangle.Height) / ((double)_bitmap.Height) * 100);
}
..where ZoomPercent is a property that allows me to change the ratio which the bitmap is drawn. For example, if ZoomPercent = 200, it will draw it at a 200% or 2.0 ratio, so a 1000x1000 bitmap would be drawn as 2000x2000.
In my head, the code above should work, but it's not. For example, if the Bitmap is 800x600, then the width is greater, and if the ClientRectangle is 1000x1000, then it should calculate 1000 / 800 = 1.25 * 100 = 125. So 125%. Which will stretch the bitmap to be 1000x750 which fits within the ClientRectangle. However it is not working in all circumstances.
Bob Powell wrote an article about this: Zoom and pan a picture.
In case the link dies, here is the posted code from that article:
public class ZoomPicBox : ScrollableControl
{
Image _image;
[
Category("Appearance"),
Description("The image to be displayed")
]
public Image Image
{
get{return _image;}
set
{
_image=value;
UpdateScaleFactor();
Invalidate();
}
}
float _zoom=1.0f;
[
Category("Appearance"),
Description("The zoom factor. Less than 1 to reduce. More than 1 to magnify.")
]
public float Zoom
{
get{return _zoom;}
set
{
if(value < 0 || value < 0.00001)
value = 0.00001f;
_zoom = value;
UpdateScaleFactor();
Invalidate();
}
}
/// <summary>
/// Calculates the effective size of the image
///after zooming and updates the AutoScrollSize accordingly
/// </summary>
private void UpdateScaleFactor()
{
if(_image==null)
this.AutoScrollMinSize=this.Size;
else
{
this.AutoScrollMinSize=new Size(
(int)(this._image.Width*_zoom+0.5f),
(int)(this._image.Height*_zoom+0.5f)
);
}
}
InterpolationMode _interpolationMode=InterpolationMode.High;
[
Category("Appearance"),
Description("The interpolation mode used to smooth the drawing")
]
public InterpolationMode InterpolationMode
{
get{return _interpolationMode;}
set{_interpolationMode=value;}
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
// do nothing.
}
protected override void OnPaint(PaintEventArgs e)
{
//if no image, don't bother
if(_image==null)
{
base.OnPaintBackground(e);
return;
}
//Set up a zoom matrix
Matrix mx=new Matrix(_zoom, 0, 0, _zoom, 0, 0);
//now translate the matrix into position for the scrollbars
mx.Translate(this.AutoScrollPosition.X / _zoom, this.AutoScrollPosition.Y / _zoom);
//use the transform
e.Graphics.Transform = mx;
//and the desired interpolation mode
e.Graphics.InterpolationMode = _interpolationMode;
//Draw the image ignoring the images resolution settings.
e.Graphics.DrawImage(_image, new rectangle(0, 0, this._image.Width, this._image.Height), 0, 0, _image.Width, _image.Height, GraphicsUnit.Pixel);
base.OnPaint(e);
}
public ZoomPicBox()
{
//Double buffer the control
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.ResizeRedraw |
ControlStyles.UserPaint |
ControlStyles.DoubleBuffer, true);
this.AutoScroll=true;
}
}