Delphi Image Processing-Image Synthesis

Source: Internet
Author: User

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.

 

During image processing, image synthesis is the most frequently used, such as display, image copy, image stitching, and layer combination and superposition.

Image synthesis is actually a mixture of pixel colors. In Photoshop, color mixing is a very complicated thing. different blending modes will produce different synthesis effects, if you thoroughly study all of this, you may have to write a book. Therefore, this article only talks about the most basic image synthesis, that is, the normal mixing mode in Photoshop.

As long as you have been involved in image processing, we all know that there is an image pixel mixing formula:

1) dstrgb = srcrgb * Alpha + dstrgb * (1-alpha)

Dstrgb indicates the pixel value of the target image, srcrgb indicates the pixel value of the source image, and Alpha indicates the blending ratio of the pixel value of the source image (opacity, range: 0-1 ).

In fact, this pixel mixing formula has great limitations and is only suitable for images without Alpha information.

To process a mix of images (layers) with Alpha channels, the complete formula should be:

2-1) srcrgb = srcrgb * srcalpha * alpha/255 (source image pre-multiplication to pargb)

2-2) dstrgb = dstrgb * dstalpha/255 (pre-multiplication of target image pixels to pargb)

2-3) dstrgb = dstrgb + srcrgb-dstrgb * srcalpha * alpha/255 (the source image pixel value is mixed with the target image pixel value)

2-4) dstalpha = dstalpha + srcalpha * alpha-dstalpha * srcalpha * alpha/255 (the alpha channel value of the target image after mixing)

2-5) dstrgb = dstrgb * 255/dstalpha (after blending, the target image pixel is converted to argb)

Dstrgb indicates the pixel value of the target image, srcrgb indicates the pixel value of the source image, dstalpha indicates the alpha channel value of the target image, srcalpha indicates the alpha channel value of the source image, and dstargb indicates the pixel value of the alpha target image; alpha is the blending ratio of the source image pixel values (opacity, range: 0-1 ).

2-1 in formula 2 is substituted into the 2-3 formula to simplify the process:

3-1) dstrgb = dstrgb * dstalpha/255

3-2) dstrgb = dstrgb + (srcrgb-dstrgb) * srcalpha * alpha/255

3-3) dstalpha = dstalpha + srcalpha * alpha-dstalpha * srcalpha * alpha/255

3-4) dstrgb = dstrgb * 255/dstalpha

When dstalpha = srcalpha = 255, the 3-1, 3-3, and 3-4 types in Formula 3 are meaningless, and the 3-2 type also changes:

4) dstrgb = dstrgb + (srcrgb-dstrgb) * alpha

It is not hard to see that formula 4 is the deformation of Formula 1. Therefore, Formula 1 is only a special case when Formula 3 (or formula 2) does not contain Alpha information (or alpha = 255) in the target image and source image.

When alpha = 1 in formula 4, the target image pixel is equal to the source image pixel. Therefore, image copying is also a field of image synthesis.

The above detailed analysis shows that even the most basic normal image mixing mode is complex. In fact, the above is not a complete analysis, because it is a complete arrangement and combination of three elements, namely the target image Alpha information, the source image Alpha information, and the source image synthesis ratio, A maximum of 8 formulas can be derived.

The following describes the code implementation in all eight cases of the normal hybrid mode (two items overlap, but the actual situation is 7), and the above text description can also be improved and supplemented:

