Click here to Skip to main content
Click here to Skip to main content

Free Image Transformation

By , 10 May 2009
 
picture.JPG

Introduction

I have written a small but powerful C# application that can scale, rotate, skew and distort an image. This program includes a user control Canvas and a class FreeTransform. Canvas can keep the picture in the center of window always, and let the user zoom the image by mouse wheel. You can pick up the corner of the picture by mouse left button and move it freely in Canvas. Image transformation is done by the class FreeTransform. When you set its Bitmap and FourCorners, you can get the transformed Bitmap. If you like high quality of picture, you can set IsBilinearInterpolation to true. How does it work? The following diagram demonstrates the key to this method:

The shortest distances of point P to image borders are w1, w2, h1 and h2. The position of point P on the original image is supposed to be at:

([w1/(w1+w2)]*imageWidth, [h1/(h1+h2)]*imageHeight) 

Then the colors at...

([w1/(w1+w2)]*imageWidth, [h1/(h1+h2)]*imageHeight) 

... on the original image were put on the point P and thus the result.
To calculate of the distances, the vector cross product was used:

dab = Math.Abs((new YLScsDrawing.Geometry.Vector(vertex[0], srcPt)).CrossProduct(AB));
dbc = Math.Abs((new YLScsDrawing.Geometry.Vector(vertex[1], srcPt)).CrossProduct(BC));
dcd = Math.Abs((new YLScsDrawing.Geometry.Vector(vertex[2], srcPt)).CrossProduct(CD));
dda = Math.Abs((new YLScsDrawing.Geometry.Vector(vertex[3], srcPt)).CrossProduct(DA));

ptInPlane.X = (float)(srcW * (dda / (dda + dbc)));ptInPlane.Y = 
					(float)(srcH*(dab/(dab+dcd)));

Thanks for trying it!

History

  • 2nd May, 2009: Initial post
  • 8th May, 2009: Added Config and Save functions

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

YLS CS
Unknown
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionPowerful But Need A Faster Waymembergoddgoh14 May '13 - 21:04 
Is there any way to make the Transformation faster?
QuestionCan you show me in your project where is smooth applied? [modified]membernambatre29 Nov '12 - 16:58 
I have a question as above, please help me! I want to apply Bilinear Interpolation to smooth image but I don't know where to put it?
 
/**
 * 
 * Linear interpolation between two points.
 * Return interpolated color Y at distance l.
 * 
 * @param A ARGB for point A.
 * @param B ARGB for point B.
 * @param l Distance Y from A.
 * @param L Distance between A and B.
 * @return Interpolated color Y.
 */
public int linearInterpolate(int A, int B, int l, int L) {
    // extract r, g, b information
    // A and B is a ARGB-packed int so we use bit operation to extract
    int Ar = (A >> 16) & 0xff ;
    int Ag = (A >> 8) & 0xff ;
    int Ab = A & 0xff ;
    int Br = (B >> 16) & 0xff ;
    int Bg = (B >> 8) & 0xff ;
    int Bb = B & 0xff ;
    // now calculate Y. convert float to avoid early rounding
    // There are better ways but this is for clarity's sake
    int Yr = (int)(Ar + l*(Br - Ar)/(float)L) ;
    int Yg = (int)(Ag + l*(Bg - Ag)/(float)L) ;
    int Yb = (int)(Ab + l*(Bb - Ab)/(float)L) ;
    // pack ARGB with hardcoded alpha
    return 0xff000000 | // alpha
            ((Yr << 16) & 0xff0000) |
            ((Yg << 8) & 0xff00) |
            (Yb & 0xff) ;
}
 
Bilinear Interpolation

modified 29 Nov '12 - 23:16.

QuestionVery Important!! How do I apply Perspective transformation on the image? [modified]memberS Keller12 Nov '12 - 7:39 
Hi YLS,
 
Are you familiar with GIMP perspective transform?
Their perspective transform seems more realistic, it seems like that they transfer point P relative to it's distance from the corner that changed position.
 
What changed in your calculation needs to be done to support a transformation similar to GIMP perspective transformation??? D'Oh! | :doh:
 
Note! In GIMP you can only move 1 corner at once so GIMP also calculates the distance of point P from the moving corner.
 
Thanks in advanced! I really need your help!! Blush | :O

modified 13 Nov '12 - 6:19.

GeneralMy vote of 5memberS Keller5 Nov '12 - 0:12 
Thank you very much!!!
QuestionMust be doing something wrong.memberMember 88456084 Sep '12 - 13:29 
I keep getting an error. When rotating image to the right everything is good. But when rotating left, I get a displacement of the image downward even though my points are correct as indicated by a blue path that is drawn.
 
Same on elevation. One direction works well and the other direction shifts the image.
 
Any thoughts? Thanks ahead of time.
 
Code I used is below...
 
        protected override void OnPaint(PaintEventArgs e)
        {
            Point ptTopLeft = new Point(320, 97);
            Point ptTopRight = new Point(653, 24);
            Point ptBottomRight = new Point(653, 553);
            Point ptBottomLeft = new Point(320, 481);
 

            YLScsDrawing.Imaging.Filters.FreeTransform filter = new YLScsDrawing.Imaging.Filters.FreeTransform();
            filter.Bitmap = (Bitmap)((System.Drawing.Image)(global::ChartThumbnailDesign.Properties.Resources.Castle));
 
            // assign FourCorners (the four X/Y coords) of the new perspective shape
            filter.FourCorners = new System.Drawing.PointF[] { (PointF)ptTopLeft, (PointF)ptTopRight, (PointF)ptBottomRight, (PointF)ptBottomLeft };
            filter.IsBilinearInterpolation = true; // optional for higher quality

            using (System.Drawing.Bitmap perspectiveImg = filter.Bitmap)
            {
                e.Graphics.DrawImage(perspectiveImg, ptTopLeft);
 
                using (GraphicsPath path = new GraphicsPath())
                {
                    path.AddPolygon(new Point[] { ptTopLeft, ptTopRight, ptBottomRight, ptBottomLeft });
                    e.Graphics.DrawPath(new Pen(Color.Blue, 4.0f), path);
                }
            }
        }

AnswerRe: Must be doing something wrong.memberMember 88456084 Sep '12 - 14:21 
Whoops. After nearly a day on this I see my simple, but silly mistake. You must draw at the point filter.ImageLocation rather than my top left point that I started with.
 
wrong ---> e.Graphics.DrawImage(perspectiveImg, ptTopLeft);
correct ---> e.Graphics.DrawImage(perspectiveImg, filter.ImageLocation);
GeneralMy vote of 5memberthams15 Aug '12 - 18:36 
great article
GeneralGreat jobmemberthams15 Aug '12 - 18:35 
Great job man, Hats off to u.
QuestionNeed anti-aliasing along the edgesmemberpeter p.16 May '12 - 16:04 
Thanks for posting this project, it works great. There is one problem, though: the edges are jagged (not smoothed.) How would you compute the alpha-channel values for the outer edges of the image?
 
Thanks.
 
-- peter
GeneralMy vote of 5memberKevin.zsh27 Feb '12 - 20:17 
GREAT!!!I've been looking for this for days!Thank you!!

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 10 May 2009
Article Copyright 2009 by YLS CS
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid