Scaling Image Colors

Hi,

So, I’m working on a linear resampling program. It involves taking weighted
samples from a surface’s pixels. My basic issue is scaling a sample taken
in Uint32 format.

Uint32 samples, as I understand it, are a single number that can store the
same number of possible colors as four Uint8 samples. The result is that
the entire color of a single pixel can be stored as one Uint32 number:

Uint32 blah = Red256256256 + Green256256 + Blue256 + Alpha1
or
Uint32 blah = Blue
256256256 + Green256256 + Red256 + Alpha1

First, is that correct? Second, because of the distributive property, it
should be possible to scale the color simply by scaling the number:
0.2blah == 0.2Red256256256 + 0.2Green256256 + 0.2Blue256 +
0.2Alpha1

The results I’m getting are not consistent with this model. The entire
color changes, not just the intensity of each channel. I’m probably doing
something wrong. But what? And is there a better, preferred way to scale
samples?

Thanks,
Ian

Hi Ian,

here is some code (untested) which should disassemble and reassemble the
color components for a pixel:

SDL_Surface *src; // Surface
int x,y; // Coordinates of pixel to decompose

Uint32 r; // Output components
Uint32 g;
Uint32 b;
Uint32 a;

SDL_PixelFormat *fmt = src->format;
Uint32 *pixel = (Uint32 *)((Uint8 *)src->pixels + src->offset + y *
src->pitch + x * fmt->BytesPerPixel);

r = ((*pixel & fmt->Rmask)>>fmt->Rshift)<Rloss;
g = ((*pixel & fmt->Gmask)>>fmt->Gshift)<Gloss;
b = ((*pixel & fmt->Bmask)>>fmt->Bshift)<Bloss;
a = ((*pixel & fmt->Amask)>>fmt->Ashift)<Aloss;

// Now scale components, but keep in range 0-255

*pixel = ((r>>fmt->Rloss)<Rshift) | ((g>>fmt->Gloss)<Gshift)
| ((b>>fmt->Bloss)<Bshift) | ((a<Aloss)<Ashift);

Hope that helps,
–AndreasOn 9/4/10 6:44 PM, Ian Mallett wrote:

Hi,

So, I’m working on a linear resampling program. It involves taking
weighted samples from a surface’s pixels. My basic issue is scaling a
sample taken in Uint32 format.

Uint32 samples, as I understand it, are a single number that can store
the same number of possible colors as four Uint8 samples. The result
is that the entire color of a single pixel can be stored as one Uint32
number:

Uint32 blah = Red256256256 + Green256256 + Blue256 + Alpha1
or
Uint32 blah = Blue
256256256 + Green256256 + Red256 + Alpha1

First, is that correct? Second, because of the distributive property,
it should be possible to scale the color simply by scaling the number:
0.2blah == 0.2Red256256256 + 0.2Green256256 + 0.2Blue256 +
0.2Alpha1

The results I’m getting are not consistent with this model. The
entire color changes, not just the intensity of each channel. I’m
probably doing something wrong. But what? And is there a better,
preferred way to scale samples?

Thanks,
Ian


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

Your problem is that just taking blah * 0.2 does not handle the fact
that you don’t want a fractional portion of green to get into blue.

Consider the case where green is 3, blue is 0, and you are multiplying by 1/2:

3256256*.5 is your new value. This is the same as 1256256 +
128*256, meaning that rather than just halving the green component,
you also increased blue to half scale.

The distributive property works, but what you need is something that
removes the fractional values of each byte, rather than strictly
adding everything together. The property is actually screwing up what
you would like to have happen.

Make sense?

-MattOn Sat, Sep 4, 2010 at 6:44 PM, Ian Mallett wrote:

Hi,

So, I’m working on a linear resampling program.? It involves taking weighted
samples from a surface’s pixels.? My basic issue is scaling a sample taken
in Uint32 format.

Uint32 samples, as I understand it, are a single number that can store the
same number of possible colors as four Uint8 samples.? The result is that
the entire color of a single pixel can be stored as one Uint32 number:

Uint32 blah = Red256256256 + Green256256 + Blue256 + Alpha1
or
Uint32 blah = Blue
256256256 + Green256256 + Red256 + Alpha1

First, is that correct?? Second, because of the distributive property, it
should be possible to scale the color simply by scaling the number:
0.2blah == 0.2Red256256256 + 0.2Green256256 + 0.2Blue256 +
0.2Alpha1

The results I’m getting are not consistent with this model.? The entire
color changes, not just the intensity of each channel.? I’m probably doing
something wrong.? But what?? And is there a better, preferred way to scale
samples?

Thanks,
Ian


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

Even though you can use an int to store a color, a color is NOT an int. You
use an int because it’s convenient to do so, it has the same number of bits,
but color ops != int ops. To do color ops, you always need to unpack the
int, operate on the channels, and pack the result back.

It’s easier to see if you use shifts instead of multiplications. For your
example, it’s

color = (R << 24) | (G << 16) | (B << 8) | A

The color you get here is the same as yours, but this makes more clear that
you’re just placing bits where it’s convenient, not calculating a number
that somehow represents the color.

–GabrielOn Sun, Sep 5, 2010 at 3:44 AM, Ian Mallett wrote:

Hi,

So, I’m working on a linear resampling program. It involves taking
weighted samples from a surface’s pixels. My basic issue is scaling a
sample taken in Uint32 format.

Uint32 samples, as I understand it, are a single number that can store the
same number of possible colors as four Uint8 samples. The result is that
the entire color of a single pixel can be stored as one Uint32 number:

Uint32 blah = Red256256256 + Green256256 + Blue256 + Alpha1
or
Uint32 blah = Blue
256256256 + Green256256 + Red256 + Alpha1

First, is that correct? Second, because of the distributive property, it
should be possible to scale the color simply by scaling the number:
0.2blah == 0.2Red256256256 + 0.2Green256256 + 0.2Blue256 +
0.2Alpha1

The results I’m getting are not consistent with this model. The entire
color changes, not just the intensity of each channel. I’m probably doing
something wrong. But what? And is there a better, preferred way to scale
samples?

Thanks,
Ian


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

Hi,

Your problem is that just taking blah * 0.2 does not handle the fact
that you don’t want a fractional portion of green to get into blue.

Consider the case where green is 3, blue is 0, and you are multiplying by
1/2:

3256256*.5 is your new value. This is the same as 1256256 +
128*256, meaning that rather than just halving the green component,
you also increased blue to half scale.

The distributive property works, but what you need is something that
removes the fractional values of each byte, rather than strictly
adding everything together. The property is actually screwing up what
you would like to have happen.

Make sense?

More or less.On Sun, Sep 5, 2010 at 12:33 AM, Matthew Kuiken <matt.kuiken at gmail.com>wrote:
On Sat, Sep 4, 2010 at 9:59 PM, Andreas Schiffler wrote:

Hi Ian,

here is some code (untested) which should disassemble and reassemble the
color components for a pixel:

With a couple modifications, it works.

Thanks everyone!
-Ian