unit main;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;type  TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);  private    { Private declarations }  public    { Public declarations }  end;var  Form1: TForm1;implementationuses Gdiplus, ImageData, Jpeg;{$R *.dfm}procedure _SetMixerMM;asm    pxor        mm7, mm7    mov         eax, 1011h    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;procedure _DoMixer(var Dest: TImageData; const Source: TImageData; Alpha: Integer);var  dstOffset, srcOffset:Integer;  alphaI: Integer;  dst: PImageData;asm    push      esi    push      edi    push      ebx    mov       dst, eax    mov       alphaI, ecx    shr       ecx, 8    movzx     ebx, [eax].TImageData.AlphaFlag    shl       ebx, 1    or        ecx, ebx    movzx     ebx, [edx].TImageData.AlphaFlag    shl       ebx, 2    or        ecx, ebx    push      ecx    call      _SetCopyRegs    mov       srcOffset, eax    pop       eax    jmp       dword ptr [@@jmpTable+eax*4]@@jmpTable:    dd @@mixer0, @@mixer1, @@mixer2, @@mixer3, @@mixer4, @@mixer5, @@mixer6, @@mixer7// src = 0, dst = 0, alpha = 0@@mixer0:    mov       eax, alphaI    movq      mm2, qword ptr ArgbTab[eax*8]    mov       eax, srcOffset    pxor      mm7, mm7@@yLoop0:    push      ecx@@xLoop0:    movd      mm0, [esi]    movd      mm1, [edi]    punpcklbw mm0, mm7    punpcklbw mm1, mm7    psubw     mm0, mm1    pmullw    mm0, mm2    psllw     mm1, 8    paddw     mm0, mm1    psrlw     mm0, 8    packuswb  mm0, mm0    movd      [edi], mm0    mov       [edi].TARGBQuad.Alpha, 255    add       esi, 4    add       edi, 4    loop      @@xLoop0    add       esi, eax    add       edi, ebx    pop       ecx    dec       edx    jnz       @@yLoop0    jmp       @@End// src = 0, dst = 0, alpha = 1@@mixer1:// src = 0, dst = 1, alpha = 1@@mixer3:    mov       eax, srcOffset@@yLoop1:    push      ecx    rep       movsd    pop       ecx    add       esi, eax    add       edi, ebx    dec       edx    jnz       @@yLoop1    jmp       @@End    mov       eax, dst    mov       [eax].TImageData.AlphaFlag, False    jmp       @@Exit// src = 0, dst = 1, alpha = 0@@mixer2:    call      _SetMixerMM    mov       eax, alphaI    imul      eax, 255    shr       eax, 8@@yLoop2:    push      ecx@@xLoop2:    push      eax    call      _PARGBMixer    movd      [edi], mm0    mov       [edi].TARGBQuad.Alpha, al    pop       eax    add       esi, 4    add       edi, 4    loop      @@xLoop2    add       esi, srcOffset    add       edi, ebx    pop       ecx    dec       edx    jnz       @@yLoop2    jmp       @@End// src = 1, dst = 0, alpha = 0@@mixer4:    mov       dstOffset, ebx    mov       ebx, alphaI    pxor      mm7, mm7@@yLoop4:    push      ecx@@xLoop4:    movzx     eax, [esi].TARGBQuad.Alpha    imul      eax, ebx    shr       eax, 8    jz        @@Next4    call      _ARGBMixer    movd      [edi], mm0    mov       [edi].TARGBQuad.Alpha, 255@@Next4:    add       esi, 4    add       edi, 4    loop      @@xLoop4    add       esi, srcOffset    add       edi, dstOffset    pop       ecx    dec       edx    jnz       @@yLoop4    jmp       @@End// src = 1, dst = 0, alpha = 1@@mixer5:    pxor      mm7, mm7@@yLoop5:    push      ecx@@xLoop5:    movzx     eax, [esi].TARGBQuad.Alpha    call      _ARGBMixer    movd      [edi], mm0    mov       [edi].TARGBQuad.Alpha, 255    add       esi, 4    add       edi, 4    loop      @@xLoop5    add       esi, srcOffset    add       edi, ebx    pop       ecx    dec       edx    jnz       @@yLoop5    jmp       @@End// src = 1, dst = 1, alpha = 0@@mixer6:    mov       dstOffset, ebx    mov       ebx, alphaI    call      _SetMixerMM@@yLoop6:    push      ecx@@xLoop6:    movzx     eax, [esi].TARGBQuad.Alpha    imul      eax, ebx    shr       eax, 8    jz        @@Next6    call      _PARGBMixer    movd      [edi], mm0    mov       [edi].TARGBQuad.Alpha, al@@Next6:    add       esi, 4    add       edi, 4    loop      @@xLoop6    add       esi, srcOffset    add       edi, dstOffset    pop       ecx    dec       edx    jnz       @@yLoop6    jmp       @@End// src = 1, dst = 1, alpha = 1@@mixer7:    call      _SetMixerMM@@yLoop7:    push      ecx@@xLoop7:    movzx     eax, [esi].TARGBQuad.Alpha    call      _PARGBMixer    movd      [edi], mm0    mov       [edi].TARGBQuad.Alpha, al    add       esi, 4    add       edi, 4    loop      @@xLoop7    add       esi, srcOffset    add       edi, ebx    pop       ecx    dec       edx    jnz       @@yLoop7@@End:    emms@@Exit:    pop       ebx    pop       edi    pop       esiend;procedure ImageMixer(var Dest: TImageData; const Source: TImageData; Alpha: Single);var  alphaI: Integer;begin  alphaI := Round(Alpha * 256);  if alphaI < 0 then Exit;  if alphaI > 256 then alphaI := 256;  _DoMixer(Dest, Source, alphaI);end;procedure TForm1.Button1Click(Sender: TObject);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);  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;procedure TForm1.Button2Click(Sender: TObject);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);  ImageMixer(dst, src, 1);  UnlockGpBitmap(source, src);  Canvas.Draw(dst.Width + src.Width, 0, dest);  g.Free;  dest.Free;  source.Free;end;end.

The preceding is a complete Delphi program. In the _ domixer process, seven image synthesis sub-processes are defined to meet the needs of image merging in all eight permutation and combination modes. In addition to the subprocesses @ mixer0 and @ mixer1, other subprocesses call the _ argbmixer and _ pargbmixer processes respectively, in fact, the processing code in @ mixer0 is basically the same as the _ argbmixer process. That is to say, the seven sub-processes use three processing methods respectively:

First, the full copy method of @ mixer1;

Second, the target image does not contain Alpha information. The source image is mixed to the _ argbmixer process of the target image by Pixel Alpha information or given opacity, this process uses the simplified formula of the previous Formula 1 or 4.

The third is the Processing Form of the target image with Alpha Information _ pargbmixer. This process uses the previous Formula 3.

If there are too many seven sub-processes, you can also simplify the code and retain only the sub-processes that meet the preceding three conditions, that is, @ mixer1, @ mixer4, and @ mixer6, it has little impact on processing efficiency.

The above program contains two examples. The first one is to use the GDI + bitmap to open two PNG images for processing. This processing calls @ mixer6. The running effect is as follows:

The next example is a hybrid processing of the GDI + bitmap and VCL bitmap. The VCL bitmap is a jpeg file without Alpha information. The running effect of this example is as follows:

 

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.