// Contributed by Thomas Kowalski, th.kowalski@online.de // March 1999 {$R-} // Turn off Range Checking because of ARRAY[0..0] construct below unit Unit7; // The new algorithms are 5 to 8 imes faster (dirty but fast) and they // not need so many memory (if the bitmap very large you have a problem -> // windows must use the swapfile). interface uses Windows, Graphics; procedure SpiegelnHorizontal (Bitmap:TBitmap); procedure SpiegelnVertikal (Bitmap:TBitmap); procedure Drehen90Grad (Bitmap:TBitmap); procedure Drehen270Grad (Bitmap:TBitmap); procedure Drehen180Grad (Bitmap:TBitmap); implementation USES dialogs, Classes, // Rect SysUtils; TYPE EBitmapError = CLASS(Exception); TRGBArray = ARRAY[0..0] OF TRGBTriple; pRGBArray = ^TRGBArray; procedure SpiegelnHorizontal(Bitmap:TBitmap); var i,j,w : INTEGER; RowIn : pRGBArray; RowOut: pRGBArray; begin w := bitmap.width*sizeof(TRGBTriple); Getmem(rowin,w); for j := 0 to Bitmap.Height-1 do begin move(Bitmap.Scanline[j]^,rowin^,w); rowout := Bitmap.Scanline[j]; for i := 0 to Bitmap.Width-1 do rowout[i] := rowin[Bitmap.Width-1-i]; end; bitmap.Assign(bitmap); Freemem(rowin); end; procedure SpiegelnVertikal(Bitmap : TBitmap); var j,w : INTEGER; help : TBitmap; begin help := TBitmap.Create; help.Width := Bitmap.Width; help.Height := Bitmap.Height; help.PixelFormat := Bitmap.PixelFormat; w := Bitmap.Width*sizeof(TRGBTriple); for j := 0 to Bitmap.Height-1 do move(Bitmap.Scanline[j]^,Help.Scanline[Bitmap.Height - 1 - j]^,w); Bitmap.Assign(help); help.free; end; type THelpRGB = packed record rgb : TRGBTriple; dummy : byte; end; procedure Drehen270Grad(Bitmap:TBitmap); var aStream : TMemorystream; header : TBITMAPINFO; dc : hDC; P : ^THelpRGB; x,y,b,h : Integer; RowOut: pRGBArray; BEGIN aStream := TMemoryStream.Create; aStream.SetSize(Bitmap.Height*Bitmap.Width * 4); with header.bmiHeader do begin biSize := SizeOf(TBITMAPINFOHEADER); biWidth := Bitmap.Width; biHeight := Bitmap.Height; biPlanes := 1; biBitCount := 32; biCompression := 0; biSizeimage := aStream.Size; biXPelsPerMeter :=1; biYPelsPerMeter :=1; biClrUsed :=0; biClrImportant :=0; end; dc := GetDC(0); P := aStream.Memory; GetDIBits(dc,Bitmap.Handle,0,Bitmap.Height,P,header,dib_RGB_Colors); ReleaseDC(0,dc); b := bitmap.Height; // rotate h := bitmap.Width; // rotate bitmap.Width := b; bitmap.height := h; for y := 0 to (h-1) do begin rowOut := Bitmap.ScanLine[(h-1)-y]; P := aStream.Memory; // reset pointer inc(p,y); for x := (b-1) downto 0 do begin rowout[x] := p^.rgb; inc(p,h); end; end; aStream.Free; end; procedure Drehen90Grad(Bitmap:TBitmap); var aStream : TMemorystream; header : TBITMAPINFO; dc : hDC; P : ^THelpRGB; x,y,b,h : Integer; RowOut: pRGBArray; BEGIN aStream := TMemoryStream.Create; aStream.SetSize(Bitmap.Height*Bitmap.Width * 4); with header.bmiHeader do begin biSize := SizeOf(TBITMAPINFOHEADER); biWidth := Bitmap.Width; biHeight := Bitmap.Height; biPlanes := 1; biBitCount := 32; biCompression := 0; biSizeimage := aStream.Size; biXPelsPerMeter :=1; biYPelsPerMeter :=1; biClrUsed :=0; biClrImportant :=0; end; dc := GetDC(0); P := aStream.Memory; GetDIBits(dc,Bitmap.Handle,0,Bitmap.Height,P,header,dib_RGB_Colors); ReleaseDC(0,dc); b := bitmap.Height; // rotate h := bitmap.Width; // rotate bitmap.Width := b; bitmap.height := h; for y := 0 to (h-1) do begin rowOut := Bitmap.ScanLine[y]; P := aStream.Memory; // reset pointer inc(p,y); for x := 0 to (b-1) do begin rowout[x] := p^.rgb; inc(p,h); end; end; aStream.Free; end; procedure Drehen180Grad(Bitmap:TBitmap); var i,j : INTEGER; rowIn : pRGBArray; rowOut: pRGBArray; help : TBitmap; begin help := TBitmap.Create; help.Width := Bitmap.Width; help.Height := Bitmap.Height; help.PixelFormat := Bitmap.PixelFormat; // only pf24bit for now FOR j := 0 TO Bitmap.Height - 1 DO BEGIN rowIn := Bitmap.ScanLine[j]; rowOut := help.ScanLine[Bitmap.Height - j - 1]; FOR i := 0 TO Bitmap.Width - 1 DO rowOut[Bitmap.Width - i - 1] := rowIn[i] END; bitmap.assign(help); help.free; end; end.