请给一点建议(100分)

  • 主题发起人 李崇文
  • 开始时间

李崇文

Unregistered / Unconfirmed
GUEST, unregistred user!
我想做一个简单的图像编辑工具,只需实现图像的复制、剪切、粘贴、旋转和灰度
处理功能,请问我该如何实现?图像显示采用什么控件最好?说白拉,就是实现Windows
自带的画图工具的部分功能。先给100分作见面礼,等问题答完后,我再另添300大洋
 
你所说的基本功能不需要用控件来做哦
 
只用image 就可以了,再用相关的方法和函数便可实现的。
 
BBS中有很多关于图像的处理。你可以先搜索一下。
这些功能应该不难实现。
 
灰度级处理
procedure Gray(bmp: TBitmap);
var
p: PByteArray;
w: Integer;
i, j: Integer;
begin
bmp.pixelformat := pf24bit;
for i := 0 to bmp.height - 1 do
begin
p := bmp.scanline;
j := 0;
while j < (bmp.width-1) * 3 do
begin
w :=(p[j] * 28 + p[j+1] * 151 + p[j+2]*77);
w := w shr 8;
p[j] := byte(w);
p[j+1] := byte(w);
p[j+2] := byte(w);
inc(j, 3)
end;
end;
end;

**************************
//This function turns a colored Bitmap into Grayshades
uses
Windows, Graphics;

function ConvertBitmapToGrayscale1(const Bitmap: TBitmap): TBitmap;
var
i, j: Integer;
Grayshade, Red, Green, Blue: Byte;
PixelColor: Longint;
begin
with Bitmap do
for i := 0 to Width - 1 do
for j := 0 to Height - 1 do
begin
PixelColor := ColorToRGB(Canvas.Pixels[i, j]);
Red := PixelColor;
Green := PixelColor shr 8;
Blue := PixelColor shr 16;
Grayshade := Round(0.3 * Red + 0.6 * Green + 0.1 * Blue);
Canvas.Pixels[i, j] := RGB(Grayshade, Grayshade, Grayshade);
end;
Result := Bitmap;
end;



procedure ConvertBitmapToGrayscale2(const Bmp: TBitmap);
{From: Pascal Enz, pascal.enz@datacomm.ch }
type
TRGBArray = array[0..32767] of TRGBTriple;
PRGBArray = ^TRGBArray;
var
x, y, Gray: Integer;
Row: PRGBArray;
begin
Bmp.PixelFormat := pf24Bit;
for y := 0 to Bmp.Height - 1 do
begin
Row := Bmp.ScanLine[y];
for x := 0 to Bmp.Width - 1 do
begin
Gray := (Row[x].rgbtRed + Row[x].rgbtGreen + Row[x].rgbtBlue) div 3;
Row[x].rgbtRed := Gray;
Row[x].rgbtGreen := Gray;
Row[x].rgbtBlue := Gray;
end;
end;
end;


procedure ConvertBitmapToGrayscale3(const Bitmap: TBitmap);
type
PPixelRec = ^TPixelRec;
TPixelRec = packed record
B: Byte;
G: Byte;
R: Byte;
Reserved: Byte;
end;
var
X: Integer;
Y: Integer;
P: PPixelRec;
Gray: Byte;
begin
Assert(Bitmap.PixelFormat = pf32Bit);
for Y := 0 to (Bitmap.Height - 1) do
begin
P := Bitmap.ScanLine[Y];
for X := 0 to (Bitmap.Width - 1) do
begin
Gray := Round(0.30 * P.R + 0.59 * P.G + 0.11 * P.B);
// Gray := (P.R shr 2) + (P.R shr 4) + (P.G shr 1) + (P.G shr 4) + (P.B shr 3);
P.R := Gray;
P.G := Gray;
P.B := Gray;
Inc(P);
end;
end;
屏 幕 的 图 象 拷 贝 :

var //变量声明
Fullscreen:Tbitmap;
FullscreenCanvas:TCanvas;
dc:HDC;
//------------------------------------------------------------
DC := GetDC (0); //取得屏幕的 DC,参数0指的是屏幕
FullscreenCanvas := TCanvas.Create; //创建一个CANVAS对象
FullscreenCanvas.Handle := DC; //将屏幕的DC赋给HANDLE
Fullscreen.Canvas.CopyRect
(Rect (0, 0, screen.Width,screen.Height),
fullscreenCanvas,
Rect (0, 0, Screen.Width, Screen.Height));
//把整个屏幕复制到BITMAP中
FullscreenCanvas.Free; //释放CANVAS对象
ReleaseDC (0, DC); //释放DC
//SCREEN对象是DELPHI预先定义的屏幕对象,直接使用就行了。
****************************
下面的代码抓窗口:
procedure ScreenShot(hWindow: HWND; bm: TBitmap);
var
Left, Top, Width, Height: Word;
R: TRect;
dc: HDC;
lpPal: PLOGPALETTE;
begin
{Check if valid window handle}
if not IsWindow(hWindow) then Exit;
{Retrieves the rectangular coordinates of the specified window}
GetWindowRect(hWindow, R);
Left := R.Left;
Top := R.Top;
Width := R.Right - R.Left;
Height := R.Bottom - R.Top;

