главная продукты downloads форум тех. поддержка

 

Главная страница

GDI+ FAQ: Calculating Best-Fit Drawing Using A Transform

 

Often, an image needs to be displayed in a rectangle that is not the same size or aspect ratio as the original image. One solution is to make a temporary copy of an image, perhaps a thumbnail, and use this to display the image. Another method often used is to simply stretch the image into the rectangle and hope for the best. This is the PictureBox controls best-fit method. However, in cases where the aspect ratio of the image is important stretching is a poor choice.

 

My favourite method employs the power of GDI+ transforms to draw the image directly without making a copy. A transform can be calculated that fits the longest dimension of the image into the shortest dimension of the destination rectangle, An offset can also be calculated that moves the image into the horizontal or vertical center of the destination rectangle. The resulting transform is then used to draw the image directly into the destination without having to copy the image.

 

The images in Figure 1 show how the image is displayed on a form after transformation.

 

Figure 1 

The code that performs this is shown in listing 1. The work is all handled in the Form1_Paint routine.

 

using System;

using System.Drawing;

using System.Drawing.Drawing2D;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

 

namespace bestfit

{

  /// <summary>

  /// Summary description for Form1.

  /// </summary>

  public class Form1 : System.Windows.Forms.Form

  {

    public Image _image=null;

 

    /// <summary>

    /// Required designer variable.

    /// </summary>

    private System.ComponentModel.Container components = null;

 

    public Form1()

    {

      //

      // Required for Windows Form Designer support

      //

      InitializeComponent();

 

      SetStyle(

        ControlStyles.ResizeRedraw |

        ControlStyles.AllPaintingInWmPaint |

        ControlStyles.DoubleBuffer,

        true);

    }

 

    /// <summary>

    /// Clean up any resources being used.

    /// </summary>

    protected override void Dispose( bool disposing )

    {

      if( disposing )

      {

        if (components != null)

        {

          components.Dispose();

        }

      }

      base.Dispose( disposing );

    }

 

    #region Windows Form Designer generated code

    /// <summary>

    /// Required method for Designer support - do not modify

    /// the contents of this method with the code editor.

    /// </summary>

    private void InitializeComponent()

    {

      //

      // Form1

      //

      this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

      this.ClientSize = new System.Drawing.Size(464, 261);

      this.Name = "Form1";

      this.Text = "Form1";

      this.Load += new System.EventHandler(this.Form1_Load);

      this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);

 

    }

    #endregion

 

    /// <summary>

    /// The main entry point for the application.

    /// </summary>

    [STAThread]

    static void Main()

    {

      Application.Run(new Form1());

    }

 

    private void Form1_Load(object sender, System.EventArgs e)

    {

      OpenFileDialog dlg= new OpenFileDialog();

      dlg.Filter="Image files (*.bmp, *.jpg, *.gif)|*.BMP;*.JPG;*.GIF";

      if(dlg.ShowDialog()==DialogResult.OK)

      {

        this._image=Image.FromFile(dlg.FileName);

        Invalidate();

      }

    }

 

    private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)

    {

      if(_image==null)

        return;

      double largestRatio=Math.Max((double)_image.Width/this.ClientSize.Width,(double)_image.Height/this.ClientSize.Height);

      float posX=(float)(this.ClientSize.Width*largestRatio/2-_image.Width/2);

      float posY=(float)(this.ClientSize.Height*largestRatio/2-_image.Height/2);

      Matrix mx=new Matrix(1.0f/(float)largestRatio,0,0,1.0f/(float)largestRatio,0,0);

      mx.Translate(posX,posY);

      e.Graphics.Transform=mx;

      e.Graphics.DrawImageUnscaled(_image,0,0);

    }

  }

}

 

Back to the GDI+ FAQ

 

e-mail:

 

bousoft@mail.ru