C++图像处理 -- 图像黑白调整应用

阅读提示

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

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

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

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

 

    Photoshop CS的图像黑白调整功能,是通过对红、黄、绿、青、蓝和洋红等6种颜色的比例调节来完成的。能更精细地将彩色图片转换为高质量的黑白照片。

    Photoshop CS图像黑白调整功能的计算公式为:

    gray = (max - mid) * ratio_max + (mid - min) * ratio_max_mid + min

    公式中:gray为像素灰度值,max、mid和min分别为图像像素R、G、B分量颜色的最大值、中间值和最小值,ratio_max为max所代表的分量颜色(单色)比率,ratio_max_mid则为max与mid两种分量颜色所形成的复色比率。

    用上面公式计算的灰度值,与我们通常所用的灰度计算方法有很大不同,通常所用的灰度公式为,是直接将颜色各分量乘以相应的比率相加而成,如:gray = 0.3R + 0.59G + 0.11B,而上面公式则是在最小值代表的颜色分量基础上,用最大值与最小值之差表示单色部分(红、绿、蓝),用中间值与最小值之差表示复色部分(黄、青、洋红),将单色和复色部分分别乘以与之对应的比率后相加,再加上最小值而得到灰度值。对于每个单独的像素来说,计算灰度值只需要用到上述6种颜色比率中的2种即可。在计算过程中可根据像素RGB相互关系选择对应的单色和复色比率,如像素RGB的大小关系为R>G>B,单色比率选最大值R红色,复色比率则为最大值R与中间值G所形成的复色黄色。

    用程序代码实现上面的灰度计算公式并不复杂,难点还是前面所说的根据像素RGB相互关系选择对应的单色和复色比率。在前天我写的《C++图像处理 -- 图像颜色混合(上)》文章中,已经实现了这项功能,同时,Photoshop图像黑白调整功能中附加的着色功能,也在文章中实现。本文的在上面文章代码基础上,编写一个相对简单的图像黑白调整界面,来实现图像动态黑白调整。

    下面是用BCB2007写的一个界面程序代码:

    程序头文件部分:

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

#ifndef bwMainH
#define bwMainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
#include <Dialogs.hpp>
#include <ExtCtrls.hpp>

#define	USE_GDIPLUS

#include "BmpData.h"
//---------------------------------------------------------------------------
enum TLockType {ltEdit, ltTrack};
typedef Set<TLockType, ltEdit, ltTrack> TLockTypes;

class TForm1 : public TForm
{
__published:	// IDE-managed Components
	TPaintBox *PaintBox1;
	TLabel *Label1;
	TLabel *Label2;
	TLabel *Label3;
	TLabel *Label4;
	TLabel *Label5;
	TLabel *Label6;
	TLabel *Label7;
	TLabel *Label8;
	TLabel *Label9;
	TLabel *Label10;
	TLabel *Label11;
	TLabel *Label12;
	TLabel *Label13;
	TLabel *Label18;
	TComboBox *ComboBox1;
	TEdit *Edit1;
	TTrackBar *TrackBar1;
	TEdit *Edit2;
	TTrackBar *TrackBar2;
	TEdit *Edit3;
	TTrackBar *TrackBar3;
	TEdit *Edit4;
	TTrackBar *TrackBar4;
	TEdit *Edit5;
	TTrackBar *TrackBar5;
	TEdit *Edit6;
	TTrackBar *TrackBar6;
	TCheckBox *CheckBox1;
	TGroupBox *GroupBox1;
	TLabel *Label14;
	TLabel *Label15;
	TLabel *Label16;
	TLabel *Label17;
	TPaintBox *PaintBox2;
	TEdit *Edit7;
	TTrackBar *TrackBar7;
	TEdit *Edit8;
	TTrackBar *TrackBar8;
	TColorDialog *ColorDialog1;
	void __fastcall FormCreate(TObject *Sender);
	void __fastcall FormDestroy(TObject *Sender);
	void __fastcall ComboBox1Change(TObject *Sender);
	void __fastcall TrackBar1Change(TObject *Sender);
	void __fastcall Edit1Change(TObject *Sender);
	void __fastcall Edit1KeyPress(TObject *Sender, char &Key);
	void __fastcall Edit1Exit(TObject *Sender);
	void __fastcall CheckBox1Click(TObject *Sender);
	void __fastcall TrackBar7Change(TObject *Sender);
	void __fastcall Edit7Change(TObject *Sender);
	void __fastcall Edit7KeyPress(TObject *Sender, char &Key);
	void __fastcall PaintBox2Click(TObject *Sender);
	void __fastcall PaintBox1Paint(TObject *Sender);
	void __fastcall PaintBox2Paint(TObject *Sender);
	void __fastcall TrackBar8Change(TObject *Sender);
private:	// User declarations
	Bitmap *Source;					// 源图像
	Bitmap *Dest;					// 调整后的图像
	BitmapData srcData;
	BitmapData dstData;
	float bwColors[6];				// 灰度选项数组
	int Bright;						// 亮度
	TTrackBar *TrackBars[6];		// 灰度选项条元件数组
	TEdit *Edits[6];				// 灰度选项编辑框数组
	TLockTypes Lock;
	Gdiplus::Rect rect;
	ARGBQuad MixColor;				// 混合颜色

