Dimming an image on screen

Hi all,

I’m wanting to get a snapshot of the screen that I’ve drawn (I get this out of
the back buffer, and it works OK since I’m working purely on event-driven
things). But then I want to halve the brightness of each pixel, then blit
another image over the top of that.

At present, I’ve got a nested loop structure to go over the whole screen, and
it shifts the pixel value, masks it, and then tries to put it back onto the
screen. Only it doesn’t work. Here’s the code (dest is the SDL_Surface
pointer that is the back buffer):

Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
int width = dest->w;
int height = dest->h;
Uint8 colourdepth = dest->format->BitsPerPixel;
SDL_Surface * buffer = SDL_CreateRGBSurface(SDL_HWSURFACE, width, height,
colourdepth, rmask, gmask, bmask, amask);
SDL_LockSurface(dest);

SDL_Rect fill;
fill.h = fill.w = 1;
for(int j=0 ; j<height ; ++j) {
fill.y = j;
for(int i=0 ; i<width ; ++i) {
Uint8 * srcptr = (Uint8*)(dest->pixels);
srcptr += ydest->pitch;
srcptr += x
dest->format->BytesPerPixel;
fill.x = i;
Uint32 pixel = ((Uint32)srcptr);
Uint32 gpixel = pixel | dest->format->Gmask;
Uint32 rpixel = pixel | dest->format->Rmask;
Uint32 bpixel = pixel | dest->format->Bmask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
gpixel = (gpixel >> 1) | dest->format->Gmask;
rpixel = (rpixel >> 1) | dest->format->Rmask;
bpixel = (bpixel >> 1) | dest->format->Bmask;
#else
gpixel = (gpixel << 1) | dest->format->Gmask;
rpixel = (rpixel << 1) | dest->format->Rmask;
bpixel = (bpixel << 1) | dest->format->Bmask;
#endif
Uint32 newpixel = gpixel | rpixel | bpixel;
SDL_FillRect(buffer, &fill, newpixel);
}
}

SDL_UnlockSurface(dest);

(buffer is blitted to dest a bit later on after a few other things)

I have a few questions about this:

  1. Would what I want to do work with alpha blending? I have no idea how to use
    alpha blending and haven’t found a satisfactory explanation of how it works
    despite lots of searching
  2. Have I got the shifting right for little-endian machines, in that I shift
    right and not left?
  3. Is there something other than the SDL_FillRect that might be a better choice
    to make this work?
  4. Can anyone see why this doesn’t work?
  5. If anyone has a better algorithm, I’d really, really like to know what it is
    (especially if it works!).

TIA,
-J

Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif

i am not a graphics expert so i might be wrong, but isnt the rgba mask
determined by the video hardware or graphics driver ? for example,
that code above worked fine on x68 and ppc, but failed when i tried it
on the playstation2.

mattOn Wed, 18 Jul 2007 03:00:42 +0000 (UTC) Jason <jesus_freak at picknowl.com.au> wrote:

matt <mattmatteh earthlink.net> writes:

Uint32 rmask, gmask, bmask, amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif

i am not a graphics expert so i might be wrong, but isnt the rgba mask
determined by the video hardware or graphics driver ? for example,
that code above worked fine on x68 and ppc, but failed when i tried it
on the playstation2.

Those quantities are only used in the call to SDL_CreateRGBSurface, and is
straight out of the docs. What I have realised just now, though, is that those
are only true for 32-bit surfaces. I should actually use the masks out of
dest->format instead. Doing that actually makes the created surface compatible,
and so this code actually does something!

Second step to fixing it is to bitwise-AND the masks with the pixel value, not
bitwise-OR them. D’uh!

Now, I just get complete black… Here’s the updated code:

Uint32 rmask, gmask, bmask, amask;
rmask = dest->format->Rmask;
gmask = dest->format->Gmask;
bmask = dest->format->Bmask;
amask = dest->format->Amask;

int width = dest->w;
int height = dest->h;
Uint8 colourdepth = dest->format->BitsPerPixel;
SDL_Surface * buffer = SDL_CreateRGBSurface(SDL_HWSURFACE, width, height,
colourdepth, rmask, gmask, bmask, amask);
SDL_LockSurface(dest);

SDL_Rect fill;
fill.h = fill.w = 1;
for(int j=0 ; j<height ; ++j) {
fill.y = j;
for(int i=0 ; i<width ; ++i) {
Uint8 * srcptr = (Uint8*)(dest->pixels);
srcptr += ydest->pitch;
srcptr += x
dest->format->BytesPerPixel;
fill.x = i;
Uint32 pixel = ((Uint32)srcptr);
Uint32 gpixel = pixel & gmask;
Uint32 rpixel = pixel & rmask;
Uint32 bpixel = pixel & bmask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
gpixel = (gpixel >> 1) & gmask;
rpixel = (rpixel >> 1) & rmask;
bpixel = (bpixel >> 1) & bmask;
#else
gpixel = (gpixel << 1) & gmask;
rpixel = (rpixel << 1) & rmask;
bpixel = (bpixel << 1) & bmask;
#endif
Uint32 newpixel = gpixel | rpixel | bpixel;
SDL_FillRect(buffer, &fill, newpixel);
}
}

SDL_UnlockSurface(dest);

-J> On Wed, 18 Jul 2007 03:00:42 +0000 (UTC) Jason <jesus_freak picknowl.com.au> wrote:

