Reading Tips:
《Delphi Image ProcessingThe series focuses on efficiency. The general code is Pascal, and the core code is BaSm.
《C ++ Image ProcessingThe series focuses on code clarity and readability, and all uses C ++ code.
Make sure that the two items are consistent and can be compared with each other.
The code in this article must include the imagedata. Pas unit in "Delphi Image Processing-data type and public process.
Image High Fidelity contrast processing is simple. The procedure is as follows:
1. Back up original image data;
2. Perform Gaussian blur on the Image Based on the given radius;
3. Subtract the original pixel from the Gaussian Blur pixel to form a difference;
4. Increase the difference value by 128.
The following is a high-fidelity contrast code, including Gaussian fuzzy code (for details about Gaussian blur, see the article 《Delphi Image Processing-Gaussian blur, The following Gaussian fuzzy code is also copied from this article ):
Procedure crossblur (var dest: timagedata; const Source: timagedata; weights: pointer; radius: integer); var height, srcstride: integer; dstoffset, srcoffset: integer; ASM push ESI push EDI push EBX push ECx mov ECx, [edX]. timagedata. stride mov srcstride, ECx call _ setcopyregs mov height, EDX mov srcoffset, eax mov dstoffset, EBX pop EBX pxor xmm7, xmm7 push ESI // PST = source. scan0 push EDI push edX Push ECx // blur Col mov eax, srcstride mov edX, eax SHR edX, 2 // width = source. width mov EDI, radius shl edi, 1 imul EDI, eax add EDI, ESI // PSB = PST + radius * 2 * Source. stride @ cyloop: Push edX @ cxloop: Push ESI push EDI push EBX mov ECx, radius pxor xmm0, xmm0 // sum = 0 cblurloop: movd xmm1, [esi] // for (I = 0; I <radius; I ++) movd xmm2, [EDI] // {punpcklbw xmm1, xmm7 punpcklbw XMM 2, xmm7 paddw xmm1, xmm2 // PS = PST + psb punpcklwd xmm1, xmm7 cvtdq2ps xmm1, xmm1 // PFS (flaot * 4) = ps (int * 4) mulps xmm1, [EBX] // PFS * = weights [I] addps xmm0, xmm1 // sum + = PFS add EBX, 16 Add ESI, eax // PST + = source. stride sub EDI, eax // PSB-= source. stride loop @ cblurloop //} movd xmm1, [esi] punpcklbw xmm1, xmm7 punpcklwd xmm1, xmm7 cvtdq2ps xmm1, xmm1 // PFS (flaot * 4) = PST (Int * 4) mulps xmm1, [EBX] // PFS * = weights [radius] addps xmm0, xmm1 // sum + = PFS pop EBX pop EDI pop ESI cvtps2dq xmm0, xmm0 // PS (int * 4) = sum (flaot * 4) packssdw xmm0, xmm7 packuswb xmm0, xmm7 movd [esi], xmm0 // PST (byte * 4) = ps (int * 4) pask add ESI, 4 Add EDI, 4 Dec edX jnz @ cxloop pop edX dec height jnz @ cyloop pop edX pop height pop EDI // Pd = DeST. scan0 pop ESI // PSL = PST MoV eax, radius SHL eax, 1 + 2 add eax, ESI // PSR = PSL + radius * 2 // blur row @ ryloop: Push edX // width = DeST. width @ rxloop: Push ESI push EBX push eax mov ECx, radius pxor xmm0, xmm0 // sum = 0 @ rblurloop: movd xmm1, [esi] // for (I = 0; I <radius; I ++) movd xmm2, [eax] // {punpcklbw xmm1, xmm7 punpcklbw xmm2, xmm7 paddw xmm1, xmm2 // PS = PSL + PSR punpcklwd xmm1, xmm7 cvtdq2ps xmm1, xmm1 // PFS (flaot * 4) = ps (int * 4) mulps xmm1, [EBX] // PFS * = weights [I] addps xmm0, xmm1 // sum + = PFS add EBX, 16 Add ESI, 4 // PSL ++ sub eax, 4 // PSR -- loop @ rblurloop //} movd xmm1, [esi] punpcklbw xmm1, xmm7 punpcklwd xmm1, xmm7 cvtdq2ps xmm1, xmm1 // PFS (flaot * 4) = PSL (int * 4) mulps xmm1, [EBX] // PFS * = weights [radius] addps xmm0, xmm1 // sum + = PFS cvtps2dq xmm0, xmm0 // PS (int * 4) = sum (flaot * 4) packssdw xmm0, xmm7 packuswb xmm0, xmm7 movd [EDI], xmm0 // Pd (byte * 4) = ps (int * 4) pask pop eax pop EBX pop ESI add eax, 4 Add ESI, 4 Add EDI, 4 Dec edX jnz @ rxloop add eax, srcoffset add ESI, srcoffset add EDI, dstoffset pop edX dec height jnz @ ryloop pop EBX pop EDI pop esiend; // --> st x // <-- st e ** x = 2 ** (x * log2 (E) function _ expon: extended; ASM fldl2e // y = x * Log2e fmul primary ST (0) // I = round (y) frndint fsub ST (1), St // F = Y-I fxch ST (1) // z = 2 ** F f2xm1 fld1 FADD fscale // result = z * 2 ** I fstp ST (1) end; function getweights (VAR buffer, weights: pointer; q: single; radius: integer): integer; const _ fcd1: single = 0.1; _ FC1: single = 1.0; _ FC2: single = 2.0; _ fc250: single = 250.0; fc_255: single = 255.0; var R: integer; V, qq2: Double; ASM mov R, ECx MoV ECx, eax unzip q fabs fcom _ fcd1 fstsw ax sahf Jae @ 1 then _ fcd1 fstp ST (1) // If (q <0.1) Q = 0.1 JMP @ 2 @ 1: fcom _ fc250 fstsw ax sahf jbe @ 2 then _ fc250 fstp ST (1) // If (q> 250) Q = 250 @ 2: fst q fmul _ FC2 fstp qq2 // qq2 = 2 * Q * q fwait mov eax, r test eax, eax JG @ 10 push eax // If (radius <= 0) fld1 // {fadd q // radius = ABS (q) + 1 fistp [esp]. integer fwait pop eax @ testrad IUS: // while (true) mov R, eax // {fldz // sum = 0 testloop: // For (r = radius; r> 0; r ++) fild R // {limit ST (0) fmulp ST (1), St fdiv qq2 fchs call _ expon // TMP = exp (-(R * r) /(2.0 * Q * q); cmp r, eax JNE @ 3 FST v // If (r = radius) V = TMP @ 3: faddp ST (1), ST (0) // sum + = TMP dec R jnz @ testloop //} fmul _ FC2 // sum * = 2 FADD _ FC1 // sum + = 1 fdivr v fmul _ fc255 fistp R cmp r, 0 je @ 4 // If (INT) (V/SUM * 255 + 0.5) = 0) break Inc eax // radius ++ JMP @ testradius //} @ 4: Dec eax jnz @ 5 Inc eax @ 5: mov R, eax //} @ 10: Inc eax SHL eax, 4 Add eax, 12 push edX push ECx mov edX, eax mov eax, ghnd call globalallocptr pop ECx pop edX test eax, eax JZ @ exit mov [ECx], eax // buffer = globalallocptr (ghnd, (radius + 1) * 16 + 12) add eax, 12 and eax, -16 mov [edX], eax // Wei Ghts = (char *) buffer + 12) & 0xfffffff0 mov ECx, r // ECx = radius mov edX, eax // edX = weights fldz // for (I = radius, sum = 0; I> 0; I --) @ clacloop: // {fild R limit ST (0) fmulp ST (1 ), st fdiv qq2 fchs call _ expon fstp [edX]. double // weights [I] = expon (-(I * I)/(2 * Q * q) FADD [edX]. double // sum + = weights [I] add edX, 16 dec R jnz @ clacloop //} fmul _ FC2 // sum * = 2 fld1 fstp [edX]. Double // weights [radius] = 1 FADD [edX]. double // sum + = weights [radius] Push ECx Inc ECx @ divloop: // for (I = 0; I <= radius; I ++) lead st (0) // weights [I] = round (weights [I]/SUM) fdivr [eax]. double FST [eax]. single FST [eax + 4]. single FST [eax + 8]. single fstp [eax + 12]. single add eax, 16 loop @ divloop Ffree ST (0) fwait pop eax/return radius @ Exit: end; // Gaussian blur. Procedure imagegaussiabblur (VAR data: timagedata; Q: single; radius: integer); var buffer, weights: pointer; SRC: timagedata; begin radius: = getweights (buffer, weights, Q, radius); If radius = 0 Then exit; if data. alphaflag then argbconvertpargb (data); SRC: = _ getexpanddata (data, radius); crossblur (data, SRC, weights, radius); freeimagedata (SRC); globalfreeptr (buffer ); if data. alphaflag then pargbconvertargb (data); end; Procedure dohighpass (var dest: timagedata; const Source: timagedata); ASM push ESI push EDI push EBX pxor mm7, mm7 mov ECx, 128 movd mm6, ECx pshufw mm6, mm6, 0 call _ setcopyregs @ yloop: Push ECx @ xloop: movd mm0, [esi] // mm0 = original pixel movd MM1, [EDI] // MM1 = pixel punpcklbw mm0 after Gaussian blur, mm7 punpcklbw MM1, mm7 psubw mm0, MM1 paddw mm0, mm6 // mm0 = mm0-MM1 + 128 packuswb mm0, mm7 movd [EDI], mm0 add ESI, 3 add EDI, 3 movsb loop @ xloop pop ECx add ESI, eax add EDI, EBX dec edX jnz @ yloop pop EBX pop EDI pop ESI emmsend; // High Fidelity contrast procedure imagehighpass (VAR data: timagedata; radius: single); procedcopyure data (var dest: timagedata; const Source: timagedata); ASM push ESI push EDI mov ECx, [eax]. timagedata. width imul ECx, [eax]. timagedata. height mov EDI, [eax]. timagedata. scan0 mov ESI, [edX]. timagedata. scan0 rep movsd pop EDI pop ESI end; var isinvertscan0: Boolean; SRC: timagedata; begin // back up image data SRC: = newimagedata (data. width, Data. height); isinvertscan0: = data. stride <0; If isinvertscan0 then _ invertscan0 (data); copydata (SRC, data); // use image data as Gaussian Blur imagegaussiabblur (data, radius, 0 ); // use backup image data and Gaussian fuzzy image data for High Fidelity contrast dohighpass (data, Src); freeimagedata (SRC); If isinvertscan0 then _ invertscan0 (data); end;
Simple Example:
procedure TForm1.Button2Click(Sender: TObject);var bmp: TBitmap; data: TImageData;begin bmp := TBitmap.Create; bmp.LoadFromFile('d:\source.bmp'); data := GetBitmapData(bmp); ImageHighPass(Data, 3); Canvas.Draw(0, 0, bmp); bmp.Free;end;
The following figure shows the source image and the running interface of the example:
For details about the use of GDI + units and descriptions in the "Delphi image processing" series, see the article 《GDI + for VCL basics-GDI + and VCL.
Due to limited levels, errors are inevitable. Correction and guidance are welcome. Email Address:Maozefa@hotmail.com
Here, you can access "Delphi Image Processing-Article Index".