C ++ 16-битное градиентное изображение в градациях серого из 2D-массива

В настоящее время я пытаюсь создать 16-битное градиентное изображение в градациях серого, но мои результаты выглядят странно, поэтому я не совсем правильно понимаю. Я надеялся, что кто-нибудь сможет пролить немного знаний на мою проблему. Я думаю, что «растровое изображение» я пишу неправильно? Но я не уверен.

#include "CImg.h"using namespace std;

unsigned short buffer[1250][1250];

void fill_buffer()
{
unsigned short temp_data = 0;
for (int i =0;i < 1250; i++)
{
for (int j =0 ;j < 1250;j++)
{
buffer[i][j] = temp_data;
}
temp_data += 20;
}
}

int main()
{
fill_buffer();
auto hold_arr = (uint8_t *)&buffer[0][0];
cimg_library::CImg<uint8_t> img(hold_arr, 1250, 1250);
img.save_bmp("test.bmp");
return 0;
}

Токовый выход:
Текущий выход

2

Решение

Вы не можете хранить 16-битные образцы в градациях серого в BMP … см. Википедия.

Опция 16 бит на пиксель в BMP позволяет хранить 4 бита красного, 4 бита зеленого, 4 бита синего и 4 бита альфа, но не 16-битного оттенка серого.

24-битный формат позволяет хранить 1 байт для красного, 1 байт для зеленого и один байт для синего, но не 16-битную шкалу серого.

32-битный BMP позволяет хранить 24-битный BMP плюс альфа.

Вам нужно будет использовать PNGили NetPBM Формат PGM или TIFF формат. PGM формат отличный, потому что CImg можно написать, что без каких-либо библиотек, и вы всегда можете использовать ImageMagick преобразовать это во что-нибудь еще, например:

convert image.pgm image.png

или же

convert image.pgm image.jpg

Это работает:

#define cimg_use_png
#define cimg_display 0
#include "CImg.h"
using namespace cimg_library;
using namespace std;

unsigned short buffer[1250][1250];

void fill_buffer()
{
unsigned short temp_data = 0;
for (int i =0;i < 1250; i++)
{
for (int j =0 ;j < 1250;j++)
{
buffer[i][j] = temp_data;
}
temp_data += 65535/1250;
}
}

int main()
{
fill_buffer();
auto hold_arr = (unsigned short*)&buffer[0][0];
cimg_library::CImg<unsigned short> img(hold_arr, 1250, 1250);
img.save_png("test.png");
return 0;
}

введите описание изображения здесь

Обратите внимание, что при запросе CImg чтобы написать файл PNG, вам нужно будет использовать такую ​​команду (с libpng а также zlib) Скомпилировать:

g++-7 -std=c++11 -O3 -march=native -Dcimg_display=0 -Dcimg_use_png  -L /usr/local/lib -lm -lpthread -lpng -lz -o "main" "main.cpp"

Просто для объяснения:

  • -std=c++11 просто устанавливает стандарт C ++
  • -O3 -march=native только для ускорения вещей и строго не требуется
  • -Dcimg_display=0 означает, что все заголовки X11 не анализируются, поэтому компиляция происходит быстрее — однако это означает, что вы не можете отображать изображения из вашей программы, а значит, вы «без головы»
  • -Dcimg_use_png означает, что вы можете читать / записывать изображения в формате PNG, используя libpng вместо того, чтобы устанавливать ImageMagick
  • -lz -lpng означает, что полученный код связан с библиотеками PNG и ZLIB.
3

Другие решения

У вас 8-битная или 16-битная проблема. Вы пишете 16-битные значения, но библиотека интерпретирует их как 8-битные. Это объяснение темных вертикальных полос, которые видны. Он чередуется между младшим и старшим байтами каждого значения, рассматривая их как два отдельных значения пикселей.

И причина «градиентного венецианского слепого» эффекта опять-таки связана только с учетом младшего байта. Это будет цикл от 0 до 240 в 12 шагов, а затем переполнится до 5 на следующем шаге, и так далее.

я — нет cimg_library эксперт, но хорошей отправной точкой может быть замена uint8_tс uint16_t и посмотрим, какой эффект это имеет.

3