/*
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
}
}