Problem with reusing array of surfaces

Most of my programming experience in the last years was the easy way -
java, c# even pascal but recently I have wiped the dust from my old c++
books and started some small sdl projects. I have a problem with the
code below. It simply loads images. Because I was lazy I hardcoded
several image sets that are loaded when a key is pressed. images[] is a
global variable and it is reused. If I swap the image sets a few
times (about 20 on winxp with 256) the program exits. Paul Nettle’s
memory manager does not detect any memory leaks and there but I have
noticed that while the programs runs there about 5-10Mb RAM that remain
free.
I have added calls to SDL_FreeSurface but there was no difference. I it
does not free the memory what else should be done?

void LoadImageSet01()
{
// the following loop doesn’t help either
for ( int index = 0; index < 15; index ++ )
{
if ( images[ index ] != NULL )
SDL_FreeSurface( images[ index ] );
}
// Set transparent key color to blue (255)
ColorRGB transparent;
transparent.r = 0;
transparent.g = 0;
transparent.b = 255;

// Load images
images[ 0 ] = LoadIMG( IMAGE0101, transparent );
images[ 1 ] = LoadIMG( IMAGE0102, transparent );
images[ 2 ] = LoadIMG( IMAGE0103, transparent );
images[ 3 ] = LoadIMG( IMAGE0104, transparent );
images[ 4 ] = LoadIMG( IMAGE0105, transparent );
images[ 5 ] = LoadIMG( IMAGE0106, transparent );
images[ 6 ] = LoadIMG( IMAGE0107, transparent );
images[ 7 ] = LoadIMG( IMAGE0108, transparent );
images[ 8 ] = LoadIMG( IMAGE0109, transparent );
images[ 9 ] = LoadIMG( IMAGE0110, transparent );
images[ 10 ] = LoadIMG( IMAGE0111, transparent );
images[ 11 ] = LoadIMG( IMAGE0112, transparent );
images[ 12 ] = LoadIMG( IMAGE0113, transparent );
images[ 13 ] = LoadIMG( IMAGE0114, transparent );
images[ 14 ] = LoadIMG( IMAGE0115, transparent );
}

Note: this program works under WinNT if I do not switch between the
image sets too many times but under Win98 if I run the program a second
time all transparent colors (I use color keying) are no more
transparent. I believe I do every initialization and clean up as it is
explained in the docs.

Is there any example (source code) that loads and destroys lots of large
images (1024x768) dynamically uses transparency and works correctly.

Z.

I had the same problem… Here are somethings you may or not be doing.

  1. Initialise each surface pointer to NULL when you first create it.

  2. Remember to call SDL_FreeSurface() before loading in a new image.
    SDL_Surface is a pointer to a memory location, so loading in another image
    using that pointer will not automatically free the data it will just switch
    the memory pointer leaving the original data floating around with no way to
    track it.

  3. Calling,

if (image[0] == NULL)

and image[0] was never set to NULL to begin with will / might cause seg
faults.> -----Original Message-----

From: Hri [SMTP:hr_hristov at hotmail.com]
Sent: Friday, May 09, 2003 2:19 PM
To: sdl at libsdl.org
Subject: [SDL] Problem with reusing array of surfaces.

Most of my programming experience in the last years was the easy way -
java, c# even pascal but recently I have wiped the dust from my old c++
books and started some small sdl projects. I have a problem with the
code below. It simply loads images. Because I was lazy I hardcoded
several image sets that are loaded when a key is pressed. images[] is a
global variable and it is reused. If I swap the image sets a few
times (about 20 on winxp with 256) the program exits. Paul Nettle’s
memory manager does not detect any memory leaks and there but I have
noticed that while the programs runs there about 5-10Mb RAM that remain
free.
I have added calls to SDL_FreeSurface but there was no difference. I it
does not free the memory what else should be done?

void LoadImageSet01()
{
// the following loop doesn’t help either
for ( int index = 0; index < 15; index ++ )
{
if ( images[ index ] != NULL )
SDL_FreeSurface( images[ index ] );
}
// Set transparent key color to blue (255)
ColorRGB transparent;
transparent.r = 0;
transparent.g = 0;
transparent.b = 255;

// Load images
images[ 0 ] = LoadIMG( IMAGE0101, transparent );
images[ 1 ] = LoadIMG( IMAGE0102, transparent );
images[ 2 ] = LoadIMG( IMAGE0103, transparent );
images[ 3 ] = LoadIMG( IMAGE0104, transparent );
images[ 4 ] = LoadIMG( IMAGE0105, transparent );
images[ 5 ] = LoadIMG( IMAGE0106, transparent );
images[ 6 ] = LoadIMG( IMAGE0107, transparent );
images[ 7 ] = LoadIMG( IMAGE0108, transparent );
images[ 8 ] = LoadIMG( IMAGE0109, transparent );
images[ 9 ] = LoadIMG( IMAGE0110, transparent );
images[ 10 ] = LoadIMG( IMAGE0111, transparent );
images[ 11 ] = LoadIMG( IMAGE0112, transparent );
images[ 12 ] = LoadIMG( IMAGE0113, transparent );
images[ 13 ] = LoadIMG( IMAGE0114, transparent );
images[ 14 ] = LoadIMG( IMAGE0115, transparent );
}

Note: this program works under WinNT if I do not switch between the
image sets too many times but under Win98 if I run the program a second
time all transparent colors (I use color keying) are no more
transparent. I believe I do every initialization and clean up as it is
explained in the docs.

Is there any example (source code) that loads and destroys lots of large
images (1024x768) dynamically uses transparency and works correctly.

Z.


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

.sophos.3.68.05.08.

[…]

  1. Calling,

if (image[0] == NULL)

and image[0] was never set to NULL to begin with will / might cause
seg faults.

Have you actually seen this happen on anything like a PC or
workstation CPU? It takes a rather weird architecture to segfault by
just checking the value of a pointer… The problem is that the NULL
test thinks any garbage is a valid pointer.

Either way, I’d write (NULL == image[0]) instead, just in case '=='
accidentally becomes ‘=’. I think you can also assume that NULL == 0
on any architecture currently in use, so you can just do if(image[0])
…; to avoid that problem entirely.

//David Olofson - Programmer, Composer, Open Source Advocate

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Friday 09 May 2003 16.05, Sweeney, Steven (FNB) wrote:

[…]

  1. Calling,

if (image[0] == NULL)

and image[0] was never set to NULL to begin with will / might
cause seg faults.

Have you actually seen this happen on anything like a PC or
workstation CPU? It takes a rather weird architecture to segfault
by just checking the value of a pointer… The problem is that the
NULL test thinks any garbage is a valid pointer.

Of course, that’s probably exactly what you meant… :slight_smile:

Either way, I’d write (NULL == image[0]) instead, just in case '=='
accidentally becomes ‘=’. I think you can also assume that NULL ==
0 on any architecture currently in use, so you can just do
if(image[0]) …; to avoid that problem entirely.

…and “if(NULL == image[0])” would become “if(!image[0])”, obviously.

I should probably not try to do anything important until my fever gets
a bit better. Can’t think straight. (Well, I mean, it’s harder than
usual. :wink:

//David Olofson - Programmer, Composer, Open Source Advocate

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Friday 09 May 2003 16.43, David Olofson wrote:

On Friday 09 May 2003 16.05, Sweeney, Steven (FNB) wrote:

Oops,

Sorry… Number 3 should have read,

if (image[0] != NULL)
SDL_FreeSurface(image[0]);

Which will cause problems if image[0] was never set to NULL and if image[0]
was never pointed to data.

Should never have drinkies at lunch time and then try and answer programming
questions :)> -----Original Message-----

From: David Olofson [SMTP:david at olofson.net]
Sent: Friday, May 09, 2003 3:43 PM
To: sdl at libsdl.org
Subject: Re: [SDL] Problem with reusing array of surfaces.

On Friday 09 May 2003 16.05, Sweeney, Steven (FNB) wrote:
[…]

  1. Calling,

if (image[0] == NULL)

and image[0] was never set to NULL to begin with will / might cause
seg faults.

Have you actually seen this happen on anything like a PC or
workstation CPU? It takes a rather weird architecture to segfault by
just checking the value of a pointer… The problem is that the NULL
test thinks any garbage is a valid pointer.

Either way, I’d write (NULL == image[0]) instead, just in case ‘==’
accidentally becomes ‘=’. I think you can also assume that NULL == 0 on
any architecture currently in use, so you can just do if(image[0])
…; to avoid that problem entirely.

//David Olofson - Programmer, Composer, Open Source Advocate

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

.sophos.3.68.05.09.

Hi,

just a few questions. I was just wondering what happens inside your
LoadIMG() function:

Do you make any calls to, say, SDL_DisplayFormat()?
Are you using hardware or software surfaces?
Assuming you call SDL_SetColorKey(), do you use SDL_RLEACCEL?

Posting a small, complete, example program that demonstrates the
problem with a link to, say, a pair of your images that can be used
with the above program, will likely result in getting your problem
solved.

Either you will solve it yourself in the process of making the small,
complete, example, or someone on this list will be interested enough to
try and reproduce the problem and then help solve it,

best of luck,
John.> ----- Original Message -----

From: sweenes@fnb.co.uk (Steven Sweeney))
To:
Sent: Friday, May 09, 2003 3:05 PM
Subject: RE: [SDL] Problem with reusing array of surfaces.

I had the same problem… Here are somethings you may or not be doing.

  1. Initialise each surface pointer to NULL when you first create it.

  2. Remember to call SDL_FreeSurface() before loading in a new image.
    SDL_Surface is a pointer to a memory location, so loading in another image
    using that pointer will not automatically free the data it will just
    switch
    the memory pointer leaving the original data floating around with no way
    to
    track it.

  3. Calling,

if (image[0] == NULL)

and image[0] was never set to NULL to begin with will / might cause seg
faults.

-----Original Message-----
From: Hri [SMTP:hr_hristov at hotmail.com]
Sent: Friday, May 09, 2003 2:19 PM
To: sdl at libsdl.org
Subject: [SDL] Problem with reusing array of surfaces.

Most of my programming experience in the last years was the easy way -
java, c# even pascal but recently I have wiped the dust from my old c++
books and started some small sdl projects. I have a problem with the
code below. It simply loads images. Because I was lazy I hardcoded
several image sets that are loaded when a key is pressed. images[] is a
global variable and it is reused. If I swap the image sets a few
times (about 20 on winxp with 256) the program exits. Paul Nettle’s
memory manager does not detect any memory leaks and there but I have
noticed that while the programs runs there about 5-10Mb RAM that remain
free.
I have added calls to SDL_FreeSurface but there was no difference. I it
does not free the memory what else should be done?

void LoadImageSet01()
{
// the following loop doesn’t help either
for ( int index = 0; index < 15; index ++ )
{
if ( images[ index ] != NULL )
SDL_FreeSurface( images[ index ] );
}
// Set transparent key color to blue (255)
ColorRGB transparent;
transparent.r = 0;
transparent.g = 0;
transparent.b = 255;

// Load images
images[ 0 ] = LoadIMG( IMAGE0101, transparent );
images[ 1 ] = LoadIMG( IMAGE0102, transparent );
images[ 2 ] = LoadIMG( IMAGE0103, transparent );
images[ 3 ] = LoadIMG( IMAGE0104, transparent );
images[ 4 ] = LoadIMG( IMAGE0105, transparent );
images[ 5 ] = LoadIMG( IMAGE0106, transparent );
images[ 6 ] = LoadIMG( IMAGE0107, transparent );
images[ 7 ] = LoadIMG( IMAGE0108, transparent );
images[ 8 ] = LoadIMG( IMAGE0109, transparent );
images[ 9 ] = LoadIMG( IMAGE0110, transparent );
images[ 10 ] = LoadIMG( IMAGE0111, transparent );
images[ 11 ] = LoadIMG( IMAGE0112, transparent );
images[ 12 ] = LoadIMG( IMAGE0113, transparent );
images[ 13 ] = LoadIMG( IMAGE0114, transparent );
images[ 14 ] = LoadIMG( IMAGE0115, transparent );
}

Note: this program works under WinNT if I do not switch between the
image sets too many times but under Win98 if I run the program a second
time all transparent colors (I use color keying) are no more
transparent. I believe I do every initialization and clean up as it is
explained in the docs.

Is there any example (source code) that loads and destroys lots of large
images (1024x768) dynamically uses transparency and works correctly.

Z.


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

.sophos.3.68.05.08.


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

[Off-topic for SDL, but a common misconception that I can’t let go by]

I think you can also assume that NULL == 0 on any architecture
currently in use, so you can just do if(image[0]) …; to avoid that
problem entirely.

Actually, the C language requires that a literal zero used as a
pointer shall be understood as a “null pointer constant”, regardless
of the actual bit-representation of a null pointer. In other words

p = 0;

will produce a null pointer even on platforms where

memset(p, 0, sizeof p);

won’t.

Naturally, this also extends to boolean contexts.

b

I have followed John’s advice and I have created a test version of my
functions (included bellow). It helped me to track down the main problem
to the SDL_DisplayFormat() function in LoadIMG().

It looks like this portion is:

// Set display format for fast blitting
ready = SDL_DisplayFormat( temp );
if( ready == NULL )
{
printf( “Image display format conversion failed: %s\n”,
SDL_GetError()
);
exit( 3 );
}

return ready;
}

Obviously I should destroy the surface “ready” but I don’t now how (in
this context). SDL_GetError returnes Out of memory.

And the other problems still remains. If I run the program twice on
Win98 the transparent color of the “splashImage” image is not
transparent the second time. The problem seems to be the SDL_HWPALETTE
flag in fullscreen mode (under Win98 only).

BTW I have removed ready = SDL_DisplayFormat( temp ); and it takes now
longer to crash under Win98 (under NT seems that it won’t crash).

Well, not the question might be: how to use correctly SDL_HWPALETTE and
SDL_DisplayFormat

// PVTest.cpp : Defines the entry point for the console application.

// Do not show splash
//#define NOSPLASH

// Data defines
#define MAX_IMAGES 10

#define SPLASH “./data/splash/splash.gif”

// Image collection 1
#define IMAGE0101 “./data/set01/01.jpg”
#define IMAGE0102 “./data/set01/02.jpg”
#define IMAGE0103 “./data/set01/03.jpg”
#define IMAGE0104 “./data/set01/04.jpg”
#define IMAGE0105 “./data/set01/05.jpg”
#define IMAGE0106 “./data/set01/06.jpg”
#define IMAGE0107 “./data/set01/07.jpg”
#define IMAGE0108 “./data/set01/08.jpg”
#define IMAGE0109 “./data/set01/09.jpg”
#define IMAGE0110 “./data/set01/10.jpg”

// Image collection 2
#define IMAGE0201 “./data/set02/01.jpg”
#define IMAGE0202 “./data/set02/02.jpg”
#define IMAGE0203 “./data/set02/03.jpg”
#define IMAGE0204 “./data/set02/04.jpg”
#define IMAGE0205 “./data/set02/05.jpg”
#define IMAGE0206 “./data/set02/06.jpg”
#define IMAGE0207 “./data/set02/07.jpg”
#define IMAGE0208 “./data/set02/08.jpg”
#define IMAGE0209 “./data/set02/09.jpg”
#define IMAGE0210 “./data/set02/10.jpg”

//////////////////////////////////////////////////////////
// Headers
//////////////////////////////////////////////////////////

#include <stdlib.h>
#include <stdio.h>
// SDL headers
#include “SDL/SDL.h”
#include “SDL/SDL_image.h”

// Structs
struct ColorRGB
{
int r;
int g;
int b;
};

//////////////////////////////////////////////////////////
// System variables
//////////////////////////////////////////////////////////

// Main video surface
SDL_Surface *screen = NULL;

// Video mode
#ifdef _DEBUG
int videoResolutionWidth = 640;
int videoResolutionHeight = 480;
int videoBitDepth = 0;
#define videoModeFlags SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF
#else
int videoResolutionWidth = 1024;
int videoResolutionHeight = 768;
int videoBitDepth = 32;
#define videoModeFlags SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF |
SDL_FULLSCREEN
#endif

//////////////////////////////////////////////////////////
// Variables
//////////////////////////////////////////////////////////

// Surfaces
SDL_Surface *splashImage;
SDL_Surface *images[ 15 ];

// Events
SDL_Event event;

// Game variables
bool done = false;
bool currentSet = false;
int currentImage = MAX_IMAGES;
int imageAdvanceTime = 7000;

//////////////////////////////////////////////////////////
// Helper functions
//////////////////////////////////////////////////////////

void ClearScreen()
{
SDL_Rect destination;
// Calculate screen size
destination.x = 0;
destination.y = 0;
destination.w = screen->w;
destination.h = screen->h;

// clear screen
SDL_FillRect( screen, &destination, 0 );
}

//////////////////////////////////////////////////////////
// Loaders
//////////////////////////////////////////////////////////

// Loads .JPG image with SDL_Image calls
SDL_Surface *LoadIMG( char *FileName, ColorRGB transparentColor )
{
SDL_Surface *temp = NULL;
SDL_Surface *ready = NULL;

// Load image with SDL_image call
temp = IMG_Load( FileName );
if( temp == NULL )
{
printf( “Image file load failed: %s\n”,
IMG_GetError()
);
exit( 2 );
}
// Set transparent color for this surface (image)
if ( SDL_SetColorKey( temp, SDL_SRCCOLORKEY,
SDL_MapRGB( temp->format,
transparentColor.r,
transparentColor.g,
transparentColor.b
)
) == -1 )
printf( “Failed to set transparent color: %s\n”,
SDL_GetError()
);

// Set display format for fast blitting
ready = SDL_DisplayFormat( temp );
if( ready == NULL )
{
printf( “Image display format conversion failed: %s\n”,
SDL_GetError()
);
exit( 3 );
}

return ready;
}

void LoadImageSet01()
{
for ( int index = 0; index < MAX_IMAGES; index ++ )
{
if ( images[ index ] != NULL )
SDL_FreeSurface( images[ index ] );
}
// Set transparent key color to blue (255)
ColorRGB transparent;
transparent.r = 0;
transparent.g = 0;
transparent.b = 255;

// Load images
images[ 0 ] = LoadIMG( IMAGE0101, transparent );
images[ 1 ] = LoadIMG( IMAGE0102, transparent );
images[ 2 ] = LoadIMG( IMAGE0103, transparent );
images[ 3 ] = LoadIMG( IMAGE0104, transparent );
images[ 4 ] = LoadIMG( IMAGE0105, transparent );
images[ 5 ] = LoadIMG( IMAGE0106, transparent );
images[ 6 ] = LoadIMG( IMAGE0107, transparent );
images[ 7 ] = LoadIMG( IMAGE0108, transparent );
images[ 8 ] = LoadIMG( IMAGE0109, transparent );
images[ 9 ] = LoadIMG( IMAGE0110, transparent );
}

void LoadImageSet02()
{

for ( int index = 0; index < MAX_IMAGES; index ++ )
{
if ( images[ index ] != NULL )
SDL_FreeSurface( images[ index ] );
}
// Set transparent key color to blue (255)
ColorRGB transparent;
transparent.r = 0;
transparent.g = 0;
transparent.b = 255;

// Load images
images[ 0 ] = LoadIMG( IMAGE0201, transparent );
images[ 1 ] = LoadIMG( IMAGE0202, transparent );
images[ 2 ] = LoadIMG( IMAGE0203, transparent );
images[ 3 ] = LoadIMG( IMAGE0204, transparent );
images[ 4 ] = LoadIMG( IMAGE0205, transparent );
images[ 5 ] = LoadIMG( IMAGE0206, transparent );
images[ 6 ] = LoadIMG( IMAGE0207, transparent );
images[ 7 ] = LoadIMG( IMAGE0208, transparent );
images[ 8 ] = LoadIMG( IMAGE0209, transparent );
images[ 9 ] = LoadIMG( IMAGE0210, transparent );
}

#ifndef NOSPLASH
void LoadSplash()
{
// Set transparent key color to blue (255)
ColorRGB transparent;
transparent.r = 0;
transparent.g = 0;
transparent.b = 255;

splashImage = LoadIMG( SPLASH, transparent );
}
#endif

//////////////////////////////////////////////////////////
// Initializers and de-initializers
//////////////////////////////////////////////////////////

// Initializes all SDL subsystems
void InitAll()
{
// Initialize SDL - Video and Timer subsystems
if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) < 0 )
{
fprintf( stderr,
“Couldn’t initialize SDL: %s\n”,
SDL_GetError()
);
exit( 1 );
}

// Hide cursor
#ifndef _DEBUG
if ( SDL_ShowCursor( SDL_DISABLE ) == - 1)
{
fprintf( stderr,
“Couldn’t hide the cursor: %s\n”,
SDL_GetError()
);
}
#endif

// Initialize display mode
screen = SDL_SetVideoMode( videoResolutionWidth,
videoResolutionHeight,
videoBitDepth,
videoModeFlags
);
if ( screen == NULL )
{
printf(“Couldn’t initialize 640x480x32 video mode: %s\n”,
SDL_GetError());
exit( 1 );
}
}

// Quits all SDL subsystems
void QuitAll()
{
SDL_Quit();
}

void LoadMedia()
{
#ifndef NOSPLASH
LoadSplash();
#endif
LoadImageSet01();
}

void UnloadMedia()
{
for ( int index = 0; index < 15; index ++ )
if ( images[ index ] != NULL )
{
SDL_FreeSurface( images[ index ] );
}
}

//////////////////////////////////////////////////////////
// Drawing
//////////////////////////////////////////////////////////

void UpdateScreen()
{
ClearScreen();

SDL_Rect destination;

// Calculate image size
destination.x = screen->w / 2 - images[ currentImage ]->w / 2;
destination.y = screen->h / 2 - images[ currentImage ]->h / 2;
destination.w = images[ currentImage ]->w;
destination.h = images[ currentImage ]->h;

// Blit image
SDL_BlitSurface ( images[ currentImage ], NULL, screen, &destination );

#ifndef NOSPLASH
// Calculate image size
destination.x = screen->w / 2 - splashImage->w / 2;
destination.y = screen->h / 2 - splashImage->h / 2;
destination.w = splashImage->w;
destination.h = splashImage->h;

SDL_BlitSurface( splashImage, NULL, screen, &destination);
#endif

SDL_Flip( screen );
}

void ImageSequenceAdvance( bool Forward )
//SDL_NewTimerCallBack ImageSequenceAdvance( bool Forward )
{
if ( Forward )
{
currentImage++;
if ( currentImage > MAX_IMAGES - 1 )
currentImage = 0;
}
else
{
currentImage–;
if ( currentImage < 0 )
currentImage = MAX_IMAGES - 1;
}
}

void TimedImageSequenceAdvance( int Interval )
{
static Uint32 next_time = 0;
Uint32 now;

now = SDL_GetTicks();
if ( next_time <= now ) {
    next_time = now + Interval;

ImageSequenceAdvance( true );
}
}

// The Game Loop
void Run()
{
while( !done )
{
TimedImageSequenceAdvance( imageAdvanceTime );
UpdateScreen();

while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
// Select manually next image
case SDLK_LEFT:
ImageSequenceAdvance( false );
break;
case SDLK_RIGHT:
ImageSequenceAdvance( true );
break;
// Select next image set
case SDLK_UP:
if ( currentSet == true )
LoadImageSet01();
else
LoadImageSet02();
currentSet = !currentSet;
// Reset counter to first image in sequence
currentImage = 0;
break;
case SDLK_DOWN:
if ( currentSet == true )
LoadImageSet01();
else
LoadImageSet02();
currentSet = !currentSet;
// Reset counter to first image in sequence
currentImage = 0;
break;
// Quit if user presses Escape
case SDLK_ESCAPE:
done = true;
break;
default:
break;
}
break;
// Quit if QUIT event is intercepted
case SDL_QUIT:
done = true;
break;
default:
break;
}
}
// Allow other threads to run
SDL_Delay( 10 );
}
}

int main(int argc, char* argv[])
{
InitAll();
LoadMedia();
SDL_Delay( 1000 );

// Run the “Game” Loop
Run();

// Clean up before exit
UnloadMedia();
QuitAll();

return 0;
}

Hi,

SDL_DisplayFormat() creates a new surface, so you need
to call SDL_FreeSurface( temp ); in your LoadIMG() function,
(check the docs).---------------------------------------------------------------------------
// Loads .JPG image with SDL_Image calls
SDL_Surface *LoadIMG( char *FileName, ColorRGB transparentColor )
{


ready = SDL_DisplayFormat( temp );
SDL_FreeSurface( temp ); // free temporary surface

if( ready == NULL )
{
printf( “Image display format conversion failed: %s\n”, SDL_GetError());
exit( 3 );
}
return ready;
}

Your colorkey problems may just be surface space exhaustion or
maybe you need to convert and set the colorkey on the surface
returned by SDL_DisplayFormat(), I don’t know. Anyone else?

If you supply a link to at least one test image, I will compile this
and try it,

cheers,
John.

----- Original Message -----
From: hr_hristov@hotmail.com (Hri)
To:
Sent: Saturday, May 10, 2003 4:03 PM
Subject: [SDL] Re: Problem with reusing array of surfaces.

I have followed John’s advice and I have created a test version of my
functions (included bellow). It helped me to track down the main problem
to the SDL_DisplayFormat() function in LoadIMG().

It looks like this portion is:

// Set display format for fast blitting
ready = SDL_DisplayFormat( temp );
if( ready == NULL )
{
printf( “Image display format conversion failed: %s\n”,
SDL_GetError()
);
exit( 3 );
}

return ready;
}

Obviously I should destroy the surface “ready” but I don’t now how (in
this context). SDL_GetError returnes Out of memory.

And the other problems still remains. If I run the program twice on
Win98 the transparent color of the “splashImage” image is not
transparent the second time. The problem seems to be the SDL_HWPALETTE
flag in fullscreen mode (under Win98 only).

BTW I have removed ready = SDL_DisplayFormat( temp ); and it takes now
longer to crash under Win98 (under NT seems that it won’t crash).

Well, not the question might be: how to use correctly SDL_HWPALETTE and
SDL_DisplayFormat

// PVTest.cpp : Defines the entry point for the console application.

// Do not show splash
//#define NOSPLASH

// Data defines
#define MAX_IMAGES 10

#define SPLASH “./data/splash/splash.gif”

// Image collection 1
#define IMAGE0101 “./data/set01/01.jpg”
#define IMAGE0102 “./data/set01/02.jpg”
#define IMAGE0103 “./data/set01/03.jpg”
#define IMAGE0104 “./data/set01/04.jpg”
#define IMAGE0105 “./data/set01/05.jpg”
#define IMAGE0106 “./data/set01/06.jpg”
#define IMAGE0107 “./data/set01/07.jpg”
#define IMAGE0108 “./data/set01/08.jpg”
#define IMAGE0109 “./data/set01/09.jpg”
#define IMAGE0110 “./data/set01/10.jpg”

// Image collection 2
#define IMAGE0201 “./data/set02/01.jpg”
#define IMAGE0202 “./data/set02/02.jpg”
#define IMAGE0203 “./data/set02/03.jpg”
#define IMAGE0204 “./data/set02/04.jpg”
#define IMAGE0205 “./data/set02/05.jpg”
#define IMAGE0206 “./data/set02/06.jpg”
#define IMAGE0207 “./data/set02/07.jpg”
#define IMAGE0208 “./data/set02/08.jpg”
#define IMAGE0209 “./data/set02/09.jpg”
#define IMAGE0210 “./data/set02/10.jpg”

//////////////////////////////////////////////////////////
// Headers
//////////////////////////////////////////////////////////

#include <stdlib.h>
#include <stdio.h>
// SDL headers
#include “SDL/SDL.h”
#include “SDL/SDL_image.h”

// Structs
struct ColorRGB
{
int r;
int g;
int b;
};

//////////////////////////////////////////////////////////
// System variables
//////////////////////////////////////////////////////////

// Main video surface
SDL_Surface *screen = NULL;

// Video mode
#ifdef _DEBUG
int videoResolutionWidth = 640;
int videoResolutionHeight = 480;
int videoBitDepth = 0;
#define videoModeFlags SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF
#else
int videoResolutionWidth = 1024;
int videoResolutionHeight = 768;
int videoBitDepth = 32;
#define videoModeFlags SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF |
SDL_FULLSCREEN
#endif

//////////////////////////////////////////////////////////
// Variables
//////////////////////////////////////////////////////////

// Surfaces
SDL_Surface *splashImage;
SDL_Surface *images[ 15 ];

// Events
SDL_Event event;

// Game variables
bool done = false;
bool currentSet = false;
int currentImage = MAX_IMAGES;
int imageAdvanceTime = 7000;

//////////////////////////////////////////////////////////
// Helper functions
//////////////////////////////////////////////////////////

void ClearScreen()
{
SDL_Rect destination;
// Calculate screen size
destination.x = 0;
destination.y = 0;
destination.w = screen->w;
destination.h = screen->h;

// clear screen
SDL_FillRect( screen, &destination, 0 );
}

//////////////////////////////////////////////////////////
// Loaders
//////////////////////////////////////////////////////////

// Loads .JPG image with SDL_Image calls
SDL_Surface *LoadIMG( char *FileName, ColorRGB transparentColor )
{
SDL_Surface *temp = NULL;
SDL_Surface *ready = NULL;

// Load image with SDL_image call
temp = IMG_Load( FileName );
if( temp == NULL )
{
printf( “Image file load failed: %s\n”,
IMG_GetError()
);
exit( 2 );
}
// Set transparent color for this surface (image)
if ( SDL_SetColorKey( temp, SDL_SRCCOLORKEY,
SDL_MapRGB( temp->format,
transparentColor.r,
transparentColor.g,
transparentColor.b
)
) == -1 )
printf( “Failed to set transparent color: %s\n”,
SDL_GetError()
);

// Set display format for fast blitting
ready = SDL_DisplayFormat( temp );
if( ready == NULL )
{
printf( “Image display format conversion failed: %s\n”,
SDL_GetError()
);
exit( 3 );
}

return ready;
}

void LoadImageSet01()
{
for ( int index = 0; index < MAX_IMAGES; index ++ )
{
if ( images[ index ] != NULL )
SDL_FreeSurface( images[ index ] );
}
// Set transparent key color to blue (255)
ColorRGB transparent;
transparent.r = 0;
transparent.g = 0;
transparent.b = 255;

// Load images
images[ 0 ] = LoadIMG( IMAGE0101, transparent );
images[ 1 ] = LoadIMG( IMAGE0102, transparent );
images[ 2 ] = LoadIMG( IMAGE0103, transparent );
images[ 3 ] = LoadIMG( IMAGE0104, transparent );
images[ 4 ] = LoadIMG( IMAGE0105, transparent );
images[ 5 ] = LoadIMG( IMAGE0106, transparent );
images[ 6 ] = LoadIMG( IMAGE0107, transparent );
images[ 7 ] = LoadIMG( IMAGE0108, transparent );
images[ 8 ] = LoadIMG( IMAGE0109, transparent );
images[ 9 ] = LoadIMG( IMAGE0110, transparent );
}

void LoadImageSet02()
{

for ( int index = 0; index < MAX_IMAGES; index ++ )
{
if ( images[ index ] != NULL )
SDL_FreeSurface( images[ index ] );
}
// Set transparent key color to blue (255)
ColorRGB transparent;
transparent.r = 0;
transparent.g = 0;
transparent.b = 255;

// Load images
images[ 0 ] = LoadIMG( IMAGE0201, transparent );
images[ 1 ] = LoadIMG( IMAGE0202, transparent );
images[ 2 ] = LoadIMG( IMAGE0203, transparent );
images[ 3 ] = LoadIMG( IMAGE0204, transparent );
images[ 4 ] = LoadIMG( IMAGE0205, transparent );
images[ 5 ] = LoadIMG( IMAGE0206, transparent );
images[ 6 ] = LoadIMG( IMAGE0207, transparent );
images[ 7 ] = LoadIMG( IMAGE0208, transparent );
images[ 8 ] = LoadIMG( IMAGE0209, transparent );
images[ 9 ] = LoadIMG( IMAGE0210, transparent );
}

#ifndef NOSPLASH
void LoadSplash()
{
// Set transparent key color to blue (255)
ColorRGB transparent;
transparent.r = 0;
transparent.g = 0;
transparent.b = 255;

splashImage = LoadIMG( SPLASH, transparent );
}
#endif

//////////////////////////////////////////////////////////
// Initializers and de-initializers
//////////////////////////////////////////////////////////

// Initializes all SDL subsystems
void InitAll()
{
// Initialize SDL - Video and Timer subsystems
if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) < 0 )
{
fprintf( stderr,
“Couldn’t initialize SDL: %s\n”,
SDL_GetError()
);
exit( 1 );
}

// Hide cursor
#ifndef _DEBUG
if ( SDL_ShowCursor( SDL_DISABLE ) == - 1)
{
fprintf( stderr,
“Couldn’t hide the cursor: %s\n”,
SDL_GetError()
);
}
#endif

// Initialize display mode
screen = SDL_SetVideoMode( videoResolutionWidth,
videoResolutionHeight,
videoBitDepth,
videoModeFlags
);
if ( screen == NULL )
{
printf(“Couldn’t initialize 640x480x32 video mode: %s\n”,
SDL_GetError());
exit( 1 );
}
}

// Quits all SDL subsystems
void QuitAll()
{
SDL_Quit();
}

void LoadMedia()
{
#ifndef NOSPLASH
LoadSplash();
#endif
LoadImageSet01();
}

void UnloadMedia()
{
for ( int index = 0; index < 15; index ++ )
if ( images[ index ] != NULL )
{
SDL_FreeSurface( images[ index ] );
}
}

//////////////////////////////////////////////////////////
// Drawing
//////////////////////////////////////////////////////////

void UpdateScreen()
{
ClearScreen();

SDL_Rect destination;

// Calculate image size
destination.x = screen->w / 2 - images[ currentImage ]->w / 2;
destination.y = screen->h / 2 - images[ currentImage ]->h / 2;
destination.w = images[ currentImage ]->w;
destination.h = images[ currentImage ]->h;

// Blit image
SDL_BlitSurface ( images[ currentImage ], NULL, screen, &destination );

#ifndef NOSPLASH
// Calculate image size
destination.x = screen->w / 2 - splashImage->w / 2;
destination.y = screen->h / 2 - splashImage->h / 2;
destination.w = splashImage->w;
destination.h = splashImage->h;

SDL_BlitSurface( splashImage, NULL, screen, &destination);
#endif

SDL_Flip( screen );
}

void ImageSequenceAdvance( bool Forward )
//SDL_NewTimerCallBack ImageSequenceAdvance( bool Forward )
{
if ( Forward )
{
currentImage++;
if ( currentImage > MAX_IMAGES - 1 )
currentImage = 0;
}
else
{
currentImage–;
if ( currentImage < 0 )
currentImage = MAX_IMAGES - 1;
}
}

void TimedImageSequenceAdvance( int Interval )
{
static Uint32 next_time = 0;
Uint32 now;

now = SDL_GetTicks();
if ( next_time <= now ) {
    next_time = now + Interval;

ImageSequenceAdvance( true );
}
}

// The Game Loop
void Run()
{
while( !done )
{
TimedImageSequenceAdvance( imageAdvanceTime );
UpdateScreen();

while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
// Select manually next image
case SDLK_LEFT:
ImageSequenceAdvance( false );
break;
case SDLK_RIGHT:
ImageSequenceAdvance( true );
break;
// Select next image set
case SDLK_UP:
if ( currentSet == true )
LoadImageSet01();
else
LoadImageSet02();
currentSet = !currentSet;
// Reset counter to first image in sequence
currentImage = 0;
break;
case SDLK_DOWN:
if ( currentSet == true )
LoadImageSet01();
else
LoadImageSet02();
currentSet = !currentSet;
// Reset counter to first image in sequence
currentImage = 0;
break;
// Quit if user presses Escape
case SDLK_ESCAPE:
done = true;
break;
default:
break;
}
break;
// Quit if QUIT event is intercepted
case SDL_QUIT:
done = true;
break;
default:
break;
}
}
// Allow other threads to run
SDL_Delay( 10 );
}
}

int main(int argc, char* argv[])
{
InitAll();
LoadMedia();
SDL_Delay( 1000 );

// Run the “Game” Loop
Run();

// Clean up before exit
UnloadMedia();
QuitAll();

return 0;
}


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

Your colorkey problems may just be surface space exhaustion or
maybe you need to convert and set the colorkey on the surface
returned by SDL_DisplayFormat(), I don’t know. Anyone else?

If you supply a link to at least one test image, I will compile this
and try it,

Well, thank you very much! Unfortunately I don’t have any idea where to
upload images, programs and stuff right now.
I’ll look next week (or the week after next week) for a free hosting
site where I can upload stuff.

Or maybe the problems is that I use SDL_HWPALETTE in 32 bit mode? This
does not happen under WinNT just under Win98.

Your colorkey problems may just be surface space exhaustion or
maybe you need to convert and set the colorkey on the surface
returned by SDL_DisplayFormat(), I don’t know. Anyone else?

If you supply a link to at least one test image, I will compile this
and try it,

Well, thank you very much! Unfortunately I don’t have any idea where to
upload images, programs and stuff right now.
I’ll look next week (or the week after next week) for a free hosting
site where I can upload stuff.

Or maybe the problems is that I use SDL_HWPALETTE in 32 bit mode? This
does not happen under WinNT just under Win98.

Hi,

when you say WinNT, do you mean NT3/4 or are you including Win2K and XP?

Win2K, XP, 9X, and ME use the DirectX drivers by default.
NT3/4 use the WinDIB drivers by default.

That might be the root cause of the differences in behaviour you are
getting.

I suspect that SDL_HWPALETTE is ignored unless a paletted video mode
is in use.

A common problem is that the transparent colour on a surface is different
after an SDL_DisplayFormat() call, and I am not certain that a surface
created by SDL_DisplayFormat() retains accurate colorkey information.

Have you tried mapping and setting the colour key on the surface created
by SDL_DisplayFormat() rather than on the surface you load and then
convert? In other word, setting the colourkey, as a last act, on the
surface returned by LoadIMG().

cheers,
John.> ----- Original Message -----

From: hr_hristov@hotmail.com (Hri)
To:
Sent: Sunday, May 11, 2003 5:38 PM
Subject: [SDL] Re: Re: Problem with reusing array of surfaces.

Your colorkey problems may just be surface space exhaustion or
maybe you need to convert and set the colorkey on the surface
returned by SDL_DisplayFormat(), I don’t know. Anyone else?

If you supply a link to at least one test image, I will compile this
and try it,

Well, thank you very much! Unfortunately I don’t have any idea where to
upload images, programs and stuff right now.
I’ll look next week (or the week after next week) for a free hosting
site where I can upload stuff.

Or maybe the problems is that I use SDL_HWPALETTE in 32 bit mode? This
does not happen under WinNT just under Win98.


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

Hi,

just to correct myself:

… I am not certain that a surface created by SDL_DisplayFormat()
retains accurate colorkey information.

I checked the docs (should have done so before my last post!) and,
of course, this should be fine. In fact, SDL may do an RLE
optimisation here to speed up colorkeyed blitting (would be a
shame if it used the wrong colour!),

cheers,
John.

Hi, John,

you are so responsive! Thank you!

when you say WinNT, do you mean NT3/4 or are you including Win2K and
XP?

Win2K, XP, 9X, and ME use the DirectX drivers by default.
NT3/4 use the WinDIB drivers by default.

I have tested this code on Win2K SP2, WinXP and Win98 SE.

A common problem is that the transparent colour on a surface is
different
after an SDL_DisplayFormat() call, and I am not certain that a surface
created by SDL_DisplayFormat() retains accurate colorkey information.

Have you tried mapping and setting the colour key on the surface
created
by SDL_DisplayFormat() rather than on the surface you load and then
convert? In other word, setting the colourkey, as a last act, on the
surface returned by LoadIMG().

Not yet. I’ll try it.

I have found that there is no colorkey problem under Win98 SE
if I use 8bit mode and it appears only when the program is fullscreen.
This happens always if I run the program twice fullscreen. In window
mode there is no problem, in fullscreen 8bit too. It happens only with
32bit mode (don’t remember about 16bit). If do not use the SDL_HWPALETTE
in 32bit mode - again there is no problem.
Well, perhaps I should avoid using SDL_HWPALETTE in hi-color modes. I
think that SDL_HWPALETTE makes sense only in paletted 8bit modes and
eventually this is undetermined behavior.
Once again this is a problem with Win98 SE only and not with WinNT 5.0+.

I’ve just wanted to know why I get these results. I’m trying to avoid
the “I-have-almost-understood-it” way of doing things :wink: which is soo…
easier and soo… stupid and I’m so addicted to it.

I suspect that SDL_HWPALETTE is ignored unless a paletted video mode
is in use.

…or it causes a problem with Win98 :wink: What bothers me if there is a
problem with WinNT 5.0+ (or maybe even Linux and other OSs) too that is
not obvious and could appear later. Or simply certain flags are
incompatible but this is not documented feature (or at least I cannot
find it yet).

Until then I’ll have to avoid using SDL_HWPALETTE or maybe it is a
better idea to write a function that sets video mode with the best
flags.

Thanks again!

I use a classic PCI Diamod Viper550 with Detonator 23.11 (all newer
drivers are problematic).

… OK. I got it! If the desktop color depth is 32 and I run the program
in 16 bit color; twice there is a problem.
If the color depth is 16 bit and I run the program in 32bit twice; there
is a problem. There is no problem running the program in 32bit with
32bit desktop settings or in 16bit mode with 16bit desktop settings.
It’s probably just a bug. Driver bug? Who does know? I do not!