Hi all,

I’m wanting to get a snapshot of the screen that I’ve drawn (I get this
out of
the back buffer, and it works OK since I’m working purely on event-driven
things). But then I want to halve the brightness of each pixel, then blit
another image over the top of that.

  1. Would what I want to do work with alpha blending? I have no idea how to
    use
    alpha blending and haven’t found a satisfactory explanation of how it
    works
    despite lots of searching

If you just want to half the brightness of the pixels, alpha-blending would
be the
fastest way I think. Simply set the Alpha-value to 128 before you blit it to
the
screen, if I recall correctly.

Cheers,
Peter

Peter Ketting <peterketting sysmatrix.net> writes:

If you just want to half the brightness of the pixels, alpha-blending would
be the
fastest way I think. Simply set the Alpha-value to 128 before you blit it to
the
screen, if I recall correctly.

Cheers,
Peter

Thanks, Peter, I’ll give it a try. Would it be correct to assume that the alpha
is basically a multiplier: if it is half the 256 possible values, the other
components of the pixel will wind up at half value?

-J

Behalf Of Peter Ketting

Hi all,

I’m wanting to get a snapshot of the screen that I’ve drawn (I get
this out of the back buffer, and it works OK since I’m working purely
on event-driven things). But then I want to halve the brightness of
each pixel, then blit another image over the top of that.

  1. Would what I want to do work with alpha blending? I have no idea
    how to use
    alpha blending and haven’t found a satisfactory explanation of how
    it works
    despite lots of searching

I do something similar in my game. However, I just create a full-screen
image that is all black and blit it over the background. Then you can vary
the alpha up/down slowly to show more or less of the image beneath it.

To change the alpha on the surface you can call:

         SDL_SetAlpha( pSurface,SDL_SRCALPHA,(Uint8)nAlpha );

To turn off the alpha call:

        SDL_SetAlpha( pSurface,0,SDL_ALPHA_OPAQUE );

Ken Rogoway
Homebrew Software
http://www.homebrewsoftware.com/


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

No virus found in this incoming message.
Checked by AVG Free Edition.
Version: 7.5.476 / Virus Database: 269.10.8/904 - Release Date: 7/16/2007
5:42 PM

No virus found in this outgoing message.
Checked by AVG Free Edition.
Version: 7.5.476 / Virus Database: 269.10.8/904 - Release Date: 7/16/2007
5:42 PM

----- Original Message -----
From: sdl-bounces@lists.libsdl.org [mailto:sdl-bounces at lists.libsdl.org] On
Sent: Tuesday, July 17, 2007 10:56 PM
To: A list for developers using the SDL library. (includes SDL-announce)
Subject: Re: [SDL] Dimming an image on screen

Behalf Of Ken Rogoway

Behalf Of Peter Ketting

Hi all,

I’m wanting to get a snapshot of the screen that I’ve drawn (I get
this out of the back buffer, and it works OK since I’m working purely
on event-driven things). But then I want to halve the brightness of
each pixel, then blit another image over the top of that.

  1. Would what I want to do work with alpha blending? I have no idea
    how to use
    alpha blending and haven’t found a satisfactory explanation of how
    it works
    despite lots of searching

I do something similar in my game. However, I just create a full-screen
image that is all black and blit it over the background. Then you can vary
the alpha up/down slowly to show more or less of the image beneath it.

To change the alpha on the surface you can call:

         SDL_SetAlpha( pSurface,SDL_SRCALPHA,(Uint8)nAlpha );

To turn off the alpha call:

        SDL_SetAlpha( pSurface,0,SDL_ALPHA_OPAQUE );

To be clear you don’t need to create an additional surface to fade the alpha
up/down. My example just treats the black surface as an overlay.

Ken Rogoway
Homebrew Software
http://www.homebrewsoftware.com/


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

No virus found in this incoming message.
Checked by AVG Free Edition.
Version: 7.5.476 / Virus Database: 269.10.8/904 - Release Date: 7/16/2007
5:42 PM

No virus found in this outgoing message.
Checked by AVG Free Edition.
Version: 7.5.476 / Virus Database: 269.10.8/904 - Release Date: 7/16/2007
5:42 PM


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

No virus found in this incoming message.
Checked by AVG Free Edition.
Version: 7.5.476 / Virus Database: 269.10.8/904 - Release Date: 7/16/2007
5:42 PM

No virus found in this outgoing message.
Checked by AVG Free Edition.
Version: 7.5.476 / Virus Database: 269.10.8/904 - Release Date: 7/16/2007
5:42 PM

----- Original Message -----
From: sdl-bounces@lists.libsdl.org [mailto:sdl-bounces at lists.libsdl.org] On
Sent: Tuesday, July 17, 2007 11:19 PM
To: 'A list for developers using the SDL library. (includes SDL-announce)'
Subject: Re: [SDL] Dimming an image on screen
-----Original Message-----
From: sdl-bounces@lists.libsdl.org [mailto:sdl-bounces at lists.libsdl.org] On
Sent: Tuesday, July 17, 2007 10:56 PM
To: A list for developers using the SDL library. (includes SDL-announce)
Subject: Re: [SDL] Dimming an image on screen

Jason <jesus_freak picknowl.com.au> writes:

Ta muchly, Peter. It works very nicely using the alpha channel.

-J