Method for drawing gradient

zhaozj2021-02-08  204

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;

转载请注明原文地址:https://www.9cbs.com/read-2581.html

New Post(0)