bm.Width := Width;
bm.Height := Height;
{get the screen dc}
dc := GetDc(0);
if (dc = 0) then
begin
Exit;
end;
{do we have a palette device?}
if (GetDeviceCaps(dc, RASTERCAPS) and
RC_PALETTE = RC_PALETTE) then
begin
{allocate memory for a logical palette}
GetMem(lpPal,
SizeOf(TLOGPALETTE) +
(255 * SizeOf(TPALETTEENTRY)));
{zero it out to be neat}
FillChar(lpPal^,
SizeOf(TLOGPALETTE) +
(255 * SizeOf(TPALETTEENTRY)),
#0);
{fill in the palette version}
lpPal^.palVersion := $300;
{grab the system palette entries}
lpPal^.palNumEntries :=
GetSystemPaletteEntries(dc,
0,
256,
lpPal^.palPalEntry);
if (lpPal^.PalNumEntries <> 0) then
begin
{create the palette}
bm.Palette := CreatePalette(lpPal^);
end;
FreeMem(lpPal, SizeOf(TLOGPALETTE) +
(255 * SizeOf(TPALETTEENTRY)));
end;
{copy from the screen to the bitmap}
BitBlt(bm.Canvas.Handle,
0,
0,
Width,
Height,
Dc,
Left,
Top,
SRCCOPY);
{release the screen dc}
ReleaseDc(0, dc);
end;

// Example: Capture the foreground window:

procedure TForm1.Button1Click(Sender: TObject);
begin
ScreenShot(GetForeGroundWindow, Image1.Picture.Bitmap);
end;
***********************
以下代码抓(X,Y)和指定宽度的屏幕内容,并且能够保存调色板
Most of the screenshot code you will see forgets about
the possibility of a palette.

Here is some code that will take a palette into account (if needed).


procedure ScreenShot(x : integer;
y : integer;
Width : integer;
Height : integer;
bm : TBitMap);
var
dc: HDC;
lpPal : PLOGPALETTE;
begin
{test width and height}
if ((Width = 0) OR
(Height = 0)) then begin
exit;
end;
bm.Width := Width;
bm.Height := Height;
{get the screen dc}
dc := GetDc(0);
if (dc = 0) then begin
exit;
end;
{do we have a palette device?}
if (GetDeviceCaps(dc, RASTERCAPS) AND
RC_PALETTE = RC_PALETTE) then begin
{allocate memory for a logical palette}
GetMem(lpPal,
sizeof(TLOGPALETTE) +
(255 * sizeof(TPALETTEENTRY)));
{zero it out to be neat}
FillChar(lpPal^,
sizeof(TLOGPALETTE) +
(255 * sizeof(TPALETTEENTRY)),
#0);
{fill in the palette version}
lpPal^.palVersion := $300;
{grab the system palette entries}
lpPal^.palNumEntries :=
GetSystemPaletteEntries(dc,
0,
256,
lpPal^.palPalEntry);
if (lpPal^.PalNumEntries <0) then begin
{create the palette}
bm.Palette := CreatePalette(lpPal^);
end;
FreeMem(lpPal, sizeof(TLOGPALETTE) +
(255 * sizeof(TPALETTEENTRY)));
end;
{copy from the screen to the bitmap}
BitBlt(bm.Canvas.Handle,
0,
0,
Width,
Height,
Dc,
x,
y,
SRCCOPY);
{release the screen dc}
ReleaseDc(0, dc);
end;

Joe
******************
下面的代码抓矩形:
function CaptureScreen(const Rect: TRect; const BitDepth: TPixelFormat =
pfDevice): TBitmap;
var
hDC: Windows.HDC;
hDesktop: THandle;
begin
// create and define the bitmap
Result := Graphics.TBitmap.Create;

try
case BitDepth of
pfCustom, pfDevice:
Result.PixelFormat := pfDevice;
else
Result.PixelFormat := BitDepth;
end;

Result.Width := Rect.Right - Rect.Left;
Result.Height := Rect.Bottom - Rect.Top;

hDesktop := GetDeskTopWindow();
hDC := GetDC(hDesktop);
try
BitBlt(Result.Canvas.Handle, 0, 0, Result.Width, Result.Height, hDC,
Rect.Left, Rect.Top, SRCCOPY);
finally
ReleaseDC(hDesktop, hDC);
end;

except
FreeAndNil(Result);
end;
创建一个位图:
procedure TForm1.Button1Click(Sender: TObject);
var
x,y : integer;
BitMap : TBitMap;
lplogpal:pMaxLogPalette;//pointer of TMaxLogPalette
p:pByteArray;
begin
BitMap := TBitMap.create;
Bitmap.Width:=256;
Bitmap.Height:=256;
Bitmap.PixelFormat:= pf8bit;
GetMem(lpLogPal,sizeof(TLOGPALETTE) + ((255) * sizeof(TPALETTEENTRY)));
lpLogPal.palVersion := $0300;
lpLogPal.palNumEntries := 256;
for x := 0 to 255 do
begin
lpLogPal.palPalEntry[x].peRed := x;
lpLogPal.palPalEntry[x].peGreen := x;
lpLogPal.palPalEntry[x].peBlue := x;
end;
Bitmap.Palette := CreatePalette(pLogPalette(lpLogPal)^);
FreeMem(lpLogPal,sizeof(TLOGPALETTE) + ((255) * sizeof(TPALETTEENTRY)));
for y := 0 to BitMap.Height -1 do
begin
P := BitMap.ScanLine[y];
for x := 0 to BitMap.Width -1 do
P[x] := Byte(x*y);
end;
canvas.draw(0,0,BitMap);//form.canvas, just for a look:)
end;

**********************
创建位图


One way to create a bitmap from a pixel array is to use the
Windows API function CreateDiBitmap(). This will allow you to
use one of many device independent bitmap formats that Windows
uses to store your pixel data. This has the advantage that it
will work on any Windows system, without knowing the pixel
format that the device uses ahead of time. Properly executed by
optimizing your code, theCreateDiBitmap function can be quite
fast as well. The following example creates a 256 color bitmap
from a pixel array. The bitmap fades from white to black using
256 gray shades. Note that normally, Windows reserves the first
and last ten colors for use as system colors, so you may only
get a maximum of 236 gray shades.

{$IFNDEF WIN32}
type
{Used for pointer math under Win16}
PPtrRec = ^TPtrRec;
TPtrRec = record
Lo: Word;
Hi: Word;
end;
{$ENDIF}

{Used for huge pointer math}

function GetBigPointer(lp: pointer;
Offset: Longint): Pointer;
begin
{$IFDEF WIN32}
GetBigPointer := @PByteArray(lp)^[Offset];
{$ELSE}
Offset := Offset + TPtrRec(lp).Lo;
GetBigPointer := Ptr(TPtrRec(lp).Hi + TPtrRec(Offset).Hi *
SelectorInc,
TPtrRec(Offset).Lo);
{$ENDIF}
end;

procedure TForm1.Button1Click(Sender: TObject);
var
hPixelBuffer : THandle; {Handle to the pixel buffer}
lpPixelBuffer : pointer; {pointer to the pixel buffer}
lpPalBuffer : PLogPalette; {The palette buffer}
lpBitmapInfo : PBitmapInfo; {The bitmap info header}
BitmapInfoSize : longint; {Size of the bitmap info header}
BitmapSize : longint; {Size of the pixel array}
PaletteSize : integer; {Size of the palette buffer}
i : longint; {loop variable}
j : longint; {loop variable}
OldPal : hPalette; {temp palette}
hPal : hPalette; {handle to our palette}
hBm : hBitmap; {handle to our bitmap}
Bm : TBitmap; {temporary TBitmap}
Dc : hdc; {used to convert the DOB to a DDB}
IsPaletteDevice : bool;
begin
Application.ProcessMessages;
{If range checking is on - turn it off for now}
{we will remember if range checking was on by defining}
{a define called CKRANGE if range checking is on.}
{We do this to access array members past the arrays}
{defined index range without causing a range check}
{error at runtime. To satisfy the compiler, we must}
{also access the indexes with a variable. ie: if we}
{have an array defined as a: array[0..0] of byte,}
{and an integer i, we can now access a[3] by setting}
{i := 3; and then accessing a without error}
{$IFOPT R+}
{$DEFINE CKRANGE}
{$R-}
{$ENDIF}

{Lets check to see if this is a palette device - if so, then}
{we must do palette handling for a successful operation.}
{Get the screen's dc to use since memory dc's are not reliable}
dc := GetDc(0);
IsPaletteDevice :=
GetDeviceCaps(dc, RASTERCAPS) and RC_PALETTE = RC_PALETTE;
{Give back the screen dc}
dc := ReleaseDc(0, dc);

{The bitmap info size must be the size of the BitmapInfo}
{plus the size of the color table - one color table entry}
{is already defined in TBitmapInfo}
BitmapInfoSize := sizeof(TBitmapInfo) + (sizeof(TRGBQUAD) * 255);

{The bitmap size must be the width of the bitmap rounded}
{up to the nearest 32 bit boundary}
BitmapSize := (sizeof(byte) * 256) * 256;

{The size of the palette must be the size of a TLogPalette}
{plus the number of color palette entries - 1, since there}
{is already one palette entry defined in TLogPalette}
if IsPaletteDevice then
PaletteSize := sizeof(TLogPalette) + (sizeof(TPaletteEntry) * 255);

{Get the memory for the BitmapInfo, the PixelBuffer, and the Palette}
GetMem(lpBitmapInfo, BitmapInfoSize);
hPixelBuffer := GlobalAlloc(GHND, BitmapSize);
lpPixelBuffer := GlobalLock(hPixelBuffer);

if IsPaletteDevice then
GetMem(lpPalBuffer, PaletteSize);

{Zero out the BitmapInfo, the PixelBuffer, and the Palette}
FillChar(lpBitmapInfo^, BitmapInfoSize, #0);
FillChar(lpPixelBuffer^, BitmapSize, #0);
if IsPaletteDevice then
FillChar(lpPalBuffer^, PaletteSize, #0);

{Fill in the BitmapInfo structure}
lpBitmapInfo^.bmiHeader.biSize := sizeof(TBitmapInfoHeader);
lpBitmapInfo^.bmiHeader.biWidth := 256;
lpBitmapInfo^.bmiHeader.biHeight := 256;
lpBitmapInfo^.bmiHeader.biPlanes := 1;
lpBitmapInfo^.bmiHeader.biBitCount := 8;
lpBitmapInfo^.bmiHeader.biCompression := BI_RGB;
lpBitmapInfo^.bmiHeader.biSizeImage := BitmapSize;
lpBitmapInfo^.bmiHeader.biXPelsPerMeter := 0;
lpBitmapInfo^.bmiHeader.biYPelsPerMeter := 0;
lpBitmapInfo^.bmiHeader.biClrUsed := 256;
lpBitmapInfo^.bmiHeader.biClrImportant := 256;

{Fill in the BitmapInfo color table with gray shades: black to white}
for i := 0 to 255 do
begin
lpBitmapInfo^.bmiColors.rgbRed := i;
lpBitmapInfo^.bmiColors.rgbGreen := i;
lpBitmapInfo^.bmiColors.rgbBlue := i;
end;

{Fill in the pixel buffer array with shades: black to white}
{In a 256 color bitmap the color is an index into the color table}
for i := 0 to 255 do
for j := 0 to 255 do
Byte(GetBigPointer(lpPixelBuffer, i + (j * 256))^) := j;

{Fill in the palette structure}
if IsPaletteDevice then
begin
lpPalBuffer^.palVersion := $300;
lpPalBuffer^.palNumEntries := 256;
{Fill in the palette structure color table}
for i := 0 to 255 do
begin
lpPalBuffer^.PalPalEntry.peRed := i;
lpPalBuffer^.PalPalEntry.peGreen := i;
lpPalBuffer^.PalPalEntry.peBlue := i;
end;

{Create a palette}
hPal := CreatePalette(lpPalBuffer^);
end;

{Get the screen's dc to use for the conversion since}
{memory dc's are not reliable to use for conversions}
dc := GetDc(0);

if IsPaletteDevice then
begin
{If we are using a palette, it must be}
{selected into the dc during the conversion}
OldPal := SelectPalette(dc, hPal, TRUE);
{Realize the palette}
RealizePalette(dc);
end;

{Do the conversion}
hBm := CreateDiBitmap(dc,
lpBitmapInfo^.bmiHeader,
CBM_INIT,
pChar(lpPixelBuffer),
lpBitmapInfo^,
DIB_RGB_COLORS);

if IsPaletteDevice then
begin
{Select the old palette back in}
SelectPalette(dc, OldPal, TRUE);
{Realize the old palette}
RealizePalette(dc);
end;

{Give back the screen dc}
dc := ReleaseDc(0, dc);

{Create a temporory TBitmap}
bm := TBitmap.Create;

{Free up the memory we used}
if IsPaletteDevice then
FreeMem(lpPalBuffer, PaletteSize);
GlobalUnlock(hPixelBuffer);
GlobalFree(hPixelBuffer);
FreeMem(lpBitmapInfo, BitmapInfoSize);

{Assign the palette}
if IsPaletteDevice then
bm.Palette := hPal;

{Assign the handle}
bm.Handle := hBm;

{Size Image1}
Image1.Width := 256;
Image1.Height := 256;

{Assign the bitmap}
Image1.Picture.Bitmap := bm;

SelectPalette(Image1.Picture.Bitmap.Canvas.Handle,
Image1.Picture.Bitmap.Palette,
false);

{Turn range checking back on if it was on when we started}
{$IFDEF CKRANGE}
{$UNDEF CKRANGE}
{$R+}
{$ENDIF}
end;
位图的旋转
http://www.efg2.com/lab/ImageProcessing/RotateScanline.htm

CONST
MaxPixelCount = 32768;

TYPE
TRGBTripleArray = ARRAY[0..MaxPixelCount-1] OF TRGBTriple;
pRGBTripleArray = ^TRGBTripleArray;
...

// "Simple" approach. For pixel (i,j), use "reverse" rotation to find
// where the rotated pixel must have been before the rotation.
// Don't bother with center of pixel adjustment.
// Assumes input BitmapOriginal has PixelFormat = pf24bit.
FUNCTION RotateBitmapMethod1 (CONST BitmapOriginal: TBitmap;
CONST iRotationAxis, jRotationAxis: INTEGER;
CONST AngleOfRotation: DOUBLE {radians} ): TBitmap;

VAR
cosTheta : EXTENDED;
i : INTEGER;
iOriginal : INTEGER;
iPrime : INTEGER;
j : INTEGER;
jOriginal : INTEGER;
jPrime : INTEGER;
RowOriginal: pRGBTripleArray;
RowRotated : pRGBTRipleArray;
sinTheta : EXTENDED;
BEGIN
// The size of BitmapRotated is the same as BitmapOriginal. PixelFormat
// must also match since 24-bit GBR triplets are assumed in ScanLine.
RESULT := TBitmap.Create;
RESULT.Width := BitmapOriginal.Width;
RESULT.Height := BitmapOriginal.Height;
RESULT.PixelFormat := pf24bit; // Force this

// Get SIN and COS in single call from math library
sincos(AngleOfRotation, sinTheta, cosTheta);

// If no math library, then use this:
// sinTheta := SIN(AngleOfRotation);
// cosTheta := COS(AngleOfRotation);

// Step through each row of rotated image.
FOR j := RESULT.Height-1 DOWNTO 0 DO
BEGIN
RowRotated := RESULT.Scanline[j];
jPrime := j - jRotationAxis;

FOR i := RESULT.Width-1 DOWNTO 0 DO
BEGIN
iPrime := i - iRotationAxis;
iOriginal := iRotationAxis + ROUND(iPrime * CosTheta - jPrime * sinTheta);
jOriginal := jRotationAxis + ROUND(iPrime * sinTheta + jPrime * cosTheta);

// Make sure (iOriginal, jOriginal) is in BitmapOriginal. If not,
// assign blue color to corner points.
IF (iOriginal >= 0) AND (iOriginal <= BitmapOriginal.Width-1) AND
(jOriginal >= 0) AND (jOriginal <= BitmapOriginal.Height-1)
THEN BEGIN
// Assign pixel from rotated space to current pixel in BitmapRotated
RowOriginal := BitmapOriginal.Scanline[jOriginal];
RowRotated := RowOriginal[iOriginal]
END
ELSE BEGIN
RowRotated.rgbtBlue := 255; // assign "corner" color
RowRotated.rgbtGreen := 0;
RowRotated.rgbtRed := 0
END

END
END
END {RotateBitmapMethod1};
图象扭曲算法:
procedure Twist(var Bmp, Dst: TBitmap; Amount: integer);
var
fxmid, fymid : Single;
txmid, tymid : Single;
fx,fy : Single;
tx2, ty2 : Single;
r : Single;
theta : Single;
ifx, ify : integer;
dx, dy : Single;
OFFSET : Single;
ty, tx : Integer;
weight_x, weight_y : array[0..1] of Single;
weight : Single;
new_red, new_green : Integer;
new_blue : Integer;
total_red, total_green : Single;
total_blue : Single;
ix, iy : Integer;
sli, slo : PBytearray;

function ArcTan2(xt,yt : Single): Single;
begin
if xt = 0 then
if yt > 0 then
Result := Pi/2
else
Result := -(Pi/2)
else begin
Result := ArcTan(yt/xt);
if xt < 0 then
Result := Pi + ArcTan(yt/xt);
end;
end;

begin
OFFSET := -(Pi/2);
dx := Bmp.Width - 1;
dy := Bmp.Height - 1;
r := Sqrt(dx * dx + dy * dy);
tx2 := r;
ty2 := r;
txmid := (Bmp.Width-1)/2; //Adjust these to move center of rotation
tymid := (Bmp.Height-1)/2; //Adjust these to move ......
fxmid := (Bmp.Width-1)/2;
fymid := (Bmp.Height-1)/2;
if tx2 >= Bmp.Width then tx2 := Bmp.Width-1;
if ty2 >= Bmp.Height then ty2 := Bmp.Height-1;

for ty := 0 to Round(ty2) do begin
for tx := 0 to Round(tx2) do begin
dx := tx - txmid;
dy := ty - tymid;
r := Sqrt(dx * dx + dy * dy);
if r = 0 then begin
fx := 0;
fy := 0;
end
else begin
theta := ArcTan2(dx,dy) - r/Amount - OFFSET;
fx := r * Cos(theta);
fy := r * Sin(theta);
end;
fx := fx + fxmid;
fy := fy + fymid;

ify := Trunc(fy);
ifx := Trunc(fx);
// Calculate the weights.
if fy >= 0 then begin
weight_y[1] := fy - ify;
weight_y[0] := 1 - weight_y[1];
end else begin
weight_y[0] := -(fy - ify);
weight_y[1] := 1 - weight_y[0];
end;
if fx >= 0 then begin
weight_x[1] := fx - ifx;
weight_x[0] := 1 - weight_x[1];
end else begin
weight_x[0] := -(fx - ifx);
Weight_x[1] := 1 - weight_x[0];
end;

if ifx < 0 then
ifx := Bmp.Width-1-(-ifx mod Bmp.Width)
else if ifx > Bmp.Width-1 then
ifx := ifx mod Bmp.Width;
if ify < 0 then
ify := Bmp.Height-1-(-ify mod Bmp.Height)
else if ify > Bmp.Height-1 then
ify := ify mod Bmp.Height;

total_red := 0.0;
total_green := 0.0;
total_blue := 0.0;
for ix := 0 to 1 do begin
for iy := 0 to 1 do begin
if ify + iy < Bmp.Height then
sli := Bmp.scanline[ify + iy]
else
sli := Bmp.scanline[Bmp.Height - ify - iy];
if ifx + ix < Bmp.Width then begin
new_red := sli[(ifx + ix)*3];
new_green := sli[(ifx + ix)*3+1];
new_blue := sli[(ifx + ix)*3+2];
end
else begin
new_red := sli[(Bmp.Width - ifx - ix)*3];
new_green := sli[(Bmp.Width - ifx - ix)*3+1];
new_blue := sli[(Bmp.Width - ifx - ix)*3+2];
end;
weight := weight_x[ix] * weight_y[iy];
total_red := total_red + new_red * weight;
total_green := total_green + new_green * weight;
total_blue := total_blue + new_blue * weight;
end;
end;
slo := Dst.scanline[ty];
slo[tx*3] := Round(total_red);
slo[tx*3+1] := Round(total_green);
slo[tx*3+2] := Round(total_blue);
end;
end;
end;
procedure Twist(var Bmp, Dst: TBitmap; Amount: integer);
这里的Bmp为源位图,Dst为目标位图,Amount为扭曲常数,你可以定义为任意整数,例如100.

 
好的,感谢各位回答,我去试一试
 
看看一些经典的例子,很有启发,特别是象fastbmp等,很多书上也有相关的介绍
 
顶部