int png_save_surface(char *filename, SDL_Surface *surf) { FILE *fp; png_structp png_ptr; png_infop info_ptr; int i, colortype; png_bytep *row_pointers; /* Opening output file */ fp = fopen(filename, "wb"); if (fp == NULL) { conAdd(LERR, "png_save %s : %s", filename, strerror(errno)); return -1; } /* Initializing png structures and callbacks */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_user_error, png_user_warn); if (png_ptr == NULL) { conAdd(LERR, "png_save: png_create_write_struct error!"); return -1; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); conAdd(LERR, "png_save: png_create_info_struct error!"); return -1; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return -1; } png_init_io(png_ptr, fp); colortype = png_colortype_from_surface(surf); png_set_IHDR(png_ptr, info_ptr, surf->w, surf->h, 8, colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Writing the image */ png_write_info(png_ptr, info_ptr); png_set_packing(png_ptr); row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*surf->h); for (i = 0; i < surf->h; i++) row_pointers[i] = (png_bytep)(Uint8 *)surf->pixels + i*surf->pitch; png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); /* Cleaning out... */ free(row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return 0; }
int IMG_SavePNG_RW (SDL_Surface *face, SDL_RWops *src) { png_structp png_ptr = 0; png_infop info_ptr = NULL; //png_colorp palette = 0; png_bytep *row_pointers = NULL; int i; int colortype; int result = -1; png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, png_user_error, png_user_warn); if (png_ptr == NULL) { IMG_SetError ("Couldn't allocate memory for PNG file"); return -1; } /* Allocate/initialize the image information data. REQUIRED */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { IMG_SetError("Couldn't create image information for PNG file"); goto done; } /* Set error handling. */ if (setjmp(png_jmpbuf(png_ptr))) { /* If we get here, we had a problem reading the file */ IMG_SetError("Error writing the PNG file"); goto done; } png_set_write_fn (png_ptr, src, png_write_data, png_io_flush); /* Set the image information here. Width and height are up to 2^31, * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also * depend on the color_type selected. color_type is one of * PNG_COLOR_TYPE_GRAY, PNG_COLOR_TYPE_GRAY_ALPHA, * PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, or * PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or * PNG_INTERLACE_ADAM7, and the compression_type and filter_type * MUST currently be PNG_COMPRESSION_TYPE_BASE and * PNG_FILTER_TYPE_BASE. REQUIRED */ colortype = png_colortype_from_surface (face); png_set_IHDR (png_ptr, info_ptr, face->w, face->h, 8, colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* Write the file header information. REQUIRED */ png_write_info (png_ptr, info_ptr); /* pack pixels into bytes */ png_set_packing (png_ptr); /* Create the array of pointers to image data */ row_pointers = (png_bytep*) malloc (sizeof(png_bytep)*face->h); if (row_pointers == NULL) { IMG_SetError("Couldn't allocate PNG row pointers"); goto done; } for (i = 0; i < face->h; i++) row_pointers[i] = (png_bytep)(Uint8 *)face->pixels + i*face->pitch; /* write out the entire image data in one call */ png_write_image (png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); result = 0; /* success! */ done: if (row_pointers != NULL) free (row_pointers); if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); png_destroy_write_struct (&png_ptr, (png_infopp)NULL); return result; }
/* This is taken from http://encelo.netsons.org/programming/sdl (GPLed) */ void *sdl_surface_to_png(SDL_Surface *surf, size_t *out_sz) { png_structp png_ptr; png_infop info_ptr; int i, colortype; png_bytep *row_pointers; png_colorp palette; struct png_write_user_struct out; if (!surf) return NULL; out.sz = 0; out.data = NULL; /* Initializing png structures and callbacks */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_user_error, png_user_warn); if (png_ptr == NULL) { printf("png_create_write_struct error!\n"); return NULL; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); printf("png_create_info_struct error!\n"); exit(-1); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); exit(-1); } png_set_write_fn(png_ptr, (void *)&out, user_write_fn, NULL); colortype = png_colortype_from_surface(surf); png_set_IHDR(png_ptr, info_ptr, surf->w, surf->h, 8, colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (colortype & PNG_COLOR_MASK_PALETTE) { /* Set the palette if there is one. REQUIRED for indexed-color images */ palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof(png_color)); /* KLUDGE! For some reason, surf->format->palette doesn't work... */ for (int i = 0; i < PALETTE_SIZE; i++) { SDL_Color *p = &sdl_palette[i]; palette[i].red = p->r; palette[i].green = p->g; palette[i].blue = p->b; } /* ... Set palette colors ... */ png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); } /* Writing the image */ png_write_info(png_ptr, info_ptr); png_set_packing(png_ptr); row_pointers = (png_bytep*) xmalloc(sizeof(png_bytep)*surf->h); for (i = 0; i < surf->h; i++) row_pointers[i] = (png_bytep)(Uint8 *)surf->pixels + i*surf->pitch; png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); /* Cleaning out... */ free(row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); *out_sz = out.sz; return out.data; }