C # Picture Free transform arbitrary twist

Source: Internet
Author: User
Have thought about to do a subway driving game, which want to put some originally rectangular picture into a trapezoid, but found gid+ above no similar method. So in Google Valley a bit. No. Can only find the coveted, and no source. Try it for a day or two with your own ideas, but it's not really that way. Later I knew that in Digital image processing is called "Perspective transformation." So the internet to find the relevant information, the principle of looking, did not understand. The code is not much, there is ActionScript, unknown, there is C, unknown. How stupid. Later on CodeProject saw a foreigner's blog, the whole English can not understand, but read a picture, probably know what he meant. Down the source look, C + +. Finally translated into C # (feeling or retain a lot of C + + style things), compiled through, normal operation. Then read the code step-by-step. Not all understand, first the understanding of the part of the record down. Continue to add further research later.

First look at the effect

Interface is modeled on a person (online version too much, can not find the original author), the interface is not the focus, the focus is the algorithm. The following is directly attached to the foreigner's picture of the general talk about thinking.

The first is from the original picture into an idealized image of the target, the picture is only idealized, the final picture is the most right one. The process of conversion is based on the four corners of the converted image to calculate the size of the target picture, generate a matrix, that is, that destination image, and then the idealized goal of the image to cover the past, the idealized picture of each "pixel lattice" (already not the real pixel lattice, Because of the distorted deformation of the matrix in contrast, to see what the coverage of the lattice, covering the number of areas, in percent to add color to the corresponding lattice. In fact, that lattice is the pixel point of the new picture. The final target graph is generated according to the Matrix.

Then we introduce the method hierarchy called in the algorithm.

To post code that has been understood (does not represent full understanding), first is the outermost method

 1 public void CreateTransform (Bitmap src,ref Bitmap DST, list<double> Xcorner, list<double> Ycorner,
 Aaf_callback Callbackfunc) 2 {3 int right = 0, bottom = 0;
 4 5//mainly according to the coordinates of the new picture, calculate the picture width and height, construct the target picture of the bitmap 6 double offx = xcorner[0];
 7 Double offy = ycorner[0]; 8 for (int i = 1; i < 4 i++) 9 {if (Xcorner[i] < OFFX) OFFX = xcorner[
I];
One if (Ycorner[i] < Offy) Offy = Ycorner[i]; 
for (int i = 0; i < 4; i++) {xcorner[i]-= OFFX;
Ycorner[i]-= Offy;
if (Roundup (Xcorner[i]) > right) right = Roundup (xcorner[i));
if (Roundup (Ycorner[i]) > Bottom) bottom = Roundup (ycorner[i));
DST = new Bitmap (right, bottom);
Transform (SRC, DST, xcorner, ycorner, NULL);      23   } 

The above method only set the size of the target picture and nothing else. The following method has not done much to convert the thing

 1 private void Transform (Bitmap src,bitmap DST, list<double> Xcorner, list<double> Ycorner, AAF_CALLB Ack Callbackfunc) 2 {3//make sure the coordinates are valid 4 if (Xcorner. Count!= 4 | | Ycorner.
 Count!= 4) 5 return; 6 7//load The SRC bitmaps Information 8 9//create the intial arrays 10//Live according to original picture into a picture that is wider than the original image, 11//This matrix is used to record the coordinates of the upper-left corner of each pixel after conversion pixelgrid = new aafpnt[(src. Width + 1) * (src.
Height + 1)];
Polyoverlap = new AAFPNT[16];
polysorted = new AAFPNT[16];
Corners = new Aafpnt[4];
//load the corners array double[] dx = {0.0, 1.0, 1.0, 0.0};
double[] dy = {0.0, 0.0, 1.0, 1.0};                 for (int i = 0; i < 4; i++) {corners[i].x = dx[i]; 23
CORNERS[I].Y = Dy[i]; 24} 25 26             Find the rectangle of DST to draw to Outstartx = RoundDown (xcorner[0));
Outstarty = RoundDown (ycorner[0]);
outwidth = 0;
outheight = 0; 31//Here calculates the coordinates of the starting point after the transformation (int i = 1; i < 4; i++) (Roun
Ddown (Xcorner[i]) < OUTSTARTX) Outstartx = RoundDown (xcorner[i));
if (RoundDown (Ycorner[i]) < Outstarty) Outstarty = RoundDown (ycorner[i)); (int i = 0; i < 4; i++) {roundup (xcorner[i)
-Outstartx) > Outwidth) outwidth = Roundup (xcorner[i)-OUTSTARTX);
if (Roundup (Ycorner[i]-Outstarty) > Outheight) outheight = Roundup (Ycorner[i]-outstarty);             The//fill out Pixelgrid array 45//calculates the coordinates of the upper-left corner of each "pixel" in the ideal target picture 46         if (Creategrid (SRC, Xcorner, ycorner)) 47 {48        Do the transformation 49//Convert to Dotransform (SRC,DST, Callbackfunc);
//return if the function completed properly; 55}

