home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / rec / games / programm / 4757 < prev    next >
Encoding:
Text File  |  1992-11-19  |  4.4 KB  |  170 lines

  1. Newsgroups: rec.games.programmer
  2. Path: sparky!uunet!cs.utexas.edu!zaphod.mps.ohio-state.edu!caen!destroyer!cs.ubc.ca!news.UVic.CA!softwords!cue!krisr
  3. From: krisr@cue.bc.ca (Kristof Roomp)
  4. Subject: Bitmap rotation & scaling solution
  5. Message-ID: <krisr.722200021@cue>
  6. Summary: How to use a linear xfrom to rotate & scale bitmaps
  7. Keywords: graphics bitmap
  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 Nov 92 19:07:01 GMT
  12. Lines: 156
  13.  
  14.  
  15. hey guys!
  16. while dreaming my way through linear algebra, I suddenly realized that
  17. linear transformations could be quite handy in rotating, scaling, etc. of
  18. bitmaps. here's a quicky version of my idea.... it should be possible to
  19. make it use integer arithmetic with little trouble (ie. a LOT faster). I
  20. just wanted to make clear what the program was doing...
  21.  
  22. here ya go...
  23.  
  24. typedef struct
  25.         {
  26.        double a,b,c,d;
  27.         } MATRIX22;
  28.  
  29. // initializes a transform matrix.
  30.  
  31. void initmatrix(MATRIX *m)
  32.      {
  33.      m->a=1; m->b=0; m->c=0; m->d=1;
  34.      }
  35.  
  36. // multiplies two matrices. resu stored in m1.
  37. void matrixmul(MATRIX22 *m1,MATRIX22 *m2)
  38.      {
  39.      MATRIX22 m3;
  40.  
  41.      m3.a=m1->a*m2->a + m1->b*m2->c;
  42.      m3.b=m1->a*m2->b + m1->b*m2->d;
  43.      m3.c=m1->c*m2->a + m1->d*m2->c;
  44.      m3.d=m1->c*m2->b + m1->d*m2->d;
  45.  
  46.      *m1=m3;
  47.      }
  48.  
  49. // scales x axis by factor
  50. void ScaleX(MATRIX22 *m,double factor)
  51.      {
  52.      MATRIX22 m2;
  53.  
  54.      m2.a=factor; m2.b=0;
  55.      m2.c=0; m2.d=1;
  56.  
  57.      matrixmul(m,&m2);
  58.      }
  59.  
  60. // scales y axis by factor
  61. void ScaleY(MATRIX22 *m,double factor)
  62.      {
  63.      MATRIX22 m2;
  64.  
  65.      m2.a=1; m2.b=0;
  66.      m2.c=0; m2.d=factor;
  67.  
  68.      matrixmul(m,&m2);
  69.      }
  70.  
  71. // rotates counterclockwise by angle
  72. void Rotate(MATRIX22 *m,double angle)
  73.      {
  74.      MATRIX22 m2;
  75.  
  76.      m2.a=cos(angle); m2.b=-sin(angle);
  77.      m2.c=sin(angle); m2.d=cos(angle);
  78.  
  79.      matrixmul(m,&m2);
  80.      }
  81.  
  82. // reflects about a line through the origin of angle angle
  83. void Reflect(MATRIX22 *m,double angle)
  84.      {
  85.      MATRIX22 m2;
  86.  
  87.      m2.a=cos(2*angle); m2.b=sin(2*angle);
  88.      m2.c=sin(2*angle); m2.d=-cos(2*angle);
  89.  
  90.      matrixmul(m,&m2);
  91.      }
  92.  
  93. // notice you can perform as many of the above transformation as you want
  94. // on the matrix before passing it to LinearTransform. you might rotate,
  95. // scale, and rotate again... all done in one swoop.
  96.  
  97. // very inefficient linear transform from one bitmap to another
  98. // lots of optimization possible, though.
  99.  
  100. #define min(a,b) ( (a<b) ? a : b )
  101. #define max(a,b) ( (a>b) ? a : b )
  102.  
  103. void LinearTransform(HBITMAP source,HBITMAP target,int xorg,int yorg,
  104.                 int xtarg,int ytarg,MATRIX22 *m)
  105.     {
  106.     double a,b,c,d,ai,bi,ci,di,det;
  107.     int x1,y1,x2,y2,x3,y3,x4,y4,minx,miny,maxx,maxy,x,y,xp,yp;
  108.  
  109.     a=m->a; b=m->b; c=m->c; d=m->d;
  110.  
  111.     det=a*d-b*c;
  112.     if (det==0)
  113.         Error("LinearTransform: a non-invertible transform matrix");
  114.  
  115.     ai=d/det; bi=-b/det; ci=-c/det; di=a/det;
  116.  
  117.     x1=-xorg*a + -yorg*b;
  118.     y1=-xorg*c + -yorg*d;
  119.  
  120.     x2=(source->xsize-xorg)*a + -yorg*b;
  121.     y2=(source->xsize-xorg)*c + -yorg*d;
  122.  
  123.     x3=-xorg*a + (source->ysize-yorg)*b;
  124.     y3=-xorg*c + (source->ysize-yorg)*d;
  125.  
  126.     x4=(source->xsize-xorg)*a + (source->ysize-yorg)*b;
  127.     y4=(source->xsize-xorg)*c + (source->ysize-yorg)*d;
  128.  
  129.     minx=min(x1,min(x2,min(x3,x4) ) );
  130.     maxx=max(x1,max(x2,max(x3,x4) ) );
  131.  
  132.     miny=min(y1,min(y2,min(y3,y4) ) );
  133.     maxy=max(y1,max(y2,max(y3,y4) ) );
  134.  
  135.     for (y=miny;y<=maxy;y++)
  136.         {
  137.         for(x=minx;x<=maxx;x++)
  138.             {
  139.             xp=x*ai + y*bi;
  140.             yp=x*ci + y*di;
  141.             DrawPixel(target,x+xtarg,y+ytarg,
  142.                 GetPixel(source,xp+xorg,yp+yorg));
  143.             }
  144.         }
  145.     }
  146.  
  147.  
  148. void main(void)
  149.      {
  150.      MATRIX22 m;
  151.  
  152.      // set up graphics et al.
  153.  
  154.      initmatrix(&m);
  155.      ScaleX(&m,2);              // make x twice as big
  156.      Rotate(&m,1.04719);        // rotate bitmap by pi/3 (60 degrees)
  157.      ScaleY(&m,2);              // make y twice as big
  158.      Reflect(&m,0.7853);        // reflect about a line with an angle of pi/4
  159.                               (45 degrees)
  160.      LinearTransform(source,target,source->xsize/2,source->ysize/2,
  161. get->xsize/2,target->ysize/2,&m);
  162.         // transform source to target (origin is at the center of both
  163.         //      bitmaps
  164.  
  165.      // continue program...
  166.      }
  167.  
  168. thats it... see if you can come up with some clever integer arithmetic to
  169. speed up the process...
  170.