C++图像处理 -- 亮度/对比度调整

阅读提示

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

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

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

    本文代码必须包括《C++图像处理 -- 数据类型及公用函数文章中的BmpData.h头文件。

 

    在《Delphi图像处理 -- 亮度/对比度调整》一文实现了Photoshop的亮度/对比度调整功能,这是其C/C++版。

    还是先简单介绍一下Photoshop图像亮度/对比度调整的原理:

    一、对比度算法公式。

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

    如果用newRGB表示图像像素新的R、G、B分量,RGB表示图像像素R、G、B分量,Threshold为给定的阀值,Contrast为对比度增量,当Contrast大于0时:

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

    其中,当Contrast等于255时(RGB - Threshold) * (1 / (1 - Contrast / 255) - 1)为无限(±),由于RGB最大最小值分别为255和0,因此,只能按Threshold来确定newRGB,即newRGB = RGB >= Threshold? 255 : 0,这实际就是设置图像阀值,图像由最多八种颜色组成,即红、黄、绿、青、蓝、紫及黑与白,在灰度图上也只有最多8条线。

    当Contrast小于0时:

        2) newRGB = RGB + (RGB - Threshold) * Contrast / 255

    其中,当Contrast等于-255时,图像RGB各分量都等于阀值,图像呈全灰色,灰度图上只有1条线,即阀值灰度。

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

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

    下面是用BCB2007和GDI+位图数据写的Photoshop图像亮度/对比度调整代码,包括例子代码:

//---------------------------------------------------------------------------

FORCEINLINE
INT CheckValue(INT value)
{
	return (value & ~0xff) == 0? value : value > 255? 255 : 0;
}
//---------------------------------------------------------------------------

// 亮度/对比度调整
VOID BrightAndContrast(BitmapData *data, INT bright, INT contrast, BYTE threshold)
{
	if (bright == 0 && contrast == 0)
		return;
	FLOAT cv = contrast <= -255? -1.0f : contrast / 255.0f;
	if (contrast > 0 && contrast < 255)
		cv = 1.0f / (1.0f - cv) - 1.0f;

	BYTE values[256];
	for (INT i = 0; i < 256; i ++)
	{
		INT v = contrast > 0? CheckValue(i + bright) : i;
		if (contrast >= 255)
			v = v >= threshold? 255 : 0;
		else
			v = CheckValue(v + (INT)((v - threshold) * cv + 0.5f));
		values[i] = contrast <= 0? CheckValue(v + bright) : v;
	}

	PARGBQuad p = (PARGBQuad)data->Scan0;
	INT offset = data->Stride - data->Width * sizeof(ARGBQuad);

	for (UINT y = 0; y < data->Height; y ++, (BYTE*)p += offset)
	{
		for (UINT x = 0; x < data->Width; x ++, p ++)
		{
			p->Blue		= values[p->Blue];
			p->Green	= values[p->Green];
			p->Red		= values[p->Red];
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
	Gdiplus::Bitmap *bmp =  new Gdiplus::Bitmap(L"..\\..\\media\\source1.jpg");

	Gdiplus::Graphics *g = new Gdiplus::Graphics(Canvas->Handle);
	g->DrawImage(bmp, 0, 0);

	BitmapData data;
	LockBitmap(bmp, &data);
	BrightAndContrast(&data, 0, 255, 121);
	UnlockBitmap(bmp, &data);

	g->DrawImage(bmp, data.Width, 0);

	delete g;
	delete bmp;
}
//---------------------------------------------------------------------------

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

    下面是例子程序运行界面截图(对比度255时):

 

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

    这里可访问《C++图像处理 -- 文章索引

  • 13
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
Gamma Manager is based on Gamma Slider control. This control allows to change gamma monitor on most graphic cards. The goal for this project is very simple and control is for VC6 & VC7. The other day I downloaded a N64 emulator but the screen was so black that I did not see anything. I had thus to find this solution to lighten my screen. I know that the tools of my video chart make it possible to change gamma of my screen, but it is faster with this tool. Implementation The implementation of this slider control is very easy. Import GammaSlider.h and GammaSlider.cpp into your project. Include reference to the class control. Add slider control on a form. Use ClassWizard to declare variable name derived from CGammaSlider control. That's it, enjoy! Under the hood Windows provides two APIs GetDeviceGammaRamp/ SetDeviceGammaRamp to perform gamma correction. In fact we need to have a 3 dimensional buffer of 256 WORD to manipulate gamma correction. To change gamma, it is necessary to change the RGB value of each color contained in the buffer by a float factor between 0.0 and 2.0. Example We need to save current gamma for future restore. Collapse Copy CodeWORD m_RampSaved[256*3]; if (!GetDeviceGammaRamp(::GetDC(NULL), m_RampSaved)) { TRACE("WARNING: Cannot initialize DeviceGammaRamp.\n"); }To change gamma, cycle into ramp buffer and change RGB color where Gamma is the float factor. Collapse Copy CodeWORD ramp[256*3]; for( int i=0; i<256; i++ ) { ramp[i+0] = ramp[i+256] = ramp[i+512] = (WORD)min(65535, max(0, pow((i+1) / 256.0, Gamma) * 65535 + 0.5)); } SetDeviceGammaRamp(::GetDC(NULL), ramp);Now to trap slider control message, we need to use a special message ON_WM_HSCROLL_REFLECT() that can provide message to be dispatched into control class itself.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值