Advertisement

GDI Colors

Started by September 28, 2000 09:13 PM
8 comments, last by mr_jrt 24 years, 3 months ago
Info: GDI''s BitBlt re-maps my image colours each time I blt to a DDraw surface after I''ve faded the palette to a single colour(which screws it up when I fade the palette back to normal). Point: Anyone know a quick and easy way of getting a bitmap files image data onto a directdraw surface without GDI remapping the colours? More Detail: I''m using LoadImage to load a bitmap onto a DC, which I then BitBlt to a DirectDraw surface. This works fine. Well, I recently (half an hour ago) finished my routines to fade the palette to any RGB coour or another palette. These also (finally!) work perfectly, but I have noticed a problem. In the little test program I''m using to test the game "engine", I have a setup where the first joystick adds an animated "sprite" with one button, and removes one with the other. Now, because I reload the image data fresh when each sprite is created, when BitBlt moves the image data to my DDraw surface (part of the sprite''s class), it maps the colours to the palette at that instant, not copying the values directly, which is what I''m after. Cheers for any help. Waassaap!!
Waassaap!!
quote: Original post by mr_jrt

I'm using LoadImage to load a bitmap onto a DC, which I then BitBlt to a DirectDraw surface. This works fine. Well, I recently (half an hour ago) finished my routines to fade the palette to any RGB coour or another palette.

...

Now, because I reload the image data fresh when each sprite is created, when BitBlt moves the image data to my DDraw surface (part of the sprite's class), it maps the colours to the palette at that instant, not copying the values directly, which is what I'm after.


Well now you are saying you are using palettes, but that you want it to display the true bitmap RGB values. This is not possible in 8-bit palettized mode.

If, in the IDirectDraw7::SetDisplayMode() function, you specified '8' for the bpp parameter (which is required to use palettes), then DirectDraw is treating the bitmap data as indexes to the palette you created, not as RGB values. I'm surprised the bitmap is loading at all if it's has a depth of greater than 8 bpp. If it IS a 8 bpp bitmap, than again you can't display "true" RGB values because by definition, 8-bit bitmap data are indexes to a palette, not a color definition.



Edited by - Steel on September 28, 2000 11:08:45 PM
Advertisement
What I meant was in the bitmap (256 colour), lets say I''ve got a image of a line with colours:

0, 1, 2 , 4 , 5

Now, when I load them before I do the fade (updating the palette''s RGB values), the current palette is the same as the one used in the bitmap, so the image is dislayed fine.

However, as I adjust the palette during the fade (done in increments over 128 frames), when I create new sprites from the image data, (GDI) BitBlt''s attempts to match colours is not what I want.

This is because when I fade back up to the original palette, this is not the palette that their (the sprites loaded during the fade) colours were mapped to when they were created, so they look wrong when the fade is complete.

Cheers for taking the time to reply.


Waassaap!!
Waassaap!!
quote: However, as I adjust the palette during the fade (done in increments over 128 frames), when I create new sprites from the image data, (GDI) BitBlt's attempts to match colours is not what I want.


Ok well first I am assuming you are using 'SRCCOPY' for the raster-operation code parameter of the GDI's BitBlt() function. BitBlt simply transfers bits...it does NOT "attempt to match colors". The bitmap data transferred via the BitBlt() function is never changed unless you are using a different raster-operation code.

quote: Now, when I load them before I do the fade (updating the palette's RGB values), the current palette is the same as the one used in the bitmap, so the image is dislayed fine.


There is no "palette" stored in a bitmap file. Most bitmap documention say that the data in a bitmap file define the colors. For 8-bit, 256-color bitmaps, this is somewhat of a misnomer. Each 8-bit number does not define a color - it defines an index that point to a color, which is defined by the palette.

So let's say you have bitmap that is a single line 5 pixels long with the values '4,200,5,12,23'. These numbers are not the actual colors. DirectDraw will take the first 8-bit value (pixel) '4' and look up what RGB color is stored in the 4th index of your palette. DirectDraw takes the second value, '200', then looks up the 200th RGB value in your palette.

Say, for example, the 200th RGB value in your pallete was 0xFFFFFF, which is white. In this case, the second pixel in the bitmap described above will be white. Now if you change the 200th entry in the pallete to 0x000000 (black), the second pixel in the bitmap will instantly change to black. This is the way 8-bit palettized mode works.

quote: This is because when I fade back up to the original palette, this is not the palette that their (the sprites loaded during the fade) colours were mapped to when they were created, so they look wrong when the fade is complete.


If it looked right originally, then you are simply not restoring the original palette as you thought you were.

When you create a bitmap, it doesn't matter what you "see" in you image editor. The only thing being stored in an 8-bit, 256-color bitmap is an 8-bit value for each pixel. So an 8-bit bitmap isn't mapped to "colors". No, they just have numbers; a PALETTE is mapped to colors. So your image editor could be using a different pallete. That is, your image editor might be using the number '4' for "red", but your "original" DirectDrawSurface Palette could be using '150' for "red".

quote: Now, because I reload the image data fresh when each sprite is created, when BitBlt moves the image data to my DDraw surface (part of the sprite's class), it maps the colours to the palette at that instant, not copying the values directly, which is what I'm after.


That's a quote from your first message. Indeed, BitBlt in fact IS copying the values directly, but the values don't represent colors in 8-bit mode, they just *point* to your Palette's table of colors. If you are trying to make your sprites look the same as you change the colors in your palette, you are going to have to dynamically change the data in the sprite's bitmap. Even then, this won't work if you are changing the entire palette to one color.

Say you changed every palette entry to the same color:
0: 0xFF0000
1: 0xFF0000
...
4: 0xFF0000
5: 0xFF0000
...
200: 0xFF0000
201: 0xFF0000
...
254: 0xFF0000
255: 0xFF0000

And now you have a bitmap with just five 8-bit values (or five pixels): 4, 200, 5, 12, 23.
So what is the RGB value stored in Palette entry #4? It's 0xFF0000. And what is the RGB value stored in Palette entry #200? Again it's 0xFF0000. The third pixel is the value '5'; what's the RGB value in Palette entry #5? That's right, 0xFF0000. So now you see why it changed "instantly". And if every palette entry is the same RGB value (say all of them were red), then every value in your bitmap ends up pointing to "red". Oh, they do point to a different pallete entry, but all the entries are red!

If the sprite displayed correctly before changing the palette, and it looked wrong after restoring the orginal palette, than like I said before, you simply are not restoring the original palette values like you thought you were. Either that or you are inadvertently changing the bitmap data somewhere else. But you said you reload it fresh each time so that can't be it (and this is unnecessary anyway if all you are doing is changing the palette values -- remember the bitmap bits won't change!).

I sincerly hope I am understanding the problem! If not, please explain more!


Edited by - Steel on September 28, 2000 12:32:22 AM
I assumed that BitBlt (yes, I''m using SRCCOPY) was the problem as it''s the only data transfer that is occuring in the image loading process.


There is no "palette" stored in a bitmap file. Most bitmap documention say that the data in a bitmap file define the colors. For 8-bit, 256-color bitmaps, this is somewhat of a misnomer. Each 8-bit number does not define a color - it defines an index that point to a color, which is defined by the palette.


I''m unsure at what you''re getting at here, first you say there''s no palette in a bitmap, then you say there is. Bitmap files can have palettes, which the file does have (Just to make sure I even used a hex editor on it), as it is a 256 colour bitmap I created in PSP5. The image data is stored as a series of palette "indexes" to the RGB values stored in the palette (which is stored after the header in the file, but before the image data).

I am doing the fade by taking the palette each frame, adjusting each colour towards the colour I''m fading to, then updating the palette with these (adjusted) values, so the actual image data isn''t changed anywhere.

There must be some colour conversion going on somewhere because like I said, when I create a sprite before I fade the colours it appears fine, but if I create one during the fade, the colours are VERY different to those in the original (now faded) sprite, which if it was using the same image data would have the same (faded) colours.

I''ll do some more debugging and check the image data is actually the same for all the sprites.

Waassaap!!
Waassaap!!
Dude I''m sorry I sounded so ambiguous. It was very late when I wrote that post and even I didn''t understand what the hell I was trying to say sometimes.

Anyway, you are right: DIBs can store an optional color table (palette information).

Now let me ask you something: how are you defining the original palette attached to the Primary Surface? Are you creating it manually with your own algorithm? Or are you filling in the PALETTEENTRY array with data from one of your bitmaps'' RGBQUAD structures?

Here''s the thing: either way, in 8-bit palettized mode you can only display 256 colors at once (which, of course, you are aware of). So everything is dandy when you first load the sprite bitmap, but then you change the Primary Surface palette. That right there is causing your "problem".

It doesn''t matter what the color table (palette info) that is stored in the bitmap file contains. It''s only useful if you use that color table (it''s an RGBQUAD structure in Win32) to fill your PALETTEENTRY array used in your DirectDrawPalette object(which is then attached to your Primary Surface).

The actual bitmap bits, which define your pixels, are used as an index to the color table/palette defined in your surface''s palette. They are NOT used as an index into the color table stored in the bitmap file. They will always point to values in the Primary Surface''s palette. Like I said just before, the color table in the file is used to define your Primary Surface''s color table/palette, if you so desire.

So when you are fading the DirectDrawPalette''s colors (that is, changing the values in the palette''s PALETTEENTRY array), the bits stored in the bitmap are *mapped* to those new values you defined in the DirectDrawPalette (hence the name "bitmap").

You want to start fading to a single color, but halfway through, you want to display a bitmap the way you see it in Photoshop? This is simply not possible in 8-bit palettized mode, because those (unchanged) bits are pointing to the DirectDrawPalette''s color table/palette, not your bitmap file''s color table/palette.


Now what exactly do you *want* to see on screen?
Advertisement
The idea is this:

I have these litlle sprites doing their thing, bouncing around, using the palette from the bitmap file.

*want to see sprites using palette from bitmap file*

I then fade the palette in increments to a single colour (aka. I adjust the R,G & B components of each palette entry towards the colour I''m fading to.

E.g. to fade from black (0,0,0) to white (255, 255, 255) over 128 frames, I add 2 to the value in the palette each frame, and at frame 128, the palette entry will be white. Obviously I''m updating the primary surface''s palette each frame).

*want to see solid white screen*

However, the image data (the indexes) haven''t been modified, just the colours in the palette they point to, I want to fade back to the palette from the file.

*want to see sprites using palette from bitmap file*

This works fine if the sprite was created before the fade started, but screws up the colours if the sprite was created during the fade.

I just can''t understand how these sprite, being crated from the same image data (the palette indexes) can be using different colours to the other sprites on screen at the same time without somewhere adjusting my image data.

Steel, I can send you a executable to show you what I mean if you think that will help. (41K RAR file)

Cheers again for actually taking the time to stick here with me on this.

Jamie.


Waassaap!!
Waassaap!!
Whoops!

It would seem that you were right about BitBlt not altering the image data, I used memcpy instead and I got the same results as before, and whist scanning through my code the function "CreateCompatibleDC" jumped out at me and bit me on the butt-ocks.

Looking at the parameters for said function, I found this:

quote:
Parameters
hdc
Handle to an existing device context. If this handle is NULL, the function creates a memory device context compatible with the application's current screen.


Bang, there's where the problem lies. I was passing NULL, which meant the DC created was compatible with the screen with it's (faded) palette, which meant when the bitmap object is selected into it, it's image data is mapped to the current palette.

Now I just need to work out how to get the bitmap data onto the directdraw surface directly from the bitmap file.

Oh well, back to work I suppose...
hmmm....I wonder what this button does......



Edited by - mr_jrt on September 30, 2000 4:37:20 PM
Waassaap!!
boy, now doesn''t that feel good?
Well, I''m now closing this thread.

I''ve fixed the problem by not using DC''s at all, instead I take my HBITMAP from LoadImage and use GetObject to get a pointer to the bitmap data, which I copy onto the surface directly line-by-line using memcpy.

After I fixed this, I was able to fix a lot of the minor flaws in my fading code, and now I can fade (in a 256-colour mode) to any 24-Bit single colour or fade to a whole 256 colour palette. The fading (finally!) works fine.

Phew.

Cheers Steel for your help.
(You''re right, it feels damn good)

-Jamie

Waassaap!!
Waassaap!!

This topic is closed to new replies.

Advertisement