Well, I don’t think I have the resources to solve this mistery. I’m
neither Microsoft, nor NVIDIA not even somebody among the SDL
developers.

So thank you John once again. I don’t think that it makes much sense to
try and research this problem any longer (for now). I think that the
same driver version is used by the other Windows installations (XP and
2K) so it might not be a driver problem after all.

BTW. SDL is pretty cool! Great job!

Hi,

… This happens always if I run the program twice fullscreen. …

This is starting to sound like a video-card driver problem. What video
card is this? Have you got the latest Win98SE drivers for it?

It isn’t unknown for video drivers to leak surface memory …

mode there is no problem, in fullscreen 8bit too. It happens only with
32bit mode (don’t remember about 16bit). If do not use the SDL_HWPALETTE
in 32bit mode - again there is no problem.

I had a look throught the SDL source and I can’t see how SDL_HWPALETTE
can cause a problem. The flags variable in SDL_SetVideoMode() is used
to get a list of modes (but only the fullscreen bit is tested) and if
the chosen mode is greater than 8-bit then SDL_HWPALETTE is explicitly
cleared
before anything else happens.

cheers,
John.> ----- Original Message -----

From: hr_hristov@hotmail.com (Hri)
To:
Sent: Monday, May 12, 2003 4:17 PM
Subject: [SDL] Re: Re: Re: Problem with reusing array of surfaces.

Hi, John,

you are so responsive! Thank you!

when you say WinNT, do you mean NT3/4 or are you including Win2K and
XP?

Win2K, XP, 9X, and ME use the DirectX drivers by default.
NT3/4 use the WinDIB drivers by default.

I have tested this code on Win2K SP2, WinXP and Win98 SE.

A common problem is that the transparent colour on a surface is
different
after an SDL_DisplayFormat() call, and I am not certain that a surface
created by SDL_DisplayFormat() retains accurate colorkey information.

Have you tried mapping and setting the colour key on the surface
created
by SDL_DisplayFormat() rather than on the surface you load and then
convert? In other word, setting the colourkey, as a last act, on the
surface returned by LoadIMG().

Not yet. I’ll try it.

I have found that there is no colorkey problem under Win98 SE
if I use 8bit mode and it appears only when the program is fullscreen.
This happens always if I run the program twice fullscreen. In window
mode there is no problem, in fullscreen 8bit too. It happens only with
32bit mode (don’t remember about 16bit). If do not use the SDL_HWPALETTE
in 32bit mode - again there is no problem.
Well, perhaps I should avoid using SDL_HWPALETTE in hi-color modes. I
think that SDL_HWPALETTE makes sense only in paletted 8bit modes and
eventually this is undetermined behavior.
Once again this is a problem with Win98 SE only and not with WinNT 5.0+.

I’ve just wanted to know why I get these results. I’m trying to avoid
the “I-have-almost-understood-it” way of doing things :wink: which is soo…
easier and soo… stupid and I’m so addicted to it.

I suspect that SDL_HWPALETTE is ignored unless a paletted video mode
is in use.

…or it causes a problem with Win98 :wink: What bothers me if there is a
problem with WinNT 5.0+ (or maybe even Linux and other OSs) too that is
not obvious and could appear later. Or simply certain flags are
incompatible but this is not documented feature (or at least I cannot
find it yet).

Until then I’ll have to avoid using SDL_HWPALETTE or maybe it is a
better idea to write a function that sets video mode with the best
flags.

Thanks again!


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

If the color depth is 16 bit and I run the program in 32bit twice; there
is a problem. There is no problem running the program in 32bit with
32bit desktop settings or in 16bit mode with 16bit desktop settings.
It’s probably just a bug. Driver bug? Who does know? I do not!

I can’t answer these questions, but maybe this can help you : you can set
the video mode by passing 0 for the color depth and it will set a video mode
with the desktop color depth, so, you will always have the same depth in
your program and on the desktop.

If there is a bug somewhere in the driver, this doesn’t fix it, but it may
avoid the program to crash.

Hope that helps

Julien

… This happens always if I run the program twice fullscreen. …

This is starting to sound like a video-card driver problem. What video
card is this? Have you got the latest Win98SE drivers for it?

Well, it is a driver problem after all :wink: I have just changed the driver
and the problem disappeared. So the duscussion is over I guess.

Just one last question: does it make sense to add SDL_HWPALETTE in high
color modes? You have mentioned something about the RLE compression but
doesn’t it work with 8 bit pictures only? If I change the surface format
of an image to match the main surface format it would be converted it to
the same bit depth (high color in modern times). Then SDL_HWPALETTE is
redundunt after all. Is this true?

Thank you very much!

Hi,

Well, it is a driver problem after all :wink: I have just changed the driver
and the problem disappeared. So the duscussion is over I guess.

glad to hear that you’ve fixed it.

Just one last question: does it make sense to add SDL_HWPALETTE in high
color modes?

This flag is ignored (harmless) unless an 8-bit screen mode is in use.
If you are targeting 16-bit or 32-bit displays, then it should be omitted
for clarity.

You have mentioned something about the RLE compression but
doesn’t it work with 8 bit pictures only?

It is available for all images formats that have a colour-key and use the
software renderer. RLE can always efficiently ‘compress’ runs of the
transparent colour into ‘blit-nothing’ instructions.

If I change the surface format of an image to match the main surface
format it would be converted it to the same bit depth (high color in
modern times). Then SDL_HWPALETTE is redundunt after all. Is this true?

8-bit -> 24(32)-bit conversion is perfect, but converting images from
8-bit -> 16-bit can result in loss of colour information because the
8-bit image contains, say, 256 unique 24-bit colours which can’t
necessarily be perfectly mapped onto a 565 16-bit pixel. It is noticable
with images containing a large number of similar colours e.g. flesh-tones.

So, if no 24/32 bit video mode is available, it is possible to get better
image fidelity from 8-bit images by using 8-bit surfaces. Using
SDL_HWPALETTE
simply guarantees that SDL will get the colours it requests (8-bit only),

hope that helps,
cheers,
John.