这段代码实现了将一张图片转换为 HSV 颜色空间,并对其进行亮度调整后再转换回 RGB 颜色空间的功能。

首先,代码引入了一些必要的头文件和命名空间:

#include<iostream>
#include<atlimage.h>
#include<cmath>
using namespace std;

然后定义了一个 HSV 类,包含了色度 (H)、饱和度 (S) 和亮度 (V) 三个成员变量:

class HSV
{
public:
	double H;//色度[0,360)
	double S;//饱和度[0,1]
	double V;//亮度[0,1]
	HSV() {}
	HSV(double h, double s, double v) :H(h), S(s), V(v) {}
};

接下来定义了一些辅助函数:

  • getMax 函数用于返回三个参数的最大值。
double getMax(double a, double b, double c)
{
	//需要实现,返回三个参数的最大值
	return max(max(a, b), c);
}
  • getMin 函数用于返回三个参数的最小值。
double getMin(double a, double b, double c)
{
	//需要实现,返回三个参数的最小值
	return min(min(a, b), c);
}
  • getMod 函数用于计算一个浮点数对另一个整数取模的结果。
double getMod(double a, int b)
{
	return a - (int)(a / b) * b;
}

接下来是两个重要的函数:

  • RGB2HSV 函数将一个 RGB 颜色 (COLORREF 类型) 转换为 HSV 颜色 (HSV 类型)。
HSV RGB2HSV(COLORREF c)
{
	//需要实现,把 COLORREF(RGB)类对象 c 转换为 HSV 类对象,返回
	double R = GetRValue(c);
	double G = GetGValue(c);
	double B = GetBValue(c);
	R = R / 255;
	G = G / 255;
	B = B / 255;
	double V = getMax(R, G, B);
	double S;
	if (V != 0)
		S = (V - getMin(R, G, B)) / V;
	else
		S = 0;
	double H;
	if (V == getMin(R, G, B))
		H = 0;
	else if (V == R)
		H = 60 * (G - B) / (V - getMin(R, G, B));
	else if (V == G)
		H = 120 + (60 * (B - R) / (V - getMin(R, G, B)));
	else if (V == B)
		H = 240 + (60 * (R - G) / (V - getMin(R, G, B)));
	if (H < 0)
		H = H + 360;
	return HSV(H, S, V);
}
  • HSV2RGB 函数将一个 HSV 颜色 (HSV 类型) 转换为 RGB 颜色 (COLORREF 类型)。
COLORREF HSV2RGB(HSV hsv)
{
	//需要实现,把 HSV 类对象 hsv 转换为 COLORREF(RGB)类对象,返回
	double C, X, m;
	double R, G, B;
	double H = hsv.H, S = hsv.S, V = hsv.V;
	C = V * S;
	double mod = getMod(H / 60, 2);
	X = C * (1 - abs(mod - 1));
	m = V - C;
	if (0 <= H && H < 60)
	{
		R = C;
		G = X;
		B = 0;
	}
	else if (60 <= H && H < 120)
	{
		R = X;
		G = C;
		B = 0;
	}
	else if (120 <= H && H < 180)
	{
		R = 0;
		G = C;
		B = X;
	}
	else if (180 <= H && H < 240)
	{
		R = 0;
		G = X;
		B = C;
	}
	else if (240 <= H && H < 300)
	{
		R = X;
		G = 0;
		B = C;
	}
	else if (300 <= H && H < 360)
	{
		R = C;
		G = 0;
		B = X;
	}
	R = round((R + m) * 255);
	G = round((G + m) * 255);
	B = round((B + m) * 255);
	return RGB(R, G, B);
}

最后是主函数 main,其中首先加载了一张图片,并获取了其宽度、高度、位深和像素行宽等信息:

int main()
{
	LPCTSTR srcFilePath = _T("6.jpg");
	LPCTSTR destFilePath = _T("6-ans.jpg");
	CImage srcImage;
	srcImage.Load(srcFilePath);
	int width = srcImage.GetWidth();
	int height = srcImage.GetHeight();
	int bpp = srcImage.GetBPP();
	int pitch = srcImage.GetPitch();
	BYTE* pData = (BYTE*)srcImage.GetBits();

然后通过循环遍历每个像素点,获取其 RGB 值,并将其转换为 HSV 颜色:

for (int x = 0; x < width; x++)
{
	for (int y = 0; y < height; y++)
	{
		BYTE b = *(pData + pitch * y + x * bpp / 8 + 0);
		BYTE g = *(pData + pitch * y + x * bpp / 8 + 1);
		BYTE r = *(pData + pitch * y + x * bpp / 8 + 2);
		COLORREF c = RGB(r, g, b);
		HSV h = RGB2HSV(c);

接下来对 HSV 颜色的亮度进行了调整,具体调整方式如下:

  • 如果亮度 (V) 小于 0.4,则将其乘以 3。
  • 如果亮度 (V) 大于 0.995,则将其除以 1.065。
  • 如果亮度 (V) 大于 0.99,则将其除以 1.06。
  • 如果亮度 (V) 大于 0.985,则将其除以 1.055。
  • 如果亮度 (V) 大于 0.98,则将其除以 1.05。
  • 如果亮度 (V) 大于 0.975,则将其除以 1.045。
  • 如果亮度 (V) 大于 0.97,则将其除以 1.04。
  • 如果亮度 (V) 大于 0.965,则将其除以 1.035。
  • 如果亮度 (V) 大于 0.96,则将其除以 1.03。
  • 如果亮度 (V) 大于 0.955,则将其除以 1.025。
  • 如果亮度 (V) 大于 0.95,则将其除以 1.02。
  • 如果亮度 (V) 大于 0.945,则将其除以 1.015。
		if (h.V < 0.4) h.V *= 3;
		else if (h.V > 0.995)h.V /= 1.065;//0.939
		else if (h.V > 0.99)h.V /= 1.06;//0.938
		else if (h.V > 0.985)h.V /= 1.055;//0.938
		else if (h.V > 0.98)h.V /= 1.05;//0.937
		else if (h.V > 0.975)h.V /= 1.045;//0.937
		else if (h.V > 0.97)h.V /= 1.04;//0.937
		else if (h.V > 0.965)h.V /= 1.035;
		else if (h.V > 0.96)h.V /= 1.03;
		else if (h.V > 0.955)h.V /= 1.025;
		else if (h.V > 0.95)h.V /= 1.02;
		else if (h.V > 0.945)h.V /= 1.015;

最后将调整后的 HSV 颜色转换回 RGB 颜色,并更新原图像的像素值:

		COLORREF ans = HSV2RGB(h);
		*(pData + pitch * y + x * bpp / 8 + 0) = GetBValue(ans);
		*(pData + pitch * y + x * bpp / 8 + 1) = GetGValue(ans);
		*(pData + pitch * y + x * bpp / 8 + 2) = GetRValue(ans);
	}
}

最后保存调整后的图片,并结束程序:

srcImage.Save(destFilePath);
return 0;
}
C++ 图片亮度调整:RGB 到 HSV 转换

原文地址: https://www.cveoy.top/t/topic/o4EF 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录