int saveMMBitmapAsPNG(MMBitmapRef bitmap, const char *path) { FILE *fp = fopen(path, "wb"); PNGWriteInfoRef info; if (fp == NULL) return -1; if ((info = createPNGWriteInfo(bitmap)) == NULL) { fclose(fp); return -1; } png_init_io(info->png_ptr, fp); png_write_png(info->png_ptr, info->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); fclose(fp); destroyPNGWriteInfo(info); return 0; }
uint8_t *createPNGData(MMBitmapRef bitmap, size_t *len) { PNGWriteInfoRef info = NULL; struct io_data data = {NULL, 0, 0}; assert(bitmap != NULL); assert(len != NULL); if ((info = createPNGWriteInfo(bitmap)) == NULL) return NULL; png_set_write_fn(info->png_ptr, &data, &png_append_data, NULL); png_write_png(info->png_ptr, info->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); destroyPNGWriteInfo(info); *len = data.size; return data.buffer; }
/* bool savePNGSprite (FILE * fp, struct spriteBank *sprites, int index, bool sig) { png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fclose (fp); return false; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr){ png_destroy_write_struct(&png_ptr, (png_infopp)NULL); fclose (fp); return false; } png_init_io(png_ptr, fp); if (!sig) png_set_sig_bytes(png_ptr, 8); const int h = 21, w = 21; png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); unsigned char * row_pointers[h]; unsigned char data[w*h*4]; for (int i = 0; i < h; i++) { row_pointers[i] = data + 4 * i * w; if (!(i % 20) || (i > (h-2))) { for (int x = 0; x < w; x++) { *(unsigned char *)(row_pointers[i]+x*4) = 255; *(unsigned char *)(row_pointers[i]+x*4+1) = 0; *(unsigned char *)(row_pointers[i]+x*4+2) = *(unsigned char *)(row_pointers[i]+x*4+3) = 255; } } else { for (int x = 0; x < w; x++) { if (x % 20 && x < (w-1)) { *(unsigned char *)(row_pointers[i]+x*4) = *(unsigned char *)(row_pointers[i]+x*4+1) = *(unsigned char *)(row_pointers[i]+x*4+2) = 0; *(unsigned char *)(row_pointers[i]+x*4+3) = 0; } else { *(unsigned char *)(row_pointers[i]+x*4) = 255; *(unsigned char *)(row_pointers[i]+x*4+1) = 0; *(unsigned char *)(row_pointers[i]+x*4+2) = 255; *(unsigned char *)(row_pointers[i]+x*4+3) = 255; } } } } png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); return true; } */ bool savePNGSprite (FILE * fp, struct spriteBank *sprites, int index, bool sig) { if (sprites->sprites[index].width < 1) return errorBox ("Error saving", "Can't save a sprite that has no width."); if (sprites->sprites[index].height < 1) { sprites->sprites[index].height = 1; unsigned char * d = new unsigned char [sprites->sprites[index].width*4]; if (!d) return errorBox ("Error saving", "Out of RAM memory."); for (int i = 0; i < sprites->sprites[index].width*4; i++) { d[i] = 0; } delete sprites->sprites[index].data; sprites->sprites[index].data = d; } png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fclose (fp); return false; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr){ png_destroy_write_struct(&png_ptr, (png_infopp)NULL); fclose (fp); return false; } png_init_io(png_ptr, fp); if (!sig) png_set_sig_bytes(png_ptr, 8); png_set_IHDR(png_ptr, info_ptr, sprites->sprites[index].width, sprites->sprites[index].height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); unsigned char * row_pointers[sprites->sprites[index].height]; for (int i = 0; i < sprites->sprites[index].height; i++) { row_pointers[i] = sprites->sprites[index].data + 4*i*sprites->sprites[index].width; } png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); return true; }
int dummyFunc() { // For Broken Sword 2.5 volatile int i; i = clock(); rename("dummyA", "dummyB"); png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_set_write_fn(png_ptr, NULL, NULL, NULL); png_infop info_ptr; png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); png_destroy_write_struct(&png_ptr, &info_ptr); // For lua's usage of libc: very heavy usage so it pulls in sockets? setsockopt(0, 0, 0, NULL, 0); getsockopt(0, 0, 0, NULL, NULL); return i; }
void write_png(char* filename, unsigned w, unsigned h, unsigned char** data, png_text* comments) { FILE* fp = fopen(filename, "wb"); if (!fp) { fprintf(stderr, "ERROR: Could not open output file %s\n", filename); exit(-1); } png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) { fprintf(stderr, "ERROR: Could not open output file %s\n", filename); fclose(fp); exit(-1); } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, 0, 0); fprintf(stderr, "ERROR: Could not open output file %s\n", filename); fclose(fp); exit(-1); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fprintf(stderr, "ERROR: Could not open output file %s\n", filename); fclose(fp); exit(-1); } png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_text(png_ptr, info_ptr, comments, 1); png_set_rows(png_ptr, info_ptr, data); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); fclose(fp); }
void image_write(Image * image, const char *filename) { FILE *file; png_structp png_ptr; png_infop info_ptr; png_bytep *row_pointers; int i; file = fopen(filename, "wb"); assert(file != NULL); png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); assert(png_ptr != NULL); info_ptr = png_create_info_struct(png_ptr); assert(info_ptr != NULL); assert(setjmp(png_jmpbuf(png_ptr)) == 0); png_init_io(png_ptr, file); png_set_IHDR(png_ptr, info_ptr, image->width, image->height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); row_pointers = png_malloc(png_ptr, image->height * sizeof(png_bytep)); assert(row_pointers != NULL); for (i = 0; i < image->height; i++) row_pointers[i] = (png_bytep)(&image->pixel[i*image->width]); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); png_free(png_ptr, row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(file); }
int write_image_png(handle_t handle, picture_t *pic, config_t *config) { png_output_t *h = handle; uint8_t *out_data = malloc(config->width * config->height * 4); uint8_t **rows = calloc(config->height, sizeof(*rows)); picture_t pic_out; struct SwsContext *sws_ctx; int i; pic_out.img.plane[0] = out_data; pic_out.img.plane[1] = pic_out.img.plane[2] = pic_out.img.plane[3] = NULL; pic_out.img.stride[0] = 3 * config->width; pic_out.img.stride[1] = pic_out.img.stride[2] = pic_out.img.stride[3] = 0; sws_ctx = sws_getContext(config->width, config->height, PIX_FMT_YUV420P, config->width, config->height, PIX_FMT_RGB24, SWS_FAST_BILINEAR | SWS_ACCURATE_RND, NULL, NULL, NULL); sws_scale(sws_ctx, pic->img.plane, pic->img.stride, 0, config->height, pic_out.img.plane, pic_out.img.stride); __asm__ volatile ("emms\n\t"); png_set_IHDR(h->png, h->info, config->width, config->height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); for (i = 0; i < config->height; i++) rows[i] = pic_out.img.plane[0] + i * pic_out.img.stride[0]; png_set_rows(h->png, h->info, rows); png_write_png(h->png, h->info, 0, NULL); free(rows); free(out_data); return 0; }
void PngWriter::Compress(unsigned int width, unsigned int height, unsigned int pitch, PixelFormat format) { png_set_IHDR(pimpl_->png_, pimpl_->info_, width, height, pimpl_->bitDepth_, pimpl_->colorType_, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(pimpl_->png_, pimpl_->info_); if (height > 0) { switch (format) { case PixelFormat_Grayscale16: case PixelFormat_SignedGrayscale16: { int transforms = 0; if (Toolbox::DetectEndianness() == Endianness_Little) { transforms = PNG_TRANSFORM_SWAP_ENDIAN; } png_set_rows(pimpl_->png_, pimpl_->info_, &pimpl_->rows_[0]); png_write_png(pimpl_->png_, pimpl_->info_, transforms, NULL); break; } default: png_write_image(pimpl_->png_, &pimpl_->rows_[0]); } } png_write_end(pimpl_->png_, NULL); }
// split out of png_encode to simplify resource cleanup and avoid // "dtor / setjmp interaction" warning. static Status png_encode_impl(Tex* t, png_structp png_ptr, png_infop info_ptr, DynArray* da) { const png_uint_32 w = (png_uint_32)t->w, h = (png_uint_32)t->h; const size_t pitch = w * t->bpp / 8; int colour_type; switch(t->flags & (TEX_GREY|TEX_ALPHA)) { case TEX_GREY|TEX_ALPHA: colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; case TEX_GREY: colour_type = PNG_COLOR_TYPE_GRAY; break; case TEX_ALPHA: colour_type = PNG_COLOR_TYPE_RGB_ALPHA; break; default: colour_type = PNG_COLOR_TYPE_RGB; break; } png_set_write_fn(png_ptr, da, io_write, io_flush); png_set_IHDR(png_ptr, info_ptr, w, h, 8, colour_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); u8* data = tex_get_data(t); std::vector<RowPtr> rows = tex_codec_alloc_rows(data, h, pitch, t->flags, TEX_TOP_DOWN); // PNG is native RGB. const int png_transforms = (t->flags & TEX_BGR)? PNG_TRANSFORM_BGR : PNG_TRANSFORM_IDENTITY; png_set_rows(png_ptr, info_ptr, (png_bytepp)&rows[0]); png_write_png(png_ptr, info_ptr, png_transforms, 0); return INFO::OK; }
void writePNG(const char * filename, const uchar3 * imgData, const int width, const int height) { FILE * fp = fopen(filename,"wb"); png_byte* rowPointers[height]; mainprog_info progInfo; png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, &progInfo, png_error_handler, NULL); png_infop infoPtr = png_create_info_struct(pngPtr); if (setjmp(png_jmpbuf(pngPtr))) { goto png_failure; } png_set_IHDR( pngPtr, infoPtr, width, height, sizeof(unsigned char)*8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); for (int y = 0; y<height; ++y) { rowPointers[y] = (png_byte*)&imgData[y*width]; } png_init_io(pngPtr, fp); png_set_rows(pngPtr,infoPtr,rowPointers); png_write_png(pngPtr,infoPtr,PNG_TRANSFORM_SWAP_ENDIAN,NULL); png_failure: png_destroy_write_struct(&pngPtr,&infoPtr); fclose(fp); }
void wrPng(BYTE *bits, int w, int h, int line, FILE *f) { png_structp png_ptr; png_infop info_ptr; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if(png_ptr){ info_ptr = png_create_info_struct(png_ptr); if(info_ptr){ if(!setjmp(png_jmpbuf(png_ptr))){ png_init_io(png_ptr, f); png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); BYTE **row_pointers = (BYTE**)png_malloc(png_ptr, h*png_sizeof(png_bytep)); for(int i=0; i<h; i++){ row_pointers[i]= bits+(h-i-1)*line; } png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, 0); png_free(png_ptr, row_pointers); } } png_destroy_write_struct(&png_ptr, &info_ptr); } }
WritePng(const char *file_name, grid<T> &grd){ transforms = PNG_TRANSFORM_IDENTITY; status = PENDING; this->grd = &grd; FILE *fp = fopen(file_name, "wb"); if (!fp){ status = FILE_ERROR; return; } png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); if (!png_ptr){ status = PNG_ERROR; return; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr){ png_destroy_write_struct(&png_ptr, (png_infopp)NULL); status = PNG_ERROR; return; } png_init_io(png_ptr, fp); setup_png(); setup_rows(); png_set_rows(png_ptr, info_ptr, rows); png_write_png(png_ptr, info_ptr, transforms, NULL); status = OK; fclose(fp); return; };
/** * RGB byte [8 bits per channel] buffer to PNG file. * * @param uint8_t *buffer * @param int width * @param int height * @param char *path * @return -1 on error **/ int buffer_to_png(uint8_t *buffer, int width, int height, char *path) { int x, y, i; int bytes_per_row = width * 3; /* libpng stuff */ png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_byte **row_pointers = NULL; FILE *fp = fopen(path, "wb"); if (!fp) { return -1; } /* Initialize */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); return -1; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_write_struct(&png_ptr, NULL); fclose(fp); return -1; } /* Error Handling */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return -1; } png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Copy RGB buffer into PNG buffer */ row_pointers = png_malloc(png_ptr, height * sizeof(png_byte *)); i = 0; for (y = 0; y < height; ++y) { uint8_t *data = png_malloc(png_ptr, sizeof(uint8_t) * bytes_per_row); row_pointers[y] = (png_byte *)data; for (x = 0; x < width; ++x) { *data++ = buffer[i++]; *data++ = buffer[i++]; *data++ = buffer[i++]; } } /* Write file */ png_init_io(png_ptr, fp); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); /* Free memory, cleanup */ for (y = 0; y < height; y++) { png_free(png_ptr, row_pointers[y]); } png_free(png_ptr, row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return 0; }
int RE_SavePNG( const char *filename, byte *buf, size_t width, size_t height, int byteDepth ) { fileHandle_t fp; png_structp png_ptr = NULL; png_infop info_ptr = NULL; unsigned int x, y; png_byte ** row_pointers = NULL; /* "status" contains the return value of this function. At first it is set to a value which means 'failure'. When the routine has finished its work, it is set to a value which means 'success'. */ int status = -1; /* The following number is set by trial and error only. I cannot see where it it is documented in the libpng manual. */ int depth = 8; fp = ri->FS_FOpenFileWrite( filename ); if ( !fp ) { goto fopen_failed; } png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { goto png_create_write_struct_failed; } info_ptr = png_create_info_struct (png_ptr); if (info_ptr == NULL) { goto png_create_info_struct_failed; } /* Set up error handling. */ if (setjmp (png_jmpbuf (png_ptr))) { goto png_failure; } /* Set image attributes. */ png_set_IHDR (png_ptr, info_ptr, width, height, depth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Initialize rows of PNG. */ row_pointers = (png_byte **)png_malloc (png_ptr, height * sizeof (png_byte *)); for ( y=0; y<height; ++y ) { png_byte *row = (png_byte *)png_malloc (png_ptr, sizeof (uint8_t) * width * byteDepth); row_pointers[height-y-1] = row; for (x = 0; x < width; ++x) { byte *px = buf + (width * y + x)*3; *row++ = px[0]; *row++ = px[1]; *row++ = px[2]; } } /* Write the image data to "fp". */ // png_init_io (png_ptr, fp); png_set_write_fn( png_ptr, (png_voidp)&fp, user_write_data, user_flush_data ); png_set_rows (png_ptr, info_ptr, row_pointers); png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); /* The routine has successfully written the file, so we set "status" to a value which indicates success. */ status = 0; for (y = 0; y < height; y++) { png_free (png_ptr, row_pointers[y]); } png_free (png_ptr, row_pointers); png_failure: png_create_info_struct_failed: png_destroy_write_struct (&png_ptr, &info_ptr); png_create_write_struct_failed: ri->FS_FCloseFile( fp ); fopen_failed: return status; }
/** * Save PNG file from RGB24 buffer * * @param uint32_t *buffer * @param int width * @param int height * @param char *path * @return -1 on error **/ int rgb24_to_png(uint32_t *buffer, int width, int height, char *path) { int x, y; int bytes_per_row = width * 3; uint8_t r, g, b; uint32_t *in = buffer; /* libpng stuff */ png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_byte **row_pointers = NULL; FILE *fp = fopen(path, "wb"); if (!fp) { return -1; } /* Initialize */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); return -1; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_write_struct(&png_ptr, NULL); fclose(fp); return -1; } /* Error Handling */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return -1; } png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Copy RGB buffer into PNG buffer */ row_pointers = png_malloc(png_ptr, height * sizeof(png_byte *)); for (y = 0; y < height; y++) { /* Allocate */ row_pointers[y] = png_malloc(png_ptr, sizeof(uint8_t) * bytes_per_row); for (x = 0; x < width; x++) { /* Unpack pixels */ UNPACK_RGB(r, g, b, tvxx_rgb_format_rgb24, *in); /*UNPACK_RGB(r, g, b, tvxx_rgb_format_rgb15, *in); r *= (255/31); g *= (255/31); b *= (255/31);*/ /* Copy */ row_pointers[y][(x * 3) + 0] = r; row_pointers[y][(x * 3) + 1] = g; row_pointers[y][(x * 3) + 2] = b; /* Increment RGB24 pointer */ in++; } } /* Write file */ png_init_io(png_ptr, fp); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); /* Free memory, cleanup */ for (y = 0; y < height; y++) { png_free(png_ptr, row_pointers[y]); } png_free(png_ptr, row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return 0; }
bool save_heightmap_png(long double lat, long double lon, long double span_h, long double span_w, const char *outfile) { int x1, x2, y1, y2; bool ret = false; FILE *fp = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; size_t x, y, w, h, skip; png_bytepp row_pointers; png_bytep row; int16_t elevation, height; /* Pointer to humongous (7GB) S_MAPW x S_MAPH 16-bit map data (see map.c) */ int16_t *mapp = (int16_t *)map[0]; /* Map longitude/latidude to pixel coordinates in source image */ x1 = ((lon + 180.0) / (long double)360) * S_MAPW; x2 = (((lon + span_w) + 180.0) / (long double)360) * S_MAPW - 1; y1 = ((90 - lat) / (long double)180) * S_MAPH; y2 = ((90 - (lat - span_h)) / (long double)180) * S_MAPH - 1; w = x2 - x1 + 1; h = y2 - y1 + 1; printf("%s: %dx%d ... ", outfile, (int)w, (int)h); fflush(stdout); /* Advance mapp to first pixel */ mapp += (uint64_t)x1 + (uint64_t)S_MAPW * (uint64_t)y1; /* Skip this many int16_t:s to get to next line */ skip = S_MAPW - w; /* libpng stuff below */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { goto out; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_write_struct(&png_ptr, NULL); goto out; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); goto out; } /* Specify 16-bit grayscale in png header */ png_set_IHDR(png_ptr, info_ptr, w, h, 16, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Alloc mem for png image data */ row_pointers = (png_bytepp)png_malloc(png_ptr, h * png_sizeof(png_bytep)); for (y = 0; y < h; y++) { row_pointers[y] = png_malloc(png_ptr, w * 2); } /* Copy image data from mapp to row_pointers */ for (y = 0; y < h; y++) { row = row_pointers[y]; for (x = 0; x < w; x++) { /* Read 2 big endian source bytes */ elevation = *mapp++; /* Clamp negative heights to 0 */ height = ntohs(elevation); /* swap bytes if little endian */ if (height < 0) { elevation = 0; } /* Write 2 bytes to destination */ *row++ = (png_byte)(elevation & 0xff); *row++ = (png_byte)(elevation >> 8); } mapp += skip; } /* Write image data to fp */ if (!(fp = fopen(outfile, "w"))) { perror(outfile); goto out2; } png_init_io(png_ptr, fp); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); ret = true; out2: /* Cleanup. */ for (y = 0; y < h; y++) { png_free(png_ptr, row_pointers[y]); } png_free(png_ptr, row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); if (fp) { fclose(fp); } out: if (ret) { puts("ok"); } else { puts("fail"); } return ret; }
bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ if (!file || !image) return false; // Allocate the png write struct png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)png_cpexcept_error, NULL); if (!png_ptr) { os::Printer::log("PNGWriter: Internal PNG create write struct failure\n", file->getFileName(), ELL_ERROR); return false; } // Allocate the png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { os::Printer::log("PNGWriter: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR); png_destroy_write_struct(&png_ptr, NULL); return false; } // for proper error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); return false; } png_set_write_fn(png_ptr, file, user_write_data_fcn, NULL); // Set info switch(image->getColorFormat()) { case ECF_A8R8G8B8: case ECF_A1R5G5B5: png_set_IHDR(png_ptr, info_ptr, image->getDimension().Width, image->getDimension().Height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); break; default: png_set_IHDR(png_ptr, info_ptr, image->getDimension().Width, image->getDimension().Height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } s32 lineWidth=image->getDimension().Width; switch(image->getColorFormat()) { case ECF_R8G8B8: case ECF_R5G6B5: lineWidth*=3; break; case ECF_A8R8G8B8: case ECF_A1R5G5B5: lineWidth*=4; break; } u8* tmpImage = new u8[image->getDimension().Height*lineWidth]; if (!tmpImage) { os::Printer::log("PNGWriter: Internal PNG create image failure\n", file->getFileName(), ELL_ERROR); png_destroy_write_struct(&png_ptr, &info_ptr); return false; } u8* data = (u8*)image->lock(); switch(image->getColorFormat()) { case ECF_R8G8B8: CColorConverter::convert_R8G8B8toR8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage); break; case ECF_A8R8G8B8: CColorConverter::convert_A8R8G8B8toA8R8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage); break; case ECF_R5G6B5: CColorConverter::convert_R5G6B5toR8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage); break; case ECF_A1R5G5B5: CColorConverter::convert_A1R5G5B5toA8R8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage); break; } image->unlock(); // Create array of pointers to rows in image data //Used to point to image rows u8** RowPointers = new png_bytep[image->getDimension().Height]; if (!RowPointers) { os::Printer::log("PNGWriter: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR); png_destroy_write_struct(&png_ptr, &info_ptr); delete [] tmpImage; return false; } data=tmpImage; // Fill array of pointers to rows in image data for (u32 i=0; i<image->getDimension().Height; ++i) { RowPointers[i]=data; data += lineWidth; } // for proper error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); delete [] RowPointers; delete [] tmpImage; return false; } png_set_rows(png_ptr, info_ptr, RowPointers); if (image->getColorFormat()==ECF_A8R8G8B8 || image->getColorFormat()==ECF_A1R5G5B5) png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, NULL); else { png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); } delete [] RowPointers; delete [] tmpImage; png_destroy_write_struct(&png_ptr, &info_ptr); return true; #else return false; #endif }
void impl_save_png ( const std::string& file_name, std::vector<unsigned char*>& row_pointers, const long width, const png_type type, const int bit_depth ) { FILE *fp; png_structp png_ptr; png_infop info_ptr; /* Open the file */ fp = fopen(file_name.c_str(), "wb"); if (fp == NULL) throw image_save_error("Unable to open " + file_name + " for writing."); /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also check that * the library version is compatible with the one used at compile time, * in case we are using dynamically linked libraries. REQUIRED. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &png_reader_user_error_fn_silent, &png_reader_user_warning_fn_silent); if (png_ptr == NULL) { fclose(fp); throw image_save_error("Error while writing PNG file " + file_name); } /* Allocate/initialize the image information data. REQUIRED */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_write_struct(&png_ptr, NULL); throw image_save_error("Error while writing PNG file " + file_name); } /* Set error handling. REQUIRED if you aren't supplying your own * error handling functions in the png_create_write_struct() call. */ if (setjmp(png_jmpbuf(png_ptr))) { /* If we get here, we had a problem writing the file */ fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); throw image_save_error("Error while writing PNG file " + file_name); } int color_type = 0; switch(type) { case png_type_rgb: color_type = PNG_COLOR_TYPE_RGB; break; case png_type_rgb_alpha: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break; case png_type_gray: color_type = PNG_COLOR_TYPE_GRAY; break; default: { fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); throw image_save_error("Invalid color type"); } } /* Set up the output control if you are using standard C streams */ png_init_io(png_ptr, fp); const int png_transforms = PNG_TRANSFORM_IDENTITY; const long height = row_pointers.size(); png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_rows(png_ptr, info_ptr, &row_pointers[0]); png_write_png(png_ptr, info_ptr, png_transforms, NULL); /* Clean up after the write, and free any memory allocated */ png_destroy_write_struct(&png_ptr, &info_ptr); /* Close the file */ fclose(fp); }
void save_as_png(T1 & file, T2 const& image, int compression = Z_DEFAULT_COMPRESSION, int strategy = Z_DEFAULT_STRATEGY, int alpha = false, bool use_miniz = false) { if (use_miniz) { MiniZ::PNGWriter writer(compression); if (alpha) { writer.writeIHDR(image.width(), image.height(), 32); writer.writeIDAT(image); } else { writer.writeIHDR(image.width(), image.height(), 24); writer.writeIDATStripAlpha(image); } writer.writeIEND(); writer.toStream(file); return; } png_voidp error_ptr=0; png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, error_ptr,0, 0); if (!png_ptr) return; // switch on optimization only if supported #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) && defined(PNG_MMX_CODE_SUPPORTED) png_uint_32 mask, flags; flags = png_get_asm_flags(png_ptr); mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE); png_set_asm_flags(png_ptr, flags | mask); #endif png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE); png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr,(png_infopp)0); return; } jmp_buf* jmp_context = (jmp_buf*) png_get_error_ptr(png_ptr); if (jmp_context) { png_destroy_write_struct(&png_ptr, &info_ptr); return; } png_set_write_fn (png_ptr, &file, &write_data<T1>, &flush_data<T1>); png_set_compression_level(png_ptr, compression); png_set_compression_strategy(png_ptr, strategy); png_set_compression_buffer_size(png_ptr, 32768); png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(), 8, alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_bytep row_pointers[image.height()]; for (unsigned int i = 0; i < image.height(); i++) { row_pointers[i] = (png_bytep)image.getRow(i); } png_set_rows(png_ptr, info_ptr, (png_bytepp)&row_pointers); png_write_png(png_ptr, info_ptr, alpha ? PNG_TRANSFORM_IDENTITY : PNG_TRANSFORM_STRIP_FILLER_AFTER, NULL); png_destroy_write_struct(&png_ptr, &info_ptr); }
void SavePng(const Image<unsigned char>& image, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first) { PANGOLIN_UNUSED(image); PANGOLIN_UNUSED(filename); PANGOLIN_UNUSED(top_line_first); // Check image has supported bit depth for(unsigned int i=1; i < fmt.channels; ++i) { if( fmt.channel_bits[i] != fmt.channel_bits[0] ) { throw std::runtime_error("PNG Saving only supported for images where each channel has the same bit depth."); } } #ifdef HAVE_PNG FILE *fp; png_structp png_ptr; png_infop info_ptr; // Open file for writing (binary mode) fp = fopen(filename.c_str(), "wb"); if (fp == NULL) { throw std::runtime_error( "PNG Error: Could not open file '" + filename + "' for writing" ); } // Initialize write structure png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); throw std::runtime_error( "PNG Error: Could not allocate write struct." ); } // Initialize info structure info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); fclose(fp); throw std::runtime_error( "PNG Error: Could not allocate info struct." ); } // Setup Exception handling if (setjmp(png_jmpbuf(png_ptr))) { png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); png_destroy_write_struct(&png_ptr, (png_infopp)NULL); fclose(fp); throw std::runtime_error( "PNG Error: Error during png creation." ); } png_init_io(png_ptr, fp); const int bit_depth = fmt.channel_bits[0]; int colour_type; switch (fmt.channels) { case 1: colour_type = PNG_COLOR_TYPE_GRAY; break; case 2: colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; case 3: colour_type = PNG_COLOR_TYPE_RGB; break; case 4: colour_type = PNG_COLOR_TYPE_RGBA; break; default: throw std::runtime_error( "PNG Error: unexpected image channel number"); } // Write header png_set_IHDR( png_ptr, info_ptr, (png_uint_32)image.w, (png_uint_32)image.h, bit_depth, colour_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); // Setup rows to write: std::vector<png_bytep> rows(image.h); if(top_line_first) { for (unsigned int y = 0; y< image.h; y++) { rows[y] = image.ptr + y*image.pitch; } }else{ for (unsigned int y = 0; y< image.h; y++) { rows[y] = image.ptr + (image.h-1-y)*image.pitch; } } png_set_rows(png_ptr,info_ptr, &rows[0]); // Write image data: switch to little-endian byte order, to match host. png_write_png(png_ptr,info_ptr, PNG_TRANSFORM_SWAP_ENDIAN, 0); // Free resources fclose(fp); png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); png_destroy_write_struct(&png_ptr, (png_infopp)NULL); #else throw std::runtime_error("PNG Support not enabled. Please rebuild Pangolin."); #endif }
/* Save the two dimensional array as a png image * Arguments: * double *data is a pointer to an array of nx*ny values * int nx is the number of COLUMNS to be written * int ny is the number of ROWS to be written * char *fname is the name of the picture * char lang is either 'c' or 'f' denoting the memory * layout. That is, if 'f' is given, then rows * and columns are swapped. */ int save_png(double *data, const int height, const int width, const char *fname, const char lang) { FILE *fp; png_structp pngstruct_ptr = NULL; png_infop pnginfo_ptr = NULL; png_byte **row_pointers = NULL; int i, j; /* Default return status is failure */ int status = -1; int pixel_size = 3; int depth = 8; fp = fopen(fname, "wb"); if (fp == NULL) goto fopen_failed; pngstruct_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (pngstruct_ptr == NULL) goto pngstruct_create_failed; pnginfo_ptr = png_create_info_struct(pngstruct_ptr); if (pnginfo_ptr == NULL) goto pnginfo_create_failed; if (setjmp(png_jmpbuf(pngstruct_ptr))) goto setjmp_failed; png_set_IHDR(pngstruct_ptr, pnginfo_ptr, (size_t) width, (size_t) height, depth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); row_pointers = png_malloc(pngstruct_ptr, height * sizeof(png_byte *)); for (i = 0; i < height; i++) { png_byte *row = png_malloc(pngstruct_ptr, sizeof(uint8_t) * width * pixel_size); row_pointers[i] = row; // Branch according to the memory layout if (lang == 'c' || lang == 'C') { for (j = 0; j < width; j++) { pixel_t pixel; // Scale the values so that values between // 0 and 100 degrees are mapped to values // between 0 and 255 cmap(data[j + i * width], 2.55, 0.0, &pixel); *row++ = pixel.red; *row++ = pixel.green; *row++ = pixel.blue; } } else { for (j = 0; j < width; j++) { pixel_t pixel; // Scale the values so that values between // 0 and 100 degrees are mapped to values // between 0 and 255 cmap(data[i + j * height], 2.55, 0.0, &pixel); *row++ = pixel.red; *row++ = pixel.green; *row++ = pixel.blue; } } } png_init_io(pngstruct_ptr, fp); png_set_rows(pngstruct_ptr, pnginfo_ptr, row_pointers); png_write_png(pngstruct_ptr, pnginfo_ptr, PNG_TRANSFORM_IDENTITY, NULL); status = 0; for (i = 0; i < height; i++) { png_free(pngstruct_ptr, row_pointers[i]); } png_free(pngstruct_ptr, row_pointers); setjmp_failed: pnginfo_create_failed: png_destroy_write_struct(&pngstruct_ptr, &pnginfo_ptr); pngstruct_create_failed: fclose(fp); fopen_failed: return status; }
void SavePNG( Img const& img, RGBx const* palette, const char* filename ) { assert(img.Format()==Img::INDEXED8BIT); // TODO: set error handler to capture error msg? FILE *fp = fopen(filename, "wb"); if (!fp) { throw Wobbly( "open failed: %s", strerror(errno) ); } png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)0,0,0 ); if (!png_ptr) { fclose(fp); throw Wobbly( "failed writing PNG (png_create_write() failed)" ); } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fclose(fp); png_destroy_write_struct(&png_ptr, (png_infopp)NULL); throw Wobbly( "failed writing PNG (png_create_info_struct() failed)" ); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); throw Wobbly( "failed writing PNG" ); } png_init_io(png_ptr, fp); png_set_IHDR( png_ptr, info_ptr, img.W(), img.H(), 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); { png_color tmp_palette[256]; int i; for(i=0;i<256;++i) { tmp_palette[i].red = palette[i].r; tmp_palette[i].green = palette[i].g; tmp_palette[i].blue = palette[i].b; } png_set_PLTE( png_ptr, info_ptr, tmp_palette, 256 ); } //png_set_bKGD( png_ptr, info_ptr, 0 ); { png_bytep row_pointers[ img.H() ]; int y; for( y=0;y<img.H();++y) row_pointers[y] = (png_bytep)img.PtrConst(0,y); png_set_rows( png_ptr, info_ptr, row_pointers ); png_write_png(png_ptr, info_ptr, 0, NULL); } png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); }
void saveCorePNG (FILE * writer, GLuint texture, int w, int h) { GLint tw, th; glBindTexture (GL_TEXTURE_2D, texture); getTextureDimensions(texture, &tw, &th); GLubyte* image = new GLubyte [tw*th*4]; if (! checkNew (image)) return; glPixelStorei (GL_PACK_ALIGNMENT, 1); // glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, image); setPixelCoords (true); //glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const GLfloat texCoords[] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f }; int xoffset = 0; while (xoffset < tw) { int w = (tw-xoffset < viewportWidth) ? tw-xoffset : viewportWidth; int yoffset = 0; while (yoffset < th) { int h = (th-yoffset < viewportHeight) ? th-yoffset : viewportHeight; glClear(GL_COLOR_BUFFER_BIT); // Clear The Screen const GLfloat vertices[] = { (GLfloat)-xoffset, (GLfloat)-yoffset, 0., (GLfloat)tw-xoffset, (GLfloat)-yoffset, 0., (GLfloat)-xoffset, (GLfloat)-yoffset+th, 0., (GLfloat)tw-xoffset, (GLfloat)-yoffset+th, 0. }; glUseProgram(shader.texture); setPMVMatrix(shader.texture); drawQuad(shader.texture, vertices, 1, texCoords); glUseProgram(0); for (int i = 0; i<h; i++) { glReadPixels(viewportOffsetX, viewportOffsetY+i, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, image+xoffset*4+(yoffset+i)*4*tw); } yoffset += viewportHeight; } xoffset += viewportWidth; } setPixelCoords (false); png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fatal ("Error saving image!"); return; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr){ png_destroy_write_struct(&png_ptr, (png_infopp)NULL); fatal ("Error saving image!"); return; } png_init_io(png_ptr, writer); png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); unsigned char * row_pointers[h]; for (int i = 0; i < h; i++) { row_pointers[i] = image + 4*i*tw; } png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); delete [] image; image = NULL; }
int writepng(char *fname, uint16_t *data, size_t width, size_t height) { int i; FILE *fp; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_byte **row_pointers = NULL; fp = fopen(fname, "wb"); if(!fp) { return -1; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) { fclose(fp); return -1; } info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_write_struct(&png_ptr, NULL); fclose(fp); return -1; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return -1; } png_set_IHDR(png_ptr, info_ptr, width, height, 16, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); row_pointers = png_malloc(png_ptr, height * sizeof(png_byte *)); for (i = 0; i < height; i++) { uint8_t *row = png_malloc(png_ptr, width * 2); row_pointers[i] = (png_byte *)row; memcpy(row_pointers[i], &data[i * width], width * 2); } png_init_io(png_ptr, fp); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); for (i = 0; i < height; i++) { png_free(png_ptr, row_pointers[i]); } png_free(png_ptr, row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return 0; }
void Screendump(const char* destFile, const int width, const int height) { std::string dir = FileSystem::GetUserDir("screenshots"); FileSystem::rawFileSystem.MakeDirectory(dir); std::string fname = FileSystem::JoinPathBelow(dir, destFile); // pad rows to 4 bytes, which is the default row alignment for OpenGL const int stride = (3*width + 3) & ~3; std::vector<png_byte> pixel_data(stride * height); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glPixelStorei(GL_PACK_ALIGNMENT, 4); // never trust defaults glReadBuffer(GL_FRONT); glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, &pixel_data[0]); glFinish(); png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) { fprintf(stderr, "Couldn't create png_write_struct\n"); return; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, 0); fprintf(stderr, "Couldn't create png_info_struct\n"); return; } //http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-3.1 if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fprintf(stderr, "Couldn't set png jump buffer\n"); return; } FILE *out = fopen(fname.c_str(), "wb"); if (!out) { png_destroy_write_struct(&png_ptr, &info_ptr); fprintf(stderr, "Couldn't open %s for writing\n", fname.c_str()); return; } png_init_io(png_ptr, out); png_set_filter(png_ptr, 0, PNG_FILTER_NONE); png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_bytepp rows = new png_bytep[height]; for (int i = 0; i < height; ++i) { rows[i] = reinterpret_cast<png_bytep>(&pixel_data[(height-i-1) * stride]); } png_set_rows(png_ptr, info_ptr, rows); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0); png_destroy_write_struct(&png_ptr, &info_ptr); delete[] rows; fclose(out); printf("Screenshot %s saved\n", fname.c_str()); }
bool SavePng(std::string filename, const DepthImage& img) { // Open up a file for writing FILE* output = fopen(filename.c_str(), "wb"); if (output == NULL) { printf("Failed to open PNG file for writing (errno = %i)\n", errno); return false; } // Create a png pointer with the callbacks above png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, on_png_error, on_png_warn); if (png_ptr == NULL) { fprintf(stderr, "Failed to allocate png write_struct\n"); fclose(output); return false; } // Create an info pointer png_infop info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "Failed to create png info_struct"); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(output); return false; } // Set physical vars png_set_IHDR(png_ptr, info_ptr, img.cols(), img.rows(), 16, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_init_io(png_ptr, output); const float zmax = img.maxCoeff(); const float zmin = (img == -std::numeric_limits<float>::infinity()) .select(DepthImage::Constant(img.rows(), img.cols(), zmax), img) .minCoeff(); auto scaled = (zmax == zmin) ? DepthImage((img - zmin) + 65535) : DepthImage((img - zmin) * 65534 / (zmax - zmin) + 1); Eigen::Array<uint16_t, Eigen::Dynamic, Eigen::Dynamic> pixels = scaled.cast<uint16_t>().transpose(); std::vector<uint16_t*> rows; for (int i=pixels.cols() - 1; i >= 0; --i) { rows.push_back(pixels.data() + i * pixels.rows()); } png_set_rows(png_ptr, info_ptr, reinterpret_cast<png_bytepp>(&rows[0])); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_SWAP_ENDIAN, NULL); fclose(output); png_destroy_write_struct(&png_ptr, &info_ptr); return true; }
// Note: Calls req.Respond(). Other data can be added afterward. static bool StreamBufferToDataURI(DebuggerRequest &req, const GPUDebugBuffer &buf, bool includeAlpha, int stackWidth) { #ifdef USING_QT_UI req.Fail("Not supported on Qt yet, pull requests accepted"); return false; #else u8 *flipbuffer = nullptr; u32 w = (u32)-1; u32 h = (u32)-1; const u8 *buffer = ConvertBufferToScreenshot(buf, includeAlpha, flipbuffer, w, h); if (!buffer) { req.Fail("Internal error converting buffer for PNG encode"); return false; } if (stackWidth > 0) { u32 totalPixels = w * h; w = stackWidth; while ((totalPixels % w) != 0) --w; h = totalPixels / w; } png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (!png_ptr) { req.Fail("Internal error setting up PNG encoder (png_ptr)"); return false; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, nullptr); req.Fail("Internal error setting up PNG encoder (info_ptr)"); return false; } // Speed. Wireless N should give 35 KB/ms. For most devices, zlib/filters will cost more. png_set_compression_strategy(png_ptr, Z_RLE); png_set_compression_level(png_ptr, 1); png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE); auto &json = req.Respond(); json.writeInt("width", w); json.writeInt("height", h); // Start a value... json.writeRaw("uri", ""); req.Flush(); // Now we'll write it directly to the stream. req.ws->AddFragment(false, "\"data:image/png;base64,"); struct Context { DebuggerRequest *req; uint8_t buf[3]; size_t bufSize; }; Context ctx = { &req, {}, 0 }; auto write = [](png_structp png_ptr, png_bytep data, png_size_t length) { auto ctx = (Context *)png_get_io_ptr(png_ptr); auto &req = *ctx->req; // If we buffered some bytes, fill to 3 bytes for a clean base64 encode. // This way we don't have padding. while (length > 0 && ctx->bufSize > 0 && ctx->bufSize != 3) { ctx->buf[ctx->bufSize++] = data[0]; data++; length--; } if (ctx->bufSize == 3) { req.ws->AddFragment(false, Base64Encode(ctx->buf, ctx->bufSize)); ctx->bufSize = 0; } assert(ctx->bufSize == 0 || length == 0); // Save bytes that would result in padding for next time. size_t toBuffer = length % 3; for (size_t i = 0; i < toBuffer; ++i) { ctx->buf[i] = data[length - toBuffer + i]; ctx->bufSize++; } if (length > toBuffer) { req.ws->AddFragment(false, Base64Encode(data, length - toBuffer)); } }; auto flush = [](png_structp png_ptr) { // Nothing, just here to prevent stdio flush. }; png_bytep *row_pointers = new png_bytep[h]; u32 stride = includeAlpha ? w * 4 : w * 3; for (u32 i = 0; i < h; ++i) { row_pointers[i] = (u8 *)buffer + stride * i; } png_set_write_fn(png_ptr, &ctx, write, flush); int colorType = includeAlpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB; png_set_IHDR(png_ptr, info_ptr, w, h, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr); png_destroy_write_struct(&png_ptr, &info_ptr); delete [] row_pointers; delete [] flipbuffer; if (ctx.bufSize > 0) { req.ws->AddFragment(false, Base64Encode(ctx.buf, ctx.bufSize)); ctx.bufSize = 0; } // End the string. req.ws->AddFragment(false, "\""); return true; #endif }
bool writePNG(Common::WriteStream &out, const Graphics::Surface &input, const bool bottomUp) { #ifdef USE_PNG const Graphics::PixelFormat requiredFormat_3byte(3, 8, 8, 8, 0, 16, 8, 0, 0); const Graphics::PixelFormat requiredFormat_4byte(4, 8, 8, 8, 8, 0, 8, 16, 24); if (input.format.bytesPerPixel == 3) { if (input.format != requiredFormat_3byte) { warning("Cannot currently write PNG with 3-byte pixel format other than %s", requiredFormat_3byte.toString().c_str()); return false; } } else if (input.format.bytesPerPixel != 4) { warning("Cannot currently write PNG with pixel format of bpp other than 3, 4"); return false; } int colorType; Graphics::Surface *tmp = NULL; const Graphics::Surface *surface; if (input.format == requiredFormat_3byte) { surface = &input; colorType = PNG_COLOR_TYPE_RGB; } else { if (input.format == requiredFormat_4byte) { surface = &input; } else { surface = tmp = input.convertTo(requiredFormat_4byte); } colorType = PNG_COLOR_TYPE_RGB_ALPHA; } png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!pngPtr) { return false; } png_infop infoPtr = png_create_info_struct(pngPtr); if (!infoPtr) { png_destroy_write_struct(&pngPtr, NULL); return false; } png_set_error_fn(pngPtr, NULL, pngError, pngWarning); // TODO: The manual says errors should be handled via setjmp png_set_write_fn(pngPtr, &out, pngWriteToStream, pngFlushStream); png_set_IHDR(pngPtr, infoPtr, surface->w, surface->h, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); Common::Array<const uint8 *> rows; rows.reserve(surface->h); if (bottomUp) { for (uint y = surface->h; y-- > 0;) { rows.push_back((const uint8 *)surface->getBasePtr(0, y)); } } else { for (uint y = 0; y < surface->h; ++y) { rows.push_back((const uint8 *)surface->getBasePtr(0, y)); } } png_set_rows(pngPtr, infoPtr, const_cast<uint8 **>(&rows.front())); png_write_png(pngPtr, infoPtr, 0, NULL); png_destroy_write_struct(&pngPtr, &infoPtr); // free tmp surface if (tmp) { tmp->free(); delete tmp; } return true; #else return false; #endif }
int begin(char* base_file_name, unsigned char *png_buf, long long png_length) { MY_PNG_READ_OFFSET = 0; PNG_LENGTH = png_length; ENTIRE_PNG_BUF = png_buf; if (png_sig_cmp(ENTIRE_PNG_BUF, 0, 8) != 0) { error(-1, "png_sig_cmp", E_INVALID); return -1; } DEBUG_PRINT(("Initial png size is %lld bytes\n", PNG_LENGTH)); my_png_meta *pm = calloc(1, sizeof(my_png_meta)); my_init_libpng(pm); //If libpng errors, we end up here if (setjmp(png_jmpbuf(pm->read_ptr))) { DEBUG_PRINT(("libpng called setjmp!\n")); my_deinit_libpng(pm); free(ENTIRE_PNG_BUF); error(-1, "libpng", "libpng encountered an error\n"); return -1; } //Normally a file, but instead make it our buffer void *read_io_ptr = png_get_io_ptr(pm->read_ptr); png_set_read_fn(pm->read_ptr, read_io_ptr, my_png_read_fn); //Transform all PNG image types to RGB int transforms = PNG_TRANSFORM_GRAY_TO_RGB | PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_EXPAND; png_read_png(pm->read_ptr, pm->info_ptr, transforms, NULL); //Now that it was read and transformed, its size will differ PNG_LENGTH = 0; //Lets collect our metadata struct ihdr_infos_s ihdr_infos; ihdr_infos.bit_depth = png_get_bit_depth(pm->read_ptr, pm->info_ptr); ihdr_infos.color_type = png_get_color_type(pm->read_ptr, pm->info_ptr); ihdr_infos.filter_method = png_get_filter_type(pm->read_ptr, pm->info_ptr); ihdr_infos.compression_type = png_get_compression_type(pm->read_ptr, pm->info_ptr); ihdr_infos.interlace_type = png_get_interlace_type(pm->read_ptr, pm->info_ptr); ihdr_infos.height = png_get_image_height(pm->read_ptr, pm->info_ptr); ihdr_infos.width = png_get_image_width(pm->read_ptr, pm->info_ptr); if (ihdr_infos.color_type != 2) { DEBUG_PRINT((E_INVALID)); free(ENTIRE_PNG_BUF); my_deinit_libpng(pm); DEBUG_PRINT(("Looks like libpng could not correctly convert to RGB\n")); return -1; } //Just in case we want to enable alpha, etc switch(ihdr_infos.color_type) { case 0: //greyscale case 3: //indexed ihdr_infos.bytes_per_pixel = 1; break; case 4: ihdr_infos.bytes_per_pixel = 2; break; //greyscale w/ alpha case 2: ihdr_infos.bytes_per_pixel = 3; break; //Truecolour (RGB) case 6: ihdr_infos.bytes_per_pixel = 4; break; //Truecolour w/ alpha default: error_fatal(1, "ihdr_infos", "Unknown image type"); //should never happen } ihdr_infos.scanline_len = (ihdr_infos.bytes_per_pixel * ihdr_infos.width) + 1; DEBUG_PRINT(("HEIGHT: %u\n", ihdr_infos.height)); DEBUG_PRINT(("WIDTH: %u\n", ihdr_infos.width)); DEBUG_PRINT(("BIT_DEPTH: %u\n", ihdr_infos.bit_depth)); // Don't compress, since we are merely copying it to memory, // we will be decompressing it again anyway png_set_compression_level(pm->write_ptr, Z_NO_COMPRESSION); void *write_io_ptr = png_get_io_ptr(pm->write_ptr); png_set_write_fn(pm->write_ptr, write_io_ptr, my_png_write_fn, my_png_dummy_flush); //Make sure we use all filters png_set_filter(pm->write_ptr, 0, PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | PNG_FILTER_UP | PNG_FILTER_VALUE_UP | PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG | PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH); //Set our comment struct png_text_struct comment_struct; comment_struct.compression = -1; comment_struct.key = " Glitched by pnglitch.xyz "; comment_struct.text = NULL; comment_struct.text_length = 0; png_set_text(pm->write_ptr, pm->info_ptr, &comment_struct, 1); //Buffer is Written using callback my_png_write_fn to buffer //ENTIRE_PNG_BUF. PNG_LENGTH will be updated automatically by it png_write_png(pm->write_ptr, pm->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); my_deinit_libpng(pm); DEBUG_PRINT(("libpng output buf is %lld bytes\n", PNG_LENGTH)); //Now that libpng has converted the image //and we have it in a buffer, we process it by hand with zlib struct z_stream_s inflate_stream; my_init_zlib(&inflate_stream); inflateInit(&inflate_stream); //Pointer to keep track of where we are unsigned char *pngp = ENTIRE_PNG_BUF; //Skip PNG Signature pngp += 8; //Get Header unsigned char ihdr_bytes_buf[4+4+13+4]; // size + label + content + crc buf_read(ihdr_bytes_buf, &pngp, 4+4+13+4); //When we run into non-idat chunks, we will want to preserve them. //The spec says there's no chunk that needs to go after IDAT, //so we can simply concatenate all of these chunks into a buffer //then write them all at once after the IHDR //ancillary chunks, eg comments unsigned char *ancil_chunks_buf = calloc(1,1); long long ancil_chunks_len = 0; unsigned char *unzip_idats_buf = calloc(1, 1); long unzip_buf_len = 1; long unzip_buf_offset = 0; long long zipped_idats_len = 0; //Length of all idats as we read them unsigned long accum_png_len = 8 + (4+4+13+4); int chunk_count = 0; printf("Uncompressing image data...\n"); while (1) { unsigned char chunk_label[4]; unsigned char chunk_len_buf[4]; buf_read(chunk_len_buf, &pngp, 4); //first 4 bytes are the length of data section long chunk_len = four_bytes_to_int(chunk_len_buf); accum_png_len += chunk_len + 4 + 4 + 4; // plus len, crc, label DEBUG_PRINT(("at %lu --> %lld\n", accum_png_len, PNG_LENGTH)); //leave at end of buffer if (accum_png_len >= PNG_LENGTH) break; //read the chunk label (name of this header) buf_read(chunk_label, &pngp, 4); DEBUG_PRINT(("Reading chunk %d with label '%c%c%c%c', size %ld\n", chunk_count, chunk_label[0], chunk_label[1], chunk_label[2], chunk_label[3], chunk_len)); chunk_count += 1; if (memcmp(chunk_label, "IDAT", 4) == 0) { zipped_idats_len += chunk_len; //read the chunk's data section unsigned char *raw_chunk_buf = calloc(chunk_len, 1); buf_read(raw_chunk_buf, &pngp, chunk_len); //Tell inflate to uncompress it inflate_stream.next_in = raw_chunk_buf; inflate_stream.avail_in = chunk_len; //Now uncompress it (resizes buffer automatically) unsigned char *check_uncompress = uncompress_buffer(&inflate_stream, unzip_idats_buf, &unzip_buf_len, &unzip_buf_offset); //Stop if error if (check_uncompress == NULL) { DEBUG_PRINT((E_GLITCH)); free(ancil_chunks_buf); free(raw_chunk_buf); free(unzip_idats_buf); free(ENTIRE_PNG_BUF); return -1; } //Moving on unzip_idats_buf = check_uncompress; free(raw_chunk_buf); pngp += 4; // skip CRC } else { //This is not an idat ancil_chunks_buf = realloc(ancil_chunks_buf, ancil_chunks_len + 4 + 4 + chunk_len + 4); //make room for new data //append length and label bytes append_bytes(ancil_chunks_buf, chunk_len_buf, &ancil_chunks_len, 4); append_bytes(ancil_chunks_buf, chunk_label, &ancil_chunks_len, 4); //append chunk data unsigned char *raw_chunk_buf = calloc(chunk_len, 1); buf_read(raw_chunk_buf, &pngp, chunk_len); append_bytes(ancil_chunks_buf, raw_chunk_buf, &ancil_chunks_len, chunk_len ); //append chunk crc unsigned char chunk_crc_buf[4]; buf_read(chunk_crc_buf, &pngp, 4); append_bytes(ancil_chunks_buf, chunk_crc_buf, &ancil_chunks_len, 4); free(raw_chunk_buf); DEBUG_PRINT(("ancillary chunks length: %lld\n", ancil_chunks_len)); } } //buf contains all idats uncompressed, concatenated unsigned long unzipped_idats_len = inflate_stream.total_out; unzip_idats_buf = realloc(unzip_idats_buf, unzipped_idats_len); //we already have ancillary chunks and idats, don't need the original free(ENTIRE_PNG_BUF); inflateEnd(&inflate_stream); printf("Uncompressed %lld bytes to %ld bytes\n", zipped_idats_len, unzipped_idats_len); printf("Glitching image data...\n"); for (int g=0;g<NUM_OUTPUT_FILES;g++) { //do glitches switch(g) { case 5: glitch_random(unzip_idats_buf, unzipped_idats_len, ihdr_infos.scanline_len, 0.0005); break; case 6: glitch_random_filter(unzip_idats_buf, unzipped_idats_len, ihdr_infos.scanline_len); break; default: glitch_filter(unzip_idats_buf, unzipped_idats_len, ihdr_infos.scanline_len, g); } //recompress so we can write them to file long long glitched_idats_len = 0; unsigned char *glitched_idats = zip_idats(unzip_idats_buf, unzipped_idats_len, &glitched_idats_len); if (glitched_idats == NULL) { DEBUG_PRINT((E_GLITCH)); free (unzip_idats_buf); free (ancil_chunks_buf); return -1; } char path[MAX_PATH_LENGTH]; bzero(path, MAX_PATH_LENGTH); snprintf(path, MAX_PATH_LENGTH, "%s%s%s-%d.png", OUTPUT_DIRECTORY, DIR_SEP, base_file_name, g); DEBUG_PRINT(("Output file name is %s\n", path)); FILE *outfp = fopen(path, "wb"); write_glitched_image(glitched_idats, glitched_idats_len, ihdr_bytes_buf, ancil_chunks_buf, ancil_chunks_len, outfp); printf("%s\n", path); fflush(stdout); fclose(outfp); free(glitched_idats); } free(ancil_chunks_buf); free(unzip_idats_buf); return 0; }
/* Write "bitmap" to a PNG file specified by "path"; returns 0 on success, non-zero on error. */ int save_png_to_file (Bitmap *bitmap, const char *path) { FILE * fp; png_structp png_ptr = NULL; png_infop info_ptr = NULL; size_t x, y; png_bytep *row_pointers = NULL; /* "status" contains the return value of this function. At first it is set to a value which means 'failure'. When the routine has finished its work, it is set to a value which means 'success'. */ int status = -1; /* The following number is set by trial and error only. I cannot see where it it is documented in the libpng manual. */ int pixel_size = 3; int depth = 8; fp = fopen (path, "wb"); if (! fp) { goto fopen_failed; } png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { goto png_create_write_struct_failed; } info_ptr = png_create_info_struct (png_ptr); if (info_ptr == NULL) { goto png_create_info_struct_failed; } /* Set up error handling. */ if (setjmp (png_jmpbuf (png_ptr))) { goto png_failure; } /* Set image attributes. */ png_set_IHDR (png_ptr, info_ptr, bitmap->width, bitmap->height, depth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Initialize rows of PNG. */ row_pointers = (png_bytep*) png_malloc(png_ptr, bitmap->height*sizeof(png_byte *)); for (y = 0; y < bitmap->height; ++y) { png_byte *row = (png_byte *)png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size); row_pointers[y] = row; for (x = 0; x < bitmap->width; ++x) { WPixel* pixel = pixel_at(bitmap, x, y); *row++ = pixel->red; *row++ = pixel->green; *row++ = pixel->blue; } } /* Write the image data to "fp". */ png_init_io (png_ptr, fp); png_set_rows (png_ptr, info_ptr, row_pointers); png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); /* The routine has successfully written the file, so we set "status" to a value which indicates success. */ status = 0; for (y = 0; y < bitmap->height; y++) { png_free (png_ptr, row_pointers[y]); } png_free (png_ptr, row_pointers); png_failure: png_create_info_struct_failed: png_destroy_write_struct (&png_ptr, &info_ptr); png_create_write_struct_failed: fclose (fp); fopen_failed: return status; }