[英]Stretchdraw on TPNGImage
當我使用位圖調用canvas.stretchdraw時,從左到右的位圖將被鏡像/翻轉。 對於PNG,這不會發生。 這是錯誤嗎? 我該如何解決?
要復制,請嘗試以下代碼:
procedure TForm1.TestStretchdraw;
var
vBMP: TBitmap;
vPNG: TPNGImage;
X0,Y0,X1,Y1 : integer;
R : TRect;
procedure FlipRect;
var
T : integer;
begin
T := R.Left;
R.Left := R.Right;
R.Right := T;
end;
begin
vBMP := TBitmap.Create;
vPNG := TPNGImage.Create;
try
vBMP.LoadFromFile('c:\temp\pic\pic.bmp');
vPNG.LoadFromFile('c:\temp\pic\pic.png');
X0 := 0;
Y0 := 0;
X1 := X0 + vBMP.Width;
Y1 := Y0 + vBMP.Height;
R := Rect(X0,Y0,X1,Y1);
FlipRect;
Canvas.StretchDraw(R,vBMP); //This image will be drawn mirrored
X0 := vBMP.Width+10;
Y0 := 0;
X1 := X0 + vPNG.Width;
Y1 := Y0 + vPNG.Height;
R := Rect(X0,Y0,X1,Y1);
FlipRect;
Canvas.StretchDraw(R,vPNG); //This will not
finally
vPNG.Free;
vBMP.Free;
end;
end;
(但是用自己的一些替換我的testimages)
在這里,我編寫了一個函數,該函數無需任何類似Gr32的庫即可翻轉png。 透明度保留在翻轉的PNG中。
procedure FlipPNG(aSource, aDest: TPngImage);
var
X, Y: Integer;
AlphaPtr: PByteArray;
RGBLine: pRGBLine;
PalleteLine: PByteArray;
AlphaPtrDest: PByteArray;
RGBLineDest: pRGBLine;
PalleteLineDest: PByteArray;
begin
aDest.Assign(aSource);
if (aSource.Header.ColorType = COLOR_PALETTE) or
(aSource.Header.ColorType = COLOR_GRAYSCALEALPHA) or
(aSource.Header.ColorType = COLOR_GRAYSCALE) then
begin
for y := 0 to aSource.Height - 1 do
begin
AlphaPtr := aSource.AlphaScanline[y];
PalleteLine := aSource.Scanline[y];
AlphaPtrDest := aDest.AlphaScanline[y];
PalleteLineDest := aDest.Scanline[y];
for x := 0 to aSource.Width - 1 do
begin
PalleteLineDest^[aSource.Width - x -1] := PalleteLine^[x];
if Assigned(AlphaPtr) then
AlphaPtrDest^[aSource.Width - x -1] := AlphaPtr^[x];
end;
end;
end else
if (aSource.Header.ColorType = COLOR_RGBALPHA) or
(aSource.Header.ColorType = COLOR_RGB) then
begin
for y := 0 to aSource.Height - 1 do
begin
AlphaPtr := aSource.AlphaScanline[y];
RGBLine := aSource.Scanline[y];
AlphaPtrDest := aDest.AlphaScanline[y];
RGBLineDest := aDest.Scanline[y];
for x := 0 to aSource.Width - 1 do
begin
RGBLineDest^[aSource.Width - x -1] := RGBLine^[x];
if Assigned(AlphaPtr) then
AlphaPtrDest^[aSource.Width - x -1] := AlphaPtr^[x];
end;
end;
end;
end;
是的,這是正確的。 StretchDraw
調用TGraphic
的適當后代的Draw
方法。 您可以自己比較TBitmap.Draw
和TPngImage.Draw
。 TBitmap.Draw
自然會簡單地調用Windows API函數StretchBlt
。 TPngImage.Draw
但是,首先調用AdjustRect
:
procedure AdjustRect(var Rect: TRect);
var
t: Integer;
begin
if Rect.Right < Rect.Left then
begin
t := Rect.Right;
Rect.Right := Rect.Left;
Rect.Left := t;
end;
if Rect.Bottom < Rect.Top then
begin
t := Rect.Bottom;
Rect.Bottom := Rect.Top;
Rect.Top := t;
end
end;
如您所見,它無情地撤消了您對left
和right
交換。
我不會考慮這樣的情況,其中Left
大於Right
,這是一個有效的矩形定義,所以我的答案是:不要那樣稱呼它。 您可以在調用StretchDraw
之前確保矩形定義有效:
if (R.Left > R.Right) then
Swap (R.Left, R.Right);
if (R.Top> R.Bottom) then
Swap (R.Top, R.Bottom);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.