Я пытаюсь записать 16-битное изображение RGB, используя libpng, где каждый точечный цвет поступает из экземпляра ввода «массив». Следующий код работает, но дает 8-битный код.Создание 16-битного изображения с помощью libpng
template<typename T> void savePNG(Array2<Vec3<T> > *arrayImg, const std::string filename){
/* create file */
FILE *fp = fopen(filename.c_str(), "wb");
if (!fp){
std::runtime_error("[write_png_file] File could not be opened for writing");
return;
}
/* initialize stuff */
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr){
std::runtime_error("[write_png_file] png_create_write_struct failed");
return;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr){
std::runtime_error("[write_png_file] png_create_info_struct failed");
return;
}
if (setjmp(png_jmpbuf(png_ptr))){
std::runtime_error("[write_png_file] Error during init_io");
return;
}
png_init_io(png_ptr, fp);
/* write header */
if (setjmp(png_jmpbuf(png_ptr))){
std::runtime_error("[write_png_file] Error during writing header");
return;
}
png_set_IHDR(png_ptr, info_ptr,
(png_uint_32) arrayImg->dimension[0], (png_uint_32) arrayImg->dimension[1],
(png_byte) 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_write_info(png_ptr, info_ptr);
/* write bytes */
if (setjmp(png_jmpbuf(png_ptr))){
std::runtime_error("[write_png_file] Error during writing bytes");
return;
}
/* Initialize rows of PNG. */
png_bytepp row_pointers = (png_bytepp) malloc (sizeof(png_bytep)*arrayImg->dimension[1]);
for (size_t y = 0; y < arrayImg->dimension[1]; ++y) {
row_pointers[y] = (png_bytep) malloc (png_get_rowbytes(png_ptr,info_ptr));
for (size_t x = 0; x < arrayImg->dimension[0]; ++x) {
for (size_t k = 0; k < 3; k++) {
row_pointers[y][x*3+k] = (uint8_t) (clamp((*arrayImg)[y][x][k],T(0.0),T(1.0))*T(255));
}
}
}
/* Writes PNG. */
png_write_image(png_ptr, (png_bytepp) row_pointers);
/* end write */
if (setjmp(png_jmpbuf(png_ptr))){
std::runtime_error("[write_png_file] Error during end of write");
return;
}
png_write_end(png_ptr, NULL);
/* cleanup heap allocation */
for (size_t y=0; y<arrayImg->dimension[1]; y++){
free(row_pointers[y]);
}
free(row_pointers);
fclose(fp);
}
Следующий код должен содержать 16-битную версию. Она производит изображение, которое имеет правильные размеры, но данные все смещены влево:
template<typename T> void savePNG(Array2<Vec3<T> > *arrayImg, const std::string filename){
/* create file */
FILE *fp = fopen(filename.c_str(), "wb");
if (!fp){
std::runtime_error("[write_png_file] File could not be opened for writing");
return;
}
/* initialize stuff */
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr){
std::runtime_error("[write_png_file] png_create_write_struct failed");
return;
}
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr){
std::runtime_error("[write_png_file] png_create_info_struct failed");
return;
}
if (setjmp(png_jmpbuf(png_ptr))){
std::runtime_error("[write_png_file] Error during init_io");
return;
}
png_init_io(png_ptr, fp);
/* write header */
if (setjmp(png_jmpbuf(png_ptr))){
std::runtime_error("[write_png_file] Error during writing header");
return;
}
png_set_IHDR(png_ptr, info_ptr,
(png_uint_32) arrayImg->dimension[0], (png_uint_32) arrayImg->dimension[1],
(png_byte) 16, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_write_info(png_ptr, info_ptr);
/* write bytes */
if (setjmp(png_jmpbuf(png_ptr))){
std::runtime_error("[write_png_file] Error during writing bytes");
return;
}
/* Initialize rows of PNG. */
png_bytepp row_pointers = (png_bytepp) malloc (sizeof(png_bytep)*arrayImg->dimension[1]);
for (size_t y = 0; y < arrayImg->dimension[1]; ++y) {
row_pointers[y] = (png_bytep) malloc (png_get_rowbytes(png_ptr,info_ptr));
for (size_t x = 0; x < arrayImg->dimension[0]; ++x) {
for (size_t k = 0; k < 3; k++) {
row_pointers[y][x*3+k] = (uint16_t) (clamp((*arrayImg)[y][x][k],T(0.0),T(1.0))*T(65535));
}
}
}
/* Writes PNG. */
png_write_image(png_ptr, (png_bytepp) row_pointers);
/* end write */
if (setjmp(png_jmpbuf(png_ptr))){
std::runtime_error("[write_png_file] Error during end of write");
return;
}
png_write_end(png_ptr, NULL);
/* cleanup heap allocation */
for (size_t y=0; y<arrayImg->dimension[1]; y++){
free(row_pointers[y]);
}
free(row_pointers);
fclose(fp);
}
Мое понимание проблемы заключается в том, что данные в настоящее время получения усечены из-за png_byte, png_bytep и/или типов png_bytepp , Как я могу записать 16-битные данные в два 8 бит?
_ «Что я делаю неправильно?» _ Это слишком расплывчато, [тщательно продумайте] (http://stackoverflow.com/help/mcve)! –
Определить * «не работает» *. –