	int __fastcall GetHue(void);
	int __fastcall GetSat(void);
	void __fastcall SetHue(int hue);
	void __fastcall SetSat(int sat);

	void __fastcall MixColorToHSV(void);
	void __fastcall HSVToMixColor(void);
	void __fastcall Execute(void);
	void __fastcall MixColorChange(void);
public:		// User declarations
	__fastcall TForm1(TComponent* Owner);

	__property int Hue = {read=GetHue, write=SetHue};	// 色相
	__property int Sat = {read=GetSat, write=SetSat};	// 饱和度
};
//---------------------------------------------------------------------------
const CustomIndex = 11;				// 自定义选项索引
const DefaultTint = 0xe1d3b3;		// 缺省混合颜色
const int DefOptions[][6] =			// 预定义灰度选项
{
	{40, 60, 40, 60, 20, 80},
	{128, 128, 100, 100, 128, 100},
	{100, 100, 100, 100, 100, 100},
	{0, 0, 0, 0, 0, 0},
	{-40, 235, 144, -68, -3, -107},
	{120, 110, -10, -50, 0, 120},
	{50, 120, 90, 50, 0, 0},
	{0, 0, 0, 110, 110, 110},
	{120, 120, -10, -50, -50, 120},
	{-50, -50, -50, 150, 150, 150},
	{120, 110, 40, -30, 0, 70}
};

extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

     代码文件部分:

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

#include <vcl.h>
#pragma hdrstop

#include "bwMain.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
ULONG gdiplusToken;

typedef FLOAT		BWParams, *PBWParams;

// 黑白调整缺省参数:红,黄,绿,洋红,蓝,青
CONST INT _BWDefault[] = {410, 614, 410, 819, 205, 614};

enum
{
	BWIndexBlue		= 0x40000,
	BWIndexGreen	= 0x20000,
	BWIndexRed		= 0x00000
};

enum
{
	IndexBlue	= 0x00000,
	IndexGreen	= 0x10000,
	IndexRed	= 0x20000
};

typedef union 				// 颜色分量交换结构
{
	INT tmp;				// 交换时用的临时变量
	struct
	{
		SHORT value;		// 颜色分量值
		SHORT index;		// 颜色分量索引
	};
}RGBIndex;
//---------------------------------------------------------------------------

// 交换像素分量
FORCEINLINE
VOID SwapRgb(RGBIndex &a, RGBIndex &b)
{
	a.tmp ^= b.tmp;
	b.tmp ^= a.tmp;
	a.tmp ^= b.tmp;
}
//---------------------------------------------------------------------------

