Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2013-04

Slow pointer assignments

6 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Leonardo M. Ramé

Hi, this routine copies pixel data from a buffer onto a TBitmap.RawImage.Data structure.

var
  PixelPtr: PByte;
  PixelRowPtr: PByte;
begin
  PixelRowPtr := Fbmp.RawImage.Data;
  for Y := 0 to Self.Height - 1 do
  begin
    PixelPtr := PixelRowPtr;
    for X := 0 to Self.Width - 1 do
    begin
      PixelPtr^ := lRed;
      Inc(PixelPtr, 1);
      PixelPtr^ := lGreen;
      Inc(PixelPtr, 1);
      PixelPtr^ := lBlue;
      Inc(PixelPtr, 1);
      PixelPtr^ := 255;
      Inc(PixelPtr, 1);
    end;
    Inc(PixelRowPtr, FBmp.RawImage.Description.BytesPerLine);
  end;
end;

I've found it's very slow (in terms of milliseconds) when the TBitmap is bigger. What I can do to make it faster?.

P.S.: as you can see, I removed the way lRed, lGreen and lBlue are calculated, because that won't change the overall speed of the routine.

-
Leonardo M. Ram?
http://leonardorame.blogspot.com

Reply by email

leledumbo
to Leonardo M. Ramé

Assign all the RGBA value in one go, that would reduce the inner loop by 4 times. i.e.:

var
  PixelPtr: PLongWord;
  PixelRowPtr: PByte;
begin
  PixelRowPtr := Fbmp.RawImage.Data;
  for Y := 0 to Self.Height - 1 do
  begin
    PixelPtr := PLongWord(PixelRowPtr);
    for X := 0 to (Self.Width - 1) div 4 do
    begin
      PixelPtr^ := (lRed shl 24) or (lGreen shl 16) or (lBlue shl 8) or 255;
      Inc(PixelPtr);
    end;
    Inc(PixelRowPtr, FBmp.RawImage.Description.BytesPerLine);
  end;
end;
View this message in context: http://free-pascal-lazarus.989080.n3.nabble.com/Lazarus-Slow-pointer-assignments-tp4030759p4030762.html Sent from the Free Pascal - Lazarus mailing list .

Reply by email

Leonardo M. Ramé
to leledumbo
leledumbo wrote 20 lines
Assign all the RGBA value in one go, that would reduce the inner loop by 4 times. i.e.: var PixelPtr: PLongWord; PixelRowPtr: PByte; begin PixelRowPtr := Fbmp.RawImage.Data; for Y := 0 to Self.Height - 1 do begin PixelPtr := PLongWord(PixelRowPtr); for X := 0 to (Self.Width - 1) div 4 do begin PixelPtr^ := (lRed shl 24) or (lGreen shl 16) or (lBlue shl 8) or 255; Inc(PixelPtr); end; Inc(PixelRowPtr, FBmp.RawImage.Description.BytesPerLine); end; end;

Great!, I'll try it.

Reply by email

Leonardo M. Ramé
to Leonardo M. Ramé
Leonardo M. Ram? wrote 24 lines
On 2013-04-18 08:48:11 -0700, leledumbo wrote: > Assign all the RGBA value in one go, that would reduce the inner loop by 4 > times. i.e.: > > var > PixelPtr: PLongWord; > PixelRowPtr: PByte; > begin > PixelRowPtr := Fbmp.RawImage.Data; > for Y := 0 to Self.Height - 1 do > begin > PixelPtr := PLongWord(PixelRowPtr); > for X := 0 to (Self.Width - 1) div 4 do > begin > PixelPtr^ := (lRed shl 24) or (lGreen shl 16) or (lBlue shl 8) or 255; > Inc(PixelPtr); > end; > Inc(PixelRowPtr, FBmp.RawImage.Description.BytesPerLine); > end; > end; > Great!, I'll try it.

Well, it's speed improved, but the image is blue... Do you know why?.

Reply by email

Ludo Brands
to Leonardo M. Ramé
Leonardo M. Ram? wrote 28 lines
On 2013-04-18 12:49:07 -0300, Leonardo M. Ram? wrote: > On 2013-04-18 08:48:11 -0700, leledumbo wrote: >> Assign all the RGBA value in one go, that would reduce the inner loop by 4 >> times. i.e.: >> >> var >> PixelPtr: PLongWord; >> PixelRowPtr: PByte; >> begin >> PixelRowPtr := Fbmp.RawImage.Data; >> for Y := 0 to Self.Height - 1 do >> begin >> PixelPtr := PLongWord(PixelRowPtr); >> for X := 0 to (Self.Width - 1) div 4 do >> begin >> PixelPtr^ := (lRed shl 24) or (lGreen shl 16) or (lBlue shl 8) or 255; >> Inc(PixelPtr); >> end; >> Inc(PixelRowPtr, FBmp.RawImage.Description.BytesPerLine); >> end; >> end; >> > > Great!, I'll try it. > Well, it's speed improved, but the image is blue... Do you know why?.

The Longword is saved low byte first on a LE arch. You need to change the order of the colors to
PixelPtr^ := lRed or (lGreen shl 8) or (lBlue shl 16) or ($ff shl 24); Also make sure lRed, etc are bytes. If not use (lRed and $ff) etc.

Ludo

Reply by email

Leonardo M. Ramé
to Ludo Brands
Ludo Brands wrote 36 lines
On 04/18/2013 07:53 PM, Leonardo M. Ram? wrote: > On 2013-04-18 12:49:07 -0300, Leonardo M. Ram? wrote: >> On 2013-04-18 08:48:11 -0700, leledumbo wrote: >>> Assign all the RGBA value in one go, that would reduce the inner loop by 4 >>> times. i.e.: >>> >>> var >>> PixelPtr: PLongWord; >>> PixelRowPtr: PByte; >>> begin >>> PixelRowPtr := Fbmp.RawImage.Data; >>> for Y := 0 to Self.Height - 1 do >>> begin >>> PixelPtr := PLongWord(PixelRowPtr); >>> for X := 0 to (Self.Width - 1) div 4 do >>> begin >>> PixelPtr^ := (lRed shl 24) or (lGreen shl 16) or (lBlue shl 8) or 255; >>> Inc(PixelPtr); >>> end; >>> Inc(PixelRowPtr, FBmp.RawImage.Description.BytesPerLine); >>> end; >>> end; >>> >> >> Great!, I'll try it. >> > > Well, it's speed improved, but the image is blue... Do you know why?. > The Longword is saved low byte first on a LE arch. You need to change the order of the colors to PixelPtr^ := lRed or (lGreen shl 8) or (lBlue shl 16) or ($ff shl 24); Also make sure lRed, etc are bytes. If not use (lRed and $ff) etc. Ludo

Yes!, now it works. Thank you and Leledumbo, it works pretty fast.

Reply by email