2D Graphics C#

/*
Code revised from chapter 6
GDI+ Custom Controls with Visual C# 2005
By Iulian Serban, Dragos Brezoi, Tiberiu Radu, Adam Ward 
Language English
Paperback 272 pages [191mm x 235mm]
Release date July 2006
ISBN 1904811604
Sample chapter
http://www.packtpub.com/files/1604_CustomControls_SampleChapter.pdf
For More info on GDI+ Custom Control with Microsoft Visual C# book 
visit website www.packtpub.com 
*/ 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace ImageWarperApp
{
    public partial class Form1 : Form
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
        public Form1()
        {
            InitializeComponent();
        }
        private void applyButton_Click(object sender, EventArgs e)
        {
            imageWarperControl1.ImageAngle = Double.Parse(angleBox.Text) * System.Math.PI / 180;
            imageWarperControl1.ImageScale = Double.Parse(scaleBox.Text) / 100;
            imageWarperControl1.ImageSkew = new SizeF(float.Parse(skewHorizontalBox.Text), float.Parse(skewVerticalBox.Text));
        }
        private System.ComponentModel.IContainer components = null;
        /// 
        /// Clean up any resources being used.
        /// 

        /// true if managed resources should be disposed; otherwise, false.
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        #region Windows Form Designer generated code
        /// 
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// 

        private void InitializeComponent()
        {
            this.angleBox = new System.Windows.Forms.TextBox();
            this.scaleBox = new System.Windows.Forms.TextBox();
            this.skewHorizontalBox = new System.Windows.Forms.TextBox();
            this.skewVerticalBox = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.label3 = new System.Windows.Forms.Label();
            this.label4 = new System.Windows.Forms.Label();
            this.applyButton = new System.Windows.Forms.Button();
            this.imageWarperControl1 = new ImageWarperApp.ImageWarperControl();
            this.SuspendLayout();
            // 
            // angleBox
            // 
            this.angleBox.Location = new System.Drawing.Point(128, 42);
            this.angleBox.Name = "angleBox";
            this.angleBox.Size = new System.Drawing.Size(100, 20);
            this.angleBox.TabIndex = 1;
            // 
            // scaleBox
            // 
            this.scaleBox.Location = new System.Drawing.Point(128, 100);
            this.scaleBox.Name = "scaleBox";
            this.scaleBox.Size = new System.Drawing.Size(100, 20);
            this.scaleBox.TabIndex = 2;
            // 
            // skewHorizontalBox
            // 
            this.skewHorizontalBox.Location = new System.Drawing.Point(128, 157);
            this.skewHorizontalBox.Name = "skewHorizontalBox";
            this.skewHorizontalBox.Size = new System.Drawing.Size(100, 20);
            this.skewHorizontalBox.TabIndex = 3;
            // 
            // skewVerticalBox
            // 
            this.skewVerticalBox.Location = new System.Drawing.Point(128, 217);
            this.skewVerticalBox.Name = "skewVerticalBox";
            this.skewVerticalBox.Size = new System.Drawing.Size(100, 20);
            this.skewVerticalBox.TabIndex = 4;
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(7, 45);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(104, 13);
            this.label1.TabIndex = 5;
            this.label1.Text = "Rotation Angle (deg)";
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(7, 103);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(84, 13);
            this.label2.TabIndex = 6;
            this.label2.Text = "Scale Factor (%)";
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(7, 160);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(117, 13);
            this.label3.TabIndex = 7;
            this.label3.Text = "Skew Horizontal Factor";
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(7, 220);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(105, 13);
            this.label4.TabIndex = 8;
            this.label4.Text = "Skew Vertical Factor";
            // 
            // applyButton
            // 
            this.applyButton.BackColor = System.Drawing.SystemColors.ActiveCaption;
            this.applyButton.Location = new System.Drawing.Point(61, 285);
            this.applyButton.Name = "applyButton";
            this.applyButton.Size = new System.Drawing.Size(118, 34);
            this.applyButton.TabIndex = 9;
            this.applyButton.Text = "Apply New Settings";
            this.applyButton.UseVisualStyleBackColor = false;
            this.applyButton.Click += new System.EventHandler(this.applyButton_Click);
            // 
            // imageWarperControl1
            // 
            this.imageWarperControl1.ImageAngle = 0;
            this.imageWarperControl1.ImageScale = 0;
            this.imageWarperControl1.ImageSkew = new System.Drawing.SizeF(0F, 0F);
            this.imageWarperControl1.Location = new System.Drawing.Point(253, 45);
            this.imageWarperControl1.Name = "imageWarperControl1";
            this.imageWarperControl1.Size = new System.Drawing.Size(185, 192);
            this.imageWarperControl1.TabIndex = 0;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(450, 342);
            this.Controls.Add(this.applyButton);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.skewVerticalBox);
            this.Controls.Add(this.skewHorizontalBox);
            this.Controls.Add(this.scaleBox);
            this.Controls.Add(this.angleBox);
            this.Controls.Add(this.imageWarperControl1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
            this.PerformLayout();
        }
        #endregion
        private ImageWarperControl imageWarperControl1;
        private System.Windows.Forms.TextBox angleBox;
        private System.Windows.Forms.TextBox scaleBox;
        private System.Windows.Forms.TextBox skewHorizontalBox;
        private System.Windows.Forms.TextBox skewVerticalBox;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.Button applyButton;
        
    }
    public partial class ImageWarperControl : UserControl
    {
        public ImageWarperControl()
        {
            InitializeComponent();
        }
        private void ImageWarperControl_Load(object sender, EventArgs e)
        {
            
            img = CreatePicture();
        }
        private void ImageWarperControl_Paint(object sender, PaintEventArgs e)
        {
                  // set up all our parameters first before calling DrawWarpedPicture.
      Graphics target = this.CreateGraphics(); //draw onto the form's surface
      PointF pivotOnImage = new PointF(img.Width / 2, img.Height / 2);
      PointF pivotOnTarget = new PointF(this.Width / 2, this.Height / 2);
      double rotate = imageAngle;
      double scaleFactor = imageScale;
      SizeF skewing = imageSkew;
      DrawWarpedPicture(target, img, pivotOnImage, pivotOnTarget, rotate, scaleFactor, skewing);
       }
        private Image CreatePicture()
        {
            // Create a new Bitmap object, 50 x 50 pixels in size
            Image canvas = new Bitmap(50, 50);
            // create an object that will do the drawing operations
            Graphics artist = Graphics.FromImage(canvas);
            // draw a few shapes on the canvas picture
            artist.Clear(Color.Lime);
            artist.FillEllipse(Brushes.Red, 3, 30, 30, 30);
            artist.DrawBezier(new Pen(Color.Blue, 3), 0, 0, 40, 15, 10, 35, 50, 50);
            // now the drawing is done, we can discard the artist object
            artist.Dispose();
            // return the picture
            return canvas;
        }
        public void DrawWarpedPicture(
            Graphics surface,   //the surface to draw on
            Image img,    //the image to draw
            PointF sourceAxle,  //pivot point passing through image.
            PointF destAxle,  //pivot point's position on destination surface
            double degrees,  //degrees through which the image is rotated clockwise
            double scale,     //size multiplier
            SizeF skew      //the slanting effect size, applies BEFORE scaling or rotation
          )
        {
            //give this array temporary coords that will be overwritten in the loop below
            //the skewing is done here orthogonally, before any trigonometry is applied
            PointF[] temp = new PointF[3] {  new PointF(skew.Width, -skew.Height),
                    new PointF((img.Width - 1) + skew.Width, skew.Height),
                    new PointF(-skew.Width,(img.Height - 1) - skew.Height) };
            double ang, dist;
            //convert the images corner points into scaled, rotated, skewed and translated points
            for (int i = 0; i < 3; i++)
            {
                //measure the angle to the image's corner and then add the rotation value to it
                ang = GetBearingRadians(sourceAxle, temp[i], out dist) + degrees;
                dist *= scale; //scale
                temp[i] = new PointF((Single)((Math.Cos(ang) * dist) + destAxle.X), (Single)((Math.Sin(ang) * dist) + destAxle.Y));
            }
            surface.DrawImage(img, temp);
        }
        private static double GetBearingRadians(PointF reference, PointF target, out double distance)
        {
            double dx = target.X - reference.X;
            double dy = target.Y - reference.Y;
            double result = Math.Atan2(dy, dx);
            distance = Math.Sqrt((dx * dx) + (dy * dy));
            if (result < 0)
                result += (Math.PI * 2); //add  the negative number to 360 degrees to correct the atan2 value
            return result;
        }
        private double imageAngle;
        private double imageScale;
        private SizeF imageSkew;
        private Image img = null;
        public double ImageAngle
        {
            get
            {
                return imageAngle;
            }
            set
            {
                if (imageAngle != value)
                {
                    imageAngle = value;
                    Invalidate();
                }
            }
        }
        public double ImageScale
        {
            get
            {
                return imageScale;
            }
            set
            {
                if (imageScale != value)
                {
                    imageScale = value;
                    Invalidate();
                }
            }
        }
        public SizeF ImageSkew
        {
            get
            {
                return imageSkew;
            }
            set
            {
                if (imageSkew != value)
                {
                    imageSkew = value;
                    Invalidate();
                }
            }
        }
        private System.ComponentModel.IContainer components = null;
        ///  
        /// Clean up any resources being used.
        /// 

        /// true if managed resources should be disposed; otherwise, false.
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        #region Component Designer generated code
        ///  
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// 

        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // ImageWarperControl
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.Name = "ImageWarperControl";
            this.Load += new System.EventHandler(this.ImageWarperControl_Load);
            this.Paint += new System.Windows.Forms.PaintEventHandler(this.ImageWarperControl_Paint);
            this.ResumeLayout(false);
        }
        #endregion
    }
    
}