home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / graphics / 13058 < prev    next >
Encoding:
Text File  |  1992-12-21  |  5.4 KB  |  184 lines

  1. Xref: sparky comp.graphics:13058 rec.games.programmer:5104
  2. Newsgroups: comp.graphics,rec.games.programmer
  3. Path: sparky!uunet!usc!howland.reston.ans.net!sol.ctr.columbia.edu!destroyer!cs.ubc.ca!news.UVic.CA!softwords!cue!krisr
  4. From: krisr@cue.bc.ca (Kristof Roomp)
  5. Subject: Algorithm for Bitmap rotation & scaling
  6. Message-ID: <krisr.724726801@cue>
  7. Summary: An algorithm to scale and rotate bitmaps
  8. Sender: news@softwords.bc.ca (CNews)
  9. Nntp-Posting-Host: cue.bc.ca
  10. Organization: Softwords Research International Ltd., Victoria, B.C., Canada
  11. Date: 19 Dec 92 01:00:01 GMT
  12. Lines: 170
  13.  
  14.  
  15. while dreaming my way through linear algebra, I suddenly realized that
  16. linear transformations could be quite handy in rotating, scaling, etc. of
  17. aps. I do have an assembler version of this if anyone is interested.
  18. (A lot faster, as only uses integer adds between pixels).
  19.  
  20. First here's a bunch of matrix operation, just in case you don't know how
  21. to construct you own favorate matrices. What you basically do is create
  22. a matrix with initmatrix. If you pass this matrix to LinearTransform, it
  23. will faithfully draw bitmap onto the screen as if no manipulatios were made.
  24. (ie BitBlt, but a bit slower).
  25. Now, suppose you want to rotate the bitmap. Easy... just all the rotate 
  26. procedure on the matrix you created with initmatrix. Pass it the angle
  27. (in rads) and it will modify the matrix accordingly. You do not have the
  28. hange the source bitmap in any way. Now just call LinearTransform with
  29. the new matrix, and tada! the bitmap has been rotated about its center.
  30. ou can apply as many operations on tp of each ther witno loss of acuracy
  31. in the bitmap. When assembler is used to speed things up, you can get 
  32. Wing Commander performance (i think this is how wing commander does it
  33. anyhow). The only problem i'm having is with the boundry points. How to quickly
  34. skip over the pixels that are not contained in the source bitmap. 
  35. Anyhow, enough talk... here it is:
  36.  
  37. // a matrix that looks something like
  38. // [ a b ]
  39. / [ c d ]
  40.  
  41. typedef struct
  42.         {
  43.         double a,b,c,d;
  44.         } MATRIX22;
  45.  
  46. // initializes a transform matrix.
  47.  
  48. void initmatrix(MATRIX *m)
  49.      {
  50.      m->a=1; m->b=0; m->c=0; m->d=1;
  51.      }
  52.  
  53. // multiplies two matrices. result is stored in m1.
  54. void matrixmul(MATRIX22 *m1,MATRIX22 *m2)
  55.      {
  56.      MATRIX22 m3;
  57.  
  58.      m3.a=m1->a*m2->a + m1->b*m2->c;
  59.      m3.b=m1->a*m2->b + m1->b*m2->d;
  60.      m3.c=m1->c*m2->a + m1->d*m2->c;
  61.      m3.d=m1->c*m2->b + m1->d*m2->d;
  62.  
  63.      *m1=m3;
  64.      }
  65.  
  66. // scales x axis by factor
  67. void ScaleX(MATRIX22 *m,double factor)
  68.      {
  69.      MATRIX22 m2;
  70.  
  71.      m2.a=factor; m2.b=0;
  72.      m2.c=0; m2.d=1;
  73.  
  74.      matrixmul(m,&m2);
  75.      }
  76.  
  77. // scales y axis by factor
  78. void ScaleY(MATRIX22 *m,double factor)
  79.      {
  80.      MATRIX22 m2;
  81.  
  82.      m2.a=1; m2.b=0;
  83.      m2.c=0; m2.d=factor;
  84.  
  85.      matrixmul(m,&m2);
  86.      }
  87.  
  88. // rotates counterclockwise by angle
  89. void Rotate(MATRIX22 *m,double angle)
  90.      {
  91.      MATRIX22 m2;
  92.  
  93.      m2.a=cos(angle); m2.b=-sin(angle);
  94.      m2.c=sin(angle); m2.d=cos(angle);
  95.  
  96.      matrixmul(m,&m2);
  97.      }
  98.  
  99. // reflects about a line through the origin of angle angle
  100. void Reflect(MATRIX22 *m,double angle)
  101.      {
  102.      MATRIX22 m2;
  103.  
  104.      m2.a=cos(2*angle); m2.b=sin(2*angle);
  105.      m2.c=sin(2*angle); m2.d=-cos(2*angle);
  106.  
  107.      matrixmul(m,&m2);
  108.     }
  109.  
  110. // notice you can perform as many of the above transformation as you want
  111. / on the matrix before passing it to LinearTransform. you might rotate,
  112. // scale, and rotate again... all done in one swoop.
  113.  
  114. // very inefficient linear transform from one bitmap to another
  115. // lots of optimization possible, though.
  116.  
  117. #define min(a,b) ( (a<b) ? a : b )
  118. #define max(a,b) ( (a>b) ? a : b )
  119.  
  120. void LinearTransform(HBITMAP source,HBITMAP target,int xorg,int yorg,
  121.                 int xtarg,int ytarg,MATRIX22 *m)
  122.     {
  123.     double a,b,c,d,ai,bi,ci,di,det;
  124.     int x1,y1,x2,y2,x3,y3,x4,y4,minx,miny,maxx,maxy,x,y,xp,yp;
  125.  
  126.     a=m->a; b=m->b; c=m->c; d=m->d;
  127.  
  128.     det=a*d-b*c;
  129.     if (det==0)
  130.         Error("LinearTransform: a non-invertible transform matrix");
  131.  
  132.     ai=d/det; bi=-b/det; ci=-c/det; di=a/det;
  133.  
  134.     x1=-xorg*a + -yorg*b;
  135.     y1=-xorg*c + -yorg*d;
  136.  
  137.     x2=(source->xsize-xorg)*a + -yorg*b;
  138.     y2=(source->xsize-xorg)*c + -yorg*d;
  139.  
  140.     x3=-xorg*a + (source->ysize-yorg)*b;
  141.     y3=-xorg*c + (source->ysize-yorg)*d;
  142.  
  143.     x4=(source->xsize-xorg)*a + (source->ysize-yorg)*b;
  144.     y4=(source->xsize-xorg)*c + (source->ysize-yorg)*d;
  145.  
  146.     minx=min(x1,min(x2,min(x3,x4) ) );
  147.     maxx=max(x1,max(x2,max(x3,x4) ) );
  148.  
  149.     miny=min(y1,min(y2,min(y3,y4) ) );
  150.     maxy=max(y1,max(y2,max(y3,y4) ) );
  151.  
  152.     for (y=miny;y<=maxy;y++)
  153.         {
  154.         for(x=minx;x<=maxx;x++)
  155.             {
  156.             xp=x*ai + y*bi;
  157.             yp=x*ci + y*di;
  158.             DrawPixel(target,x+xtarg,y+ytarg,
  159.                 GetPixel(source,xp+xorg,yp+yorg));
  160.             }
  161.         }
  162.     }
  163.  
  164.  
  165. void main(void)
  166.      {
  167.      MATRIX22 m;
  168.  
  169.      // set up graphics et al.
  170.  
  171.      initmatrix(&m);
  172.      ScaleX(&m,2);              // make x twice as big
  173.      Rotate&m,1.04719);        // rotate bitmap by pi/3 (60 degrees)
  174.      ScaleY(&m,2);              // make y twice as big
  175.      Reflect(&m,0.7853);        // reflect about a line with an angle of pi/4
  176.                                    (45 degrees)
  177.      LinearTransform(source,target,source->xsize/2,source->ysize/2,
  178.         target->xsize/2,target->ysize/2,&m);
  179.         // transform source to target (origin is at the center of both
  180.         //      bitmaps
  181.  
  182.      // continue program...
  183.      }
  184.