閱讀提示:
《Delphi影像處理》系列以效率為側重點,一般代碼為PASCAL,核心代碼採用BASM。
《C++影像處理》系列以代碼清晰,可讀性為主,全部使用C++代碼。
儘可能保持二者內容一致,可相互對照。
本文代碼必須包括文章《Delphi影像處理 -- 資料類型及公用過程》中的ImageData.pas單元。
本文代碼是在《Delphi影像處理 -- 亮度/對比調整》基礎上,通過改非亮度為線性亮度而成的。
映像亮度調整分為非線性和線性兩種方法。
非線性映像亮度是將映像像素的R、G、B分別加上或減去某個值,其優點是代碼簡單,亮度調整速度快;缺點是映像資訊損失較大,調整過的 映像顯得平淡,無層次感。
線性映像亮度一般是將映像像素的RGB轉換為HSL(HSV)等色彩空間,對L(V)部分進行增減調整後,再轉換為RGB色彩空間,優點是調整過映像層次感很強;缺點是代碼較複雜,調整速度慢,而且當映像亮度增減量較大時有很大的失真。
針對上面兩種方法的優缺點,本人蔘照Photoshop的對比、飽和度調整原理(可參見本人的有關文章),對映像亮度調整方法進行了改進,經測試,效果還不錯,主要有不失真調整範圍寬、有較好的層次感、儘可能減少映像資訊損失量等;同時,在代碼處理上,採用了灰階表尋找法,先按製造了一個256個元素大小的線性亮度/對比尋找表,然後對映像資料逐像素按R、G、B分量值在尋找表中取得調整後的資料,因此處理速度同《Delphi影像處理 -- 亮度/對比調整》中的非線性亮度/對比是基本相同的。
原理用公式表示為:
如果亮度增減量value範圍為 -1 -- +1,當value > 0時:
rgb = RGB + RGB * (1 / (1 - value) - 1)
當value < 0時:
rgb = RGB + RGB * value
下面是映像線性亮度/對比調整代碼:
function _CheckRgb(Rgb: Integer): Integer;asm test eax, eax jge @@1 xor eax, eax ret@@1: cmp eax, 255 jle @@2 mov eax, 255@@2:end;procedure ImageLineBrightContrast(var Data: TImageData; Bright, Contrast, Threshold: Integer);var vs: TGrayTable; cv, bv: Single; i, v: Integer; height, dataOffset: Integer;begin if (Bright = 0) and (Contrast = 0) then Exit; if Bright <= -255 then bv := -1 else bv := Bright / 255; if (Bright > 0) and (Bright < 255) then bv := 1 / (1 - bv) - 1; if Contrast <= -255 then cv := -1 else cv := Contrast / 255; if (Contrast > 0) and (Contrast < 255) then cv := 1 / (1 - cv) - 1; for i := 0 to 255 do begin if Contrast > 0 then v := _CheckRgb(i + Round(i * bv)) else v := i; if Contrast >= 255 then begin if v >= Threshold then v := 255 else v := 0; end else v := _CheckRgb(v + Round((v - Threshold) * cv)); if Contrast <= 0 then vs[i] := _CheckRgb(v + Round(v * bv)) else vs[i] := v; end; asm mov eax, Data call _SetDataRegs mov height, edx mov dataOffset, ebx lea esi, vs;@@yLoop: push ecx@@xLoop: movzx eax, [edi].TARGBQuad.Blue movzx ebx, [edi].TARGBQuad.Green movzx edx, [edi].TARGBQuad.Red mov al, [esi+eax] mov bl, [esi+ebx] mov dl, [esi+edx] mov [edi].TARGBQuad.Blue, al mov [edi].TARGBQuad.Green, bl mov [edi].TARGBQuad.Red, dl add edi, 4 loop @@xLoop pop ecx add edi, dataOffset dec height jnz @@yLoop@@Exit: end;end;
下面是用RGB非線性亮度調整(中)、HSL線性亮度調整(右)以及本文介紹的改進線性亮度調整方法(左)對同一照片的調整結果貼圖:
原圖:
《Delphi影像處理》系列使用GDI+單元和說明見文章《GDI+ for VCL基礎 -- GDI+ 與 VCL》。
因水平有限,錯誤在所難免,歡迎指正和指導。郵箱地址:maozefa@hotmail.com
這裡可訪問《Delphi影像處理 -- 文章索引》。