// 获取黑白灰度
FORCEINLINE
INT	GetBWGray(CONST PARGBQuad pixel, CONST PINT bwParams)
{
	RGBIndex max, mid, min;
	min.tmp = pixel->Blue | BWIndexBlue;
	mid.tmp = pixel->Green | BWIndexGreen;
	max.tmp = pixel->Red | BWIndexRed;

	if (max.value < mid.value)
		SwapRgb(max, mid);
	if (max.value < min.value)
		SwapRgb(max, min);
	if (min.value > mid.value)
		SwapRgb(min, mid);

	return (((max.value - mid.value) * bwParams[max.index] +
		(mid.value - min.value) * bwParams[max.index + mid.index - 1] +
		512) >> 10) + min.value;
}
//---------------------------------------------------------------------------

VOID ColorMix(PARGBQuad pd, CONST PARGBQuad ps, INT gray)
{
	// 灰度计算常数:蓝,绿、红
	CONST INT ys[3] = {113, 604, 307};

	RGBIndex max, mid, min;
	min.tmp = ps->Blue | IndexBlue;
	mid.tmp = ps->Green | IndexGreen;
	max.tmp = ps->Red | IndexRed;

	if (max.value < mid.value)
		SwapRgb(max, mid);
	if (max.value < min.value)
		SwapRgb(max, min);
	if (min.value > mid.value)
		SwapRgb(min, mid);

	INT max_min = max.value - min.value;
	// 饱和度为0,返回灰度
	if (max_min == 0)
	{
		pd->Blue = pd->Green = pd->Red = gray;
		return;
	}
	INT mid_min = mid.value - min.value;

	INT newMax, newMid, newMin;
	gray <<= 10;
	newMax = (gray + (max_min - mid_min) * ys[mid.index] + max_min * ys[min.index] + 512) >> 10;
	newMin = newMax - max_min;
	if (newMax > 255)
	{
		INT hueCoef = (mid_min << 10) / max_min;
		INT v0 = (ys[mid.index] * hueCoef) >> 10;
		INT v1 = ys[min.index] + ys[mid.index] - v0;
		newMin = (gray - (ys[max.index] + v0) * 255 + (v1 >> 1)) / v1;
		newMid = newMin + (((255 ^ newMin) * hueCoef + 512) >> 10);
		newMax = 255;

	}
	else if (newMin < 0)
	{
		INT hueCoef = (mid_min << 10) / max_min;
		INT tmp = ys[max.index] + ((ys[mid.index] * hueCoef + 512) >> 10);
		newMax = (gray + (tmp >> 1)) / tmp;
		newMid = (newMax * hueCoef + 512) >> 10;
		newMin = 1;
	}
	else
		newMid = newMin + mid_min;

	((LPBYTE)pd)[max.index] = newMax;
	((LPBYTE)pd)[mid.index] = newMid;
	((LPBYTE)pd)[min.index] = newMin;
}
//---------------------------------------------------------------------------

// 图像黑白调整。
// 调整参数bwParams为元素数等于6的数组指针,分别为红,黄,绿,青,蓝,洋红
VOID ImageBWCopy(BitmapData *dest, CONST BitmapData *source, CONST PBWParams bwParams = NULL)
{
	// 拷贝像素灰度参数,并交换青色和洋红色
	INT params[6], *pparams;
	if (bwParams)
	{
		for (INT i = 0; i < 6; i ++)
			params[i] = (INT)(bwParams[i] * 1024 + 0.5);
		params[3] ^= params[5];
		params[5] ^= params[3];
		params[3] ^= params[5];
		pparams = params;
	}
	else
		pparams = (INT*)_BWDefault;

	PARGBQuad pd, ps;
	UINT width, height;
	INT dstOffset, srcOffset;
	GetDataCopyParams(dest, source, width, height, pd, ps, dstOffset, srcOffset);

	for (UINT y = 0; y < height; y ++, pd += dstOffset, ps += srcOffset)
	{
		for (UINT x = 0; x < width; x ++, pd ++, ps ++)
		{
			INT gray = GetBWGray(ps, pparams);
			pd->Blue = pd->Green = pd->Red =
				(gray & ~0xff) == 0? gray : gray > 255? 255 : 0;
		}
	}
}
//---------------------------------------------------------------------------

