[C#] 濾鏡筆記 – 調整Gamma數值
2012-12-06
關於Gamma 網路上眾說紛紜,但是我看到一段比較讓人容易理解的解釋為
Gamme 是因應人類視覺特性而生的一種色彩處理方式。人類視覺特性之一 ,在微光的敏銳度大於強光中的敏銳度
也說在暗的環境下面,人眼所能區分的亮暗層次會比較多,簡單的說人類對於光的感受度是成對數而非線性分布
但是數位相機感應光線方式跟人類眼睛不同,他單純是紀錄感應到的光亮,對光線感受是呈現線性,一班的對比調整都是偏線性
移動調整,和人的感感受不同,於是Gamma曲線調整 使數位影像逼近人類看到的影像
參考文件:
http://www.photosharp.com.tw/blog20/article.aspx?m=didadida&id=5800
這兩篇都有對Gamma 的定義跟緣由做解釋..
就我眼殘的人而言,我看到的似乎是更自然的對比校正,還有亮度調整但是自然很多
彷彿可以做到讓修圖前的圖片進行現形…
因為有一群數學家已經處理好這Gamma的計算方式通常調整值落於 0.2~ 5 之間
直接來看Code :
/// <summary>
/// 調整Gamma 值
/// </summary>
/// <param name="src">原圖</param>
/// <param name="r"></param>
/// <param name="g"></param>
/// <param name="b"></param>
/// <returns></returns>
public Bitmap AdjustGamma(Bitmap src, double r, double g, double b)
{
// 判斷是不是在0.2~5 之間
r = Math.Min(Math.Max(0.2, r), 5);
g = Math.Min(Math.Max(0.2, g), 5);
b = Math.Min(Math.Max(0.2, b), 5);
// 依照 Format24bppRgb 每三個表示一 Pixel 0: 藍 1: 綠 2: 紅
BitmapData bitmapData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe
{
// 抓住第一個 Pixel 第一個數值
byte* p = (byte*)(void*)bitmapData.Scan0;
// 跨步值 - 寬度 *3 可以算出畸零地 之後跳到下一行
int nOffset = bitmapData.Stride - src.Width * 3;
for (int y = 0; y < src.Height; y++)
{
for (int x = 0; x < src.Width; x++)
{
double buffer = 0;
p[2] = (byte)Math.Min(255, (int)((255.0 * Math.Pow(p[2] / 255.0, 1.0 / r)) + 0.5));
p[1] = (byte)Math.Min(255, (int)((255.0 * Math.Pow(p[1] / 255.0, 1.0 / g)) + 0.5));
p[0] = (byte)Math.Min(255, (int)((255.0 * Math.Pow(p[0] / 255.0, 1.0 / b)) + 0.5));
// 跳去下一個 Pixel
p += 3;
}
// 跨越畸零地
p += nOffset;
}
}
src.UnlockBits(bitmapData);
return src;
}
當數值為平均略拉高 過曝效果被修正 且比線性調整更加自然
var result = AdjustGamma(b,0.4,0.4,0.4);
拉高 R Gamma
var result = AdjustGamma(b,1,0.2,0.2);
拉高G Gamma
var result = AdjustGamma(b,.2,1,0.2);
拉高 B Gamma
var result = AdjustGamma(b,.2,.2,1);
全部都拉高時會產生 高亮度效果…
var result = AdjustGamma(b,2,2,2);
參考:
http://www.smokycogs.com/blog/image-processing-in-c-sharp-adjusting-the-gamma/
ps. 任性的 Shih-Ming Tung 說他堅持要看張韶涵的照片 = =