From: warwick@cs.uq.oz.au (Warwick Allison)
Newsgroups: rec.games.programmer
Subject: Re: Question: Rotating a small bitmapped image?
Date: 27 Aug 92 07:08:17 GMT
Reply-To: warwick@cs.uq.oz.au

mucds@uxa.ecn.bgu.edu (Corey D. Stinson) writes:

>And suggestions on one that would not
>degrade the image?  Thanx for any help you can offer :)

Well the 6 posts before this one are all ways I've tried, so I can't
really flame them - but they are all quite poor.


The best algorithm I know is:


  1. Draw your image (by hand) at one rotation (say, facing right)

              # # . .
              . # # #
              . # # #
              # # . .

  2. Double (or even quadruple) the image using mechanical means
    (ie. each pixel twice)

              # # # # . . . .
              # # # # . . . .
              . . # # # # # #
              . . # # # # # #
              . . # # # # # #
              . . # # # # # #
              # # # # . . . .
              # # # # . . . .

  3. Improve on this expanded image (by hand) WITHOUT ADDING DETAIL.
    (ie. just smooth the corners - added detail just muddies the
         final result, since you'd be using pixels that don't exist)

              # # # # . . . .
              # # # # # # . .
              . # # # # # # .
              . . # # # # # #
              . . # # # # # #
              . # # # # # # .
              # # # # # # . .
              # # # # . . . .

  4. For each destination rotation you want to create (64 of them is GREAT),

       For each pixel (x,y) in the destination (16 of them is this example),

         Consider 4 points (or 16 if you quadrupled earlier)

           (x,y), (x+0.5,y), (x,y+0.5), (x+0.5,y+0.5)

	    (or (x+(0.25|0.5|0.75).... etc for the 16 if 4x)

         Rotate each of these points in the reverse direction, scale
          them by 2 (or by 4 for 4x), then look up that point in the
          source, and examine the colours at those points.  Find the
          average colour (R, G, B - wise will do) of the 4 points, and
          then find the colour in your palette which is closest to the
          average, and use a point of that colour to plot a the original
          (x,y) pixel in the destination.


This may sound like a LOT of work, but the results are truly AWESOME.

I have sourcecode for this, but it is quite crappy since it started out
as Modula-2, then I converted it to C++.

Things to remember:

    1. Use floating point.  Don't try for efficiency - after all this is
        just to pregenerate the sprite images.

    2. Do all your calculations on a co-ordinate system that
        ranges from -width/2 to +width/2 (and same for height),
        that makes rotations etc. much less confusing.

    3. Write the program as well as possible to allow room for extension,
        eg. make the "doubling" or "quadrupling" a parameter.


Something else you might want to do (I did) is to also rotate the "hot spot"
of the sprite in the process - that way you can join rotating objects
(eg. SpaceShip and ShipThrust) together with ease - put the hot-spot of
the spaceship in it's centre-of-mass, and the hot-spot of the thrust
out in front of the thrust (where the hot-spot of the ship is when the
thrust is correctly aligned).


This stuff really works - any Q's I'm happy to answer.

--
Warwick
--
  _-_|\      warwick@cs.uq.oz.au            /Disclaimer:
 /     * <-- Computer Science Department,  /  
 \_.-._/     University of Queensland,    /      void (if removed)
      v      Brisbane, Australia.        /  
Newsgroups: rec.games.programmer