DirectDraw:
16 bit Color Keys
By: Jeff Smith (aka MetalWarrior)
Written: September 2000
First
off, I want to give credit where credit is due. I really can't take any credit
for this tutorial, all I've done to get this code was paste it together from
various other tutorials. So here it is, all credit goes to: Patrice Scribe,
and Steven Blom (in that order). Also thanks to various people on various message
boards, who pointed out that it is indeed BGR, and not RGB.
Okay, so what is this tutorial about? Well, if you have any experience with
DirectDraw, you know about Color Keys. You probably also know that trying to
key out colors in any other color mode than 24-bit (or 32) can be a pain. This
tutorial deals with this problem for 16-bit mode. It shows, through code, how
to take either an RGB Long, or three separate RGB components, and convert them
to a 16-bit Long color code.
Let's start with the first step: Initialization. To be able to do our conversions,
we need to get the color shift values. So we need some code to get these. Here's
the two functions we'll need, along with a few public variables:
'COLOR SHIFT VALUES Public
RedShiftLeft As Long Public
RedShiftRight As Long Public
GreenShiftLeft As Long Public
GreenShiftRight As Long Public
BlueShiftLeft As Long Public
BlueShiftRight As Long
Public Sub GetColorShiftValues(PrimarySurface As
DirectDrawSurface7)
Dim PixelFormat As
DDPIXELFORMAT
PrimarySurface.GetPixelFormat
PixelFormat
MaskToShiftValues
PixelFormat.lRBitMask,
RedShiftRight,
RedShiftLeft
MaskToShiftValues
PixelFormat.lGBitMask,
GreenShiftRight,
GreenShiftLeft
MaskToShiftValues
PixelFormat.lBBitMask,
BlueShiftRight,
BlueShiftLeft
End Sub
Public Sub MaskToShiftValues(ByVal
Mask As Long,
ShiftRight As Long,
ShiftLeft As Long)
Dim ZeroBitCount As Long Dim
OneBitCount As Long
' Count zero bits
ZeroBitCount
= 0 Do While
(Mask And
1) = 0
ZeroBitCount
=
ZeroBitCount
+ 1
Mask =
Mask \
2 ' Shift right Loop
' Count one bits
OneBitCount
= 0 Do While
(Mask And
1) = 1
OneBitCount
=
OneBitCount
+ 1
Mask =
Mask \
2 ' Shift right Loop
' Shift right 8-OneBitCount bits
ShiftRight
= 2 ^
(8 -
OneBitCount) ' Shift left ZeroBitCount bits
ShiftLeft
= 2 ^
ZeroBitCount End Sub |
|
|
|
Once we have these functions in place, all we need to do is call GetColorShiftValues
once during our initialization (after creating the primary surface). This sets
up our Shift variables for use later in the color conversion.
Now what we need is a function to take a red, green, and blue component, adjust
them according to our shift values, and give us a properly formatted 16-bit
Long color. We can make that with a single line of code:
Public Function
DDRGB(Red As Long,
Green As Long,
Blue As Long) As Long
DDRGB
= (Red
\
RedShiftRight)
*
RedShiftLeft
+ _
(Green
\
GreenShiftRight)
*
GreenShiftLeft
+ _
(Blue
\
BlueShiftRight)
*
BlueShiftLeft
End Function |
|
|
|
Yes, that's really just one line. :) So now we can pass our red, green, and
blue values to this function, and get a 16-bit RGB Long all nicely formatted
to work with DirectDraw. One last thing though, what happens if we already have
a 24-bit RGB we want converted? Well, all we have to do is split it down into
red, green, and blue components, and pass those to our DDRGB function. The following
two functions will take care of it for us:
Public Sub
GetRGBfromColor(ByVal
Color As Long, ByRef
Red As Long, ByRef
Green As Long, ByRef
Blue As Long) Dim
HexadecimalValue As String 'This will store the Hexadecimal Value as a string
'This line will convert a Long decimal to Hexadecimal
HexadecimalValue
=
Hex(Val(Color))
If Len(HexadecimalValue) < 6 Then
HexadecimalValue
=
String(6
-
Len(HexadecimalValue),
"0")
+
HexadecimalValue
End If
Blue = CLng("&H"
+
Mid(HexadecimalValue,
1, 2))
Green
= CLng("&H"
+
Mid(HexadecimalValue,
3, 2))
Red = CLng("&H"
+
Mid(HexadecimalValue,
5, 2))
End Sub
Public Function DDColor(RGBColor As Long) As Long
Dim RedVal As Long Dim
GreenVal As Long Dim
BlueVal As Long
GetRGBfromColor
RGBColor,
RedVal,
GreenVal,
BlueVal
DDColor
=
DDRGB(RedVal,
GreenVal,
BlueVal) End Function |
|
|
|
You'll notice in the GetRGBfromColor function that the colors are stored
in the order, BGR, rather than RGB. That one had me stumped for a while. :)
Anyway, there it is. You can use the two functions DDRGB and DDColor to get
a 16-bit color. So now you can key out any color in 16-bit, and not just black,
white, and magenta. :)
Once again, all code was written by Patrice Scribe, except for the function
to split up colors from a single Long, which was written by Steven Blom. The
only code I actually wrote here was the DDColor function. ;) I hope you found
this tutorial helpful.
--MetalWarrior aka Jeff Smith
|