200 lines
9.6 KiB
Plaintext
200 lines
9.6 KiB
Plaintext
#############################################################################
|
|
# #
|
|
# #### #### ### # ##### #### #
|
|
# # # # # # # # # #
|
|
# ### # ##### # ### # # #
|
|
# # # # # # # # # #
|
|
# #### #### # # ##### ##### #### #
|
|
# #
|
|
# #### ##### ##### ##### ### #### #### #
|
|
# # # # # # # # # # # # # #
|
|
# #### # # # # # ##### #### ### #
|
|
# # # # # # # # # # # # #
|
|
# #### ##### # # # # # # # #### #
|
|
# #
|
|
# Trainer #
|
|
# #
|
|
# by #
|
|
# #
|
|
# Tumblin / Bodies In Motion #
|
|
# #
|
|
#############################################################################
|
|
|
|
|
|
|
|
Hello there, this doc file is intended to be a trainer for doing
|
|
scaled bitmaps. The routines accompanying this file are not meant to be as
|
|
fast as possible, but clear and easy to learn what is going on when doing
|
|
this effect. With this in mind, lets put on our thinking caps and get our
|
|
hands dirty!
|
|
|
|
Okay, first a little bit of background theory. The basic algorithm
|
|
that my implementation of scaled bitmaps is based on is the infamous
|
|
Bresenham's Algorithm. This is the favoured technique for drawing lines
|
|
very quickly. But for scaled bitmaps, we modify it a little so that we can
|
|
take a column of pixels and stretch them out or squash them down. Lets go
|
|
through an example that we could use to draw a scaled bitmap, in the form of
|
|
a vertical column of pixels on the screen by taking pixel colors from a one
|
|
dimensional array.
|
|
|
|
The following pseudo code example will *stretch* a source bitmap to a larger
|
|
destination bitmap (a 64 pixel bitmap to a 124 pixel bitmap):
|
|
|
|
-----------------------------------------------------------------------------
|
|
source_height = 64
|
|
start_y = 0
|
|
end_y = 123
|
|
destination_height = end_y - start_y
|
|
error_term = 0
|
|
source_index = 0
|
|
screen_x = 0
|
|
screen_y = start_y
|
|
|
|
do
|
|
{
|
|
color=bitmap[source_index]
|
|
draw_pixel(screen_x,screen_y)
|
|
error_term = error_term + source_height
|
|
if error_term > destination_height
|
|
error_term = error_term - destination_height
|
|
source_index = source_index + 1
|
|
endif
|
|
screen_y = screen_y + 1
|
|
} while screen_y < end_y
|
|
-----------------------------------------------------------------------------
|
|
Here's the explanation.
|
|
|
|
In the do loop, you start out by grabbing a color from the source
|
|
bitmap that you want to scale onto the screen. You then draw that color on
|
|
the screen at the current screen coordinates. Then there is this error_term
|
|
thingy. What it is used for is to help us decide when it will be time to
|
|
change the index into the source bitmap so that we can pull out the next
|
|
color. What you do is you add the height of the source bitmap to the error
|
|
term, then you do a test to see if the error term has exceeded the size of
|
|
the destination bitmap. If it did, then you subtract the size of the
|
|
destination bitmap from the error term and also increase the index into the
|
|
source bitmap. After this decision is done, you increase the screen
|
|
coordinate. You keep repeating this do loop until the screen coordinate is
|
|
equal to the ending coordinate that you specified at the beginning. The
|
|
whole gist of scaling a small source bitmap to a larger destination bitmap is
|
|
to always increment the screen coordinate through each time through the loop
|
|
and only increment the index to the source bitmap when it is necessary to.
|
|
Every pixel in the source bitmap will be drawn at least once, even repeated
|
|
if need be. Just think in your mind that you are "stretching" the bitmap.
|
|
Pretty simple really.
|
|
|
|
|
|
|
|
Now here is what it would look like if you wanted to *shrink* a source bitmap
|
|
to a smaller destination bitmap (a 101 pixel bitmap to a 74 pixel bitmap):
|
|
|
|
-----------------------------------------------------------------------------
|
|
source_height = 101
|
|
start_y = 0
|
|
end_y = 73
|
|
destination_height = end_y - start_y
|
|
error_term = 0
|
|
source_index = 0
|
|
screen_x = 0
|
|
screen_y = start_y
|
|
|
|
do
|
|
{
|
|
color=bitmap[source_index]
|
|
draw_pixel(screen_x,screen_y)
|
|
error_term = error_term + destination_height
|
|
if error_term > source_height
|
|
error_term = error_term - source_height
|
|
screen_y = screen_y + 1
|
|
endif
|
|
source_index = source_index + 1
|
|
} while screen_y < end_y
|
|
-----------------------------------------------------------------------------
|
|
|
|
This is the same idea as before but with a few changes. In this one, you
|
|
grab a color from the source bitmap and draw it on the screen like in the
|
|
previous example. Then you add the size of the destination bitmap to the
|
|
error term. If the error term exceeds the size of the source bitmap then you
|
|
just subtract the size of the source bitmap from the error term and also
|
|
increment the screen coordinate. After the if statement, you manditorialy
|
|
increment the index into the source bitmap. So the gist of scaling a larger
|
|
source bitmap to a smaller destination bitmap is to always increment the
|
|
index into the source bitmap, but only drawing the pixels that are necessary.
|
|
This means that some of the pixels in the source bitmap will be skipped.
|
|
|
|
|
|
Now then, how do you scale a whole rectangular source bitmap to a
|
|
rectangular destination bitmap??? Well, you have to combine the techniques
|
|
above to take care both cases of drawing vertically stretched single columns
|
|
of pixels. Okay, so that takes care of drawing scaled vertical lines, but
|
|
what about the horizontal dimension? You basically use the same routines
|
|
explained above, but switch the x's with y's and use the index into the
|
|
source bitmap to select which column of the source bitmap you want to work
|
|
with and then use the very same routines that we used before. Actually
|
|
scaled bitmaps are nested Bresenham loops. Just remember that when you are
|
|
doing your routines, make sure you cover the two types of vertical scaling
|
|
(large to smaller, and small to larger), and the two types of horizontal
|
|
scaling (large to smaller and small to larger). Oops, actually there is one
|
|
more additional case, I forgot to mention the case where the source and
|
|
destination bitmaps are equal in size! But that is *easily* accounted for.
|
|
All you have to do is let one of the four cases also include an equality in
|
|
the sizes of both dimensions of the source and destination bitmaps. Another
|
|
thing to remember is that when you are done doing a vertical line, reset the
|
|
index to the source bitmap back to zero and reset the screen y coordinate to
|
|
the top again. All of this will be clear when you see the complete source
|
|
code ;-)
|
|
|
|
|
|
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
|
|
|
Here are some tips for getting the code compiled:
|
|
|
|
My system consists of a 486DX 33MHz, Trident 8900 SVGA 1MB, 120MB hard drive,
|
|
Sound Blaster Pro, and I use Turbo C++ 3.0.
|
|
|
|
|
|
First you need a copy of XLIB06.ZIP
|
|
Unzip this file into a directory and then edit MAKEFILE to change the line
|
|
that says MODEL=s to MODEL=l (I used the large memory model to compile this
|
|
demo). This is what might have caused some people some confusion when they
|
|
tried to compile my previous release VECTBALL.ZIP. I included the
|
|
VECTBALL.PRJ file with it and I had the memmory model on the Large setting.
|
|
XLib 6 was released with the memory model set to Small. Please make sure
|
|
that the memory models match!
|
|
|
|
I might also mention that I also had to change the line that says CC=bcc to
|
|
CC=tcc (I compiled it with my Turbo C++ 3.0 and worked fine).
|
|
|
|
Next type MAKE and watch XLib 6 get compiled before your very eyes. When I
|
|
did it myself, I noticed some strange warnings fly up the screen, but they
|
|
didn't hurt anything one bit. I guess one of the demo programs didn't get
|
|
compiled, but the most important thing is that the XLIB6L.LIB file got
|
|
compiled okay.
|
|
|
|
Now you create a project file by typing BC BMSCALER.PRJ if you have the
|
|
Borland C++ 3.1 compiler or TC BMSCALER.PRJ if you have the Turbo C++ 3.0
|
|
compiler.
|
|
|
|
Next you add the BMSCALER.CPP and XLIB6L.LIB files into your project.
|
|
|
|
Use the Options/Code Generations option and select the Large memory model.
|
|
|
|
When you are done that, you should be all ready to compile the BMSCALER.CPP
|
|
by using Complile/Make, or compile it and run it in the IDE by doing a
|
|
Compile/Run.
|
|
|
|
Play around with the call to the bmscaler function and use some strange
|
|
coordinate combinations, they can make some pretty interesting visual effects.
|
|
|
|
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
|
|
|
I guess that about wraps up my discussion on scaled bitmaps. If you have
|
|
any questions or comments, email me.
|
|
|
|
If you use this code in any demos you write, greet me, or send me a cool
|
|
post card from your country.
|
|
|
|
|
|
|
|
Tumblin / Bodies In Motion
|