{ this functions returns the number of bytes needed to represent 1 pixel
in the current PixelFormat of the bitmap. }
function GetPixelSize(aBitmap: TBitmap): Integer;
var
nBitCount, nMultiplier: Integer;
begin
case aBitmap.PixelFormat of
pfDevice : begin
nBitCount := GetDeviceCaps(aBitmap.Canvas.Handle, BITSPIXEL);
nMultiplier := nBitCount div BitsPerByte;
if (nBitCount mod BitsPerByte)>0 then
begin
Inc(nMultiplier);
end;
end;
pf1bit : nMultiplier := 1;
pf4bit : nMultiplier := 1;
pf8bit : nMultiplier := 1;
pf15bit : nMultiplier := 2;
pf16bit : nMultiplier := 2;
pf24bit : nMultiplier := 3;
pf32bit : nMultiplier := 4;
else
//raise EInvalidPixelFormat.Create('Bitmap pixelformat is unknown.');
nMultiplier := 2;
end;
Result := nMultiplier;
end;
{ this procedure rotates the image counterclockwise by 90 degrees.
i could have made this routine rotate clockwise but doing it in
counter-clockwise is easier and thus less prone to bugs.
what we do here is grab the first scanline and distribute each pixel
along one column of the new image (or in this case new scanlines buffer)
we do this until we run out of scanlines then we are done.}
procedure ImageRotate90(aBitmap: TBitmap);
var
nIdx, nOfs,
x, y, i,
nMultiplier: integer;
nMemWidth, nMemHeight, nMemSize,
nScanLineSize: LongInt;
GetMem(aScnLnBuffer, nMemSize);
try
nScanLineSize := aBitmap.Width * nMultiplier;
GetMem(aScanLine, nScanLineSize);
try
for y := 0 to aBitmap.Height-1 do
begin
Move(aBitmap.ScanLine[y]^, aScanLine^, nScanLineSize);
for x := 0 to aBitmap.Width-1 do
begin
nIdx := ((aBitmap.Width-1) - x) * nMultiplier;
// y component of the dst x component of the dst
nOfs := (x * nMemWidth * nMultiplier) + (y * nMultiplier);
for i := 0 to nMultiplier-1 do
Byte(aScnLnBuffer[nOfs + i]) := aScanLine[nIdx+i];
end;
end;
for y := 0 to nMemHeight-1 do
begin
nOfs := y * nMemWidth * nMultiplier;
Move((@(aScnLnBuffer[nOfs]))^, aBitmap.ScanLine[y]^, nMemWidth * nMultiplier);
end;
ImageRotate90() 이 함수를 호출하면 돌아갈겁니다.
즐프하세요...
{ this functions returns the number of bytes needed to represent 1 pixel
in the current PixelFormat of the bitmap. }
function GetPixelSize(aBitmap: TBitmap): Integer;
var
nBitCount, nMultiplier: Integer;
begin
case aBitmap.PixelFormat of
pfDevice : begin
nBitCount := GetDeviceCaps(aBitmap.Canvas.Handle, BITSPIXEL);
nMultiplier := nBitCount div BitsPerByte;
if (nBitCount mod BitsPerByte)>0 then
begin
Inc(nMultiplier);
end;
end;
pf1bit : nMultiplier := 1;
pf4bit : nMultiplier := 1;
pf8bit : nMultiplier := 1;
pf15bit : nMultiplier := 2;
pf16bit : nMultiplier := 2;
pf24bit : nMultiplier := 3;
pf32bit : nMultiplier := 4;
else
//raise EInvalidPixelFormat.Create('Bitmap pixelformat is unknown.');
nMultiplier := 2;
end;
Result := nMultiplier;
end;
{ this procedure rotates the image counterclockwise by 90 degrees.
i could have made this routine rotate clockwise but doing it in
counter-clockwise is easier and thus less prone to bugs.
what we do here is grab the first scanline and distribute each pixel
along one column of the new image (or in this case new scanlines buffer)
we do this until we run out of scanlines then we are done.}
procedure ImageRotate90(aBitmap: TBitmap);
var
nIdx, nOfs,
x, y, i,
nMultiplier: integer;
nMemWidth, nMemHeight, nMemSize,
nScanLineSize: LongInt;
aScnLnBuffer: PChar;
aScanLine: PByteArray;
begin
nMultiplier := GetPixelSize(ABitmap);
nMemWidth := aBitmap.Height;
nMemHeight := aBitmap.Width;
nMemSize := nMemWidth * nMemHeight * nMultiplier;
GetMem(aScnLnBuffer, nMemSize);
try
nScanLineSize := aBitmap.Width * nMultiplier;
GetMem(aScanLine, nScanLineSize);
try
for y := 0 to aBitmap.Height-1 do
begin
Move(aBitmap.ScanLine[y]^, aScanLine^, nScanLineSize);
for x := 0 to aBitmap.Width-1 do
begin
nIdx := ((aBitmap.Width-1) - x) * nMultiplier;
// y component of the dst x component of the dst
nOfs := (x * nMemWidth * nMultiplier) + (y * nMultiplier);
for i := 0 to nMultiplier-1 do
Byte(aScnLnBuffer[nOfs + i]) := aScanLine[nIdx+i];
end;
end;
aBitmap.Height := nMemHeight;
aBitmap.Width := nMemWidth;
for y := 0 to nMemHeight-1 do
begin
nOfs := y * nMemWidth * nMultiplier;
Move((@(aScnLnBuffer[nOfs]))^, aBitmap.ScanLine[y]^, nMemWidth * nMultiplier);
end;
finally
FreeMem(aScanLine, nScanLineSize);
end;
finally
FreeMem(aScnLnBuffer, nMemSize);
end;
end;