Delphi Image Processing-Image Color Mixing

Source: Internet
Author: User

Reading Tips:

Delphi Image ProcessingThe series focuses on efficiency. The general code is Pascal, and the core code is BaSm.

The C ++ image processing series focuses on code clarity and readability, all using 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.

 

Photoshop provides a rich set of Image Layer blending modes. The color blending mode is to mix the brightness of the layer image with the layer filled color or image color, the gray level of the lower-layer image is retained. Based on this hybrid feature, the color mixing mode is often used to color the grayscale image.

In C ++ Image Processing-image color mixing (I), c ++ Image Processing-image color mixing (medium), and 《C ++ Image Processing-image color mixing (bottom)I have introduced the principles, algorithm optimization, and code improvement methods of image color mixing in many articles, so I will not introduce them here. I will directly post the delpha implementation code (BaSm) and examples. Due to the long BaSm assembly code, the image black and white adjustment and grayscale image dyeing functions in the C ++ version of the color mixing article are prepared for another article.

Image Color Mixing implementation code:

Procedure _ setmixermm; ASM pxor mm7, mm7 mov eax, 1011 h movd mm6, eax pshufw mm6, mm6, 0 mov eax, 8 movd MM5, eax pshufw MM5, MM5, 0end; // --> mm7 4 * word = 0 // --> mm6 4 * word = 0x1101 // --> MM5 4 * word = 4 // --> eax source alpha/ /--> ESI source pixel (argb) // --> edi dest pixel (argb) // <-- eax DEST Alpha !!! // <-- Mm0 DEST pixelprocedure _ pargbmixer (srcalpha: integer); ASM push edX movd mm0, [esi] movd MM1, [EDI] punpcklbw mm0, mm7 punpcklbw MM1, mm7 // DeST. RGB = DeST. RGB * DeST. alpha/255 movzx edX, [EDI]. targbquad. alpha pmullw MM1, qword PTR argbtab [edX * 8] pmulhuw MM1, mm6 paddusw MM1, MM5 psrlw MM1, 4 // DeST. RGB = (DEST. RGB * 255 + (source. RGB-Dest. RGB) * sourec. alpha)/255 psubw mm0, MM1 pmullw mm0, qword PTR argbtab [eax * 8] pmullw MM1, qword PTR argbtab [255*8] paddw mm0, MM1 pmulhuw mm0, mm6 paddusw mm0, MM5 psrlw mm0, 4 // DeST. alpha + = (source. alpha-(DEST. alpha * Source. alpha + 127)/255) Push eax add [esp], EDX imul eax, EDX add eax, 127 Mul dword ptr divtab [255*4] Pop eax sub eax, edX // DeST. RGB = DeST. RGB * 255/DeST. alpha movq MM1, mm0 psllw mm0, 8 psubw mm0, MM1 pmulhuw mm0, qword PTR mmdivtab [eax * 8] packuswb mm0, mm7 pop edxend; // --> mm7 4 * word = 0 // --> eax source Alpha // --> ESI source pixel (argb) // --> edi dest pixel (argb) // <-- mm0 DEST pixel (RGB) procedure _ argbmixer (srcalpha: integer); ASM movd mm0, [esi] movd MM1, [EDI] punpcklbw mm0, mm7 punpcklbw MM1, mm7 psubw mm0, MM1 pmullw mm0, qword PTR argbtab [eax * 8] psllw MM1, 8 paddw mm0, MM1 psrlw mm0, 8 packuswb mm0, mm0end; const bwdefault: array [0 .. 5] of integer = (410,614,410,819,205,614); grayconst: array [0 .. 2] of integer = (113,604,307); // eax, EDX, ECx = R, G, B ESI, SDI, EBX = rindex, gindex, bindexprocedure comparergb; ASM CMP eax, ECX Jae @ 1 xchg eax, ECx xchg ESI, EBX @ 1: CMP eax, EDX Jae @ 2 xchg eax, EDX xchg ESI, EDI @ 2: CMP ECx, edX jbe @ 3 xchg ECx, EDX xchg EBX, EDI @ 3: end; // In: EDI = pixel // out: eax = bwgrayprocedure getbwgray; ASM push ESI push EDI movzx ECx, [EDI]. targbquad. blue movzx edX, [EDI]. targbquad. green movzx eax, [EDI]. targbquad. red mov EBX, 4 // blue index mov EDI, 2 // green index xor esi, ESI // red index call comparergb // comparergb (red, green, blue) sub eax, edX // max-mid sub edX, ECx // mid-min add EDI, ESI dec EDI imul eax, bwdefault [ESI * 4]. integer imul edX, bwdefault [EDI * 4]. integer add eax, EDX // gray = (max-mid) * Params [maxindex] + Add eax, 512 // (mid-min) * Params [maxindex + midindex-1] + SAR eax, 10 // 512)> 10) + min add eax, ECx pop EDI pop esiend; // in: ESI = srcpixel, EDI = dstpixel, eax = gray // out: [EDI] = mixercolorprocedure colormix; var gray, max_min: longword; ASM push ESI push EDI mov gray, eax movzx ECx, [esi]. targbquad. blue movzx edX, [esi]. targbquad. green movzx eax, [esi]. targbquad. red xor ebx, EBX // blue index mov EDI, 1 // green index mov ESI, 2 // red index call comparergb // comparergb (red, green, blue) sub eax, ECX // max-min jnz @ 4 pop EDI mov eax, gray mov [EDI]. targbquad. blue, Al mov [EDI]. targbquad. green, Al mov [EDI]. targbquad. red, Al JMP @ exit @ 4: Sub edX, ECx // mid-min mov max_min, eax mov ECx, eax sub eax, EDX imul eax, grayconst [EDI * 4]. integer imul ECx, grayconst [EBX * 4]. integer add eax, ECx add eax, 512 // Nmax = gray + SHR eax, 10 // (max_min-mid_min) * grayconst [midindex] + Add eax, gray // max_min * grayconst [minindex] CMP eax, 255 ja @ 5 mov ECx, eax sub ECx, max_min // Nmin = Nmax-max_min JS @ 6 Add edX, ECX // nmid = Nmin + mid_min JMP @ 8 @ 5: // Nmax> 255 SHL edX, 10 // huecoef = (mid_min <10)/max_min mov eax, max_min xchg eax, EDX Mul divtab [edX * 4]. integer push edX mov ECx, grayconst [EDI * 4]. integer imul edX, ECx SHR edX, 10 // V0 = (YS [mid. index] * huecoef)> 10 Add ECx, grayconst [EBX * 4]. integer sub ECx, EDX // V1 = ys [mid. index] + ys [Min. index]-V0 add edX, grayconst [ESI * 4]. integer mov eax, edx shl edX, 8 sub edX, eax mov eax, gray SHL eax, 10 sub eax, EDX mov edX, ECx SHR edX, 1 add eax, edX Mul divtab [ECx * 4]. integer mov ECx, EDX // Nmin = (gray <10)-(YS [Max. index] + V0) * Pop eax // 255 + (V1> 1)/V1 XOR edX, 255 imul edX, eax add edX, 512 SHR edX, 10 Add edX, ECX // nmid = Nmin + (255 ^ newmin) * huecoef + 512)> 10) mov eax, 255 // Nmax = 255 JMP @ 8 @ 6: // Nmin <0 SHL edX, 10 // huecoef = (mid_min <10)/max_min mov eax, max_min xchg eax, EDX Mul divtab [edX * 4]. integer push edX imul edX, grayconst [EDI * 4]. integer add edX, 512 SHR edX, 10 // TMP = ys [Max. index] + (YS [mid. index] * huecoef + 512)> 10) add edX, grayconst [ESI * 4]. integer mov eax, gray SHL eax, 10 mov ECx, edx shr edX, 1 add eax, EDX Mul divtab [ECx * 4]. integer mov eax, EDX // Nmax = (gray <10) + (TMP> 1)/tmp pop edX imul edX, eax add edX, 512 SHR edX, 10 // nmid = (Nmax * huecoef + 512)> 10 mov ECx, 1 // Nmin = 1 @ 8: mov ah, DL pop edX mov [edX + esi], Al mov [edX + EDI], Ah mov [edX + EBX], CL mov EDI, EDX @ Exit: Pop esiend; procedure _ docolormixer (var dest: timagedata; const Source: timagedata; Alpha: integer); var width, height, dstoffset, srcoffset: integer; DST, Src: longword; alphai: integer; ASM push ESI push EDI push EBX mov alphai, ECx mov Cl, [eax]. timagedata. alphaflag mov CH, [edX]. timagedata. alphaflag and [edX]. timagedata. alphaflag, CL push ECx call _ setcopyregs mov width, ECx mov height, EDX mov srcoffset, eax mov dstoffset, EBX pop ECx CMP alphai, 256 JNE @ mixera cmp ch, true je @ mixera CMP Cl, true je @ mixerb @ yloop: Push width @ xloop: Call getbwgray call colormix add ESI, 4 Add EDI, 4 Dec width jnz @ xloop pop width add ESI, srcoffset add EDI, dstoffset dec height jnz @ yloop JMP @ end @ mixera: CMP Cl, true je @ mixerb pxor mm7, mm7 @ yloopa: Push width @ xloopa: movzx eax, [esi]. targbquad. alpha Mul alphai SHR eax, 8 JZ @ nexta push ESI push EDI push eax mov eax, [EDI] mov DST, eax Lea EDI, DST call getbwgray // get DEST blackwhite gray call colormix // DST = source. HS mixer DeST. gray mov ESI, EDI pop eax // mixalpha = source. alpha * alpha/256 pop EDI call _ argbmixer // DeST. RGB = DST. RGB mixer DeST. RGB movd [EDI], mm0 mov [EDI]. targbquad. alpha, 255 pop ESI @ nexta: Add ESI, 4 Add EDI, 4 Dec width jnz @ xloopa pop width add ESI, srcoffset add EDI, dstoffset dec height jnz @ yloopa Emms JMP @ end @ mixerb: Call _ setmixermm @ yloopb: Push width @ xloopb: movzx eax, [esi]. targbquad. alpha Mul alphai SHR eax, 8 JZ @ nextb test [EDI]. targbquad. alpha, 0ffh jnz @ B _1 mov eax, [esi] mov [EDI], eax JMP @ nextb @ B _1: Push ESI push EDI push eax mov eax, [esi] mov SRC, eax mov eax, [EDI] mov DST, eax Lea EDI, DST call getbwgray // get DEST blackwhite gray call colormix // DST = source. HS mixer DeST. gray mov ESI, EDI pop eax // mixalpha = source. alpha * alpha/256 pop EDI call _ pargbmixer // DST. RGB = DST. RGB mixer DeST. RGB movd [esi], mm0 movzx eax, [EDI]. targbquad. alpha // mixalpha = DeST. alpha Lea EDI, Src call _ pargbmixer // DeST. RGB = DST. RGB mixer source. RGB pop EDI movd [EDI], mm0 mov [EDI]. targbquad. alpha, Al pop ESI @ nextb: Add ESI, 4 Add EDI, 4 Dec width jnz @ xloopb pop width add ESI, srcoffset add EDI, dstoffset dec height jnz @ yloopb Emms @ end: Pop EBX pop EDI pop esiend; // image color mode Mixed Procedure imagecolormixer (var dest: timagedata; const Source: timagedata; ALPHA: single = 1); var alphai: integer; begin alphai: = round (alpha * 256); If alphai <0 Then exit; If alphai> 256 then alphai: = 256; _ docolormixer (DEST, source, alphai); end;

Example 1:

var  source, dest: TGpBitmap;  g: TGpGraphics;  src, dst: TImageData;begin  source := TGpBitmap.Create('..\..\media\Apple.png');  dest := TGpBitmap.Create('..\..\media\xmas_011.png');  g := TGpGraphics.Create(Canvas.Handle);  g.DrawImage(dest, 0, 0);  g.DrawImage(source, dest.Width, 0);  src := LockGpBitmap(source);  dst := LockGpBitmap(dest);  ImageColorMixer(dst, src);//  ImageMixer(dst, src, 0.75);  UnlockGpBitmap(dest, dst);  UnlockGpBitmap(source, src);  g.DrawImage(dest, dst.Width + src.Width, 0);  g.Free;  dest.Free;  source.Free;end;

Example 1:

Example 2:

var  source: TGpBitmap;  dest: TBitmap;  tmp: TJpegImage;  g: TGpGraphics;  src, dst: TImageData;begin  dest := TBitmap.Create;  tmp := TJpegImage.Create;  tmp.LoadFromFile('..\..\media\IMG_9440_mf.jpg');  dest.Assign(tmp);  tmp.Free;  source := TGpBitmap.Create('..\..\media\xmas_011.png');  g := TGpGraphics.Create(Canvas.Handle);  Canvas.Draw(0, 0, dest);  g.DrawImage(source, dest.Width, 0);  dst := GetBitmapData(dest);  src := LockGpBitmap(source);  ImageColorMixer(dst, src);//  ImageMixer(dst, src, 1);  UnlockGpBitmap(source, src);  Canvas.Draw(dst.Width + src.Width, 0, dest);  g.Free;  dest.Free;  source.Free;end;

Example 2:

 

This article only provides the basic color mixing code. To realize the geometric transformation of color mixing, see this series of articles on geometric transformation.

 

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".

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.