BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Alphablending
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Graphics
View previous topic :: View next topic  
Author Message
Roy M Klever
Guest





PostPosted: Mon Oct 16, 2006 8:10 pm    Post subject: Alphablending Reply with quote



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





PostPosted: Mon Oct 16, 2006 10:14 pm    Post subject: Re: Alphablending Reply with quote



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





PostPosted: Mon Oct 16, 2006 11:54 pm    Post subject: Re: Alphablending Reply with quote



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





PostPosted: Tue Oct 17, 2006 12:32 am    Post subject: Re: Alphablending Reply with quote

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





PostPosted: Tue Oct 17, 2006 12:38 am    Post subject: Re: Alphablending Reply with quote

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





PostPosted: Tue Oct 17, 2006 1:04 am    Post subject: Re: Alphablending Reply with quote

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 Smile 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





PostPosted: Tue Oct 17, 2006 3:06 am    Post subject: Re: Alphablending Reply with quote

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





PostPosted: Tue Oct 17, 2006 3:15 am    Post subject: Re: Alphablending Reply with quote

Hi Michael,

Thanks for your suggestion.


Kind Regards
Roy Magne Klever
Back to top
Roy M Klever
Guest





PostPosted: Tue Oct 17, 2006 3:26 am    Post subject: Re: Alphablending Reply with quote

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 Smile 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





PostPosted: Tue Oct 17, 2006 3:33 am    Post subject: Re: Alphablending Reply with quote

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





PostPosted: Tue Oct 17, 2006 5:08 am    Post subject: Re: Alphablending Reply with quote

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





PostPosted: Tue Oct 17, 2006 6:31 pm    Post subject: Re: Alphablending Reply with quote

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





PostPosted: Tue Oct 17, 2006 8:20 pm    Post subject: Re: Alphablending Reply with 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 Smile 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





PostPosted: Tue Oct 17, 2006 9:28 pm    Post subject: Re: Alphablending Reply with quote

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 Smile 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





PostPosted: Tue Oct 17, 2006 9:51 pm    Post subject: Re: Alphablending Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi Graphics All times are GMT
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.