亮度/对比度调整 参考



    《Delphi图像处理》系列以效率为侧重点,一般代码为PASCAL,核心代码采用BASM。

    《C++图像处理》系列以代码清晰,可读性为主,全部使用C++代码。

    尽可能保持二者内容一致,可相互对照。

   本文代码必须包括文章《Delphi图像处理 -- 数据类型及公用过程》中的ImageData.pas单元

  

        本人已经写过几篇关于亮度调整的文章,但是关于图像的对比度调整的过程和文章却一直没有写,其原因是一直没找到一个好的算法。可能有人会说,图像的亮度,对比度调整是最简单的图形操作,其算法网上可说是一搜一大把,确实如此,可就是这最简单的操作,网上的文章却五花八门,我拣几个试了一下,好像都不太理想,关键是算法太简单,实际操作效果不好,于是想,Photoshop的对比度还是较好的,而且也通用,但偏偏网上没有介绍它的算法,用了大半天时间研究了一下,再花了1个来小时写了个Delphi过程,试了一下,居然和Photoshop的对比度调整完全一样的效果!于是认真写了个测试程序,把亮度和对比度放在一起进行调整(亮度和对比度处理过程为各自独立的,其中亮度过程基本是本BLOG文章《GDI+ 在Delphi程序的应用 -- 调整图像亮度》的代码),可是效果却和Photoshop大不一样了,是什么原因呢,Photoshop的亮度调整算法是最简单的那种,与我的亮度过程做出来的是一样的(效果比较图参见《GDI+ 在Delphi程序的应用 -- 线性调整图像亮度》),而前面说了,对比度过程算法也是和Photoshop一样的,可放在一起调整就不行了,无论是先调整亮度,还是先调整对比度都这样。后来仔细分析了一下,Photoshop是用一个函数处理亮度/对比度,而且亮度调整是按对比度的正负分别对待的,下面是实现代码(包括一个简单的例子):

[delphi]  view plain copy print ?
  1. function _CheckRgb(Rgb: Integer): Integer;  
  2. asm  
  3.     test    eax, eax  
  4.     jge     @@1  
  5.     xor     eax, eax  
  6.     ret  
  7. @@1:  
  8.     cmp     eax, 255  
  9.     jle     @@2  
  10.     mov     eax, 255  
  11. @@2:  
  12. end;  
  13.   
  14. procedure ImageBrightContrast(var Data: TImageData; Bright, Contrast, Threshold: Integer);  
  15. var  
  16.   vs: TGrayTable;  
  17.   cv: Single;  
  18.   i, v: Integer;  
  19.   height, dataOffset: Integer;  
  20. begin  
  21.   if (Bright = 0and (Contrast = 0then Exit;  
  22.   if Contrast <= -255 then cv := -1 else cv := Contrast / 255;  
  23.   if (Contrast > 0and (Contrast < 255then  
  24.     cv := 1 / (1 - cv) - 1;  
  25.   for i := 0 to 255 do  
  26.   begin  
  27.     if Contrast > 0 then v := _CheckRgb(i + bright) else v := i;  
  28.     if Contrast >= 255 then  
  29.     begin  
  30.       if v >= Threshold then v := 255 else v := 0;  
  31.     end  
  32.     else  
  33.       v := _CheckRgb(v + Round((v - Threshold) * cv));  
  34.     if Contrast <= 0 then vs[i] := _CheckRgb(v + bright) else vs[i] := v;  
  35.   end;  
  36.   asm  
  37.     mov     eax, Data  
  38.     call    _SetDataRegs  
  39.     mov     height, edx  
  40.     mov     dataOffset, ebx  
  41.     lea     esi, vs;  
  42. @@yLoop:  
  43.     push    ecx  
  44. @@xLoop:  
  45.     movzx   eax, [edi].TARGBQuad.Blue  
  46.     movzx   ebx, [edi].TARGBQuad.Green  
  47.     movzx   edx, [edi].TARGBQuad.Red  
  48.     mov     al, [esi+eax]  
  49.     mov     bl, [esi+ebx]  
  50.     mov     dl, [esi+edx]  
  51.     mov     [edi].TARGBQuad.Blue, al  
  52.     mov     [edi].TARGBQuad.Green, bl  
  53.     mov     [edi].TARGBQuad.Red, dl  
  54.     add     edi, 4  
  55.     loop    @@xLoop  
  56.     pop     ecx  
  57.     add     edi, dataOffset  
  58.     dec     height  
  59.     jnz     @@yLoop  
  60. @@Exit:  
  61.   end;  
  62. end;  
  63.   
  64. procedure TForm1.Button3Click(Sender: TObject);  
  65. var  
  66.   bmp: TGpBitmap;  
  67.   g: TGpGraphics;  
  68.   data: TImageData;  
  69. begin  
  70.   bmp := TGpBitmap.Create('..\media\source1.jpg');  
  71.   g := TGpGraphics.Create(Canvas.Handle);  
  72.   g.DrawImage(bmp, 00);  
  73.   data := LockGpBitmap(bmp);  
  74.   ImageBrightContrast(data, 500121);  
  75.   UnlockGpBitmap(bmp, data);  
  76.   g.DrawImage(bmp, data.Width, 0);  
  77.   g.Free;  
  78.   bmp.Free;  
  79. end;  

 

    下面对亮度/对比度的原理简单介绍一下。

    一、Photoshop对比度算法。可以用下面的公式来表示:

    (1)、nRGB = RGB + (RGB - Threshold) * Contrast / 255

    公式中,nRGB表示图像像素新的R、G、B分量,RGB表示图像像素R、G、B分量,Threshold为给定的阈值,Contrast为处理过的对比度增量。

    Photoshop对于对比度增量,是按给定值的正负分别处理的:

    当增量等于-255时,是图像对比度的下端极限,此时,图像RGB各分量都等于阈值,图像呈全灰色,灰度图上只有1条线,即阈值灰度;

    当增量大于-255且小于0时,直接用上面的公式计算图像像素各分量;

    当增量等于 255时,是图像对比度的上端极限,实际等于设置图像阈值,图像由最多八种颜色组成,灰度图上最多8条线,即红、黄、绿、青、蓝、紫及黑与白;

    当增量大于0且小于255时,则先按下面公式(2)处理增量,然后再按上面公式(1)计算对比度:

    (2)、nContrast = 255 * 255 / (255 - Contrast) - 255

    公式中的nContrast为处理后的对比度增量,Contrast为给定的对比度增量。

    二、图像亮度调整。本文采用的是最常用的非线性亮度调整(Phoposhop CS3以下版本也是这种亮度调整方式,CS3及以上版本也保留了该亮度调整方式的选项)。

    三、图像亮度/对比度综合调整算法。这个很简单,当亮度、对比度同时调整时,如果对比度大于0,现调整亮度,再调整对比度;当对比度小于0时,则相反,先调整对比度,再调整亮度。

    在亮度/对比度调整函数ImageBrightContrast中,首先按前面介绍的原理制造了一个256个元素大小的查找表,然后对图像数据逐像素按R、G、B分量值在查找表中取得调整后的数据,因此处理速度相当快。

    下面是对比度255时的运行截图:

 

    《Delphi图像处理》系列使用GDI+单元下载地址和说明见文章《GDI+ for VCL基础 -- GDI+ 与 VCL》。

    因水平有限,错误在所难免,欢迎指正和指导。邮箱地址:maozefa@hotmail.com

    这里可访问《Delphi图像处理 -- 文章索引》。


转自 http://blog.csdn.net/maozefa/article/details/1776824

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值