Мне интересно, как записать данные пикселей RGB в PNG с помощью библиотеки stb_image?
Я пытаюсь написать массив uint8_t, содержащий все данные.
Я начинаю с пиксельных данных для 160x60 и увеличиваю до 1280x480.
Я сделал тестовый код, который должен сделать серый PNG, но изображение представляет собой просто случайный шум.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
void zFill(char * dest, int num, int amount) // fills string with zeros
{
char str [10];
sprintf(str, "%d", num);
int len = 0;
while (len < amount - strlen(str))
{
strncat(dest, "0", 2);
len++;
}
strncat(dest, str, strlen(str));
}
void save_frame(int frame, uint8_t * data) // Saves image
{
char file[20];
sprintf(file, "output/");
zFill(file, frame, 6);
strncat(file, ".png", 5);
printf("%s\n", file);
uint8_t image[1280 * 480 * 3]; // output image is upscales 8x
int a = 0, b = 0;
for (int y = 0; y < 60; y++)
{
for (int x = 0; x < 160; x++)
{
for (int add_b = 0; add_b < 8; add_b++)
{
for (int add_a = 0; add_a < 8; add_a++)
{
image[(a + add_a) * (b + add_b) * 1] = data[x * y * 1];
image[(a + add_a) * (b + add_b) * 2] = data[x * y * 2];
image[(a + add_a) * (b + add_b) * 3] = data[x * y * 3];
}
}
a = a + 8;
}
a = 0;
b = b + 8;
}
stbi_write_png(file, 1280, 480, 3, image, 1280 * 3);
}
int main()
{
uint8_t image_data[160 * 60 * 3];
for (int y = 0; y < 60; y++)
{
for (int x = 0; x < 160; x++)
{
image_data[x * y *1] = 128;
image_data[x * y *2] = 128;
image_data[x * y *3] = 128;
}
}
save_frame(1, image_data);
return 0;
}
Вот результат:
Посмотрите на функцию stbi_write_png()
uint8_t image_buffer[160*60*3];
будет лучше? Я видел, как это использовалось в примере на C++ unsigned char image[512 * 512];
, но остальная часть кода меня смущала.
Оба будут работать, но unsigned char image[512 * 512];
имеет только один канал. but the rest of the code was confusing to me.
Вы можете опубликовать соответствующий код и спросить о конкретном синтаксисе, который вам непонятен.
Я написал тестовый код, который использует только биты записи изображения. Он создает png, но это просто случайный шум.
x * y *1
Что это за формула?
Ах! Моя математика неверна. должно быть ``` 3 * (y * ширина + x) + 0```. Я изменил это, но теперь получаю только синее изображение.
Вы пытались сохранить его без изменения масштаба? И, пожалуйста, обновите код в вопросе.
да, я удалил бит масштабирования и исправил формулу, и теперь она работает!
Проблема заключалась в неправильной математике и коде масштабирования.
Исправлено: image_data[3 * (y * 160 + x) + 2] = 128;
плюс удален код увеличения масштаба.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
void save_frame(int frame, uint8_t * data) // Saves image
{
char file[PATH_MAX];
sprintf (file, "output/%06d.png", frame);
stbi_write_png(file, 160, 60, 3, data, 160 * 3);
}
int main()
{
uint8_t image_data[160 * 60 * 3];
for (int y = 0; y < 60; y++)
{
for (int x = 0; x < 160; x++)
{
image_data[3 * (y * 160 + x)] = 128;
image_data[3 * (y * 160 + x) + 1] = 128;
image_data[3 * (y * 160 + x) + 2] = 128;
}
}
save_frame(1, image_data);
return 0;
}
Рад, что у вас все заработало, но ваш код шаткий. Избавьтесь от zFill()
это совершенно лишнее. Просто сделайте void save_frame(int frame, uint8_t * data) { char file[PATH_MAX]; sprintf (file, "output/%06d.png", frame); printf ("%s\n", file); stbi_write_png (file, 160, 60, 3, data, 160 * 3); }
Определите PATH_MAX
как что-то разумное. Линукс использует 4096
, я забыл, что делает винда, но не меньше, чем 256
. 20
недостаточно. Можно сделать (отдельными строками) #ifndef PATH_MAX
#define PATH_MAX 4096
#endif
.
Ах, я не знал, что sprintf может это сделать. Спасибо!
Вот короткая очистка вашего кода, который принимает цвет в кодировке html (например, #xxyyzz
с ведущим '#'
или без него) в качестве первого аргумента, а затем создает png этого цвета в размерах, указанных в вашем коде stb Напишите png пример. Дайте мне знать, если у вас есть вопросы.
Вы имеете в виду, что хотите записать необработанный буфер в памяти в файл PNG? Тогда данные в памяти, которые у вас есть, плохо отформатированы. Для полноцветного изображения без альфа-канала вам нужен буфер размером
X * Y * 3
байт. Так себеuint8_t image_buffer[160][60][3];
, сuint8_t
вместо (обычно) 32-битного знакового типаint
.