2007. július 8., vasárnap
How to flip, rotate and mirror bitmaps
Problem/Question/Abstract:
How to flip, rotate and mirror bitmaps
Answer:
You'll have to manually set the bitmap's PixelFormat to pf8bit, pf16bit, pf24bit, or pf32bit before calling these routines. At the end of this page are three wrappers that will call the appropriate routine based on pixel format.
{ ... }
type
TPixel8 = Byte;
TPixel16 = Word;
TPixel24 = packed record
Blue: Byte;
Green: Byte;
Red: Byte;
end;
TPixel32 = LongWord;
function GetBitmapPixelSize(const Bitmap: TBitmap): Integer;
begin
case Bitmap.PixelFormat of
pf8Bit:
Result := 1;
pf16Bit:
Result := 2;
pf24Bit:
Result := 3;
pf32Bit:
Result := 4;
else
Result := 0;
end;
end;
function GetBitmapScanlineSize(const Bitmap: TBitmap): Integer;
var
SL0: Pointer;
SL1: Pointer;
begin
if (Bitmap.Height > 1) then
begin
SL0 := Bitmap.Scanline[0];
SL1 := Bitmap.Scanline[1];
Result := LongInt(SL1) - LongInt(SL0);
end
else
Result := 0;
end;
procedure FlipBitmap_8(const Bitmap: TBitmap);
type
TPixel = TPixel8; {Dependent on Bitmap.PixelFormat}
PPixel = ^TPixel;
var
Buffer: TPixel;
PPixel1: PPixel;
PPixel2: PPixel;
PPixel1Start: PPixel;
PPixel2Start: PPixel;
I: Integer;
J: Integer;
RowSize: Integer;
begin
Assert(GetBitmapPixelSize(Bitmap) = SizeOf(TPixel));
Assert(Bitmap.Height > 0);
RowSize := GetBitmapScanlineSize(Bitmap);
PPixel1Start := Bitmap.Scanline[0];
PPixel2Start := Bitmap.Scanline[Bitmap.Height - 1];
for I := 1 to (Bitmap.Height div 2) do {Ignore middle row}
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to Bitmap.Width do
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Inc(PPixel2);
end;
Inc(LongInt(PPixel1Start), RowSize);
Dec(LongInt(PPixel2Start), RowSize);
end;
end;
procedure FlipBitmap_16(const Bitmap: TBitmap);
type
TPixel = TPixel16; {Dependent on PixelFormat}
PPixel = ^TPixel;
var
Buffer: TPixel;
PPixel1: PPixel;
PPixel2: PPixel;
PPixel1Start: PPixel;
PPixel2Start: PPixel;
I: Integer;
J: Integer;
RowSize: Integer;
begin
Assert(GetBitmapPixelSize(Bitmap) = SizeOf(TPixel));
Assert(Bitmap.Height > 0);
RowSize := GetBitmapScanlineSize(Bitmap);
PPixel1Start := Bitmap.Scanline[0];
PPixel2Start := Bitmap.Scanline[Bitmap.Height - 1];
for I := 1 to (Bitmap.Height div 2) do {Ignore middle row}
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to Bitmap.Width do
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Inc(PPixel2);
end;
Inc(LongInt(PPixel1Start), RowSize);
Dec(LongInt(PPixel2Start), RowSize);
end;
end;
procedure FlipBitmap_24(const Bitmap: TBitmap);
type
TPixel = TPixel24; {Dependent on PixelFormat}
PPixel = ^TPixel;
var
Buffer: TPixel;
PPixel1: PPixel;
PPixel2: PPixel;
PPixel1Start: PPixel;
PPixel2Start: PPixel;
I: Integer;
J: Integer;
RowSize: Integer;
begin
Assert(GetBitmapPixelSize(Bitmap) = SizeOf(TPixel));
Assert(Bitmap.Height > 0);
RowSize := GetBitmapScanlineSize(Bitmap);
PPixel1Start := Bitmap.Scanline[0];
PPixel2Start := Bitmap.Scanline[Bitmap.Height - 1];
for I := 1 to (Bitmap.Height div 2) do {Ignore middle row}
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to Bitmap.Width do
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Inc(PPixel2);
end;
Inc(LongInt(PPixel1Start), RowSize);
Dec(LongInt(PPixel2Start), RowSize);
end;
end;
procedure FlipBitmap_32(const Bitmap: TBitmap);
type
TPixel = TPixel32; {Dependent on PixelFormat.}
PPixel = ^TPixel;
var
Buffer: TPixel;
PPixel1: PPixel;
PPixel2: PPixel;
PPixel1Start: PPixel;
PPixel2Start: PPixel;
I: Integer;
J: Integer;
RowSize: Integer;
begin
Assert(GetBitmapPixelSize(Bitmap) = SizeOf(TPixel));
Assert(Bitmap.Height > 0);
RowSize := GetBitmapScanlineSize(Bitmap);
PPixel1Start := Bitmap.Scanline[0];
PPixel2Start := Bitmap.Scanline[Bitmap.Height - 1];
for I := 1 to (Bitmap.Height div 2) do {Ignore middle row}
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to Bitmap.Width do
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Inc(PPixel2);
end;
Inc(LongInt(PPixel1Start), RowSize);
Dec(LongInt(PPixel2Start), RowSize);
end;
end;
procedure MirrorBitmap_8(const Bitmap: TBitmap);
type
TPixel = TPixel8; {Dependent on PixelFormat}
PPixel = ^TPixel;
var
PPixel1: PPixel;
PPixel2: PPixel;
Buffer: TPixel;
PPixel1Start: PPixel;
PPixel2Start: PPixel;
I: Integer;
J: Integer;
RowSize: Integer;
begin
Assert(GetBitmapPixelSize(Bitmap) = SizeOf(TPixel));
Assert(Bitmap.Height > 0);
RowSize := GetBitmapScanlineSize(Bitmap);
PPixel1Start := Bitmap.Scanline[0];
PPixel2Start := PPixel1Start;
Inc(PPixel2Start, Bitmap.Width - 1);
for I := 1 to Bitmap.Height do
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to (Bitmap.Width div 2) do {Ignore middle column}
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Dec(PPixel2);
end;
Inc(LongInt(PPixel1Start), RowSize);
Inc(LongInt(PPixel2Start), RowSize);
end;
end;
procedure MirrorBitmap_16(const Bitmap: TBitmap);
type
TPixel = TPixel16; {Dependent on PixelFormat}
PPixel = ^TPixel;
var
PPixel1: PPixel;
PPixel2: PPixel;
Buffer: TPixel;
PPixel1Start: PPixel;
PPixel2Start: PPixel;
I: Integer;
J: Integer;
RowSize: Integer;
begin
Assert(GetBitmapPixelSize(Bitmap) = SizeOf(TPixel));
Assert(Bitmap.Height > 0);
RowSize := GetBitmapScanlineSize(Bitmap);
PPixel1Start := Bitmap.Scanline[0];
PPixel2Start := PPixel1Start;
Inc(PPixel2Start, Bitmap.Width - 1);
for I := 1 to Bitmap.Height do
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to (Bitmap.Width div 2) do {Ignore middle column}
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Dec(PPixel2);
end;
Inc(LongInt(PPixel1Start), RowSize);
Inc(LongInt(PPixel2Start), RowSize);
end;
end;
procedure MirrorBitmap_24(const Bitmap: TBitmap);
type
TPixel = TPixel24; {Dependent on PixelFormat}
PPixel = ^TPixel;
var
PPixel1: PPixel;
PPixel2: PPixel;
Buffer: TPixel;
PPixel1Start: PPixel;
PPixel2Start: PPixel;
I: Integer;
J: Integer;
RowSize: Integer;
begin
Assert(GetBitmapPixelSize(Bitmap) = SizeOf(TPixel));
Assert(Bitmap.Height > 0);
RowSize := GetBitmapScanlineSize(Bitmap);
PPixel1Start := Bitmap.Scanline[0];
PPixel2Start := PPixel1Start;
Inc(PPixel2Start, Bitmap.Width - 1);
for I := 1 to Bitmap.Height do
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to (Bitmap.Width div 2) do {Ignore middle column}
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Dec(PPixel2);
end;
Inc(LongInt(PPixel1Start), RowSize);
Inc(LongInt(PPixel2Start), RowSize);
end;
end;
procedure MirrorBitmap_32(const Bitmap: TBitmap);
type
TPixel = TPixel32; {Dependent on PixelFormat}
PPixel = ^TPixel;
var
PPixel1: PPixel;
PPixel2: PPixel;
Buffer: TPixel;
PPixel1Start: PPixel;
PPixel2Start: PPixel;
I: Integer;
J: Integer;
RowSize: Integer;
begin
Assert(GetBitmapPixelSize(Bitmap) = SizeOf(TPixel));
Assert(Bitmap.Height > 0);
RowSize := GetBitmapScanlineSize(Bitmap);
PPixel1Start := Bitmap.Scanline[0];
PPixel2Start := PPixel1Start;
Inc(PPixel2Start, Bitmap.Width - 1);
for I := 1 to Bitmap.Height do
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to (Bitmap.Width div 2) do {Ignore middle column}
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Dec(PPixel2);
end;
Inc(LongInt(PPixel1Start), RowSize);
Inc(LongInt(PPixel2Start), RowSize);
end;
end;
procedure RotateBitmap180_8(const Bitmap: TBitmap);
type
TPixel = TPixel8; {Dependent on PixelFormat}
PPixel = ^TPixel;
var
PPixel1: PPixel;
PPixel2: PPixel;
Buffer: TPixel;
PPixel1Start: PPixel;
PPixel2Start: PPixel;
I: Integer;
J: Integer;
RowSize: Integer;
begin
Assert(GetBitmapPixelSize(Bitmap) = SizeOf(TPixel));
Assert(Bitmap.Height > 0);
RowSize := GetBitmapScanlineSize(Bitmap);
PPixel1Start := Bitmap.Scanline[0];
PPixel2Start := Bitmap.Scanline[Bitmap.Height - 1];
Inc(PPixel2Start, Bitmap.Width - 1);
for I := 1 to (Bitmap.Height div 2) do {Ignore center row for now}
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to Bitmap.Width do
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Dec(PPixel2);
end;
Inc(LongInt(PPixel1Start), RowSize);
Dec(LongInt(PPixel2Start), RowSize);
end;
if (Odd(Bitmap.Height)) then {Process center row}
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to (Bitmap.Width div 2) do {Ignore center pixel}
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Dec(PPixel2);
end;
end;
end;
procedure RotateBitmap180_16(const Bitmap: TBitmap);
type
TPixel = TPixel16; {Dependent on PixelFormat}
PPixel = ^TPixel;
var
PPixel1: PPixel;
PPixel2: PPixel;
Buffer: TPixel;
PPixel1Start: PPixel;
PPixel2Start: PPixel;
I: Integer;
J: Integer;
RowSize: Integer;
begin
Assert(GetBitmapPixelSize(Bitmap) = SizeOf(TPixel));
Assert(Bitmap.Height > 0);
RowSize := GetBitmapScanlineSize(Bitmap);
PPixel1Start := Bitmap.Scanline[0];
PPixel2Start := Bitmap.Scanline[Bitmap.Height - 1];
Inc(PPixel2Start, Bitmap.Width - 1);
for I := 1 to (Bitmap.Height div 2) do {Ignore center row for now}
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to Bitmap.Width do
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Dec(PPixel2);
end;
Inc(LongInt(PPixel1Start), RowSize);
Dec(LongInt(PPixel2Start), RowSize);
end;
if (Odd(Bitmap.Height)) then {Process center row}
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to (Bitmap.Width div 2) do {Ignore center pixel}
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Dec(PPixel2);
end;
end;
end;
procedure RotateBitmap180_24(const Bitmap: TBitmap);
type
TPixel = TPixel24; {Dependent on PixelFormat}
PPixel = ^TPixel;
var
PPixel1: PPixel;
PPixel2: PPixel;
Buffer: TPixel;
PPixel1Start: PPixel;
PPixel2Start: PPixel;
I: Integer;
J: Integer;
RowSize: Integer;
begin
Assert(GetBitmapPixelSize(Bitmap) = SizeOf(TPixel));
Assert(Bitmap.Height > 0);
RowSize := GetBitmapScanlineSize(Bitmap);
PPixel1Start := Bitmap.Scanline[0];
PPixel2Start := Bitmap.Scanline[Bitmap.Height - 1];
Inc(PPixel2Start, Bitmap.Width - 1);
for I := 1 to (Bitmap.Height div 2) do {Ignore center row for now}
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to Bitmap.Width do
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Dec(PPixel2);
end;
Inc(LongInt(PPixel1Start), RowSize);
Dec(LongInt(PPixel2Start), RowSize);
end;
if (Odd(Bitmap.Height)) then {Process center row}
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to (Bitmap.Width div 2) do {Ignore center pixel}
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Dec(PPixel2);
end;
end;
end;
procedure RotateBitmap180_32(const Bitmap: TBitmap);
type
TPixel = TPixel32; {Dependent on PixelFormat}
PPixel = ^TPixel;
var
PPixel1: PPixel;
PPixel2: PPixel;
Buffer: TPixel;
PPixel1Start: PPixel;
PPixel2Start: PPixel;
I: Integer;
J: Integer;
RowSize: Integer;
begin
Assert(GetBitmapPixelSize(Bitmap) = SizeOf(TPixel));
Assert(Bitmap.Height > 0);
RowSize := GetBitmapScanlineSize(Bitmap);
PPixel1Start := Bitmap.Scanline[0];
PPixel2Start := Bitmap.Scanline[Bitmap.Height - 1];
Inc(PPixel2Start, Bitmap.Width - 1);
for I := 1 to (Bitmap.Height div 2) do {Ignore center row for now}
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to Bitmap.Width do
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Dec(PPixel2);
end;
Inc(LongInt(PPixel1Start), RowSize);
Dec(LongInt(PPixel2Start), RowSize);
end;
if (Odd(Bitmap.Height)) then {Process center row}
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 1 to (Bitmap.Width div 2) do {Ignore center pixel}
begin
Buffer := PPixel1^;
PPixel1^ := PPixel2^;
PPixel2^ := Buffer;
Inc(PPixel1);
Dec(PPixel2);
end;
end;
end;
procedure RotateBitmapCW_32(const Bitmap: TBitmap);
type
TPixel = TPixel32; {Dependent on Bitmap.PixelFormat}
PPixel = ^TPixel;
var
NewBitmap: TBitmap;
PPixel1: PPixel;
PPixel2: PPixel;
PPixel1Start: PPixel;
PPixel2Start: PPixel;
I: Integer;
J: Integer;
BitmapRowSize: Integer;
NewBitmapRowSize: Integer;
begin
Assert(GetBitmapPixelSize(Bitmap) = SizeOf(TPixel));
Assert(Bitmap.Height > 0);
Assert(Bitmap.Width > 0);
NewBitmap := TBitmap.Create;
try
NewBitmap.PixelFormat := Bitmap.PixelFormat;
NewBitmap.Height := Bitmap.Width;
NewBitmap.Width := Bitmap.Height;
BitmapRowSize := GetBitmapScanlineSize(Bitmap);
NewBitmapRowSize := GetBitmapScanlineSize(NewBitmap);
PPixel1Start := Bitmap.Scanline[0];
PPixel2Start := NewBitmap.Scanline[0];
Inc(PPixel2Start, NewBitmap.Width - 1);
for I := 0 to (Bitmap.Height - 1) do
begin
PPixel1 := PPixel1Start;
PPixel2 := PPixel2Start;
for J := 0 to (Bitmap.Width - 1) do
begin
PPixel2^ := PPixel1^;
Inc(PPixel1);
Inc(Integer(PPixel2), NewBitmapRowSize);
end;
Inc(Integer(PPixel1Start), BitmapRowSize);
Dec(PPixel2Start);
end;
Bitmap.Assign(NewBitmap);
finally
NewBitmap.Free;
end;
end;
procedure FlipBitmap(const Bitmap: TBitmap);
begin
case Bitmap.PixelFormat of
pf8Bit:
FlipBitmap_8(Bitmap);
pf16Bit:
FlipBitmap_16(Bitmap);
pf24Bit:
FlipBitmap_24(Bitmap);
pf32Bit:
FlipBitmap_32(Bitmap);
else
Assert(False);
end;
end;
procedure MirrorBitmap(const Bitmap: TBitmap);
begin
case Bitmap.PixelFormat of
pf8Bit:
MirrorBitmap_8(Bitmap);
pf16Bit:
MirrorBitmap_16(Bitmap);
pf24Bit:
MirrorBitmap_24(Bitmap);
pf32Bit:
MirrorBitmap_32(Bitmap);
else
Assert(False);
end;
end;
procedure RotateBitmap180(const Bitmap: TBitmap);
begin
case Bitmap.PixelFormat of
pf8Bit:
RotateBitmap180_8(Bitmap);
pf16Bit:
RotateBitmap180_16(Bitmap);
pf24Bit:
RotateBitmap180_24(Bitmap);
pf32Bit:
RotateBitmap180_32(Bitmap);
else
Assert(False);
end;
end;
procedure RotateBitmapCW(const Bitmap: TBitmap);
begin
case Bitmap.PixelFormat of
pf8Bit:
;
pf16Bit:
;
pf24Bit:
;
pf32Bit:
RotateBitmapCW_32(Bitmap);
else
Assert(False);
end;
end;
procedure RotateBitmapCCW(const Bitmap: TBitmap);
begin
case Bitmap.PixelFormat of
pf8Bit:
;
pf16Bit:
;
pf24Bit:
;
pf32Bit:
;
else
Assert(False);
end;
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése