Board index » cppbuilder » Fading Smaller Bitmap Into Larger Bitmap

Fading Smaller Bitmap Into Larger Bitmap

I would like to fade a smaller bitmap into a larger bitmap in real time.
And I would like to do this as smoothly as possible.  I have one 640 x 480
bitmap displayed on a form using a TPaintBox object. I would like to take
another smaller (150 x 150) bitmap and display it in the middle of the
larger bitmap in a progressively more distinct manner.  In other words,
starting out with the smaller bitmap 95% faded out and to then to redisplay
it in the same spot but less faded with each step.  I think that I would
need probably about ten to 12 steps, from real faded, to clear, in about 2
or 3 seconds.  The initial highly faded steps should be transparent,
allowing the background bitmap to show through.  This transparency should
decrease as the smaller bitmap gets more tangible.

The first key question is how would one go about processing the smaller
bitmap, and transferring it to the larger bitmap, to achieve these
progressive stages of faded transparency?

I would appreciate any ideas anyone might have.

Thanks,
Steven S. Showers

 

Re:Fading Smaller Bitmap Into Larger Bitmap


"Steven S. Showers" <stevenshow...@homewardboundjournal.com> wrote in
message news:3cb13df2_2@dnews...
Quote
> I would like to fade a smaller bitmap into a larger bitmap in real time.

<snip>

Quote
> The first key question is how would one go about processing the smaller
> bitmap, and transferring it to the larger bitmap, to achieve these
> progressive stages of faded transparency?

I looked into the API call AlphaBlend for this purpose.  It seems to work,
as long as you don't want per-pixel alpha.

Here's an example that may or may not work:

BLENDFUNCTION bf = {AC_SRC_OVER, 0, 128, 0};
  AlphaBlend(
    destbmp->Canvas->Handle,
    245, 165, 150, 150,
    srcbmp->Canvas->Handle,
    0, 0, 150, 150,
    bf);

That should blend the source bitmap into the middle of the destination
bitmap, assuming both are the size you specified in your message, with an
alpha value of 128/255... roughly 0.5.

To do a fade though you'll need another bitmap to build a composite in,
since you'll need your background intact for each successive operation.  I'd
suggest something along these lines:

void FadeInBitmap(
        Graphics::TBitmap* dest,
        Graphics::TBitmap* back,
        Graphics::TBitmap* fore,
        int pct)
{
  if (pct < 0)
    pct = 0;
  if (pct > 100)
    pct = 100;

  dest->Assign(back);
BLENDFUNCTION bf = {AC_SRC_OVER, 0, 0, 0};
  bf.SourceConstantAlpha = (pct * 255) / 100;

  AlphaBlend(
      dest->Canvas->Handle,
        ((dest->Width - fore->Width) >> 1),
        ((dest->Height - fore->Height) >> 1),
        fore->Width, fore->Height,
      fore->Canvas->Handle,
        0, 0, fore->Width, fore->Height,
      bf);

Quote
}

With any luck that should produce a dest with the 'fore' alpha blended over
the 'back' bitmap with an opacity percentage 'pct'.  ie: pct == 50 is half,
pct == 100 is fully visible, pct == 0 is no 'fore' image.

Now all you have to do is call it with increasing values of pct, maybe from
a timer, and display the result.

--
Corey Murtagh
The Electric Monk
"Quidquid latine dictum sit, altum viditur."

Re:Fading Smaller Bitmap Into Larger Bitmap


Quote
> I looked into the API call AlphaBlend for this purpose.  It seems to work,
> as long as you don't want per-pixel alpha.

I don't see any reference to an "AlphaBlend" API in the Windows reference
documentation, or in the CBuilder documentation.  Is this an undocumented
API or do I need a more advanced version of Windows?

I have Windows 95 and CBuilder 3.

Steven S. Showers

Re:Fading Smaller Bitmap Into Larger Bitmap


