Sam and Alan,
Despite the advice and possible reasons, I cannot seem to correct this
problem.
So I decided to write the most concise program that I could that
demonstrated the problem.
Can you give it the once over please and see if you can tell what I’m doing
wrong?
Here is the code (VC++5 Win2000) that produces it in a simple main function:
Please try these two things:
#1 run it as it is. An access violation occurs because dialogSurface’s
pixels
is set to 0 when trying to draw “doneImageSurface” the 2nd time
#2 change “amask” to “f->Amask” when creating “dialogSurface”
(SDL_CreateRGBSurface)
and run again. This time the pixels are fine but the color key of the
dialogSurface doesn’t work
//--------------------------------------------------------------------------------------------------
#include “sdl.h”
#include “sdl_image.h”
#include <memory.h>
SDL_Surface* mainSurface;
SDL_Event event;
int main(int argc, char* argv[])
{
// initialize and create the main surface
SDL_Init(SDL_INIT_EVERYTHING);
mainSurface = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);
// load a non-rectanglular image. The pixel at 0, 0 will become the
ColorKey
// my image was 300 wide by 270 tall.
// Make sure the transparent part of the image is not black so you can see
it when drawn.
SDL_Surface* dialogImageSurface1 = IMG_Load(“dialogimage.png”);
SDL_Surface* dialogImageSurface = SDL_DisplayFormat(dialogImageSurface1);
SDL_FreeSurface(dialogImageSurface1);
// load a button image to display on the dialog surface.
// The pixel at 0, 0 will become the ColorKey for the button
SDL_Surface* doneImageSurface1 = IMG_Load(“done.png”);
SDL_Surface* doneImageSurface = SDL_DisplayFormat(doneImageSurface1);
SDL_FreeSurface(doneImageSurface1);
if (SDL_MUSTLOCK(doneImageSurface)) SDL_LockSurface(doneImageSurface);
Uint32 doneColor = 0;
memcpy(&doneColor, (char*)doneImageSurface->pixels,
doneImageSurface->format->BytesPerPixel);
SDL_SetColorKey(doneImageSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL,
doneColor);
if (SDL_MUSTLOCK(doneImageSurface)) SDL_UnlockSurface(doneImageSurface);
// create an RGB surface for the dialog
SDL_PixelFormat* f = mainSurface->format;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Uint32 amask = 0x000000ff;
#else
Uint32 amask = 0xff000000;
#endif
SDL_Surface* dialogSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,
dialogImageSurface->w, dialogImageSurface->h,
f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask,
amask); // f->Amask);
// pre-draw the dialog once so it can be blitted faster later than if we
// blitted the dialog image and all the buttons and text every time it
needed repainting
SDL_BlitSurface(dialogImageSurface, NULL, dialogSurface, NULL);
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w, dialogSurface->h);
// reads the pixel at 0, 0 and use that color as the color key for the
dialogSurface
// so that we can have dialogs of non-rectanglular shape
if (SDL_MUSTLOCK(dialogSurface)) SDL_LockSurface(dialogSurface);
Uint32 color = 0;
memcpy(&color, (char*)dialogSurface->pixels,
dialogSurface->format->BytesPerPixel);
SDL_SetColorKey(dialogSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL, color);
if (SDL_MUSTLOCK(dialogSurface)) SDL_UnlockSurface(dialogSurface);
SDL_Rect rect;
rect.x = 100;
rect.y = 100;
rect.w = doneImageSurface->w;
rect.h = doneImageSurface->h;
SDL_BlitSurface(doneImageSurface, NULL, dialogSurface, &rect);
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w, dialogSurface->h);
// finally blit the dialog surface to the mainSurface
if (SDL_MUSTLOCK(mainSurface)) SDL_LockSurface(mainSurface);
SDL_BlitSurface(dialogSurface, NULL, mainSurface, NULL);
SDL_UpdateRect(mainSurface, 0, 0, 800, 600);
if (SDL_MUSTLOCK(mainSurface)) SDL_UnlockSurface(mainSurface);
// next, assume the user moused over a dialog button so we want to draw the
button again
// onto the dialogSurface (not the mainSurface)
// THIS IS WHERE PIXELS IS SET TO 0 FOR dialogSurface
void* dialogPixels = dialogSurface->pixels; // pixels is 0 here
SDL_BlitSurface(doneImageSurface, NULL, dialogSurface, &rect); // access
violation
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w, dialogSurface->h);
if (SDL_MUSTLOCK(mainSurface)) SDL_LockSurface(mainSurface);
SDL_BlitSurface(dialogSurface, NULL, mainSurface, NULL);
SDL_UpdateRect(mainSurface, 0, 0, 800, 600);
if (SDL_MUSTLOCK(mainSurface)) SDL_UnlockSurface(mainSurface);
// wait for a command to close the app
while (true)
{
SDL_WaitEvent(&event);
if (event.type == SDL_QUIT)
break;
}
SDL_Quit();
return(0);
}
//--------------------------------------------------------------------------
Thanks,
Warren Schwader
----- Original Message -----
From: slouken@devolution.com (Sam Lantinga)
To:
Sent: Sunday, December 07, 2003 11:03 AM
Subject: Re: [SDL] pixels getting set to NULL
Hi Alan, thanks for the reply. What you say is likely true, but in my
case I amusing only software surfaces. I should have stated that. I should
have also stated that I am using per surface alpha too. I can try to Lock
the sw surface and see what effect it has.
The interesting thing is that if I don’t set the color key on the
dialog’s surface then everything works OK but then I’d be stuck with square
dialogs. Another interesting thing is when I change a dialog item on my
non-square dialog, it makes the color keyed pixels appear in a color other
than what would be there if the image wasn’t color keyed. Strange.
You always need to use the SDL_MUSTLOCK() macro to see whether you need to
lock the surface before using it. If the pixels are NULL, that’s a good
clue.
See ya,
-Sam Lantinga, Software Engineer, Blizzard Entertainment
SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl