Delphi影像處理 — 設定伽瑪

來源:互聯網
上載者:User

閱讀提示:

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

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

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

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

 

    前天有個朋友發郵件向我諮詢,怎樣使用GDI+的ImageAttributes.SetGamma方法。他說他在使用GDI+ SetGamma方法時,發現所給參數值越大,映像越暗,反之則越亮,似乎與自己理解的不一樣。我測試了一下,確實如此。我查了一下.NET2.0類庫文檔,關於該方法參數的說明是:

    gamma 參數的典型值在 1.0 到 2.2 之間;但在某些情況下,0.1 到 5.0 範圍內的值也很有用。

    ImageAttributes 對象維護五種調整類別的顏色和灰階設定:預設、位元影像、畫筆、鋼筆和文本。例如,可以為預設類別指定一個伽瑪值,為位元影像類別指定另一個伽瑪值,再為鋼筆類別指定另一個伽瑪值。

    預設的顏色調整設定和灰階調整設定適用於本身沒有調整設定的所有類別。例如,如果從來沒有為鋼筆類別指定任何調整設定,則預設設定適用於鋼筆類別。

    一旦為某一類別指定了顏色調整或灰階調整設定,預設調整設定就不再適用於該類別了。例如,假定您為預設類別指定了一個調整設定集合。如果通過將 Pen 傳遞給 SetGamma 方法來為鋼筆類別設定伽瑪值,則任何預設調整設定都將不會應用於鋼筆。

    正常範圍以外的伽瑪值可用於舊式 CRT 監視器,或者用於處於非一般照明條件(例如工業環境或櫥窗陳設)下的監視器。

    而且還有個例子,摘錄在下面:

 

   void SetGammaExample( PaintEventArgs^ e )   {      // Create an Image object from the file Camera.jpg, and draw it to      // the screen.      Image^ myImage = Image::FromFile( "Camera.jpg" );      e->Graphics->DrawImage( myImage, 20, 20 );      // Create an ImageAttributes object and set the gamma to 2.2.      ImageAttributes^ imageAttr = gcnew ImageAttributes;      imageAttr->SetGamma( 2.2f );      // Draw the image with gamma set to 2.2.      Rectangle rect = Rectangle(250,20,200,200);      e->Graphics->DrawImage( myImage, rect, 0, 0, 200, 200, GraphicsUnit::Pixel, imageAttr );   }

    按說,按照例子代碼設定伽瑪校正值2.2後映像顯示的結果應該是比沒有使用伽瑪校正前要亮一些才對,可現在結果相反!是我們理解有錯,還是GDI+的BUG???

    帶著疑惑,網上搜尋了一下,果然,在MSDN論壇上發現有同樣的疑問:http://social.msdn.microsoft.com/Forums/zh-HK/csharpgeneral/thread/efc76edd-adf1-4acb-aa34-fe5fdd01b183,但版主的解答卻說這樣的效果是正確的。

    自己寫了一個設定伽瑪校正的函數,與GDI+的ImageAttributes.SetGamma方法一比較,也是剛好相反。但如果把GDI+的SetGamma方法參數用倒數的形式給出,倒是與我自己寫的函數效果是一樣的(也可以說,把我寫的函數中的exponent := 1 / Gamma語句 改為exponent := Gamma,與GDI+的SetGamma方法效果一樣):

procedure ImageSetGamma(var Data: TImageData; Gamma: Single);var  I: Integer;  exponent: Double;  gammaTab: array[0..255] of byte;begin  exponent := 1 / Gamma;  // 這一句改為exponent := Gamma;,與GDI+的SetGamma參數效果相同  for I := 0 to 255 do  begin    gammaTab[I] := Round(Power((I + 0.5) / 256, exponent) * 256 - 0.5);  end;  asm    push    ebp    push    esi    push    edi    push    ebx    mov     eax, data    call    _SetDataRegs    lea     esi, gammaTab    mov     ebp, edx@@yLoop:    push    ecx@@xLoop:    movzx   eax, [edi].TARGBQuad.Blue    movzx   edx, [edi].TARGBQuad.Green    mov     al, [esi+eax]    mov     dl, [esi+edx]    mov     [edi].TARGBQuad.Blue, al    mov     [edi].TARGBQuad.Green, dl    movzx   eax, [edi].TARGBQuad.Red    mov     al, [esi+eax]    mov     [edi].TARGBQuad.Red, al    add     edi, 4    loop    @@xLoop    pop     ecx    add     edi, ebx    dec     ebp    jnz     @@yLoop    pop     ebx    pop     edi    pop     esi    pop     ebp  end;end;//---------------------------------------------------------------------------procedure TForm1.Button3Click(Sender: TObject);var  bmp: TGpBitmap;  g: TGpGraphics;  data: TImageData;begin  bmp := TGpBitmap.Create('..\media\source.bmp');  g := TGpGraphics.Create(Canvas.Handle);  g.DrawImage(bmp, 0, 0);  data := LockGpBitmap(bmp);  ImageSetGamma(data, 2.2);  UnlockGpBitmap(bmp, data);  g.DrawImage(bmp, 0, data.Height);  g.Free;  bmp.Free;end;

 

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