This method is to calculate the original image in the upper left corner of each pixel point to the target image coordinates, the result is stored in the Pixelgrid, the two-dimensional array of rows and columns are more than the original image of the width of 1, this relationship I did not understand. With the idea of a more extreme, suppose that the picture now consists of only one pixel, width and height are 1, then if the simple storage of the upper-left corner of the coordinates, it is impossible to form a quadrilateral, which requires the other three corners of the coordinates of the corresponding record, which is stored in the array of rows and columns than the original width and height of more than 1, That is, a 2-row, 2-column array can hold 4 values, just to accommodate the four-point coordinate of that pixel. Expanding to real pictures is just as true. But this method I do not understand, seems to use the idea of vector. is roughly based on the new picture four edge to calculate.

 1 private bool Creategrid (Bitmap src, list<double> xcorner, list<double> Ycorner) 2 {3
 MMM geometry 4 double[] Sideradius = new Double[4];
 5 double[] Sidecos = new Double[4];
 6 double[] Sidesin = new Double[4];             7 8//first We find the radius, cos, and sin of all side of the polygon created by Xcorner and Ycorner 9
Int J; for (int i = 0; i < 4; i++) One {j = ja[i]; Sideradius [I] = Math.sqrt ((xcorner[i]-xcorner[j]) * (Xcorner[i]-xcorner[j]) + (Ycorner[i]-ycorner[j]) * (ycorner[i)-ycorner[
j]));
Sidecos[i] = (Xcorner[j]-xcorner[i])/sideradius[i];
Sidesin[i] = (Ycorner[j]-ycorner[i])/sideradius[i]; //next we create two lines in Ax + by = C form for (int x = 0; x < s Rc. Width + 1;   x + +) 20 {21              Double topdist = (double) x/(src.
Width)) * Sideradius[0];
Double ptxtop = xcorner[0] + topdist * sidecos[0];
Double ptytop = ycorner[0] + topdist * sidesin[0]; Double botdist = (1.0-(double) x/(src.
Width)) * sideradius[2];
Double Ptxbot = xcorner[2] + botdist * sidecos[2];
Double Ptybot = ycorner[2] + botdist * sidesin[2];
Double Ah = ptybot-ptytop;
Double Bh = Ptxtop-ptxbot; Double Ch = Ah * ptxtop + Bh * ptytop;//fork multiply for (int y = 0; y < src.) Height + 1; y++) {Double leftdist = (1.0-(double) y/(src.
Height)) * sideradius[3];
Double ptxleft = xcorner[3] + leftdist * sidecos[3];
Panax Notoginseng Double ptyleft = ycorner[3] + leftdist * sidesin[3]; Double rightdist = (double) y/(src.Height)) * sideradius[1];
Double ptxright = xcorner[1] + rightdist * sidecos[1];
Double ptyright = ycorner[1] + rightdist * sidesin[1];
Double Av = ptyright-ptyleft;
Double Bv = ptxleft-ptxright;
Double Cv = Av * ptxleft + Bv * ptyleft;                     //find where the lines intersect and store that point in the Pixelgrid array 48
Double det = Ah * Bv-av * BH;                     if (aafabs (DET) < 1e-9) is return false 52 The else {int ind = x + y * (src.
Width + 1);
pixelgrid[ind].x = (BV * CH-BH * Cv)/det;
PIXELGRID[IND].Y = (AH * CV-AV * Ch)/det;          58} 59} 60} 61 62   Yayy we didn ' t fail is true; 64}

The following method calculates the proportional color of the set of coordinate points computed using the above method. The coordinates of the four corners of each pixel above are extracted in the following way to the group back to a quadrilateral, with the combination of code and comments to see the

  1 private void Dotransform (Bitmap src,bitmap DST, Aaf_callback Callbackfunc) 2 {3 4
  Get source bitmap ' s information 5 if (src = null) return; 6 7//create The source Dib array and the DSTDIB array 8 aaf_dblrgbquad[] Dbldstdib = new AAF
  _dblrgbquad[outwidth * Outheight]; 9 for (int i = 0; i < Dbldstdib. Length;
 i++) = Dbldstdib[i] = new Aaf_dblrgbquad ();
 One//create polygon arrays aafpnt[] p = new AAFPNT[4];
 aafpnt[] Poffset = new Aafpnt[4];  //loop through the source ' pixels 17//traverse the original (essentially Pixelgrid) points for (int x = 0; x < src. Width; X + +) {for (int y = 0; y < src.) Height; y++) 21 {22///Take the current point a little right down the lower right corner point four to form a quadrilateral 23//This quadrilateral is a picture of the original image                    Vegetarian Dot 24 Construct the source pixel ' s rotated polygon from pixelgrid p[0] = pixelgrid[x + y * (src.
 Width + 1)]; P[1] = pixelgrid[(x + 1) + y * (src.
 Width + 1)]; P[2] = pixelgrid[(x + 1) + (y + 1) * (src.
 Width + 1)]; P[3] = pixelgrid[x + (y + 1) * (src.
 Width + 1)]; //find the scan area on the destination ' s pixels to int mindx = Int.
 MaxValue; int mindy = Int.
 MaxValue; int MAXDX = Int.
 MinValue;

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.