"Steven S. Showers" <stevenshow...@homewardboundjournal.com> wrote in
message news:3cb27724$1_2@dnews...

Quote

> > I looked into the API call AlphaBlend for this purpose.  It seems to
work,
> > as long as you don't want per-pixel alpha.

> I don't see any reference to an "AlphaBlend" API in the Windows reference
> documentation, or in the CBuilder documentation.  Is this an undocumented
> API or do I need a more advanced version of Windows?

> I have Windows 95 and CBuilder 3.

Ah... it requires Win98 or Win2K (or higher).  I guess it wasn't in the
headers included with BCB3 either :(

Ok, Plan B: do it by hand :>

[Warning: I rambled a bit.  Let me know if it gets confusing :> ]

Effectively this means writing a new AlphaBlend, although we can make some
assumptions and end up with a simpler routine.

First off, it's handy if you can put all three bitmaps into the same format,
and especially handy if it's an easy one like pf32bit.  pf24bit is also ok,
since we're essentially processing each color component anyway so we can
walk it a byte at a time.  (Since I prefer pf32bit, that's what I'll show
here)

Now, for a blend operation you'll need to process each pixel you're going to
affect: read the background and foreground pixels from their respective
bitmaps, blend them, then write them back to the background image.

To do the blend, split each pixel into it's R, G and B components and blend
them seperately, then combine all three back into a pixel value.  The amount
taken from back and fore pixels is controlled by the alpha value with
roughly this formula (assuming alpha in the range 0.0-1.0):

  Ro = Rf * alpha + Rb * (1 - alpha);

That's for floating point of course.  To speed things up use an alpha range
of 0..255, which lets us use all integer math:

  Ro = (Rf * alpha + Rb * (255 - alpha)) / 255;

It's a little quicker to divide by 256 (shift right 8), but the output is
very slightly wrong.  Try it and see if it's acceptable to you.

Now, to get at the pixels, use the TBitmap's ScanLine property.  I'll skip
to the code so you can see it all together:

// assumes PixelFormat == pf32bit for all bitmaps
// alpha is in the range 0-255
void BlendBitmap(Graphics::TBitmap* dest,
                 Graphics::TBitmap* back,
                 Graphics::TBitmap* fore,
                 unsigned char alpha)
{
  dest->Assign(back);

int offset_y = (back->Height - fore->Height) >> 1;
int offset_x = (back->Width - fore->Width) >> 1;

  for (int y = 0; y < fore->Height; y++)
  {
  int* fsl = (int*)(fore->ScanLine[y]);
  int* dsl = (int*)(dest->ScanLine[offset_y + y]) + offset_x;
    for (int x = 0; x < fore->Width; x++)
    {
    int Cf = fsl[x];
    int Rf = Cf & 0xFF, Gf = (Cf >> 8) & 0xFF, Bf = (Cf >> 16) & 0xFF;
    int Cb = dsl[x];
    int Rb = Cb & 0xFF, Gb = (Cd >> 8) & 0xFF, Bb = (Cd >> 16) & 0xFF;

    int Ro = (Rf * alpha + Rb * (255 - alpha)) / 255;
    int Go = (Gf * alpha + Gb * (255 - alpha)) / 255;
    int Bo = (Bf * alpha + Bb * (255 - alpha)) / 255;

        dsl[x] = Ro & 0xFF | ((Go & 0xFF) << 8) | ((Bo & 0xFF) << 16);
    }

Quote
}

Hmm... should do the trick.  Try shifting right 8 bits instead of dividing
by 255 and see if the result is acceptable.  You can probably dispense with
the '& 0xFF' in the final combine since everything should be in the right
range at that point.

--
Corey Murtagh
The Electric Monk
"Quidquid latine dictum sit, altum viditur."

Re:Fading Smaller Bitmap Into Larger Bitmap


Corey, thanks for taking the time to set forth your ideas on how to fade in
/ blend these bitmaps.
As I study the code, there are a couple of questions that come to mind.

First, when you say "assumes pixel format = pf32bit",  I would note that the
source of all the bitmaps I am using come from 24 bit Jpeg's.   I assume
that when I make these jpegs into bitmaps the pixel format is pf24bit.  Is
that right?  And if so, how would the code need to be changed to accomodate
the pf24bit format?

Second,  in the following line of code, you are introducing some new
concepts for me, being a beginner in C programming:

 int Rf = Cf & 0xFF, Gf = (Cf >> 8) & 0xFF, Bf = (Cf >> 16) & 0xFF;

What is the function of ampersand "&" in these three statements?

What is the function of the ">>"  operator in the last two statements?

Third, in regards to the following statement:

dsl[x] = Ro & 0xFF | ((Go & 0xFF) << 8) | ((Bo & 0xFF) << 16);

What is the function of the "<<"  operator in this statement?

What is the function of the two "|" operators in this statement?

Thanks,
Steven S. Showers

Re:Fading Smaller Bitmap Into Larger Bitmap


"Steven S. Showers" <stevenshow...@homewardboundjournal.com> wrote in
message news:3cb3d85d$1_2@dnews...

Quote
> Corey, thanks for taking the time to set forth your ideas on how to fade
in
> / blend these bitmaps.
> As I study the code, there are a couple of questions that come to mind.

> First, when you say "assumes pixel format = pf32bit",  I would note that
the
> source of all the bitmaps I am using come from 24 bit Jpeg's.   I assume
> that when I make these jpegs into bitmaps the pixel format is pf24bit.  Is
> that right?  And if so, how would the code need to be changed to
accomodate
> the pf24bit format?

I use pf32bit because it's nicely sized - 4 bytes per pixel.  You can use an
int* to access a pixel at a time.  The pf24bit format on the other hand is
often considered awkward to work with, since each pixel occupies 3 bytes.
On the plus side it's less wasteful, since a pf32bit bitmap generally holds
no more information about each pixel.

If your bitmaps are all 24 bit then some changes will be needed... which
I'll explain down the bottom.

Quote
> Second,  in the following line of code, you are introducing some new
> concepts for me, being a beginner in C programming:

>  int Rf = Cf & 0xFF, Gf = (Cf >> 8) & 0xFF, Bf = (Cf >> 16) & 0xFF;

> What is the function of ampersand "&" in these three statements?

The '&' operator is a bitwise and.  In this context it's used to get rid of
any extra bits that aren't relevant to the color component.

Quote
> What is the function of the ">>"  operator in the last two statements?

The '>>' operator is a bit shift right.  In the expression 'x >> y' the
operator will shift the value 'x' right by 'y' bits.

The '>>' and '&' operators are useful in this case for extracting the color
components from our integer-sized pixel.  Here's the bit layout for a
pf32bit pixel:

  00000000BBBBBBBBGGGGGGGGRRRRRRRR

where the right-most bit is bit 0 and the left-most is bit 31;

To extract the color components as values in the range 0-255 (occupying 8
bits), we shift right by 0, 8 and 16 buts respectively, then use a bitwise
and to select just the low 8 bits.  Since shift right 0 does nothing I
didn't use it.

To break down the line into 3 seperate statements:

  int Rf = Cf & 0xFF;
  int Gf = (Cf >> 8) & 0xFF;
  int Bf = (Cf >> 16) & 0xFF;

After this we have the Red, Green and Blue color components of the
foreground pixel.

Quote
> Third, in regards to the following statement:

> dsl[x] = Ro & 0xFF | ((Go & 0xFF) << 8) | ((Bo & 0xFF) << 16);

> What is the function of the "<<"  operator in this statement?

The opposite of the '>>' operator - in other words, bit shift left.

Quote
> What is the function of the two "|" operators in this statement?

These are bitwise or operations, used here to merge the color components
(after shifting them left) back into a single pixel color value.

Whew... been a while since I had to think about this stuff.  After you've
been using these operators for a while they just become automatic, like
standard arithmetic operators :)

Now, back to pf24bit.

Since the pixels are 3 bytes each, it's both harder and easier to work with
them.  Depends on what you're doing.  In this case you might find them
slightly easier to work with.

Here's the loop again, this time using pf24bit for all the bitmaps (comments
included):

// offset_x needs to be in bytes now instead of pixels
  offset_x *= 3;

// now the loops...
  for (int y = 0; y < fore->Height; y++)
  {
  // 'BYTE' is a typedef of 'unsigned char'
  BYTE* fsl = (BYTE*)(fore->ScanLine[y]);
  BYTE* dsl = (int*)(dest->ScanLine[offset_y + y]) + offset_x;

  // scan each pixel in the current line...
    for (int x = 0; x < fore->Width; x++)
    {
    // x is a pixel offset - calculate the byte offset
    int bx = x * 3;

    // extract the fore and back colors
    int Rf = fsl[bx], Gf = fsl[bx + 1], Bf = fsl[bx + 2];
    int Rd = dsl[bx], Gd = dsl[bx + 1], Bd = dsl[bx + 2];

    // blend them together
    int Ro = (Rf * alpha + Rb * (255 - alpha)) / 255;
    int Go = (Gf * alpha + Gb * (255 - alpha)) / 255;
    int Bo = (Bf * alpha + Bb * (255 - alpha)) / 255;

    // put them back in dest
        dsl[bx] = (BYTE)Ro;
        dsl[bx + 1] = (BYTE)Go;
        dsl[bx + 2] = (BYTE)Bo;
    }

Hope that made sense.  Since we're not getting a whole pixel at once we
don't need to split it up.  I guess you could do the same for pf32bit, using
a scale of 4 for offset_x.  It saves on shifts and bit operations, but adds
a little in memory fetches and stores.  I think it about evens out in terms
of speed, but this version is probably a little easier to understand.

--
Corey Murtagh
The Electric Monk
"Quidquid latine dictum sit, altum viditur."

Re:Fading Smaller Bitmap Into Larger Bitmap


Thank you for explaining the purposes of  the "&", ">>", "<<", "|" bitwise
operators in the code segment above.  I follow you, and actually understand
what you are doing there.

Therefore, I take the ">>" operator in the following two lines of code (from
the original pf32bit code segment) as a shift right one bit.

int offset_y = (back->Height - fore->Height) >> 1;
int offset_x = (back->Width - fore->Width) >> 1;

Question:  I surmise that your ultimate purpose here is to allow the loop
code to locate a region at the center of the larger bitmap (dest) which will
be the same size as the smaller bitmap (fore). How does the shift right one
bit help you to achieve it?

In regards to the code modified to work with pf24bit pixel arrangement, I
have a couple of additional questions.  And these questions revolve around
the issue of offsets as well.  Perhaps in answering the question above, you
might shed some light on these questions.

In regards to these three statements:

Quote
>   offset_x *= 3;
>   BYTE* fsl = (BYTE*)(fore->ScanLine[y]);
>   BYTE* dsl = (int*)(dest->ScanLine[offset_y + y]) + offset_x;

I understand the middle line, which returns a pointer (fsl) to a single byte
at the beginning of ScanLine[y].

But the first line, taken with the third line is somewhat opaque.  Could you
take a couple of minutes to explain what you are doing here?

Secondly, in regards to the pf24bit pixel arrangement, how does that differ
from the pf32bit pixel arrangement.  From this code I get the impression
that the red, green, blue values for a single pixel are contained in three
separate 32 bit memory locations.  Is that right?

Thank You,
Steven S. Showers

Re:Fading Smaller Bitmap Into Larger Bitmap


Hi Steven,

Sorry for the delay - been away from my computers for a few days.

"Steven S. Showers" <stevenshow...@homewardboundjournal.com> wrote in
message news:3cb66d20_1@dnews...

Quote
> Thank you for explaining the purposes of  the "&", ">>", "<<", "|" bitwise
> operators in the code segment above.  I follow you, and actually
understand
> what you are doing there.

Whew.  I'm not a particularly good teacher, so wasn't sure if you'd follow
my somewhat rambling explanation.

Quote
> Therefore, I take the ">>" operator in the following two lines of code
(from
> the original pf32bit code segment) as a shift right one bit.

> int offset_y = (back->Height - fore->Height) >> 1;
> int offset_x = (back->Width - fore->Width) >> 1;

> Question:  I surmise that your ultimate purpose here is to allow the loop
> code to locate a region at the center of the larger bitmap (dest) which
will
> be the same size as the smaller bitmap (fore). How does the shift right
one
> bit help you to achieve it?

A shift right of 1 bit is the same as a divide by two.  The long form of the
offset_y calculation is:

int offset_y = (back->Height / 2) - (fore->Height / 2);

I just juggled that to reduce the division, then since I was dividing by two
changed it to a right shift.  The compiler would probably have done that for
me anyway, but I've been programming since before compilers got that smart
so I still do some odd things.

Quote
> In regards to the code modified to work with pf24bit pixel arrangement, I
> have a couple of additional questions.  And these questions revolve around
> the issue of offsets as well.  Perhaps in answering the question above,
you
> might shed some light on these questions.

> In regards to these three statements:

> >   offset_x *= 3;
> >   BYTE* fsl = (BYTE*)(fore->ScanLine[y]);
> >   BYTE* dsl = (int*)(dest->ScanLine[offset_y + y]) + offset_x;

> I understand the middle line, which returns a pointer (fsl) to a single
byte
> at the beginning of ScanLine[y].

> But the first line, taken with the third line is somewhat opaque.  Could
you
> take a couple of minutes to explain what you are doing here?

um... did I really put that as '(int*)'?  Oops.  My bad.  Should have been
'(BYTE*)' on line 3, same as line 2.

Now, the reason behind the the multiply by 3 is that each pixel is 3 bytes
wide, so we multiply the number of pixels in the offset by 3 to get a number
of bytes offset into the buffer.

Quote
> Secondly, in regards to the pf24bit pixel arrangement, how does that
differ
> from the pf32bit pixel arrangement.  From this code I get the impression
> that the red, green, blue values for a single pixel are contained in three
> separate 32 bit memory locations.  Is that right?

Nope, each item pointed to by fsl and dsl is an 8-bit value.  Apart from the
lack of a padding byte to align each pixel to 32bit, pf24bit has the same
color information as pf32bit.

I do all of the calculations in 32bit for various reasons, but mostly
because the intermediate results can get as high as 65025 (or thereabouts),
which wouldn't fit in a byte.  Strictly speaking you could write the centre
section's calculations something like this:

  dsl[bx] = (BTYE)(((int)fsl[bx] * alpha + (int)dsl[bx] * (255 - alpha)) /
255);

...with 2 more lines for [bx + 1] and [bx + 2].  It might even be faster to
do so, but it's not quite as readable.

--
Corey Murtagh
The Electric Monk
"Quidquid latine dictum sit, altum viditur."

Re:Fading Smaller Bitmap Into Larger Bitmap


Quote
> > Secondly, in regards to the pf24bit pixel arrangement, how does that
differ
> > from the pf32bit pixel arrangement.  From this code I get the impression
> > that the red, green, blue values for a single pixel are contained in
three
> > separate 32 bit memory locations.  Is that right?

> Nope, each item pointed to by fsl and dsl is an 8-bit value.  Apart from
the
> lack of a padding byte to align each pixel to 32bit, pf24bit has the same
> color information as pf32bit.

Corey, please bear with me on this.  I am not sure if you understood the
question I asked, so I will pose it again in a more detailed manner.

First, I am assuming that on a 32bit machine, that every memory location has
32 bits.   0000 0000 0000 0000 0000 0000 0000 0000 .

Second, this line of code produces a pointer to a 32bit memory address that
contains an 8 bit byte:

BYTE* fsl = (BYTE*)(fore->ScanLine[y]);

That layout of the memory address pointed to by "fsl" would be as follows:

0000 0000 0000 0000 0000 0000 XXXX XXXX   (X= either a 1 or 0)

In reference to the following three statements:

int Rf = fsl[bx], Gf = fsl[bx + 1], Bf = fsl[bx + 2];

Each of these statements points to a unique memory address, and because
every memory address in a 32bit machine has to be 32 bits, then each of
these statements must point to a 32bit memory address.  Right?

But, only the lower 8 bits out of the 32bits is used.  Right?

Rf = fsl[bx]

Here, fsl[bx] points to a 32bit memory address
that holds the red value for the first pixel as follows:
0000 0000 0000 0000 0000 0000 RRRR RRRR
Because fsl is a pointer to a "byte", is will return only
the lower 8 bits of the 32 bit word.

Gf = fsl[bx + 1]

Here, fsl[bx + 1] points to the next 32bit memory address
that holds the green value for that pixel as follows:
0000 0000 0000 0000 0000 0000 GGGG GGGG
Again, because fsl is a pointer to a "byte", is will return
only  the lower 8 bits of the 32 bit word.

Bf = fsl[bx + 2];

Here, fsl[bx + 2] points to the next 32bit memory address
that holds the blue value for that pixel as follows:
0000 0000 0000 0000 0000 0000 BBBB BBBB
Again, because fsl is a pointer to a "byte", is will return
only the lower 8 bits of the 32 bit word.

This all seems very logical to me, i.e. if my assumptions are right.  And
it makes the more sense because one can conclude from this that a
bitmap stored in pf24bit format (while the pixel color components are
easily accessible) will use three times more memory than a bitmap stored
in the pf32bit format where all the color information for a single pixel is
contained in a single 32bit memory location (where you have to go to the
trouble of extracting the red, green and blue values from the 32 bit word
as you demonstrated in your first code example).

So when I say/ask:

Quote
> > From this code I get the impression
> > that the red, green, blue values for a single pixel are contained in
three
> > separate 32 bit memory locations.  Is that right?

Why isn't the proper response to this question "yes"?

Thanks for your help,
Steven S. Showers

Re:Fading Smaller Bitmap Into Larger Bitmap


"Steven S. Showers" <stevenshow...@homewardboundjournal.com> wrote in
message news:3cbe55b5_2@dnews...
<snip>

Quote
> First, I am assuming that on a 32bit machine, that every memory location
has
> 32 bits.   0000 0000 0000 0000 0000 0000 0000 0000 .

Sorry Steven, seems I misunderstood your question.

The memory in a PC is 8-bit, so the smallest directly addressable portion of
memory is a byte.  These are read and written in various sizes to produce
each of the larger integer types - 2 bytes for short, 4 for long int
(standard int on a 32-bit machine) and 8 for __int64.  The CPU can
comfortably handle arithmetic with 8, 16 and 32 bit ints, and to a limited
degree supports 64 bit operations.

Quote
> Second, this line of code produces a pointer to a 32bit memory address
that
> contains an 8 bit byte:

> BYTE* fsl = (BYTE*)(fore->ScanLine[y]);

> That layout of the memory address pointed to by "fsl" would be as follows:

> 0000 0000 0000 0000 0000 0000 XXXX XXXX   (X= either a 1 or 0)

The ScanLine property returns a void pointer, which we cast to BYTE* so that
the compiler will correctly index it.  The type of a pointer is used to
determine how far to step during addition, so adding an integer offset to a
pointer (either with 'ptr + x' or 'ptr[x]') uses basically this type of
code:

  ptr + (offset * sizeof(*ptr))

So if it's pointing to a BYTE then offset is added direct.  For short* it
multiplies offset by 2, by 4 for int, etc.  You can't index a void* since
void has no size.

<snip>

Quote
> Rf = fsl[bx]

> Here, fsl[bx] points to a 32bit memory address
> that holds the red value for the first pixel as follows:
> 0000 0000 0000 0000 0000 0000 RRRR RRRR
> Because fsl is a pointer to a "byte", is will return only
> the lower 8 bits of the 32 bit word.

Since fsl is a BYTE*, pointing to an unsigned 8-bit integer, when we assign
it to Rf (an integer) it will be extended to fit into a 32-bit integer
value.  The result is the same as your bit diagram above.

The same is true for the other two colors.  Since we're indexing a BYTE* for
green and blue components, the next two bytes (at offsets bx+1 and bx+2) are
read and converted to signed 32-bit numbers for processing.

Quote
> This all seems very logical to me, i.e. if my assumptions are right.  And
> it makes the more sense because one can conclude from this that a
> bitmap stored in pf24bit format (while the pixel color components are
> easily accessible) will use three times more memory than a bitmap stored
> in the pf32bit format where all the color information for a single pixel
is
> contained in a single 32bit memory location (where you have to go to the
> trouble of extracting the red, green and blue values from the 32 bit word
> as you demonstrated in your first code example).

The end result is the same - you can read the byte values directly instead
of reading the whole thing into a variable and splitting it up.  You could
do the same with a 32-bit value if fore was pf32bit:

int* fsl = (int*)(fore->ScanLine[y]);
  for (int x = 0; x < fore->Width; x++)
  {
  BYTE* bfsl = (BYTE*)(fsl + x);
  int Rf = bfsl[0];
  int Gf = bfsl[1];
  int Bf = bfsl[2];
  ...
  }

Simpler than all that shifting and masking, and probably faster too.  But it
only works with pixel formats that have 8 bits per color component: pf32bit
and pf24bit.  Since I often have to deal with other formats (5:5:5 15 bit,
5:6:5 16 bit, etc) I tend to stick to shifts and masks.

--
Corey Murtagh
The Electric Monk
"Quidquid latine dictum sit, altum viditur."

Re:Fading Smaller Bitmap Into Larger Bitmap


Quote
> The memory in a PC is 8-bit, so the smallest directly addressable portion
of
> memory is a byte.  These are read and written in various sizes to produce
> each of the larger integer types - 2 bytes for short, 4 for long int
> (standard int on a 32-bit machine) and 8 for __int64.  The CPU can
> comfortably handle arithmetic with 8, 16 and 32 bit ints, and to a limited
> degree supports 64 bit operations.

Corey, thank you for giving me a more accurate understanding of this
subject.
I appreciate having a better understanding now of what is going on behind
the
scenes.  I appreciate that little nugget of information regarding a void
pointer,
and the reason why you must cast it into a byte pointer, in terms of the
compiler
needing to know the size of the thing that it is pointing to.

Though just one question comes to mind here in regards to this statement:

Quote
> > Since fsl is a BYTE*, pointing to an unsigned 8-bit integer, when we
assign
> > it to Rf (an integer) it will be extended to fit into a 32-bit integer
> > value.  The result is the same as your bit diagram above.

Is there a reason why you need Rf to be an integer?  If you are assigning a
byte
to it, and there is never anything larger than a byte in it, why not define
it as a byte too?
(or is this just a carry over from the first pf32bit code segment which
needed Rf to
be an integer for obvious reasons?)

Now on to the original subject ....

I have implemented your bitmap blending approach and it works very
well, except for one small detail.

First let me say that because I am displaying the final large bitmap
using a TPaintBox object, and since it does not have a scanline property,
what I did was copy out the destination rectangle (the same size as
the bitmap that I am fading in) into another TBitmap, and used that
as the destination bitmap.  Because it is the same size as the foreground
bitmap, there was no need for the x_offset and y_offset code.

With each fade-in step, I CopyRect'd the destination bitmap back into
the TPaintBox canvas, and the result was a fairly even fade in, and
quite fast too.

Now, in regards to the slight glitch ....

What happens is this.  Against the background of a mountain landscape, I
fade in the portrait of a prominent person at the center of the larger
landscape.
That portrait remains on the screen for a couple of seconds, and then the
fade-out routine kicks in, and the portrait starts to fade out, returning
progressively
to the original mountain and sky background.

To accomplish the fade out, I made a copy of the unaltered background
rectangle (before any fade in operations began) from the TPaintBox canvas
into another TBitmap, and used this as the foreground bitmap.

In the fade out rountine I am using all 255 alpha steps.  In other words, I
calculate and display a blend for each alpha value between  0 and 255.
But at the very end, there still remains a very slight shadow of the
portrait
which is noticeable against a clear blue sky.  In this respect, the original
background does not completely return.

I can get around that by copying the original background rectangle into that
position as the last step.  But if you are looking closely, it is sort of a
crude
way to end it.  The remaining shadow does not fade out, but abruptly
vanishes.

Do you have any ideas in regards to what needs to be changed in the
equation, or
whatever, to get that portrait to completely fade out to the original
background?

Thanks again,
Steven S. Showers

Re:Fading Smaller Bitmap Into Larger Bitmap


"Steven S. Showers" <stevenshow...@homewardboundjournal.com> wrote in
message news:3cc1099b_1@dnews...
<snip>

Quote
> > > Since fsl is a BYTE*, pointing to an unsigned 8-bit integer, when
> > > we assign it to Rf (an integer) it will be extended to fit into
> > > a 32-bit integervalue.  The result is the same as your bit diagram
> > > above.

> Is there a reason why you need Rf to be an integer?  If you are
> assigning a byte to it, and there is never anything larger than
> a byte in it, why not define it as a byte too?

The same is true here - the intermediate values from calculations may exceed
8-bits, as high as 65025 (255*255).  I could have used an unsigned short,
but it's probably more efficient to use ints since they are the standard
size that the CPU is optimized for.

<snip>

Quote
> Do you have any ideas in regards to what needs to be changed in
> the equation, or whatever, to get that portrait to completely
> fade out to the original background?

Hmm... an alpha value of 255 SHOULD result in a perfectly solid foreground
with no visible background.  The calculation for alpha is:

  C = (C1 * alpha + C2 * (255 - alpha)) / 255;

If alpha is 255 then:

  c = (c1 * 255 + c2 * (255 - 255)) / 255;
    = (c1 * 255 + c2 * 0) / 255;
    = (c1 * 255) / 255;
    = c1;

If this isn't the case then there's something wrong with your code, either
in the fade routine or the area where you're taking the snapshot.

However, here's a question for you: if you're fading one image in over
another, why aren't you just reversing the sequence with the same images for
the fade out?  Your background and foreground images should remain
unchanged, so fading in and out is exactly the same process, only the alpha
values change direction.

// fade in, 10ms pause between frames
  for (alpha = 0; alpha <= 255; alpha++)
  {
    BlendBitmap(dest, back, fore, alpha);
    ::Sleep(10);
  }

// pause for a few seconds
  ::Sleep(3000)

// fade out, same speed as above
  for (alpha = 255; alpha >= 0; alpha--)
  {
    BlendBitmap(dest, back, fore, alpha);
    ::Sleep(10);
  }

That's probably not exactly what you want, since it doesn't allow for user
input during that time etc.  But as pseudo-code it's a good enough example.

So the fade in is:

  for alpha values from 0 to 255:
    blend back and fore into dest

And the fade out is:

  for alpha values from 255 to 0:
    blend back and fore into dest

Hope that's not too obscure for you to figure from the code above.

--
Corey Murtagh
The Electric Monk
"Quidquid latine dictum sit, altum viditur."

Other Threads