SOIL을 사용하여 이미지를 BMP로 저장했지만 SOIL (또는 stbi가 더 구체적 임) ~ 5MB 이미지 (약 1366x768 해상도 이미지 이상)가 저장되는 것으로 나타났습니다.). 그것은 아주 미쳤다.libpng를 사용하여 OpenGL 화면 픽셀을 PNG로 저장
원래 BMP 절약 코드 ( 모두가 렌더링 기능에서 수행 주) :
bool save_png_libpng(const char *filename, uint8_t *pixels, int w, int h)
{
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (!png)
return false;
png_infop info = png_create_info_struct(png);
if (!info) {
png_destroy_write_struct(&png, &info);
return false;
}
FILE *fp = fopen(filename, "wb");
if (!fp) {
png_destroy_write_struct(&png, &info);
return false;
}
png_init_io(png, fp);
png_set_IHDR(png, info, w, h, 8 /* depth */, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_colorp palette = (png_colorp)png_malloc(png, PNG_MAX_PALETTE_LENGTH * sizeof(png_color));
if (!palette) {
fclose(fp);
png_destroy_write_struct(&png, &info);
return false;
}
png_set_PLTE(png, info, palette, PNG_MAX_PALETTE_LENGTH);
png_write_info(png, info);
png_set_packing(png);
png_bytepp rows = (png_bytepp)png_malloc(png, h * sizeof(png_bytep));
for (int i = 0; i < h; ++i)
rows[i] = (png_bytep)(pixels + (h - i) * w * 3);
png_write_image(png, rows);
png_write_end(png, info);
png_free(png, palette);
png_destroy_write_struct(&png, &info);
fclose(fp);
delete[] rows;
return true;
}
참고 :
uint8_t *pixels = new uint8_t[w * h * 3];
// copy pixels from screen
glBindTexture(GL_TEXTURE_2D, screenTex);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, w, h);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *)pixels);
// invert pixels (stolen from SOILs source code)
for (int j = 0; j * 2 < h; ++j) {
int x = j * w * 3;
int y = (h - 1 - j) * w * 3;
for (int i = w * 3; i > 0; --i) {
uint8_t tmp = pixels[x];
pixels[x] = pixels[y];
pixels[y] = tmp;
++x;
++y;
}
}
// save the image
int err = SOIL_save_image(fileName, SOIL_SAVE_TYPE_BMP, w, h, 3, pixels);
if (err)
printf("Done\n");
else
printf("Failed\n");
코드 PNG를 저장하기 위해 나는 어떤을 변경하지 않은 원래 코드는 SOIL_save_image
을 save_png
으로 바 꾸었습니다. 여기 실패 후
void PNGAPI
png_write_image(png_structrp png_ptr, png_bytepp image)
{
png_uint_32 i; /* row index */
int pass, num_pass; /* pass variables */
png_bytepp rp; /* points to current row */
if (png_ptr == NULL)
return;
png_debug(1, "in png_write_image");
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Initialize interlace handling. If image is not interlaced,
* this will set pass to 1
*/
num_pass = png_set_interlace_handling(png_ptr);
#else
num_pass = 1;
#endif
/* Loop through passes */
for (pass = 0; pass < num_pass; pass++)
{
/* Loop through image */
for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
{
png_write_row(png_ptr, *rp); // HERE
}
}
}
png_write_row
:
png_write_image(png, rows)
는이 기능이 강조 표시 줄에서 실패
코드는 다음 줄에 실패 (코드에 대한 png_write_row는 여기에 게시하기에 꽤 길기 때문에이 줄 앞에 어떤 일이 발생하는지 궁금하다면 png의 소스 코드에서 pngwrite.c를 확인하십시오.)
/* Copy user's row into buffer, leaving room for filter byte. */
memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes);
P.S : 저는 MinGW에서 정확히 동일한 코드를 사용하고 있었는데 MSVC로 전환했을 때 100 % 정상적으로 작동했습니다. 실패했습니다. 나는 GCC가 마술처럼 여기에서 어떤 일을하는지, 아니면 내 코드의 잘못인지 모르겠다. 그래서 나는 배우기 위해서 알고 싶다.