A method of painting gradient, I hope everyone can help me answer this question:
http://www.9cbs.net/expert/topic/490/490274.shtm
(*
---------------principle:----------------
For any linear gradient (which is the most common), the gradient zone defined by the starting point and endpoint
Inside, the RGB component of the pixel is constant for the deflection number of X and Y coordinates. So we can use very small
The price of this binary equation is calculated, and then calculates all the ways to be pushed.
Value.
---------------- Note 1: ----------------
Gradient zone: Parallel straight lines and drawing areas passing through the starting point and end point, and vertical than the two-point connection
The boundaries enclosed in the boundary. Pixels other than this area no longer have gradient.
--------------- Note 2: ----------------
To simplify programming, I use the floating point number for accumulation calculations. In fact, you can use shift operation.
"Zoom in" color value to improve the accuracy of accumulation, then use the shift "narrow" when writing into the bitmap
The value.
---------------test:----------------
This method is debugged under Delphi6. Take re-return 1000 times under DURON800, 1152 x 864
Method test of the average value.
100 x 100: Average is 4ms;
500 x 200: Average is 18ms;
(I am still listening to MP3: P)
*)
Function SsdrawGradient (Acanvas: Tcanvas; ACLIPRECT: TRECT;
FromPoint, Topoint: Tpoint; FromColor, Tocolor: tcolor: boolean;
Type
TSSGRADIENTDIRECTION = (GDEAST, GDWEST, GDNORTH, GDSOUTH, GDOTHER);
VAR
BUF: TBITMAP;
W, H, Y, X, Xoffset, IR, IG, IB, PW, PH: Integer
C1, C2: Tcolor;
R1, G1, B1, R2, G2, B2, BR, BG, BB, Rmax, Rmin, Gmax, Gmin, Bmax, Bmin: byte
KX, KY, KX0, KY0, RX0, GX0, BX0, R0, G0, B0, DRX, DRY, DGX, DGY, DBX, DBY, DR, DG, DB: DOUBLE
P: pbytearray;
Function Getstep (V1, V2, V3: Integer): Double;
Begin
IF v2 = v1
Then Result: = 0
Else Result: = V3 / (V2-V1);
END;
Begin
Result: = FALSE;
IF (fromPoint.y = topoint.y)
AND (fromPoint.x = topoint.x)
.
BUF: = Tbitmap.create;
Try
// Initialization buffer
BUF.PIXELFORMAT: = PF24bit;
W: = WidthofRect (ACLIPRECT);
BUF.WIDTH: = W;
H: = HeightofRect (ACLIPRECT);
BUF.HEIGHT: = H;
/ / In order to prevent the inspection of the operation overflow
IF (W> Screen.width)
OR (H> Screen.height)
.
// Read the RGB value of the gradient start and the end point
C1: = colorTorgb (fromcolor);
C2: = ColorTorgb (Tocolor); R1: = GtrValue (C1);
G1: = getGValue (C1);
B1: = GetBValue (C1);
R2: = GETRVALUE (C2);
G2: = getGvalue (C2);
B2: = GetBValue (C2);
IF r1> r2
THEN
Begin rmin: = r2; rmax: = r1
end
Else
Begin Rmin: = R1; Rmax: = R2
END;
IF g1> g2
THEN
Begin gmin: = g2; gmax: = g1
end
Else
Begin Gmin: = G1; GMAX: = G2
END;
IF B1> B2
THEN
Begin Bmin: = B2; BMAX: = B1
end
Else
Begin Bmin: = B1; BMAX: = B2
END;
PW: = ABS (Topoint.x-fromPoint.x);
PH: = ABS (Topoint.y-fromPoint.y);
KX: = PW / SQRT (pH * pH pw * pw);
KY: = PH / SQRT (pH * pH pw * pw);
// calculate the linear change coefficient of the RGB value relative to the XY axis
DRX: = GetStep (ACLIPRECT.LEFT, ACLIPRECT.RIGHT, ROUND ((R2-R1) * KX);
DRY: = GetStep (ACLIPRECT.TOP, ACLIPRECT.BOTTOM, ROUND ((R2-R1) * KY);
DGX: = GetStep (ACLIPRECT.LEFT, ACLIPRECT.RIGHT, ROUND ((G2-G1) * KX);
DGY: = GetStep (ACLIPRECT.TOP, ACLIPRECT.BOTTOM, ROUND ((G2-G1) * ky);
DBX: = GetStep (ACLIPRECT.LEFT, ACLIPRECT.RIGHT, ROUND ((B2-B1) * KX);
Dby: = getStep (aclipRect.top, acliprect.bottom, round ((b2-b1) * ky);
/ / Calculate the RGB value in the upper left corner of the rectangle, standby
KX0: = getStep (fromPoint.x, topoint.x, frompoint.x);
KY0: = getStep (fromPoint.y, topoint.y, frompoint.y);
R0: = R1 (KX0 KY0) * R2;
G0: = G1 (KX0 KY0) * G2;
B0: = B1 (KX0 KY0) * B2;
// These three variables are the RGB value of each scan line
Rx0: = r0;
GX0: = G0;
BX0: = b0;
For Y: = 0
TO H-1
DO
Begin
Xoffset: = 0;
// DR means the red value of the Double type, other classes
DR: = rx0;
DG: = GX0;
DB: = bx0;
P: = BUF.SCANLINE [Y];
FOR x: = 0
TO W-1
DO
Begin
// IR means integer red value, other classes
// The reason why I must first turn into an integer, because I think the integer is more than the floating point.
// All about ROUND, it is better to do it early ...
Ir: = ROUND (DR);
Ig: = ROUND (DG);
IB: = ROUND (DB);
// BR means a red value of byte type
Br: = max (MIN (Rmax, IR), RMIN); BG: = Max (MIN (Gmax, IG), GMIN);
BB: = Max (MIN (BMAX, IB), BMIN);
/ / Set the RGB value according to the offset
P [Xoffset]: = BB;
P [Xoffset 1]: = BG;
P [Xoffset 2]: = Br;
IF fromPoint.x <> topoint.x
THEN
Begin
// The RGB value of the next pixel is incremented according to certain coefficients, respectively.
DR: = DR DRX;
DG: = DG DGX;
DB: = DB DBX;
END;
/ / Because I defined P is an array of a word, it is incremented "3" here, avoiding multiplication
INC (Xoffset, 3);
END;
IF fromPoint.Y <> topoint.y
THEN
Begin
/ / The first pixel RGB value of the next row is calculated according to the change law of the RGB in the Y-axis direction.
Rx0: = rx0 DRY;
GX0: = GX0 DGY;
BX0: = BX0 DBY;
END;
END;
// copy the buffer to the target
Bitblt (Acanvas.Handle, ACLIPRECT.LEFT, ACLIPRECT.TOP, W, H,
Buf.canvas.handle, 0, 0, srcopy;
RESULT: = TRUE;
Finally
BUF.FREE;
END;
END;