 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Roy M Klever Guest
|
Posted: Mon Oct 16, 2006 8:10 pm Post subject: Alphablending |
|
|
Hi,
This is what I use today.
// Explanation
slSize = ScanLine Size
slMain = First ScanLine of bitmap
pRGB24 = Is a pointer for a: r,g,b byte array
by, bdy, bx, bdy is blending area
FColorSelection is the color to blend in
//
// Routine
row := slSize * by + slMain;
for y := by to bdy do
begin
for x := bx to bdx do
begin
slPnt:= pRGB24(row + (x * 3));
slPnt.r := (FColorSelection.R - slPnt.r) shr 3 + slPnt.r;
slPnt.g := (FColorSelection.G - slPnt.g) shr 3 + slPnt.g;
slPnt.b := (FColorSelection.B - slPnt.b) shr 3 + slPnt.b;
end;
inc(row, slSize);
end;
Do you have any idea for a faster way of doing it. Must be for 24 bit
bitmaps not 32 bits.
This is for alphablending selection in a own component.
Kind Regards
Roy Magne Klever |
|
| Back to top |
|
 |
Michael Hansen Guest
|
Posted: Mon Oct 16, 2006 10:14 pm Post subject: Re: Alphablending |
|
|
Hi Roy,
This looks pretty optimal, but switching to MMX could perhaps give a little
more (the 24 bit structure may be a problem though). One other thing, you
could try shifting the channels instead of using the record approach (IIRC
there is a small difference in favour of shifting). Also if you could settle
for another blendbalance, you could just do an average of the two colors.
Regards,
Michael Hansen |
|
| Back to top |
|
 |
Mike Lischke Guest
|
Posted: Mon Oct 16, 2006 11:54 pm Post subject: Re: Alphablending |
|
|
Roy M Klever wrote:
| Quote: | Do you have any idea for a faster way of doing it. Must be for 24 bit
bitmaps not 32 bits.
|
If you want it fast then switch to 32 bits. 24bit requires unaligned
access which has a big penalty (particularly with modern CPUs). With
32bit you could also use MMX and speed up things significantly. I could
even give you ready-to-use code for that.
Mike
--
www.soft-gems.net |
|
| Back to top |
|
 |
Lord Crc Guest
|
Posted: Tue Oct 17, 2006 12:32 am Post subject: Re: Alphablending |
|
|
On 16 Oct 2006 11:54:22 -0700, "Mike Lischke"
<newsgroups@soft-gems.net> wrote:
| Quote: | If you want it fast then switch to 32 bits. 24bit requires unaligned
access which has a big penalty (particularly with modern CPUs). With
32bit you could also use MMX and speed up things significantly. I could
even give you ready-to-use code for that.
|
When using plain delphi code, I found some time ago (on my P3) that
using 32bit in general was slightly slower actually. I attributed it
to the increased size of the image, causing more cache misses.
I guess I should try it again tho, to see how things has changed :)
- Asbjørn |
|
| Back to top |
|
 |
Mattias Andersson Guest
|
Posted: Tue Oct 17, 2006 12:38 am Post subject: Re: Alphablending |
|
|
Roy M Klever wrote:
| Quote: | slPnt.r := (FColorSelection.R - slPnt.r) shr 3 + slPnt.r;
slPnt.g := (FColorSelection.G - slPnt.g) shr 3 + slPnt.g;
slPnt.b := (FColorSelection.B - slPnt.b) shr 3 + slPnt.b;
|
[snip]
| Quote: | Do you have any idea for a faster way of doing it. Must be for 24 bit
bitmaps not 32 bits.
|
You could replace the above code with this (F = FColorSelection, B = slPnt):
B := (F shr 3) and $1F1F1F + (B - (B shr 3) and $1F1F1F);
Otherwise I think you should consider Mike's suggestions; accessing aligned
32bit data will be much faster.
Cheers,
Mattias |
|
| Back to top |
|
 |
