请问如何编写一个旋转image中的图像的程序?如旋转90度,180度(50分)

  • 主题发起人 主题发起人 fanxm
  • 开始时间 开始时间
将图象诸点旋转!
 
奉送一个很不错的控件 <a href=/delphi/attachments/fastbmp.zip>TFastBMP</a>.
 
以下代码取自uddf, 可将bmp旋转90度:
procedure RotateBitmap90Degrees(ABitmap: TBitmap);

const
BITMAP_HEADER_SIZE = SizeOf(TBitmapFileHeader) +
SizeOf(TBitmapInfoHeader);

var
{ Things that end in R are for the rotated image. }
PbmpInfoR: PBitmapInfoHeader;
bmpBuffer, bmpBufferR: PByte;
MemoryStream, MemoryStreamR: TMemoryStream;
PbmpBuffer, PbmpBufferR: PByte;
PbmpBufferRFirstScanLine, PbmpBufferColumnZero: PByte;
BytesPerPixel, BytesPerScanLine, BytesPerScanLineR: Integer;
X, Y, T: Integer;

begin
{
Don't *ever* call GetDIBSizes! It screws up your bitmap.
I'll be posting about that shortly.
}

MemoryStream := TMemoryStream.Create;

{
To do: Put in a SetSize, which will eliminate any reallocation
overhead.
}

ABitmap.SaveToStream(MemoryStream);

{
Don't need you anymore. We'll make a new one when the time comes.
}
ABitmap.Free;

bmpBuffer := MemoryStream.Memory;

{ Set PbmpInfoR to point to the source bitmap's info header. }
{ Boy, these headers are getting annoying. }
Inc( bmpBuffer, SizeOf(TBitmapFileHeader) );
PbmpInfoR := PBitmapInfoHeader(bmpBuffer);

{ Set bmpBuffer to point to the original bitmap bits. }
Inc(bmpBuffer, SizeOf(PbmpInfoR^));
{ Set the ColumnZero pointer to point to, uh, column zero. }
PbmpBufferColumnZero := bmpBuffer;

with PbmpInfoR^ do
begin
BytesPerPixel := biBitCount shr 3;
{ ScanLines are DWORD aligned. }
BytesPerScanLine := ((((biWidth * biBitCount) + 31) div 32) * SizeOf(DWORD));
BytesPerScanLineR := ((((biHeight * biBitCount) + 31) div 32) * SizeOf(DWORD));

{ The TMemoryStream that will hold the rotated bits. }
MemoryStreamR := TMemoryStream.Create;
{
Set size for rotated bitmap. Might be different from source size
due to DWORD aligning.
}
MemoryStreamR.SetSize(BITMAP_HEADER_SIZE + BytesPerScanLineR * biWidth);
end;

{ Copy the headers from the source bitmap. }
MemoryStream.Seek(0, soFromBeginning);
MemoryStreamR.CopyFrom(MemoryStream, BITMAP_HEADER_SIZE);

{ Here's the buffer we're going to rotate. }
bmpBufferR := MemoryStreamR.Memory;
{ Skip the headers, yadda yadda yadda... }
Inc(bmpBufferR, BITMAP_HEADER_SIZE);

{
Set up PbmpBufferRFirstScanLine and advance it to end of the first scan
line of bmpBufferR.
}
PbmpBufferRFirstScanLine := bmpBufferR;
Inc(PbmpBufferRFirstScanLine, (PbmpInfoR^.biHeight - 1) * BytesPerPixel);

{ Here's the meat. Loop through the pixels and rotate appropriately. }

{ Remember that DIBs have their origins opposite from DDBs. }
for Y := 1 to PbmpInfoR^.biHeight do
begin
PbmpBuffer := PbmpBufferColumnZero;
PbmpBufferR := PbmpBufferRFirstScanLine;

for X := 1 to PbmpInfoR^.biWidth do
begin
for T := 1 to BytesPerPixel do
begin
PbmpBufferR^ := PbmpBuffer^;
Inc(PbmpBufferR);
Inc(PbmpBuffer);
end;
Dec(PbmpBufferR, BytesPerPixel);
Inc(PbmpBufferR, BytesPerScanLineR);
end;

Inc(PbmpBufferColumnZero, BytesPerScanLine);
Dec(PbmpBufferRFirstScanLine, BytesPerPixel);
end;

{ Done with the source bits. }
MemoryStream.Free;

{ Now set PbmpInfoR to point to the rotated bitmap's info header. }
PbmpBufferR := MemoryStreamR.Memory;
Inc( PbmpBufferR, SizeOf(TBitmapFileHeader) );
PbmpInfoR := PBitmapInfoHeader(PbmpBufferR);

{ Swap the width and height of the rotated bitmap's info header. }
with PbmpInfoR^ do
begin
T := biHeight;
biHeight := biWidth;
biWidth := T;
end;

ABitmap := TBitmap.Create;

{ Spin back to the very beginning. }
MemoryStreamR.Seek(0, soFromBeginning);
ABitmap.LoadFromStream(MemoryStreamR);

MemoryStreamR.Free;
end;
 
刚刚发现<a href=/delphi/attachments/fastbmp.zip>TFastBMP</a> 能:
- 自由缩放图像
- 任意旋转图像
- 锐化 / 钝化图像
- 特殊效果处理 e.g. 马赛克,加杂音点 ...

简直是个小小 Photoshop. With Delphi source ! 速度也不错!

再次推荐.
 
VAR
i: INTEGER;
j: INTEGER;
begin

WITH ImageFrom.Canvas.ClipRect DO
BEGIN
FOR i := Left TO Right DO
BEGIN

FOR j := Top TO Bottom DO
BEGIN
CASE (Sender AS TSpeedButton).Tag OF
0: ImageTo.Canvas.Pixels[i,j] :=
ImageFrom.Canvas.Pixels[i,j];

90: ImageTo.Canvas.Pixels[j,Right-i-1] :=
ImageFrom.Canvas.Pixels[i,j];

180: ImageTo.Canvas.Pixels[Right-i-1,Bottom-j-1] :=
ImageFrom.Canvas.Pixels[i,j];

270: ImageTo.Canvas.Pixels[Bottom-j-1,i] :=
ImageFrom.Canvas.Pixels[i,j]
END
END

END
END
end;
 
fanxm:

这个问题已经很长时间没有人参加讨论,为保持版面
整洁,节约网友时间,请提问者采取必要处理措施。
关于图形图象版管理细则,请参见<a href="http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=111927">这个</a>问题。如两天
内提问者没有响应,我将采取强制措施。

如有管理建议,请到<a href="http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=111927">这里</a>提出。谢谢!
 
多人接受答案了。
 
后退
顶部