c++ - 将灰度转换为 Rgb
问题描述
这是我的完整代码- 代码的摘录在问题的底部。
我的功能policz
和koloruj
. 我需要将灰度位图转换为 rgb。
有一个表格显示位图应如何从 转换n(greyscale)
为 rgb(color)
. 运行下面的代码片段显示了应该如何转换位图:
<table align="center"><tr><b><th align="center">n</th><th align="center">r<sub>n</sub></th><th align="center">g<sub>n</sub></th><th align="center">b<sub>n</sub></th></b></tr><tr><td align="center">0</td><td align="center">0</td><td align="center">0</td><td align="center">0</td></tr><tr><td align="center">1-85</td><td align="center">r<sub>n-1</sub>+3</td><td align="center">0</td><td align="center">0</td></tr><tr><td align="center">86</td><td align="center">255</td><td align="center">0</td><td align="center">0</td></tr><tr><td align="center">87-170</td><td align="center">255</td><td align="center">g<sub>n-1</sub>+3</td><td align="center">0</td></tr><tr><td align="center">171</td><td align="center">255</td><td align="center">255</td><td align="center">0</td></tr><tr><td align="center">172-255</td><td align="center">255</td><td align="center">255</td><td align="center">b<sub>n-1</sub>+3</td></tr></table>
int policz(int i, char rgb, kolor tab[])
{
int p;
switch (rgb)
{
case 'r':
p = tab[i-1].R+3;
if(p>255)
{
return 255;
}
else return p;
break;
case 'g':
p= tab[i-1].G+3;
if(p>255)
{
return 255;
}
else return p;
break;
case 'b':
p= tab[i-1].B+3;;
if(p>255)
{
return 255;
}
else return p;
break;
}
}
void koloruj(unsigned char tab[], kolor tab_k[], BITMAPINFOHEADER ob)
{
char rgb;
for(int i=0; i<ob.biSizeImage/3; i++)
{
if(tab[i]==0)
{
tab_k[i].R=0;
tab_k[i].G=0;
tab_k[i].B=0;
}
NULL;
if(tab[i]>0 && tab[i]<86)
{
rgb = 'r';
tab_k[i].R=policz(i, rgb,tab_k);
tab_k[i].G=0;
tab_k[i].B=0;
}
NULL;
if(tab[i]==86)
{
tab_k[i].R=255;
tab_k[i].G=0;
tab_k[i].B=0;
}
NULL;
if(tab[i]>86 && tab[i]<171)
{
rgb = 'b';
tab_k[i].R=255;
tab_k[i].G=policz(i, rgb,tab_k);
tab_k[i].B=0;
}
NULL;
if(tab[i]==171)
{
tab_k[i].R=255;
tab_k[i].G=255;
tab_k[i].B=0;
}
NULL;
if(tab[i]>171 && tab[i]<256)
{
rgb = 'b';
tab_k[i].R=255;
tab_k[i].G=255;
tab_k[i].B=policz(i, rgb, tab_k);
}
NULL;
}
}
我猜在两者的 1 个功能中的代码我都有错误,这让我很紧张
解决方案
首先,您的程序正在泄漏内存。尽量远离使用new
. 请改用智能指针。这是您main()
重写以使用的片段std::unique_ptr
:
std::unique_ptr<uint8_t[]> pixmap =
std::make_unique<uint8_t[]>(PictureInfo.biSizeImage / 3);
std::unique_ptr<kolor[]> kolormap =
std::make_unique<kolor[]>(PictureInfo.biSizeImage / 3);
odczytaj_obraz(obraz, pixmap.get(), PictureInfo);
koloruj(pixmap.get(), kolormap.get(), PictureInfo);
其次,您对BITMAPFILEHEADER和BITMAPINFOHEADER的定义不正确。复制并转换后,它们应如下所示:
using WORD = uint16_t;
using DWORD = uint32_t;
using LONG = int32_t;
struct BITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
};
struct BITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
};
当涉及到实际转换时,如果我正确阅读表格,它可以简化为:
<table align="center"><tr><b><th align="center">n</th><th align="center">r<sub>n</sub></th><th align="center">g<sub>n</sub></th><th align="center">b<sub>n</sub></th></b></tr> <tr><td align="center">0-85</td><td align="center">n*3</td><td align="center">0</td><td align="center">0</td></tr> <tr><td align="center">86-171</td><td align="center">255</td><td align="center">(n-86)*3</td><td align="center">0</td></tr> <tr><td align="center">172-255</td><td align="center">255</td><td align="center">255</td><td align="center">(n-171)*3</td></tr></table>
在这种情况下,可以像这样进行转换:
struct rgb_t {
uint8_t r, g, b;
};
inline uint8_t scale(uint8_t n, uint8_t cutover) {
return (n-cutover)*3;
}
rgb_t gray2rgb(uint8_t n) {
static constexpr uint8_t cutover_rg = 86;
static constexpr uint8_t cutover_gb = 171;
if(n < cutover_rg) return {scale(n, 0), 0, 0};
if(n <= cutover_gb) return {255, scale(n, cutover_rg), 0};
return {255, 255, scale(n, cutover_gb)};
}
有趣的价值观:
n r g b
---------------------------
0 0 0 0
1 3 0 0
85 255 0 0
86 255 0 0
87 255 3 0
170 255 252 0
171 255 255 0
172 255 255 3
254 255 255 249
255 255 255 252
从这个输出中,n 85和 n 86给出相同的 rgb 值,而 n 255不会导致 b 为 255,感觉应该调整表格:
<table align="center"><tr><b><th align="center">n</th><th align="center">r<sub>n</sub></th><th align="center">g<sub>n</sub></th><th align="center">b<sub>n</sub></th></b></tr> <tr><td align="center">0-85</td><td align="center">n*3</td><td align="center">0</td><td align="center">0</td></tr> <tr><td align="center">86-170</td><td align="center">255</td><td align="center">(n-85)*3</td><td align="center">0</td></tr> <tr><td align="center">171-255</td><td align="center">255</td><td align="center">255</td><td align="center">(n-170)*3</td></tr></table>
rgb_t gray2rgb_improved(uint8_t n) {
static constexpr uint8_t cutover_rg = 85;
static constexpr uint8_t cutover_gb = 170;
if(n <= cutover_rg) return {scale(n, 0), 0, 0};
if(n <= cutover_gb) return {255, scale(n, cutover_rg), 0};
return {255, 255, scale(n, cutover_gb)};
}
现在,这些值将与原始表不匹配,但会平均填充整个频谱:
n r g b
---------------------------
0 0 0 0
1 3 0 0
84 252 0 0
85 255 0 0
86 255 3 0
87 255 6 0
169 255 252 0
170 255 255 0
171 255 255 3
172 255 255 6
254 255 255 252
255 255 255 255
虽然gray2rgb()
可能会按照您的表格所说的那样做,但gray2rgb_improved()
可能会更好。
推荐阅读
- plc - 如何在没有 PLC 的情况下运行 Twincat 程序?
- flutter - 如何将使用相机包录制的视频保存到 Flutter 中的图库?
- python - 无法在 Powershell 中的同一网络上的远程计算机上激活 conda 虚拟环境
- python - 在 Python 中使用条件值进行投资组合优化
- php - 有没有办法在不使用“_server”超级全局变量的情况下做到这一点?`PhraseBuilder::comparePhrases`
- r - 从 R 脚本调用两个闪亮的应用程序
- python - Facebook Prophet API 文档
- python - 使用用户名和密码登录时未提供身份验证凭据
- svg - 如何在 Timber 中将上传的 SVG 输出为代码
- authentication - 客户端身份验证与客户端设备上存在 TPM 时的密码身份验证