Delphi影像處理 — 灰色浮雕

來源:互聯網
上載者:User

閱讀提示:

    《Delphi影像處理》系列以效率為側重點,一般代碼為PASCAL,核心代碼採用BASM。

    《C++影像處理》系列以代碼清晰,可讀性為主,全部使用C++代碼。

    儘可能保持二者內容一致,可相互對照。

    本文代碼必須包括文章《Delphi影像處理 -- 資料類型及公用過程》中的ImageData.pas單元和《Delphi影像處理 -- 平面幾何變換類》TransformMatrix.pas單元。

 

    實現映像浮雕效果的一般原理是,將映像上每個像素點與其對角線的像素點形成差值,使類比色彩值淡化,不同顏色值突出,從而產生縱深感,達到浮雕的效果,具體的做法是用處於對角線的2個像素值相減,再加上一個背景常數,一般為128而成。這種演算法的特點是簡單快捷,缺點是不能調節映像浮雕效果的角度和深度。

    用Photoshop實現的映像浮雕效果,可以任意調節浮雕角度和深度(2個像素點的距離),還可以調整浮雕像素差值的數量。其基本演算法原理和一般浮雕效果相同,但是具體做法不一樣:對每個要處理的像素點,首先按照浮雕角度和深度計算處2個相應點的位置,然後計算這2個位置的顏色值,並使之形成差值,再乘上浮雕差值數量百分比,最後加上128的背景色。注意,這裡計算的2個相應點是邏輯點,而不是實際的像素點,比如實現一個45度角,深度為3的映像浮雕效果,對每個像素點P(x, y),其對應的2個邏輯點的位置分別是P0(x - 3 * 0.7071 / 2, y - 3 * 0.7071 / 2)和P1(x + 3 * 0.7071 / 2, y + 3 * 0.7071 / 2),顯然,對於這樣的2個邏輯點,是不能直接從映像中找到其對應的像素點的,如果簡單地對其四捨五入處理,將會造成大量的,由不同角度和深度而形成的相同的浮雕效果,這可不是我們想要的結果,而且使浮雕角度和深度參數失去了它原本的意義。為此,必須對原始映像按浮雕角度和深度進行縮放後,再對每個像素點進行浮雕效果處理,完畢再縮放回原圖的大小,從而完成整個浮雕效果過程。下面是我經過反覆實驗後,寫的Photoshop浮雕效果實現過程代碼:

 

procedure GetSrcColor;asm    push      esi           // esi = src.Scan0    mov       eax, ecx    sar       eax, 12    imul      eax, ebx    add       esi, eax      // esi += (y / 4096 * src.Stride)    mov       eax, edx    sar       eax, 12    shl       eax, 2    add       esi, eax      // esi +=  (x / 4096 * 4)    call      _GetBilinearColor    movd      eax, xmm0    movd      mm0, eax    punpcklbw mm0, mm7      // return mm0 = ARGB (word * 4)    pop       esiend;procedure ImageGraySculpture(var Data: TImageData;  Angle: Single; Size: LongWord; Num: LongWord = 100);var  x, y, Radius: Integer;  xDelta, yDelta: Integer;  width, height: Integer;  dstOffset: Integer;  src: TImageData;begin  Radius := (Size + 1) shr 1; // 映像邊框擴充半徑  Angle := PI * Angle / 180;  Size := Size shl 12;        // Size = Size * 256  Num := (Num shl 9) div 100; // Num *= 5.12 轉換為2的冪  xDelta := Round(Cos(Angle) * Size);  yDelta := Round(Sin(Angle) * Size);  x := (Radius shl 12) - (xDelta div 2);  y := (Radius shl 12) - (yDelta div 2);  width := x + (Data.Width shl 12);  height := y + (Data.Height shl 12);  if Data.AlphaFlag then    ArgbConvertPArgb(Data);  src := _GetExpandData(Data, Radius);  asm    mov       eax, Data    lea       edx, src    call      _SetCopyRegs    mov       dstOffset, ebx    movq      mm5, qword ptr ArgbTab[128*8]// mm5 = 00 128 00 128 00 128 00 128    movd      mm6, Num        // mm6 = 00 Num 00 Num 00 Num 00 Num    punpcklwd mm6, mm6    punpcklwd mm6, mm6    pxor      mm7, mm7        // mm7 = 00 00 00 00 00 00 00 00    pxor      xmm7, xmm7    mov       esi, src.Scan0    mov       ebx, src.Stride    mov       ecx, y          // for (; y < Height; y += 4096)@@yLoop:                      // {mov     edx, x          //   for (; x < Width; x += 4096)@@xLoop:                      //   {    add       ecx, yDelta     //     y1 = y + yDelta    add       edx, xDelta     //     x1 = x + xDelta    call      GetSrcColor     //    movq      mm1, mm0        //     mm1 = 00 A1 00 R1 00 G1 00 B1    sub       ecx, yDelta     //     y0 = y - yDelta    sub       edx, xDelta     //     x0 = x - xDelta    call      GetSrcColor     //     mm0 = 00 A0 00 R0 00 G0 00 B0    psubw     mm0, mm1        //     mm0 = A0-A1 R0-R1 G0-G1 B0-B1    psllw     mm0, 7          //     mm0 = mm0 * 128 * Num / 65536    pmulhw    mm0, mm6    paddw     mm0, mm5        //     mm0 = A+128 R+128 G+128 B+128    packuswb  mm0, mm7        //     mm0 = 00 00 00 00 A R G B    mov       al, [edi].TARGBQuad.Alpha    movd      [edi], mm0      //     *edi = mm0    mov       [edi].TARGBQuad.Alpha, al    add       edi, 4          //     edi += 4    add       edx, 1000h    cmp       edx, width    jl        @@xLoop         //   }    add       ecx, 1000h    add       edi, dstOffset    cmp       ecx, height    jl        @@yLoop         // }    emms  end;  FreeImageData(src);  if Data.AlphaFlag then    PArgbConvertArgb(Data);end;

    下面是個示範例子代碼:

 

procedure TForm1.Button3Click(Sender: TObject);var  bmp: TGpBitmap;  g: TGpGraphics;  data: TImageData;begin  bmp := TGpBitmap.Create('..\media\20041001.jpg');  g := TGpGraphics.Create(Canvas.Handle);  g.DrawImage(bmp, 0, 0);  data := LockGpBitmap(bmp);  ImageGraySculpture(data, 45, 3, 100);  UnlockGpBitmap(bmp, data);  g.DrawImage(bmp, 0, data.Height);  g.Free;  bmp.Free;end;

    運行:

    和Photoshop浮雕效果對比,基本一致。

     補記:在文章評論中,有人說灰色浮雕不帶彩,其實是不正確的,我測試過網上和書上的很多代碼,也測試過Photoshop,都是有可能帶彩的,在浮雕深度很小而且原始映像色彩較平淡時也有可能不帶彩,可以把我上面的原圖裁下來,用Photoshop一試就清楚了。當然,如果你要達到完全不帶彩也很簡單,在浮雕處理前做一個映像灰階化即可。如果灰階浮雕完全不帶彩,程式碼可得到簡化,速度至少可再提高60%以上。

 

    《Delphi影像處理》系列使用GDI+單元和說明見文章《GDI+ for VCL基礎 -- GDI+ 與 VCL》。

    因水平有限,錯誤在所難免,歡迎指正和指導。郵箱地址:maozefa@hotmail.com

    這裡可訪問《Delphi影像處理 -- 文章索引》。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.