Resize StretchBlt vs ScanLines
E' possibile testare la differenza in termini di performance nel fare un resize di un bitmap in memoria tra la StretchBlt e le scanlines ciclando più volte come nell'esempio riportato. Se si può stabilire a priori le dimensioni dei bitmap è consigliabile settare width e height con numeri pari per sfruttare meglio i cicli come riportato in rosso qui sotto.
Type TRGB = packed record
b: byte;
g: byte;
r: byte;
end;
type RGBROW = array[0..Maxint div 16] of TRGB;
type PRGB = ^TRGB;
type PRGBROW = ^RGBROW;
procedure TForm1.GetScreenShot () ;
var
Win: HWND;
DC: HDC;
Bmp,BmpSmall,BmpLarge: TBitmap;
x, y,t: Integer;
zx, zy: Double;
sxarr: array of Integer;
dst_rgb: PRGB;
src_rgb: PRGBROW;
Start: integer;
ScreenshotW : integer;
ScreenshotH : integer;
VideoW : integer;
VideoH : integer;
begin
ScreenshotW := 136;
ScreenshotH := 72;
VideoW := 800;
VideoH := 450;
memo1.Lines.Clear;
DC:= GetWindowDC(GetDesktopWindow);
Bmp := TBitmap.Create;
Bmp.PixelFormat := pf24bit;
Bmp.Height := Screen.Height ;
Bmp.Width :=Screen.Width ;
BitBlt(Bmp.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, DC, 0, 0, SRCCOPY);
BmpSmall := TBitmap.Create;
BmpSmall.Width := ScreenshotW;
BmpSmall.Height := ScreenshotH;
BmpSmall.pixelformat:= pf24bit;
BmpLarge := TBitmap.Create;
BmpLarge.Width := VideoW;
BmpLarge.Height := VideoH;
BmpLarge.pixelformat:= pf24bit;
// Resize Windows
Start:= GetTickCount;
SetStretchBltMode(BmpSmall.Handle,HALFTONE);
for t := 0 to 500 do begin
StretchBlt(BmpSmall.Canvas.Handle,0,0,BmpSmall.Width,BmpSmall.Height, Bmp.Canvas.Handle ,0,0,Bmp.Width,Bmp.Height,SRCCOPY );
end;
memo1.Lines.Add('Test ' + IntTostr(ScreenshotW) +'x'+ IntTostr(ScreenshotH)+' Windows API StretchBlt: ' + IntTostr (GetTickCount -Start));
Start:= GetTickCount;
// Resize manuale senza api di Windows
for t := 0 to 500 do begin
zx := bmp.Width / ScreenshotW;
zy := bmp.Height / ScreenshotH;
SetLength(sxarr, ScreenshotW);
for x := 0 to ScreenshotW - 1 do
sxarr[x] := trunc(x * zx);
for y := 0 to ScreenshotH - 1 do
begin
src_rgb := bmp.Scanline[trunc(y * zy)];
dst_rgb := BmpSmall.Scanline[y];
for x := 0 to BmpSmall.Width - 1 do
begin
dst_rgb^ := src_rgb[sxarr[x]];
inc(dst_rgb);
end;
end;
end;
memo1.Lines.Add('Test ' + IntTostr(ScreenshotW) +'x'+ IntTostr(ScreenshotH)+' Manual Scanlines: ' + IntTostr (GetTickCount -Start));
// Resize Windows
Start:= GetTickCount;
SetStretchBltMode(BmpLarge.Handle,HALFTONE);
for t := 0 to 500 do begin
StretchBlt(BmpLarge.Canvas.Handle,0,0,BmpLarge.Width,BmpLarge.Height, Bmp.Canvas.Handle ,0,0,Bmp.Width,Bmp.Height,SRCCOPY );
end;
memo1.Lines.Add('Test ' + IntTostr(VideoW) +'x'+ IntTostr(VideoH)+' Windows API StretchBlt: ' + IntTostr (GetTickCount -Start));
// Resize manuale senza api di Windows
Start:= GetTickCount;
for t := 0 to 500 do begin
zx := bmp.Width /VideoW;
zy := bmp.Height / VideoH;
SetLength(sxarr, VideoW);
for x := 0 to VideoW - 1 do
sxarr[x] := trunc(x * zx);
for y := 0 to VideoH - 1 do
begin
src_rgb := bmp.Scanline[trunc(y * zy)];
dst_rgb := BmpLarge.Scanline[y];
for x := 0 to BmpLarge.Width - 1 do
begin
dst_rgb^ := src_rgb[sxarr[x]];
inc(dst_rgb);
end;
end;
end;
memo1.Lines.Add('Test ' + IntTostr(VideoW) +'x'+ IntTostr(VideoH)+' Manual Scanlines: ' + IntTostr (GetTickCount -Start));
// Resize manuale senza api di Windows con Width non dispari
Start:= GetTickCount;
for t := 0 to 500 do begin
zx := bmp.Width /VideoW;
zy := bmp.Height / VideoH;
SetLength(sxarr, VideoW);
// for x := 0 to VideoW - 1 do
// sxarr[x] := trunc(x * zx);
for x := 0 to (VideoW - 1 div 2) do begin
sxarr[x] := trunc(x * zx);
sxarr[x+1] := trunc(x+1 * zx);
end;
for y := 0 to VideoH - 1 do
begin
src_rgb := bmp.Scanline[trunc(y * zy)];
dst_rgb := BmpLarge.Scanline[y];
for x := 0 to BmpLarge.Width - 1 do
begin
dst_rgb^ := src_rgb[sxarr[x]];
inc(dst_rgb);
end;
end;
end;
memo1.Lines.Add('Test ' + IntTostr(VideoW) +'x'+ IntTostr(VideoH)+' Even Manual Scanlines : ' + IntTostr (GetTickCount -Start));
Bmp.Free;
ReleaseDC(Win, DC);
end;
Type TRGB = packed record
b: byte;
g: byte;
r: byte;
end;
type RGBROW = array[0..Maxint div 16] of TRGB;
type PRGB = ^TRGB;
type PRGBROW = ^RGBROW;
var
Win: HWND;
DC: HDC;
Bmp,BmpSmall,BmpLarge: TBitmap;
x, y,t: Integer;
zx, zy: Double;
sxarr: array of Integer;
dst_rgb: PRGB;
src_rgb: PRGBROW;
Start: integer;
ScreenshotW : integer;
ScreenshotH : integer;
VideoW : integer;
VideoH : integer;
begin
ScreenshotW := 136;
ScreenshotH := 72;
VideoW := 800;
VideoH := 450;
memo1.Lines.Clear;
DC:= GetWindowDC(GetDesktopWindow);
Bmp := TBitmap.Create;
Bmp.PixelFormat := pf24bit;
Bmp.Height := Screen.Height ;
Bmp.Width :=Screen.Width ;
BitBlt(Bmp.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, DC, 0, 0, SRCCOPY);
BmpSmall := TBitmap.Create;
BmpSmall.Width := ScreenshotW;
BmpSmall.Height := ScreenshotH;
BmpSmall.pixelformat:= pf24bit;
BmpLarge := TBitmap.Create;
BmpLarge.Width := VideoW;
BmpLarge.Height := VideoH;
BmpLarge.pixelformat:= pf24bit;
// Resize Windows
Start:= GetTickCount;
SetStretchBltMode(BmpSmall.Handle,HALFTONE);
for t := 0 to 500 do begin
StretchBlt(BmpSmall.Canvas.Handle,0,0,BmpSmall.Width,BmpSmall.Height, Bmp.Canvas.Handle ,0,0,Bmp.Width,Bmp.Height,SRCCOPY );
end;
memo1.Lines.Add('Test ' + IntTostr(ScreenshotW) +'x'+ IntTostr(ScreenshotH)+' Windows API StretchBlt: ' + IntTostr (GetTickCount -Start));
Start:= GetTickCount;
// Resize manuale senza api di Windows
for t := 0 to 500 do begin
zx := bmp.Width / ScreenshotW;
zy := bmp.Height / ScreenshotH;
SetLength(sxarr, ScreenshotW);
for x := 0 to ScreenshotW - 1 do
sxarr[x] := trunc(x * zx);
for y := 0 to ScreenshotH - 1 do
begin
src_rgb := bmp.Scanline[trunc(y * zy)];
dst_rgb := BmpSmall.Scanline[y];
for x := 0 to BmpSmall.Width - 1 do
begin
dst_rgb^ := src_rgb[sxarr[x]];
inc(dst_rgb);
end;
end;
end;
memo1.Lines.Add('Test ' + IntTostr(ScreenshotW) +'x'+ IntTostr(ScreenshotH)+' Manual Scanlines: ' + IntTostr (GetTickCount -Start));
// Resize Windows
Start:= GetTickCount;
SetStretchBltMode(BmpLarge.Handle,HALFTONE);
for t := 0 to 500 do begin
StretchBlt(BmpLarge.Canvas.Handle,0,0,BmpLarge.Width,BmpLarge.Height, Bmp.Canvas.Handle ,0,0,Bmp.Width,Bmp.Height,SRCCOPY );
end;
memo1.Lines.Add('Test ' + IntTostr(VideoW) +'x'+ IntTostr(VideoH)+' Windows API StretchBlt: ' + IntTostr (GetTickCount -Start));
// Resize manuale senza api di Windows
Start:= GetTickCount;
for t := 0 to 500 do begin
zx := bmp.Width /VideoW;
zy := bmp.Height / VideoH;
SetLength(sxarr, VideoW);
for x := 0 to VideoW - 1 do
sxarr[x] := trunc(x * zx);
for y := 0 to VideoH - 1 do
begin
src_rgb := bmp.Scanline[trunc(y * zy)];
dst_rgb := BmpLarge.Scanline[y];
for x := 0 to BmpLarge.Width - 1 do
begin
dst_rgb^ := src_rgb[sxarr[x]];
inc(dst_rgb);
end;
end;
end;
memo1.Lines.Add('Test ' + IntTostr(VideoW) +'x'+ IntTostr(VideoH)+' Manual Scanlines: ' + IntTostr (GetTickCount -Start));
// Resize manuale senza api di Windows con Width non dispari
Start:= GetTickCount;
for t := 0 to 500 do begin
zx := bmp.Width /VideoW;
zy := bmp.Height / VideoH;
SetLength(sxarr, VideoW);
// for x := 0 to VideoW - 1 do
// sxarr[x] := trunc(x * zx);
for x := 0 to (VideoW - 1 div 2) do begin
sxarr[x] := trunc(x * zx);
sxarr[x+1] := trunc(x+1 * zx);
end;
for y := 0 to VideoH - 1 do
begin
src_rgb := bmp.Scanline[trunc(y * zy)];
dst_rgb := BmpLarge.Scanline[y];
for x := 0 to BmpLarge.Width - 1 do
begin
dst_rgb^ := src_rgb[sxarr[x]];
inc(dst_rgb);
end;
end;
end;
memo1.Lines.Add('Test ' + IntTostr(VideoW) +'x'+ IntTostr(VideoH)+' Even Manual Scanlines : ' + IntTostr (GetTickCount -Start));
Bmp.Free;
ReleaseDC(Win, DC);
end;

Commenti
Posta un commento