Lord Crc Guest
|
Posted: Tue Oct 17, 2006 1:04 am Post subject: Re: Alphablending |
|
|
On Mon, 16 Oct 2006 17:10:06 +0200, Roy M Klever
<roy_m_klever (AT) rmklever (DOT) com> wrote:
| Quote: | // Routine
row := slSize * by + slMain;
for y := by to bdy do
begin
slPnt:= pRGB24(row);
for x := bx to bdx do
begin
slPnt.r := (FColorSelection.R - slPnt.r) shr 3 + slPnt.r;
slPnt.g := (FColorSelection.G - slPnt.g) shr 3 + slPnt.g;
slPnt.b := (FColorSelection.B - slPnt.b) shr 3 + slPnt.b;
inc(slPnt); // or inc(PChar(slPnt), 3);
end;
inc(row, slSize);
end;
Do you have any idea for a faster way of doing it. Must be for 24 bit
bitmaps not 32 bits.
|
That's about as fast as it gets on my box. It uses about 220ms on a
4120x8486 bitmap (largest I had handy on my AMD X2 3800+, and <10ms
for a 1200x800 bitmap.
Perhaps it would be slightly faster to copy FColorSelection to a local
variable, that's what I used.
- Asbjørn |
|
| Back to top |
|
 |
Roy M Klever Guest
|
Posted: Tue Oct 17, 2006 3:06 am Post subject: Re: Alphablending |
|
|
Hi Mike,
| Quote: | If you want it fast then switch to 32 bits. 24bit requires unaligned
access which has a big penalty (particularly with modern CPUs). With
32bit you could also use MMX and speed up things significantly. I could
even give you ready-to-use code for that.
|
Well just switching to 32 bit made it a lot slower, I would say half
speed. Just switching is not enough, maybe using MMX is faster, not tested.
But thanks for your suggestion.
Kind Regards
Roy Magne Klever |
|
| Back to top |
|
 |
Roy M Klever Guest
|
Posted: Tue Oct 17, 2006 3:15 am Post subject: Re: Alphablending |
|
|
Hi Michael,
Thanks for your suggestion.
Kind Regards
Roy Magne Klever |
|
| Back to top |
|
 |
Roy M Klever Guest
|
Posted: Tue Oct 17, 2006 3:26 am Post subject: Re: Alphablending |
|
|
Hi Lord Crc,
| Quote: | That's about as fast as it gets on my box. It uses about 220ms on a
4120x8486 bitmap (largest I had handy on my AMD X2 3800+, and <10ms
for a 1200x800 bitmap.
|
Not to bad I think :)
| Quote: | Perhaps it would be slightly faster to copy FColorSelection to a local
variable, that's what I used.
|
Well, not very much of a diffrence, but thanks for suggestion.
When using a paintbrush routine I found it to be a lot faster to change
to globale vars instead of local vars.
Kind Regards
Roy Magne Klever |
|
| Back to top |
|
 |
Roy M Klever Guest
|
Posted: Tue Oct 17, 2006 3:33 am Post subject: Re: Alphablending |
|
|
Hi Mattias,
| Quote: | B := (F shr 3) and $1F1F1F + (B - (B shr 3) and $1F1F1F);
|
I could not make it work... but thanks for suggestion.
Kind Regards
Roy Magne Klever |
|
| Back to top |
|
 |
Mattias Andersson Guest
|
Posted: Tue Oct 17, 2006 5:08 am Post subject: Re: Alphablending |
|
|
Roy M Klever wrote:
| Quote: | Hi Mattias,
B := (F shr 3) and $1F1F1F + (B - (B shr 3) and $1F1F1F);
I could not make it work... but thanks for suggestion.
|
I've attached a small example routine below. It works by first storing the
24bit foreground color in a temporary scanline and then blending this
scanline using a 32bit access pattern. I think this should be more efficient
than computing each RGB value separately.
HTH,
Mattias
procedure BlendToBitmap(Bitmap: TBitmap; Color: TRGB24);
var
I, J, DWords: Integer;
F, B: PInteger;
P, TmpLine: PRGB24;
begin
DWords := Ceil(Bitmap.Width * 3/4);
GetMem(TmpLine, DWords * 4);
P := TmpLine;
for I := 0 to Bitmap.Width - 1 do
begin
P^ := Color;
Inc(P);
end;
for J := 0 to Bitmap.Height - 1 do
begin
F := PInteger(TmpLine);
B := Bitmap.ScanLine[J];
for I := 0 to DWords - 1 do
begin
B^ := (F^ shr 3) and $1F1F1F1F + (B^ - (B^ shr 3) and $1F1F1F1F);
Inc(F);
Inc(B);
end;
end;
FreeMem(TmpLine);
end; |
|
| Back to top |
|
 |
Roy M Klever Guest
|
Posted: Tue Oct 17, 2006 6:31 pm Post subject: Re: Alphablending |
|
|
Hi Mattias,
| Quote: | After my last post, I realized that this could be done much more efficiently
using MMX. I've appended a new MMX routine below, together with the old
pascal routines.
|
Excellent will be testing it this afternoon :)
Thanks!
Kind Regards
Roy Magne Klever |
|
| Back to top |
|
 |