// 灰度图像染色。
VOID ImageTint(BitmapData *grayData, ARGB color)
{
	ARGBQuad colorTable[256];
	PARGBQuad p = colorTable;

	for (INT i = 0; i < 256; i ++, p ++)
	{
		ColorMix(p, (PARGBQuad)&color, i);
		p->Alpha = 255;
	}

	p = (PARGBQuad)grayData->Scan0;
	INT dataOffset = (grayData->Stride >> 2) - (INT)grayData->Width;

	for (UINT y = 0; y < grayData->Height; y ++, p += dataOffset)
	{
		for (UINT x = 0; x < grayData->Width; x ++, p ++)
		{
			p->Color = colorTable[p->Blue].Color;
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
	Gdiplus::GdiplusStartupInput gdiplusStartupInput;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	TrackBars[0] = TrackBar1;
	TrackBars[1] = TrackBar2;
	TrackBars[2] = TrackBar3;
	TrackBars[3] = TrackBar4;
	TrackBars[4] = TrackBar5;
	TrackBars[5] = TrackBar6;
	Edits[0] = Edit1;
	Edits[1] = Edit2;
	Edits[2] = Edit3;
	Edits[3] = Edit4;
	Edits[4] = Edit5;
	Edits[5] = Edit6;

	// 从文件装入图像到tmp
	Bitmap *tmp = new Bitmap(L"source1.jpg");
	rect.Width = tmp->GetWidth();
	rect.Height = tmp->GetHeight();
	// 分别建立新的源和目标图像数据到srcData和dstData
	GetBitmapData(rect.Width, rect.Height, &srcData);
	GetBitmapData(rect.Width, rect.Height, &dstData);
	// 将tmp图像数据分别锁定拷贝到srcData和dstData
	tmp->LockBits(&rect,
		ImageLockModeRead | ImageLockModeWrite | ImageLockModeUserInputBuf,
		PixelFormat32bppARGB, &srcData);
	tmp->UnlockBits(&srcData);
	tmp->LockBits(&rect,
		ImageLockModeRead | ImageLockModeWrite | ImageLockModeUserInputBuf,
		PixelFormat32bppARGB, &dstData);
	tmp->UnlockBits(&dstData);
	delete tmp;
	// 分别用图像数据srcData和dstData建立位图Source和Dest
	// 注:图像数据结构用于数据处理,位图用于显示,这样即可绑定数据结构和位图,
	//     又能避免每次处理图像数据时的锁定和解锁操作
	Source = new Bitmap(srcData.Width, srcData.Height, srcData.Stride,
		PixelFormat32bppARGB, (BYTE*)srcData.Scan0);
	Dest = new Bitmap(dstData.Width, dstData.Height, dstData.Stride,
		PixelFormat32bppARGB, (BYTE*)dstData.Scan0);

	ComboBox1Change(NULL);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormDestroy(TObject *Sender)
{
	delete Dest;
	delete Source;
	FreeBitmapData(&dstData);
	FreeBitmapData(&srcData);
	GdiplusShutdown(gdiplusToken);
}
//---------------------------------------------------------------------------

// 执行图像黑白调整
void __fastcall TForm1::Execute(void)
{
	for (int i = 0; i < 6; i ++)				// 获取灰度选项条数据
		bwColors[i] = TrackBars[i]->Position / 100.0;
	ImageBWCopy(&dstData, &srcData, bwColors);	// 源图黑白调整到目标图
	if (CheckBox1->Checked && Sat)				// 如果色调选项被选,着色
		ImageTint(&dstData, MixColor.Color);
	PaintBox1Paint(NULL);						// 显示图像
}
//---------------------------------------------------------------------------

// 预设黑白调整选项改变
void __fastcall TForm1::ComboBox1Change(TObject *Sender)
{
	if (ComboBox1->ItemIndex == CustomIndex)
		return;
	MixColor.Color = DefaultTint;		// 设置缺省混合颜色
	MixColorToHSV();					// 计算并设置缺省色相、饱和度控件
	Lock = TLockTypes() << ltEdit << ltTrack;
	try
	{
		for (int i = 0; i < 6; i ++)	// 装入预设的选项数据到相应的控件
		{
			TrackBars[i]->Position = DefOptions[ComboBox1->ItemIndex][i];
			Edits[i]->Text = DefOptions[ComboBox1->ItemIndex][i];
		}
		if (CheckBox1->Checked)
			CheckBox1->Checked = false;	// 取消色调选项
		else
			Execute();
	}
	__finally
	{
		Lock.Clear();
	}
}
//---------------------------------------------------------------------------

// 黑白调整数据选项条改变
void __fastcall TForm1::TrackBar1Change(TObject *Sender)
{
	if (Lock.Contains(ltTrack)) return;
	Lock = TLockTypes() << ltEdit;
	try
	{
		TTrackBar *bar = (TTrackBar*)Sender;
		Edits[bar->Tag]->Text = bar->Position;
		ComboBox1->ItemIndex = CustomIndex;	// 预设下拉框设置为自定义
		Execute();
	}
	__finally
	{
		Lock.Clear();
	}
}
//---------------------------------------------------------------------------

// 黑白调整数据编辑框改变
void __fastcall TForm1::Edit1Change(TObject *Sender)
{
	if (Lock.Contains(ltEdit)) return;
	TEdit *edit = (TEdit*)Sender;
	if (edit->Text != "" && edit->Text != "-")
		TrackBars[edit->Tag]->Position = StrToInt(edit->Text);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)
{
	if (Key >= ' ' && Key != '-' && (Key < '0' || Key > '9'))
		Key = 0;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Edit1Exit(TObject *Sender)
{
	TEdit *edit = (TEdit*)Sender;
	if (edit->Text == "")
		edit->Text = TrackBars[edit->Tag]->Position;
}
//---------------------------------------------------------------------------

// 混合颜色改变,画混合颜色,显示其RGB值
void __fastcall TForm1::MixColorChange(void)
{
	PaintBox2Paint(NULL);
	Label18->Caption = "R: " + IntToStr(MixColor.Red) +
					", G: " + MixColor.Green +
					", B: " + MixColor.Blue;
	Execute();
}
//---------------------------------------------------------------------------

inline void RgbSwap(int &a, int &b)
{
	a ^= b;
	b ^= a;
	a ^= b;
}

// 按混合颜色计算并改变HSV
void __fastcall TForm1::MixColorToHSV(void)
{
	int max, mid, min;

	max = MixColor.Red;
	mid = MixColor.Green;
	min = MixColor.Blue;
	if (max < mid) RgbSwap(max, mid);
	if (max < min) RgbSwap(max, min);
	if (min > mid) RgbSwap(min, mid);

	int max_min = max - min;
	if (max_min == 0)
	{
		Hue = 0;
		Sat = 0;
	}
	else
	{
		int H;
		if (max == MixColor.Red)
			H = ((MixColor.Green - MixColor.Blue) * 60 + 30) / max_min;
		else if (max == MixColor.Green)
			H = ((MixColor.Blue - MixColor.Red) * 60 + 30) / max_min + 120;
		else
			H = ((MixColor.Red - MixColor.Green) * 60 + 30) / max_min + 240;
		Hue = H < 0? H + 360 : H;
		Sat = (max_min * 100) / max;

	}
	Bright = max;
}
//---------------------------------------------------------------------------

inline ARGB RgbToColor(int r, int g, int b)
{
	return (r << 16) | (g << 8) | b;
}

// 按HSV计算并改变混合颜色
void __fastcall TForm1::HSVToMixColor(void)
{
	if (Sat == 0)
	{
		MixColor.Blue = MixColor.Green = MixColor.Red = Bright;
	}
	else
	{
		int index = Hue / 60;
		int f = Hue % 60;
		if ((index & 1) == 0) f = 60 - f;
		int a = Bright;
		int b = (Bright * (6000 - Sat * f)) / 6000;
		int c = (Bright * (100 - Sat)) / 100;
		switch (index)
		{
			case 0:
				MixColor.Color = RgbToColor(a, b, c);
				break;
			case 1:
				MixColor.Color = RgbToColor(b, a, c);
				break;
			case 2:
				MixColor.Color = RgbToColor(c, a, b);
				break;
			case 3:
				MixColor.Color = RgbToColor(c, b, a);
				break;
			case 4:
				MixColor.Color = RgbToColor(b, c, a);
				break;
			case 5:
				MixColor.Color = RgbToColor(a, c, b);
		}
	}
	MixColorChange();
}
//---------------------------------------------------------------------------

int __fastcall TForm1::GetHue(void)
{
	return TrackBar7->Position;
}
//---------------------------------------------------------------------------

int __fastcall TForm1::GetSat(void)
{
	return TrackBar8->Position;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SetHue(int hue)
{
	if (Hue == hue) return;
	Lock = TLockTypes() << ltEdit << ltTrack;
	try
	{
		TrackBar7->Position = hue;
		Edit7->Text = hue;
	}
	__finally
	{
		Lock.Clear();
    }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SetSat(int sat)
{
	if (Sat == sat) return;
	Lock = TLockTypes() << ltEdit << ltTrack;
	try
	{
		TrackBar8->Position = sat;
		Edit8->Text = sat;
	}
	__finally
	{
		Lock.Clear();
    }
}
//---------------------------------------------------------------------------

// 色调选盒改变
void __fastcall TForm1::CheckBox1Click(TObject *Sender)
{
	Label14->Enabled = CheckBox1->Checked;
	Label15->Enabled = CheckBox1->Checked;
	Label16->Enabled = CheckBox1->Checked;
	Label17->Enabled = CheckBox1->Checked;
	Label18->Visible = CheckBox1->Checked;
	Edit7->Enabled = CheckBox1->Checked;
	Edit8->Enabled = CheckBox1->Checked;
	TrackBar7->SliderVisible = CheckBox1->Checked;
	TrackBar8->SliderVisible = CheckBox1->Checked;

	if (CheckBox1->Checked)
		ComboBox1->ItemIndex = CustomIndex;
	MixColorChange();
}
//---------------------------------------------------------------------------

// 色相选项条改变
void __fastcall TForm1::TrackBar7Change(TObject *Sender)
{
	if (!Lock.Contains(ltTrack))
		Edit7->Text = TrackBar7->Position;
}
//---------------------------------------------------------------------------

// 饱和度选项条改变
void __fastcall TForm1::TrackBar8Change(TObject *Sender)
{
	if (!Lock.Contains(ltTrack))
		Edit8->Text = TrackBar8->Position;
}
//---------------------------------------------------------------------------

// 色相或者饱和度编辑框改变
void __fastcall TForm1::Edit7Change(TObject *Sender)
{
	TEdit *edit = (TEdit*)Sender;
	if (Lock.Contains(ltEdit) || edit->Text == "")
		return;
	Lock = TLockTypes() << ltTrack;
	try
	{
		int val = StrToInt(edit->Text);
		TTrackBar *bar = edit->Tag == 0? TrackBar7 : TrackBar8;
		if (bar->Position != val)
			bar->Position = val;
		HSVToMixColor();
	}
	__finally
	{
		Lock.Clear();
    }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Edit7KeyPress(TObject *Sender, char &Key)
{
	if (Key >= ' ' && (Key < '0' || Key > '9'))
		Key = 0;
}
//---------------------------------------------------------------------------

// 调用颜色对话框选择混合颜色
void __fastcall TForm1::PaintBox2Click(TObject *Sender)
{
	if (CheckBox1->Checked && ColorDialog1->Execute(Handle))
	{
		MixColor.Color = (ARGB)ColorDialog1->Color;
		MixColor.Blue = MixColor.Red;
		MixColor.Red = (BYTE)ColorDialog1->Color;
		MixColorToHSV();
		MixColorChange();
	}
}
//---------------------------------------------------------------------------

// 画黑白调整图像和源图像
void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
	Gdiplus::Graphics *g = new Gdiplus::Graphics(PaintBox1->Canvas->Handle);
	try
	{
		g->DrawImage(Dest, rect);
		if (Sender != NULL)
		{
			g->TranslateTransform(0, rect.Height);
			g->DrawImage(Source, rect);
		}
	}
	__finally
	{
		delete g;
	}
}
//---------------------------------------------------------------------------

// 画混合颜色
void __fastcall TForm1::PaintBox2Paint(TObject *Sender)
{
	if (CheckBox1->Checked)
		PaintBox2->Canvas->Brush->Color =
			(MixColor.Blue << 16) | (MixColor.Green << 8) | MixColor.Red;
	else
		PaintBox2->Canvas->Brush->Color = Color;
	PaintBox2->Canvas->Pen->Color = Color;
	PaintBox2->Canvas->Rectangle(PaintBox2->ClientRect);
}
//---------------------------------------------------------------------------

    界面程序中,实现图像黑白调整功能主要靠Execute函数完成。

    下面是几张程序运行界面图:

    1、缺省黑白调整参数运行界面,其中右上边的下拉编辑框显示的是一些预设黑白效果选项:

    2、选择红外线效果黑白调整参数运行界面:

    3、使用缺省参数进行黑白调整后,再用所选颜色进行着色的界面:

    4、在上面界面基础上,色调不变,加大黄色调参数,使图中人物衣服颜色明亮一些,同时减少蓝色调参数,使人物的围脖颜色变暗一些:

 

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

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

if(strPathName == "") return false; BITMAPFILEHEADER * pBFH; BITMAPINFOHEADER * pBIH; CFile file(strPathName,CFile::modeCreate | CFile::modeNoTruncate | CFile::modeRead); DWORD filelength = file.GetLength(); // 分配一块内存用于装入图象数据 if(m_hDib!=NULL) ::GlobalFree(m_hDib); m_hDib = :: GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,filelength); if(m_hDib==NULL) { return (FALSE); } m_pDib = (BYTE *)::GlobalLock(m_hDib); if(m_pDib==NULL) { ::GlobalFree(m_hDib); return (FALSE); } // 将图象数据读入内存 file.Read(m_pDib,(UINT)filelength); file.Close(); // 读入头信息 pBFH = (BITMAPFILEHEADER *) m_pDib; pBIH = (BITMAPINFOHEADER *) (m_pDib+sizeof(BITMAPFILEHEADER)); WORD bfType = pBFH->bfType; if(bfType!=19778) // "BM"标志 { AfxMessageBox("Not a valid BMP image!"); return FALSE; } //得到位图信息 m_nWidth = (int)pBIH->biWidth; m_nHeight = (int)pBIH->biHeight; m_nBits = (int)pBIH->biBitCount; m_nColors = (int)pBIH->biClrUsed; if(m_nColors == 0) { if(m_nBits <= 8) m_nColors = 1 << m_nBits; } m_strPathName = strPathName; // 载入调色板 m_Palette.DeleteObject(); if( m_nBits <= 8 ) m_nPaletteInBytes = m_nColors * sizeof( RGBQUAD ); if( m_nBits <= 8 ) { RGBQUAD *pRGBPalette; pRGBPalette = ( RGBQUAD * )&m_pDib[ sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) ]; LOGPALETTE *pLogPalette; pLogPalette = ( LOGPALETTE * )new char[ sizeof( LOGPALETTE ) + m_nColors * sizeof( PALETTEENTRY ) ]; pLogPalette->palVersion = 0x300; pLogPalette->palNumEntries = ( unsigned short )m_nColors; for(int i=0; i<m_nColors; i++ ) { pLogPalette->palPalEntry[ i ].peRed = pRGBPalette[ i ].rgbRed; pLogPalette->palPalEntry[ i ].peGreen = pRGBPalette[ i ].rgbGreen; pLogPalette->palPalEntry[ i ].peBlue = pRGBPalette[ i ].rgbBlue; pLogPalette->palPalEntry[ i ].peFlags = 0; } if( pLogPalette == NULL ) { ::GlobalUnlock( m_hDib ); return FALSE; } m_Palette.CreatePalette( pLogPalette ); delete[] pLogPalette; }
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值