[Back to EGAVGA SWAG index] [Back to Main SWAG index] [Original]

    {
    > I am trying to learn how to, and do, scaling and rotaing of images. I
    > can put the image on a extrnal page and then I would like to do stuff
    > with it.  Please help.

     Scaling, rotation, shearing, translations etc are all simple affine
    transformations. I assume you have the math, no?

     Anyhow to sum it up:

     Shearing

       Qx = Px + G*Py
       Qy = Py + H*Px

       Where: Q = new point.
              P = old point.
              G = x shear factor
              H = y shear factor

      H & G are decimal numbers normally, here's an interesting demo of
    a shear - it almost looks like 3-d rotation, but it's definitely not.
    Btw you need somesort of fast graphics unit that is 1 based (ie 1,1 is
    the top point - or rewrite the routines). Personally I'm using x320x240
    by Sean Palmer, but I've added a bunch of stuff to it..
    }

    Program Shearing;
    Uses Crt,x320x240; { by John Stephenson, 1995 }

    { Almost looks like rotation, eh? It's NOT! :-) It's just that the triangle }
    { when sheared goes down to 0, creating the effects that it is being        }
    { rotated, pretty neat, eh?                                                 }

    Type
      tPoint = record
        x,y: word;
      end;
      tTriangle = record
        color: byte;
        a,b,c: tPoint;
      end;

    Procedure DrawTriangle(var tri: tTriangle);
    begin
      with tri do begin
        line(a.x,a.y,b.x,b.y,color);
        line(b.x,b.y,c.x,c.y,color);
        line(c.x,c.y,a.x,a.y,color);
      end;
    end;

    Procedure ShearPoint(var xold,yold,x,y: word; xshear,yshear: Real);
    Begin
      x := xOld+round(yOld*xShear);
      y := yOld+round(xOld*yShear);
    End;

    Procedure ShearTriangle(var tri,stri: tTriangle; xshear,yshear: real);
    Begin
      with tri.a do ShearPoint(x,y,stri.a.x,stri.a.y,xshear,yshear);
      with tri.b do ShearPoint(x,y,stri.b.x,stri.b.y,xshear,yshear);
      with tri.c do ShearPoint(x,y,stri.c.x,stri.c.y,xshear,yshear);
    End;

    Var
      oldsTri,sTri,Tri: tTriangle;
      yshear,xshear,xdir,ydir: real;
      loop: byte;
    Begin
      graphbegin;
      Setcolor(0,0,0,0);
      For loop := 1 to 127 do setcolor(loop,255-loop div 2,0,loop div 2);
      For loop := 128 to 255 do setcolor(loop,loop div 2,0,255-loop div 2);

      with tri do begin
        a.x := 5;
        a.y := 30;
        b.x := 30;
        b.y := 1;
        c.x := 50;
        c.y := 30;

        color := 1;
      end;
      stri := tri;
      oldstri := stri;

      xshear := 0;
      yshear := 0;
      ydir := 0.05;
      xdir := 0.05;
      repeat
        cycle(1,255,1);
        xshear := xshear+xdir;
        yshear := yshear+ydir;
        if (xshear > 4) or (xshear <= 0) then xdir := -xdir;
        if (yshear > 4) or (yshear <= 0) then ydir := -ydir;
        oldstri := stri;
        sheartriangle(Tri,sTri,xshear,yshear);

        { Delete the old one }
        oldstri.color := 0;
        retrace;
        drawtriangle(oldsTri);
        { Make the new one }
        drawtriangle(sTri);
      until keypressed;
      readkey;
      graphend;
      textattr := lightgray;
      clrscr;
      textattr := lightcyan;
      writeln('Shearing demo, by John Stephenson');
    End.

    {
    Rotations are interesting.. basically the general idea is:

      Qx := (Px * cos theta) - (Py * sin theta);
      Qy := (Px * sin theta) + (Py * cos theta);

      Now Q and P are the same for shearing, etc. Theta if you don't know is
    how many degrees you want to rotate it by. In Pascal cos & sin use something
    called radians. There are 2pi (you've heard of 2*pi*r to calculate the
    circumference, right? It's based on that) radians in a circle, contrasted
    to 360 degrees in a circle. The begining point is at (radius,0) (middle
    left side) - and that's where the point of 0 radians starts for Pascal.

    Btw does anyone know what GRAD means? On my scientific calculator I have
    RAD, DEG, and GRAD. I don't get GRAD...

    Here's a simple program to illustrate:
    }

    Program Rotation;
    Uses Crt,x320x240; { by John Stephenson, 1995 }

    Type
      tPoint = record
        x,y: integer;
      end;
      tTriangle = record
        color: byte;
        a,b,c: tPoint;
      end;

    Procedure DrawTriangle(var tri: tTriangle);
    begin
      with tri do begin
        line(a.x,a.y,b.x,b.y,color);
        line(b.x,b.y,c.x,c.y,color);
        line(c.x,c.y,a.x,a.y,color);
      end;
    end;

    Procedure RotatePoint(var oldx,oldy,x,y,aroundx,aroundy: integer; rad: real);
    Begin
      x := aroundx+round(oldx*cos(rad) - oldy*sin(rad));
      y := aroundy+round(oldx*sin(rad) + oldy*cos(rad));
    End;

    Procedure RotateTriangle(var tri,rtri: tTriangle; ax,ay: integer; rad: real);
    { Rotate triangle "tri" into "rTri" around "ax","ay" "rad" radians }
    Begin
      with tri.a do rotatepoint(x,y,rTri.a.x,rTri.a.y,ax,ay,rad);
      with tri.b do rotatepoint(x,y,rTri.b.x,rTri.b.y,ax,ay,rad);
      with tri.c do rotatepoint(x,y,rTri.c.x,rTri.c.y,ax,ay,rad);
    End;

    Var
      oldsTri,sTri,Tri: tTriangle;
      rad: real;
      loop: byte;
    Begin
      graphbegin;
      Setcolor(0,0,0,0);
      For loop := 1 to 127 do setcolor(loop,255-loop div 2,0,loop div 2);
      For loop := 128 to 255 do setcolor(loop,loop div 2,0,255-loop div 2);

      with tri do begin
        a.x := 5;
        a.y := 30;
        b.x := 30;
        b.y := 1;
        c.x := 50;
        c.y := 30;

        color := 1;
      end;
      stri := tri;
      oldstri := stri;

      rad := 0;
      repeat
        cycle(1,255,1);
        rad := rad + 0.05;
        if rad > 2*pi then rad := 0;

        oldstri := stri;
        RotateTriangle(tri,stri,xmid,ymid,rad);

        { Delete the old one }
        oldstri.color := 0;
        retrace;
        drawtriangle(oldsTri);
        { Make the new one }
        drawtriangle(sTri);
      until keypressed;
      readkey;
      graphend;
      textattr := lightgray;
      clrscr;
      textattr := lightcyan;
      writeln('Rotation demo, by John Stephenson');
    End.

    {
    To translate something it's pretty easy.. ie just:

    Qx = Px + h
    Qy = Py + g

    Where h, and g are the directions.. simple idea.

      Lets see.. there's a whole bunch of affine and inverse affine
    transformations that are worth taking a look at. If you haven't taken
    atleast grade 12 or OAC math learn the basics of Cosine, Sine, and
    Tangent (or if you have, skip that).. then pick up a computer graphics
    book (hopefully for Pascal) :)

      We've gotta remember this is a pascal programming echo, and not a math
    echo :) Hopefully this has helped out a bit.. Basically remember when
    you're rotating an image, all you're -really- doing is applying the
    rotation formulae to each pixel, and same with shearing.
    }

[Back to EGAVGA SWAG index] [Back to Main SWAG index] [Original]