Во-первых, у вашей программы есть утечка памяти. Старайтесь не использовать 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)};
}
Демонстрация gray2rgb ()
Интересные значения:
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)};
}
Демонстрация gray2rgb_improved ()
Теперь значения не будут соответствовать исходной таблице, но заполнить весь спектр одинаково:
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()
, вероятно, лучше.