C++ 图片亮度调整:RGB 到 HSV 转换
这段代码实现了将一张图片转换为 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;
}
原文地址: https://www.cveoy.top/t/topic/o4EF 著作权归作者所有。请勿转载和采集!