Nils Haeck Guest
|
Posted: Tue Oct 17, 2006 8:20 pm Post subject: Re: Alphablending |
|
|
why not use
var
TmpLine: array of integer;
...
SetLength(TmpLine, Bitmap.Width)
...
F := @TmpLine[0];
The "getmem/freemem" without "try/finally" looks fishy to me Using a
dynamic array is safer imo, and more modern.
Other than that, your suggestion is pretty good, and how it should be done
:)
Another small optimization can be reached by getting rid of a call to
ScanLine for each y-line, and just do it for y=0, y=1 then calculate the
delta.
Nils |
|
| Back to top |
|
 |
Mattias Andersson Guest
|
Posted: Tue Oct 17, 2006 9:28 pm Post subject: Re: Alphablending |
|
|
Nils Haeck wrote:
| Quote: | why not use
var
TmpLine: array of integer;
..
SetLength(TmpLine, Bitmap.Width)
..
F := @TmpLine[0];
The "getmem/freemem" without "try/finally" looks fishy to me Using
a dynamic array is safer imo, and more modern.
|
Ah, yes, a try/finally block would definitely be in place. Seems I put this
together in a haste..
I guess it's debatable which one is better -- GetMem/FreeMem or SetLength.
If you're only passing the data as an argument to an assembler routine, then
I think it doesn't really matter which one you use.
However, from a performance perspective, I wouldn't use either of these. For
a temporary buffer like this, you could simply allocate memory on the stack
(which will avoid the penalty of the memory manager). See e.g. StackAlloc
and StackFree in Grids.pas.
| Quote: | Another small optimization can be reached by getting rid of a call to
ScanLine for each y-line, and just do it for y=0, y=1 then calculate
the delta.
|
Yes, but as you can see from my benchmark results, in order to improve
performance you should always focus on the innermost loops. Optimizing the
outer loop will give a noticeable performance gain only for small data
blocks -- and typically, if the data is small, the routine will be fast
enough anyway. :)
Mattias |
|
| Back to top |
|
 |
Eric Grange Guest
|
Posted: Tue Oct 17, 2006 9:51 pm Post subject: Re: Alphablending |
|
|
| Quote: | BlendLine(TmpLine, Bitmap.ScanLine[I], Bitmap.Width * 3);
|
You'll likely gain some more in the MMX variant if you replace
Bitmap.ScanLine[I]
with (typecasts left out for clarity)
scanLine := Bitmap.ScanLine[0];
scanLineDelta := Bitmap.ScanLine[1]-scanLine;
and in the loop
Inc(scanLine, scanLineDelta);
Eric |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|