size_t ImageEncoderPNG::encode( const void * _buffer, size_t _size, const CodecDataInfo* _bufferDataInfo ) { (void)_size; const ImageCodecDataInfo* dataInfo = static_cast<const ImageCodecDataInfo*>( _bufferDataInfo ); // allocate/initialize the image information data. png_infop info_ptr = png_create_info_struct( m_png_ptr ); if( info_ptr == nullptr ) { LOGGER_ERROR(m_serviceProvider)("PNG encoder error: Can't create info structure" ); return 0; } int color_type; if( dataInfo->channels == 1 ) { color_type = PNG_COLOR_TYPE_GRAY; } else if( dataInfo->channels == 3 ) { color_type = PNG_COLOR_TYPE_RGB; } else if( dataInfo->channels == 4 ) { color_type = PNG_COLOR_TYPE_RGB_ALPHA; } else { LOGGER_ERROR(m_serviceProvider)("PNG codec error: unsupported image format channels %d" , dataInfo->channels ); png_destroy_info_struct( m_png_ptr, &info_ptr ); return 0; } png_uint_32 width = (png_uint_32)dataInfo->width; png_uint_32 height = (png_uint_32)dataInfo->height; int pixel_depth = 8; png_set_IHDR( m_png_ptr, info_ptr, width, height, pixel_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE ); png_set_bgr( m_png_ptr ); // Write the file header information. png_write_info( m_png_ptr, info_ptr ); size_t pitch = m_options.pitch; png_bytep png_buffer = (png_bytep)_buffer; for( png_uint_32 k = 0; k < height; ++k) { png_write_row( m_png_ptr, png_buffer ); png_buffer += pitch; } //} // It is REQUIRED to call this to finish writing the rest of the file // Bug with png_flush png_write_end( m_png_ptr, info_ptr ); png_destroy_info_struct( m_png_ptr, &info_ptr ); size_t writeBytes = pitch * height; return writeBytes; }
void GBMapView::savePNG(LPCTSTR name) { u8 writeBuffer[1024 * 3]; FILE *fp = _tfopen(name,_T("wb")); if(!fp) { systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name); return; } png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) { fclose(fp); return; } png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_write_struct(&png_ptr,NULL); fclose(fp); return; } if(setjmp(png_ptr->jmpbuf)) { png_destroy_write_struct(&png_ptr,NULL); fclose(fp); return; } png_init_io(png_ptr,fp); 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); png_write_info(png_ptr,info_ptr); u8 *b = writeBuffer; int sizeX = w; int sizeY = h; u8 *pixU8 = (u8 *)data; for(int y = 0; y < sizeY; y++) { for(int x = 0; x < sizeX; x++) { int blue = *pixU8++; int green = *pixU8++; int red = *pixU8++; *b++ = red; *b++ = green; *b++ = blue; } png_write_row(png_ptr,writeBuffer); b = writeBuffer; } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); }
static gint export_png (GeglOperation *operation, GeglBuffer *input, const GeglRectangle *result, png_structp png, png_infop info, gint compression, gint bit_depth) { gint i, src_x, src_y; png_uint_32 width, height; guchar *pixels; png_color_16 white; int png_color_type; gchar format_string[16]; const Babl *format; src_x = result->x; src_y = result->y; width = result->width; height = result->height; { const Babl *babl = gegl_buffer_get_format (input); if (bit_depth != 16) bit_depth = 8; if (babl_format_has_alpha (babl)) if (babl_format_get_n_components (babl) != 2) { png_color_type = PNG_COLOR_TYPE_RGB_ALPHA; strcpy (format_string, "R'G'B'A "); } else { png_color_type = PNG_COLOR_TYPE_GRAY_ALPHA; strcpy (format_string, "Y'A "); } else if (babl_format_get_n_components (babl) != 1) { png_color_type = PNG_COLOR_TYPE_RGB; strcpy (format_string, "R'G'B' "); } else { png_color_type = PNG_COLOR_TYPE_GRAY; strcpy (format_string, "Y' "); } } if (bit_depth == 16) strcat (format_string, "u16"); else strcat (format_string, "u8"); if (setjmp (png_jmpbuf (png))) return -1; png_set_compression_level (png, compression); png_set_IHDR (png, info, width, height, bit_depth, png_color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_DEFAULT); if (png_color_type == PNG_COLOR_TYPE_RGB || png_color_type == PNG_COLOR_TYPE_RGB_ALPHA) { white.red = 0xff; white.blue = 0xff; white.green = 0xff; } else white.gray = 0xff; png_set_bKGD (png, info, &white); png_write_info (png, info); #if BYTE_ORDER == LITTLE_ENDIAN if (bit_depth > 8) png_set_swap (png); #endif format = babl_format (format_string); pixels = g_malloc0 (width * babl_format_get_bytes_per_pixel (format)); for (i=0; i< height; i++) { GeglRectangle rect; rect.x = src_x; rect.y = src_y+i; rect.width = width; rect.height = 1; gegl_buffer_get (input, &rect, 1.0, babl_format (format_string), pixels, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); png_write_rows (png, &pixels, 1); } png_write_end (png, info); g_free (pixels); return 0; }
void SavePNG( const char *name, const byte *pic, int width, int height, int numBytes, qboolean flip ) { png_structp png; png_infop info; int i; int row_stride; byte *buffer; byte *row; png_bytep *row_pointers; png = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); if ( !png ) { return; } // Allocate/initialize the image information data info = png_create_info_struct( png ); if ( !info ) { png_destroy_write_struct( &png, ( png_infopp ) NULL ); return; } png_compressed_size = 0; buffer = ri.Hunk_AllocateTempMemory( width * height * numBytes ); // set error handling if ( setjmp( png_jmpbuf( png ) ) ) { ri.Hunk_FreeTempMemory( buffer ); png_destroy_write_struct( &png, &info ); return; } png_set_write_fn( png, buffer, png_write_data, png_flush_data ); switch ( numBytes ) { default: png_set_IHDR( png, info, width, height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); break; case 3: png_set_IHDR( png, info, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); break; case 2: png_set_IHDR( png, info, width, height, 8, PNG_COLOR_TYPE_GA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); break; case 1: png_set_IHDR( png, info, width, height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); break; } // write the file header information png_write_info( png, info ); row_pointers = ri.Hunk_AllocateTempMemory( height * sizeof( png_bytep ) ); if ( setjmp( png_jmpbuf( png ) ) ) { ri.Hunk_FreeTempMemory( row_pointers ); ri.Hunk_FreeTempMemory( buffer ); png_destroy_write_struct( &png, &info ); return; } row_stride = width * numBytes; row = ( byte * ) pic + ( height - 1 ) * row_stride; if ( flip ) { for ( i = height - 1; i >= 0; i-- ) { row_pointers[ i ] = row; row -= row_stride; } } else { for ( i = 0; i < height; i++ ) { row_pointers[ i ] = row; row -= row_stride; } } png_write_image( png, row_pointers ); png_write_end( png, info ); // clean up after the write, and free any memory allocated png_destroy_write_struct( &png, &info ); ri.Hunk_FreeTempMemory( row_pointers ); ri.FS_WriteFile( name, buffer, png_compressed_size ); ri.Hunk_FreeTempMemory( buffer ); }
static int savePNGto(FILE *fp, gPixmap *pixmap) { gUnmanagedSurface *surface = pixmap->surface; if (!surface) return -2; png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) { eDebug("[ePNG] couldn't allocate write struct"); return -2; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { eDebug("[ePNG] failed to allocate info struct"); png_destroy_write_struct(&png_ptr, 0); return -3; } png_set_IHDR(png_ptr, info_ptr, surface->x, surface->y, surface->bpp/surface->bypp, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (setjmp(png_jmpbuf(png_ptr))) { eDebug("[ePNG] png setjump failed or activated"); png_destroy_write_struct(&png_ptr, &info_ptr); return -4; } png_init_io(png_ptr, fp); png_set_filter(png_ptr, 0, PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_PAETH); png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); png_write_info(png_ptr, info_ptr); png_set_packing(png_ptr); png_byte *row_pointer; png_byte *cr = new png_byte[surface->y * surface->stride]; if (cr == NULL) { eDebug("[ePNG] failed to allocate memory image"); return -5; } for (int i = 0; i < surface->y; ++i) { row_pointer = ((png_byte*)surface->data) + i * surface->stride; if (surface->bypp == 4) { memcpy(cr, row_pointer, surface->stride); for (int j = 0; j < surface->stride; j += 4) { unsigned char tmp = cr[j]; cr[j] = cr[j+2]; cr[j+2] = tmp; } png_write_row(png_ptr, cr); } else png_write_row(png_ptr, row_pointer); } delete [] cr; png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); return 0; }
CAMLprim value write_png_rgb_to_buffer(value buffer, value width, value height, value with_alpha) { CAMLparam4(buffer, width, height, with_alpha); CAMLlocal1(vres); png_structp png_ptr; png_infop info_ptr; /* static */ struct mem_buffer state; int w, h, a; /* initialise - put this before png_write_png() call */ state.buffer = NULL; state.size = 0; w = Int_val(width); h = Int_val(height); a = Bool_val(with_alpha); if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL ) failwith("png_create_write_struct"); if((info_ptr = png_create_info_struct(png_ptr)) == NULL ) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); failwith("png_create_info_struct"); } /* error handling */ if (setjmp(png_jmpbuf(png_ptr))) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_write_struct(&png_ptr, &info_ptr); failwith("png write error"); } /* the final arg is NULL because we dont need in flush() */ png_set_write_fn(png_ptr, &state, png_write_data_to_buffer, NULL); /* we use system default compression */ /* png_set_filter(png_ptr, 0, PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_PAETH ); */ /* png_set_compression...() */ png_set_IHDR(png_ptr, info_ptr, w, h, 8 /* fixed */, a ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, /* fixed */ PNG_INTERLACE_ADAM7, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); /* infos... */ png_write_info(png_ptr, info_ptr); { int rowbytes, i; png_bytep *row_pointers; char *buf = String_val(buffer); row_pointers = (png_bytep*)stat_alloc(sizeof(png_bytep) * h); rowbytes= png_get_rowbytes(png_ptr, info_ptr); for(i=0; i< h; i++) { row_pointers[i] = (png_bytep)(buf + rowbytes * i); } png_write_image(png_ptr, row_pointers); stat_free((void*)row_pointers); } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); vres = caml_alloc_string(state.size); memcpy(String_val(vres), state.buffer, state.size); free(state.buffer); CAMLreturn(vres); }
// this code is heavily adapted from the paint license, which is in // the file paint.license (BSD compatible) included in this // distribution. TODO, add license file to MANIFEST.in and CVS Py::Object _png_module::write_png(const Py::Tuple& args) { args.verify_length(4, 5); FILE *fp = NULL; bool close_file = false; Py::Object buffer_obj = Py::Object(args[0]); PyObject* buffer = buffer_obj.ptr(); if (!PyObject_CheckReadBuffer(buffer)) { throw Py::TypeError("First argument must be an rgba buffer."); } const void* pixBufferPtr = NULL; Py_ssize_t pixBufferLength = 0; if (PyObject_AsReadBuffer(buffer, &pixBufferPtr, &pixBufferLength)) { throw Py::ValueError("Couldn't get data from read buffer."); } png_byte* pixBuffer = (png_byte*)pixBufferPtr; int width = (int)Py::Int(args[1]); int height = (int)Py::Int(args[2]); if (pixBufferLength < width * height * 4) { throw Py::ValueError("Buffer and width, height don't seem to match."); } Py::Object py_fileobj = Py::Object(args[3]); #if PY3K int fd = PyObject_AsFileDescriptor(py_fileobj.ptr()); PyErr_Clear(); #endif if (py_fileobj.isString()) { std::string fileName = Py::String(py_fileobj); const char *file_name = fileName.c_str(); if ((fp = fopen(file_name, "wb")) == NULL) { throw Py::RuntimeError( Printf("Could not open file %s", file_name).str()); } close_file = true; } #if PY3K else if (fd != -1) { fp = fdopen(fd, "w"); } #else else if (PyFile_CheckExact(py_fileobj.ptr())) { fp = PyFile_AsFile(py_fileobj.ptr()); } #endif else { PyObject* write_method = PyObject_GetAttrString( py_fileobj.ptr(), "write"); if (!(write_method && PyCallable_Check(write_method))) { Py_XDECREF(write_method); throw Py::TypeError( "Object does not appear to be a 8-bit string path or a Python file-like object"); } Py_XDECREF(write_method); } png_bytep *row_pointers = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; try { struct png_color_8_struct sig_bit; png_uint_32 row; row_pointers = new png_bytep[height]; for (row = 0; row < (png_uint_32)height; ++row) { row_pointers[row] = pixBuffer + row * width * 4; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { throw Py::RuntimeError("Could not create write struct"); } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { throw Py::RuntimeError("Could not create info struct"); } if (setjmp(png_jmpbuf(png_ptr))) { throw Py::RuntimeError("Error building image"); } if (fp) { png_init_io(png_ptr, fp); } else { png_set_write_fn(png_ptr, (void*)py_fileobj.ptr(), &write_png_data, &flush_png_data); } png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); // Save the dpi of the image in the file if (args.size() == 5) { double dpi = Py::Float(args[4]); size_t dots_per_meter = (size_t)(dpi / (2.54 / 100.0)); png_set_pHYs(png_ptr, info_ptr, dots_per_meter, dots_per_meter, PNG_RESOLUTION_METER); } // this a a color image! sig_bit.gray = 0; sig_bit.red = 8; sig_bit.green = 8; sig_bit.blue = 8; /* if the image has an alpha channel then */ sig_bit.alpha = 8; png_set_sBIT(png_ptr, info_ptr, &sig_bit); png_write_info(png_ptr, info_ptr); png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); } catch (...) { if (png_ptr && info_ptr) { png_destroy_write_struct(&png_ptr, &info_ptr); } delete [] row_pointers; if (fp && close_file) { fclose(fp); } /* Changed calls to png_destroy_write_struct to follow http://www.libpng.org/pub/png/libpng-manual.txt. This ensures the info_ptr memory is released. */ throw; } png_destroy_write_struct(&png_ptr, &info_ptr); delete [] row_pointers; #if PY3K if (fp) { fflush(fp); } #endif if (fp && close_file) { fclose(fp); } if (PyErr_Occurred()) { throw Py::Exception(); } else { return Py::Object(); } }
int main(int argc, char *argv[]) { int result; TIFF *tiff; u_long width, height; int bwidth; u_char *raster = 0; int r; int i; png_structp png_ptr; png_infop info_ptr; png_bytep row_pointer, row; int page = 0; int angle = 0; int nwidth = -1; int lr = 0; int tb = 0; int antialias = 0; int xisy = 0; int xisflipped = 0; int yisflipped = 0; uint16 bitsPerSample; char *tiffFile = 0; char *pngFile = 0; FILE *out; int y; u_long num; u_long denom; char error[1024]; for (i = 1; (i < argc); i++) { if (!strcmp(argv[i], "-p")) { if (argc == (i + 1)) { die("-p expects a page number"); } page = atoi(argv[i + 1]) - 1; i++; if (page < 0) { die("-p expects a page number >= 1"); } } else if (!strcmp(argv[i], "-r")) { if (argc == (i + 1)) { die("-r expects an angle"); } angle = atoi(argv[i + 1]); i++; if ((angle < 0) || (angle > 270) || (angle % 90)) { die("-a expects an angle of 0, 90, 180, or 270 degrees"); } } else if (!strcmp(argv[i], "-w")) { if (argc == (i + 1)) { die("-w expects a width in pixels"); } nwidth = atoi(argv[i + 1]); i++; if (nwidth <= 0) { die("-w expects a positive width in pixels"); } } else if (!strcmp(argv[i], "-lr")) { lr = 1; } else if (!strcmp(argv[i], "-tb")) { tb = 1; } else if (!strcmp(argv[i], "-a")) { antialias = 1; } else if ((!tiffFile) && (argv[i][0] != '-')) { tiffFile = argv[i]; } else if ((!pngFile) && (argv[i][0] != '-')) { pngFile = argv[i]; } else { usage("unknown parameter"); } } if (!tiffFile) { usage("tiff filename is required"); } tiff = TIFFOpen(tiffFile, "rb"); if (!tiff) { die("Can't open file"); } if (!TIFFSetDirectory(tiff, page)) { die("Can't access page number requested"); } (void) TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width); if (nwidth == -1) { num = 1; denom = 1; } else { if (!xisy) { num = width; denom = nwidth; } else { num = height; denom = nwidth; } } if ((!num) || (!denom)) { die("Width and height must both be nonzero"); } (void) TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height); (void) TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitsPerSample); if (bitsPerSample != 1) { die("Sorry, only 1-bit (scan/fax) TIFFs are supported"); } bwidth = (int) TIFFScanlineSize(tiff); raster = calloc(1, bwidth * height); if (!raster) { die("Memory allocation error"); } for (y = 0; (y < height); y++) { TIFFReadScanline(tiff, raster + bwidth * y, y, 0); } switch (angle) { case 0: break; case 90: xisy = !xisy; yisflipped = !yisflipped; break; case 180: xisflipped = !xisflipped; yisflipped = !yisflipped; break; case 270: xisy = !xisy; xisflipped = !xisflipped; break; } if (lr) { xisflipped = !xisflipped; } if (tb) { yisflipped = !yisflipped; } row = calloc(sizeof(u_char), (xisy) ? height : width); if (!row) { die("Memory allocation error"); } png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) { die("Cannot allocate png_structp"); } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { die("Cannot allocate png_infop"); } if (setjmp(png_jmpbuf(png_ptr))) { die("Error on png write"); } if (pngFile) { out = fopen(pngFile, "wb"); if (!out) { die("Cannot create output file"); } } else { out = stdout; SET_BINARY(STDOUT_FILENO); } png_init_io(png_ptr, out); /* Turning off filtering yields a large speed improvement at a modest price in file size */ png_set_filter(png_ptr, 0, PNG_FILTER_NONE); if (nwidth == -1) { nwidth = width; } png_set_IHDR(png_ptr, info_ptr, ((xisy) ? height : width) * denom / num, ((xisy) ? width : height) * denom / num, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); for (y = 0; (y < info_ptr->height); y++) { int x; u_char *p; row_pointer = row; p = row; for (x = 0; (x < info_ptr->width); x++) { int tx, ty; int accum = 0, total = 0; int ty1 = (xisy ? x : y) * num / denom; int tx1 = (xisy ? y : x) * num / denom; int tx2, ty2; int xsteps, ysteps; if (!antialias) { tx2 = tx1 + 1; ty2 = ty1 + 1; } else { ty2 = (xisy ? (x + 1) : (y + 1)) * num / denom; tx2 = (xisy ? (y + 1) : (x + 1)) * num / denom; } ysteps = abs(ty2 - ty1); xsteps = abs(tx2 - tx1); if (xisflipped) { tx1 = width - 1 - tx1; tx2 = width - 1 - tx2; } if (yisflipped) { ty1 = height - 1 - ty1; ty2 = height - 1 - ty2; } ty = ty1; while (ty != ty2) { tx = tx1; while (tx != tx2) { accum += GetBWPixel(raster, ty, tx); total++; tx += sign(tx2 - tx1); } ty += sign(ty2 - ty1); } if (total > 0) { *p = accum / total; } p++; } png_write_row(png_ptr, row_pointer); } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); if (out != stdout) { fclose(out); } return 0; }
static BOOL DLL_CALLCONV Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { png_structp png_ptr; png_infop info_ptr; png_colorp palette = NULL; png_uint_32 width, height; BOOL has_alpha_channel = FALSE; RGBQUAD *pal; // pointer to dib palette int bit_depth, pixel_depth; // pixel_depth = bit_depth * channels int palette_entries; int interlace_type; fi_ioStructure fio; fio.s_handle = handle; fio.s_io = io; if ((dib) && (handle)) { try { // create the chunk manage structure png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler); if (!png_ptr) { return FALSE; } // allocate/initialize the image information data. info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return FALSE; } // 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 reading the file png_destroy_write_struct(&png_ptr, &info_ptr); return FALSE; } // init the IO png_set_write_fn(png_ptr, &fio, _WriteProc, _FlushProc); // set physical resolution png_uint_32 res_x = (png_uint_32)FreeImage_GetDotsPerMeterX(dib); png_uint_32 res_y = (png_uint_32)FreeImage_GetDotsPerMeterY(dib); if ((res_x > 0) && (res_y > 0)) { png_set_pHYs(png_ptr, info_ptr, res_x, res_y, 1); } // 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 width = FreeImage_GetWidth(dib); height = FreeImage_GetHeight(dib); pixel_depth = FreeImage_GetBPP(dib); BOOL bInterlaced = FALSE; if( (flags & PNG_INTERLACED) == PNG_INTERLACED) { interlace_type = PNG_INTERLACE_ADAM7; bInterlaced = TRUE; } else { interlace_type = PNG_INTERLACE_NONE; } // set the ZLIB compression level or default to PNG default compression level (ZLIB level = 6) int zlib_level = flags & 0x0F; if((zlib_level >= 1) && (zlib_level <= 9)) { png_set_compression_level(png_ptr, zlib_level); } else if((flags & PNG_Z_NO_COMPRESSION) == PNG_Z_NO_COMPRESSION) { png_set_compression_level(png_ptr, Z_NO_COMPRESSION); } // filtered strategy works better for high color images if(pixel_depth >= 16){ png_set_compression_strategy(png_ptr, Z_FILTERED); png_set_filter(png_ptr, 0, PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_PAETH); } else { png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY); } FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); if(image_type == FIT_BITMAP) { // standard image type bit_depth = (pixel_depth > 8) ? 8 : pixel_depth; } else { // 16-bit greyscale or 16-bit RGB(A) bit_depth = 16; } switch (FreeImage_GetColorType(dib)) { case FIC_MINISWHITE: // Invert monochrome files to have 0 as black and 1 as white (no break here) png_set_invert_mono(png_ptr); case FIC_MINISBLACK: png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_GRAY, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); break; case FIC_PALETTE: { png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_PALETTE, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); // set the palette palette_entries = 1 << bit_depth; palette = (png_colorp)png_malloc(png_ptr, palette_entries * sizeof (png_color)); pal = FreeImage_GetPalette(dib); for (int i = 0; i < palette_entries; i++) { palette[i].red = pal[i].rgbRed; palette[i].green = pal[i].rgbGreen; palette[i].blue = pal[i].rgbBlue; } png_set_PLTE(png_ptr, info_ptr, palette, palette_entries); // You must not free palette here, because png_set_PLTE only makes a link to // the palette that you malloced. Wait until you are about to destroy // the png structure. break; } case FIC_RGBALPHA : has_alpha_channel = TRUE; png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_RGBA, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR // flip BGR pixels to RGB if(image_type == FIT_BITMAP) png_set_bgr(png_ptr); #endif break; case FIC_RGB: png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_RGB, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR // flip BGR pixels to RGB if(image_type == FIT_BITMAP) png_set_bgr(png_ptr); #endif break; case FIC_CMYK: break; } // write possible ICC profile FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib); if (iccProfile->size && iccProfile->data) { png_set_iCCP(png_ptr, info_ptr, "Embedded Profile", 0, (png_charp)iccProfile->data, iccProfile->size); } // write metadata WriteMetadata(png_ptr, info_ptr, dib); // Optional gamma chunk is strongly suggested if you have any guess // as to the correct gamma of the image. // png_set_gAMA(png_ptr, info_ptr, gamma); // set the transparency table if ((pixel_depth == 8) && (FreeImage_IsTransparent(dib)) && (FreeImage_GetTransparencyCount(dib) > 0)) { png_set_tRNS(png_ptr, info_ptr, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib), NULL); } // set the background color if(FreeImage_HasBackgroundColor(dib)) { png_color_16 image_background; RGBQUAD rgbBkColor; FreeImage_GetBackgroundColor(dib, &rgbBkColor); memset(&image_background, 0, sizeof(png_color_16)); image_background.blue = rgbBkColor.rgbBlue; image_background.green = rgbBkColor.rgbGreen; image_background.red = rgbBkColor.rgbRed; image_background.index = rgbBkColor.rgbReserved; png_set_bKGD(png_ptr, info_ptr, &image_background); } // Write the file header information. png_write_info(png_ptr, info_ptr); // write out the image data #ifndef FREEIMAGE_BIGENDIAN if (bit_depth == 16) { // turn on 16 bit byte swapping png_set_swap(png_ptr); } #endif int number_passes = 1; if (bInterlaced) { number_passes = png_set_interlace_handling(png_ptr); } if ((pixel_depth == 32) && (!has_alpha_channel)) { BYTE *buffer = (BYTE *)malloc(width * 3); // transparent conversion to 24-bit // the number of passes is either 1 for non-interlaced images, or 7 for interlaced images for (int pass = 0; pass < number_passes; pass++) { for (png_uint_32 k = 0; k < height; k++) { FreeImage_ConvertLine32To24(buffer, FreeImage_GetScanLine(dib, height - k - 1), width); png_write_row(png_ptr, buffer); } } free(buffer); } else { // the number of passes is either 1 for non-interlaced images, or 7 for interlaced images for (int pass = 0; pass < number_passes; pass++) { for (png_uint_32 k = 0; k < height; k++) { png_write_row(png_ptr, FreeImage_GetScanLine(dib, height - k - 1)); } } } // It is REQUIRED to call this to finish writing the rest of the file // Bug with png_flush png_write_end(png_ptr, info_ptr); // clean up after the write, and free any memory allocated if (palette) { png_free(png_ptr, palette); } png_destroy_write_struct(&png_ptr, &info_ptr); return TRUE; } catch (const char *text) { FreeImage_OutputMessageProc(s_format_id, text); } } return FALSE; }
int IMG_SavePNG_RW(SDL_RWops *src, SDL_Surface *surf,int compression){ png_structp png_ptr; png_infop info_ptr; SDL_PixelFormat *fmt=NULL; SDL_Surface *tempsurf=NULL; int ret,funky_format,used_alpha; unsigned int i,temp_alpha; png_colorp palette; Uint8 *palette_alpha=NULL; png_byte **row_pointers=NULL; png_ptr=NULL;info_ptr=NULL;palette=NULL;ret=-1; funky_format=0; if( !src || !surf) { goto savedone; /* Nothing to do. */ } row_pointers=(png_byte **)malloc(surf->h * sizeof(png_byte*)); if (!row_pointers) { SDL_SetError("Couldn't allocate memory for rowpointers"); goto savedone; } png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); if (!png_ptr){ SDL_SetError("Couldn't allocate memory for PNG file"); goto savedone; } info_ptr= png_create_info_struct(png_ptr); if (!info_ptr){ SDL_SetError("Couldn't allocate image information for PNG file"); goto savedone; } /* setup custom writer functions */ png_set_write_fn(png_ptr,(voidp)src,png_write_data,NULL); if (setjmp(png_jmpbuf(png_ptr))){ SDL_SetError("Unknown error writing PNG"); goto savedone; } if(compression>Z_BEST_COMPRESSION) compression=Z_BEST_COMPRESSION; if(compression == Z_NO_COMPRESSION) // No compression { png_set_filter(png_ptr,0,PNG_FILTER_NONE); png_set_compression_level(png_ptr,Z_NO_COMPRESSION); } else if(compression<0) // Default compression png_set_compression_level(png_ptr,Z_DEFAULT_COMPRESSION); else png_set_compression_level(png_ptr,compression); fmt=surf->format; if(fmt->BitsPerPixel==8){ /* Paletted */ png_set_IHDR(png_ptr,info_ptr, surf->w,surf->h,8,PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); palette=(png_colorp) malloc(fmt->palette->ncolors * sizeof(png_color)); if (!palette) { SDL_SetError("Couldn't create memory for palette"); goto savedone; } for (i=0;i<fmt->palette->ncolors;i++) { palette[i].red=fmt->palette->colors[i].r; palette[i].green=fmt->palette->colors[i].g; palette[i].blue=fmt->palette->colors[i].b; } png_set_PLTE(png_ptr,info_ptr,palette,fmt->palette->ncolors); if (surf->flags&SDL_SRCCOLORKEY) { palette_alpha=(Uint8 *)malloc((fmt->colorkey+1)*sizeof(Uint8)); if (!palette_alpha) { SDL_SetError("Couldn't create memory for palette transparency"); goto savedone; } /* FIXME: memset? */ for (i=0;i<(fmt->colorkey+1);i++) { palette_alpha[i]=255; } palette_alpha[fmt->colorkey]=0; png_set_tRNS(png_ptr,info_ptr,palette_alpha,fmt->colorkey+1,NULL); } }else{ /* Truecolor */ if (fmt->Amask) { png_set_IHDR(png_ptr,info_ptr, surf->w,surf->h,8,PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } else { png_set_IHDR(png_ptr,info_ptr, surf->w,surf->h,8,PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } } png_write_info(png_ptr, info_ptr); if (fmt->BitsPerPixel==8) { /* Paletted */ for(i=0;i<surf->h;i++){ row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch; } if(SDL_MUSTLOCK(surf)){ SDL_LockSurface(surf); } png_write_image(png_ptr, row_pointers); if(SDL_MUSTLOCK(surf)){ SDL_UnlockSurface(surf); } }else{ /* Truecolor */ if(fmt->BytesPerPixel==3){ if(fmt->Amask){ /* check for 24 bit with alpha */ funky_format=1; }else{ /* Check for RGB/BGR/GBR/RBG/etc surfaces.*/ #if SDL_BYTEORDER == SDL_BIG_ENDIAN if(fmt->Rmask!=0xFF0000 || fmt->Gmask!=0x00FF00 || fmt->Bmask!=0x0000FF){ #else if(fmt->Rmask!=0x0000FF || fmt->Gmask!=0x00FF00 || fmt->Bmask!=0xFF0000){ #endif funky_format=1; } } }else if (fmt->BytesPerPixel==4){ if (!fmt->Amask) { /* check for 32bit but no alpha */ funky_format=1; }else{ /* Check for ARGB/ABGR/GBAR/RABG/etc surfaces.*/ #if SDL_BYTEORDER == SDL_BIG_ENDIAN if(fmt->Rmask!=0xFF000000 || fmt->Gmask!=0x00FF0000 || fmt->Bmask!=0x0000FF00 || fmt->Amask!=0x000000FF){ #else if(fmt->Rmask!=0x000000FF || fmt->Gmask!=0x0000FF00 || fmt->Bmask!=0x00FF0000 || fmt->Amask!=0xFF000000){ #endif funky_format=1; } } }else{ /* 555 or 565 16 bit color */ funky_format=1; } if (funky_format) { /* Allocate non-funky format, and copy pixeldata in*/ if(fmt->Amask){ #if SDL_BYTEORDER == SDL_BIG_ENDIAN tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff); #else tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); #endif }else{ #if SDL_BYTEORDER == SDL_BIG_ENDIAN tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x00000000); #else tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000); #endif } if(!tempsurf){ SDL_SetError("Couldn't allocate temp surface"); goto savedone; } if(surf->flags&SDL_SRCALPHA){ temp_alpha=fmt->alpha; used_alpha=1; SDL_SetAlpha(surf,0,255); /* Set for an opaque blit */ }else{ used_alpha=0; } if(SDL_BlitSurface(surf,NULL,tempsurf,NULL)!=0){ SDL_SetError("Couldn't blit surface to temp surface"); SDL_FreeSurface(tempsurf); goto savedone; } if (used_alpha) { SDL_SetAlpha(surf,SDL_SRCALPHA,(Uint8)temp_alpha); /* Restore alpha settings*/ } for(i=0;i<tempsurf->h;i++){ row_pointers[i]= ((png_byte*)tempsurf->pixels) + i*tempsurf->pitch; } if(SDL_MUSTLOCK(tempsurf)){ SDL_LockSurface(tempsurf); } png_write_image(png_ptr, row_pointers); if(SDL_MUSTLOCK(tempsurf)){ SDL_UnlockSurface(tempsurf); } SDL_FreeSurface(tempsurf); } else { for(i=0;i<surf->h;i++){ row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch; } if(SDL_MUSTLOCK(surf)){ SDL_LockSurface(surf); } png_write_image(png_ptr, row_pointers); if(SDL_MUSTLOCK(surf)){ SDL_UnlockSurface(surf); } } } png_write_end(png_ptr, NULL); ret=0; /* got here, so nothing went wrong. YAY! */ savedone: /* clean up and return */ png_destroy_write_struct(&png_ptr,&info_ptr); if (palette) { free(palette); } if (palette_alpha) { free(palette_alpha); } if (row_pointers) { free(row_pointers); } return ret; }
unsigned char * pngconv_lossless2png(void *image_data, unsigned short width, unsigned short height, void *index_data, unsigned short index_data_count, int tag_no, int format, unsigned long *length) { volatile png_structp png_ptr = NULL; volatile png_infop png_info_ptr = NULL; volatile my_png_buffer png_buff; png_uint_32 png_width = 0, png_height = 0; int bpp, color_type; volatile png_bytepp png_image_data = NULL; png_uint_32 x, y; volatile png_colorp png_palette = NULL; if (image_data == NULL) { fprintf(stderr, "pngconv_lossless2png: image_data == NULL\n"); return NULL; } if ((format != 3) && (format != 5)) { fprintf(stderr, "jpegconv_lossless2png: format=%d not implemented yes.\n", format); return NULL; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); if (! png_ptr) { fprintf(stderr, "jpegconv_lossless2png: can't create write_struct\n"); return NULL; } if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "pngconv_lossless2png: libpng error jump occured\n"); free(png_palette); if (png_image_data) { for (y=0 ; y < png_height ; y++) { free(png_image_data[y]); } free(png_image_data); } free(png_buff.data); png_destroy_write_struct((png_structpp) &png_ptr, (png_infopp) &png_info_ptr); return NULL; } png_info_ptr = png_create_info_struct(png_ptr); if (! png_info_ptr) { fprintf(stderr, "jpegconv_lossless2png: can't create info_struct\n"); png_destroy_write_struct((png_structpp) &png_ptr, NULL); return NULL; } // png_width = width; png_height = height; bpp = 8; if (format == 3) { color_type = PNG_COLOR_TYPE_PALETTE; } else if (tag_no == 20) { /* DefineBitsLossless */ color_type = PNG_COLOR_TYPE_RGB; } else if (tag_no == 36) { /* DefineBitsLossless2 */ color_type = PNG_COLOR_TYPE_RGB_ALPHA; } else { fprintf(stderr, "jpegconv_lossless2png: format!=3 and tag_no=%d not implemented.\n", tag_no); png_destroy_write_struct((png_structpp) &png_ptr, (png_infopp) &png_info_ptr); return NULL; } png_set_filter(png_ptr, 0, PNG_ALL_FILTERS); png_set_IHDR(png_ptr, png_info_ptr, png_width, png_height, bpp, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (format == 3) { register int i; if (index_data_count == 0) { fprintf(stderr, "jpegconv_lossless2png: index_data_count == 0 at line(%d)\n", __LINE__); png_destroy_write_struct((png_structpp) &png_ptr, (png_infopp) &png_info_ptr); return NULL; } png_palette = (png_colorp) malloc(sizeof(png_color)*index_data_count); png_set_packing(png_ptr); if (tag_no == 20) { swf_rgb_t *rgb_list = index_data; for (i=0 ; i < index_data_count ; i++) { png_palette[i].red = rgb_list[i].red; png_palette[i].green = rgb_list[i].green; png_palette[i].blue = rgb_list[i].blue; } } else { swf_rgba_t *rgba_list = index_data; png_bytep trans = NULL; int num_trans = 0; png_color_16p trans_values = NULL; for (i=0 ; i < index_data_count ; i++) { png_palette[i].red = rgba_list[i].red; png_palette[i].green = rgba_list[i].green; png_palette[i].blue = rgba_list[i].blue; } // scanning to end of transparent pixel for (i = index_data_count - 1 ; 0 <= i ; i--) { if (rgba_list[i].alpha < 254) { // 254 XXX break; } } num_trans = i + 1; if (num_trans > 0) { trans = malloc(num_trans); for (i = 0 ; i < num_trans ; i++) { trans[i] = rgba_list[i].alpha; } png_set_tRNS(png_ptr, png_info_ptr, trans, num_trans, trans_values); free(trans); } } png_set_PLTE( png_ptr, png_info_ptr, png_palette, index_data_count); free(png_palette); } png_image_data = (png_bytepp) malloc(png_height * sizeof(png_bytep)); if (color_type == PNG_COLOR_TYPE_PALETTE) { for (y=0 ; y < png_height ; y++) { png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr)); for (x=0 ; x < png_width ; x++) { unsigned char *data = image_data; png_image_data[y][x] = data[x + y*((png_width +3) & -4)]; } } } else if (color_type == PNG_COLOR_TYPE_RGB) { swf_xrgb_t *xrgb_list = image_data; for (y=0 ; y < png_height ; y++) { png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr)); for (x=0 ; x < png_width ; x++) { png_image_data[y][3*x] = xrgb_list[x+y*png_width].red; png_image_data[y][3*x+1] = xrgb_list[x+y*png_width].green; png_image_data[y][3*x+2] = xrgb_list[x+y*png_width].blue; } } } else { swf_argb_t *argb_list = image_data; for (y=0 ; y < png_height ; y++) { png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info_ptr)); for (x=0 ; x < png_width ; x++) { png_image_data[y][4*x] = argb_list[x+y*png_width].red; png_image_data[y][4*x+1] = argb_list[x+y*png_width].green; png_image_data[y][4*x+2] = argb_list[x+y*png_width].blue; png_image_data[y][4*x+3] = argb_list[x+y*png_width].alpha; } } } png_buff.data = NULL; png_buff.data_len = 0; png_buff.data_offset = 0; png_data_write((png_structp) png_ptr, (my_png_buffer*) &png_buff); png_write_info(png_ptr, png_info_ptr); png_write_image(png_ptr, png_image_data); png_write_end(png_ptr, png_info_ptr); // for (y=0 ; y < png_height ; y++) { free(png_image_data[y]); } free(png_image_data); png_destroy_write_struct((png_structpp) &png_ptr, (png_infopp) &png_info_ptr); *length = png_buff.data_offset; return png_buff.data; }
//saves the given SDL structure into a given filename. void save_image(surface surf, const std::string &filename) { //opens the actual file const util::scoped_FILE file(fopen(filename.c_str(),"wb")); //initializes PNG write structures //TODO: review whether providing NULL error handlers is something //sensible png_struct* png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, reinterpret_cast<png_voidp>(png_voidp_NULL), png_error_ptr_NULL, png_error_ptr_NULL); if(!png_ptr) throw exploder_failure("Unable to initialize the png write structure"); png_info* info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_write_struct(&png_ptr, static_cast<png_infopp>(NULL)); throw exploder_failure("Unable to initialize the png info structure"); } //instructs the PNG library to use the open file png_init_io(png_ptr, file); //sets compression level to the maximum png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); //configures the header png_set_IHDR(png_ptr, info_ptr, surf->w, surf->h, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); //puts the actual image data in the row_pointers array png_byte **row_pointers = new png_byte *[surf->h]; surface_lock lock(surf); //converts the data to the RGBA format. We cannot pass SDL data //directly to the png lib, even if we know its pixel format, because of //endianness problems. util::scoped_array<rgba> rgba_data(new rgba[surf->w * surf->h]); Uint32 *surf_data = lock.pixels(); int pos = 0; for(int y = 0; y < surf->h; ++y) { row_pointers[y] = reinterpret_cast<png_byte*>(rgba_data + pos); for(int x = 0; x < surf->w; ++x) { Uint8 red, green, blue, alpha; SDL_GetRGBA(*surf_data, surf->format, &red, &green, &blue, &alpha); rgba_data[pos].r = red; rgba_data[pos].g = green; rgba_data[pos].b = blue; rgba_data[pos].a = alpha; pos++; surf_data++; } } png_set_rows(png_ptr, info_ptr, row_pointers); //writes the actual image data png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); //cleans everything png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); delete [] row_pointers; }
int image_png_compress(MediaScanImage *i, MediaScanThumbSpec *spec) { int j, x, y; int color_space = PNG_COLOR_TYPE_RGB_ALPHA; volatile unsigned char *ptr = NULL; png_structp png_ptr; png_infop info_ptr; Buffer *buf; if (!i->_pixbuf_size) { LOG_WARN("PNG compression requires pixbuf data (%s)\n", i->path); return 0; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { FATAL("Could not initialize libpng\n"); } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, NULL); FATAL("Could not initialize libpng\n"); } // Initialize buffer for compressed data buf = (Buffer *)malloc(sizeof(Buffer)); buffer_init(buf, BUF_SIZE); i->_dbuf = (void *)buf; png_set_write_fn(png_ptr, buf, image_png_write_buf, image_png_flush_buf); if (setjmp(png_jmpbuf(png_ptr))) { if (ptr != NULL) free((void *)ptr); return 0; } // Match output color space with input file switch (i->channels) { case 4: case 3: LOG_DEBUG("PNG output color space set to RGBA\n"); color_space = PNG_COLOR_TYPE_RGB_ALPHA; break; case 2: case 1: LOG_DEBUG("PNG output color space set to gray alpha\n"); color_space = PNG_COLOR_TYPE_GRAY_ALPHA; break; } png_set_IHDR(png_ptr, info_ptr, spec->width, spec->height, 8, color_space, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); ptr = (unsigned char *)malloc(png_get_rowbytes(png_ptr, info_ptr)); j = 0; if (color_space == PNG_COLOR_TYPE_GRAY_ALPHA) { for (y = 0; y < spec->height; y++) { for (x = 0; x < spec->width; x++) { ptr[x * 2] = COL_BLUE(i->_pixbuf[j]); ptr[x * 2 + 1] = COL_ALPHA(i->_pixbuf[j]); j++; } png_write_row(png_ptr, (png_bytep) ptr); } } else { // RGB for (y = 0; y < spec->height; y++) { for (x = 0; x < spec->width; x++) { ptr[x * 4] = COL_RED(i->_pixbuf[j]); ptr[x * 4 + 1] = COL_GREEN(i->_pixbuf[j]); ptr[x * 4 + 2] = COL_BLUE(i->_pixbuf[j]); ptr[x * 4 + 3] = COL_ALPHA(i->_pixbuf[j]); j++; } png_write_row(png_ptr, (png_bytep) ptr); } } free((void *)ptr); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); return 1; }
// this code is heavily adapted from the paint license, which is in // the file paint.license (BSD compatible) included in this // distribution. TODO, add license file to MANIFEST.in and CVS Py::Object RendererAgg::write_png(const Py::Tuple& args) { //small memory leak in this function - JDH 2004-06-08 _VERBOSE("RendererAgg::write_png"); args.verify_length(1); FILE *fp; Py::Object o = Py::Object(args[0]); bool fpclose = true; if (o.isString()) { std::string fileName = Py::String(o); const char *file_name = fileName.c_str(); fp = fopen(file_name, "wb"); } else { if ((fp = PyFile_AsFile(o.ptr())) == NULL) throw Py::TypeError("Could not convert object to file pointer"); fpclose = false; } png_structp png_ptr; png_infop info_ptr; struct png_color_8_struct sig_bit; png_uint_32 row; png_bytep row_pointers[height]; for (row = 0; row < height; ++row) { row_pointers[row] = pixBuffer + row * width * 4; } if (fp == NULL) throw Py::RuntimeError("could not open file"); png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { if (fpclose) fclose(fp); throw Py::RuntimeError("could not create write struct"); } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { if (fpclose) fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); throw Py::RuntimeError("could not create info struct"); } if (setjmp(png_ptr->jmpbuf)) { if (fpclose) fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); throw Py::RuntimeError("error building image"); } png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); // this a a color image! sig_bit.gray = 0; sig_bit.red = 8; sig_bit.green = 8; sig_bit.blue = 8; /* if the image has an alpha channel then */ sig_bit.alpha = 8; png_set_sBIT(png_ptr, info_ptr, &sig_bit); png_write_info(png_ptr, info_ptr); png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); /* Changed calls to png_destroy_write_struct to follow http://www.libpng.org/pub/png/libpng-manual.txt. This ensures the info_ptr memory is released. */ png_destroy_write_struct(&png_ptr, &info_ptr); if (fpclose) fclose(fp); return Py::Object(); }
CAMLprim value write_png_index_to_buffer(value buffer, value cmap, value width, value height) { CAMLparam4(buffer, cmap, width, height); CAMLlocal1(vres); png_structp png_ptr; png_infop info_ptr; /* static */ struct mem_buffer state; int w, h; /* initialise - put this before png_write_png() call */ state.buffer = NULL; state.size = 0; w = Int_val(width); h = Int_val(height); if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL ) { failwith("png_create_write_struct"); } if((info_ptr = png_create_info_struct(png_ptr)) == NULL ) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); failwith("png_create_info_struct"); } /* error handling */ if (setjmp(png_jmpbuf(png_ptr))) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_write_struct(&png_ptr, &info_ptr); /* If we get here, we had a problem writing the file */ failwith("png write error"); } /* the final arg is NULL because we dont need in flush() */ png_set_write_fn(png_ptr, &state, png_write_data_to_buffer, NULL); /* we use system default compression */ /* png_set_filter(png_ptr, 0, PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_PAETH ); */ /* png_set_compression...() */ png_set_IHDR(png_ptr, info_ptr, w, h, 8 /* fixed */, PNG_COLOR_TYPE_PALETTE, /* fixed */ PNG_INTERLACE_ADAM7, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); { png_colorp palette; int num_palette; PngPalette_val(cmap, &palette, &num_palette ); if(num_palette <= 0 ) { png_destroy_write_struct(&png_ptr, &info_ptr); failwith("png write error (null colormap)"); } png_set_PLTE(png_ptr, info_ptr, palette, num_palette ); } /* infos... */ png_write_info(png_ptr, info_ptr); { int rowbytes, i; png_bytep *row_pointers; char *buf = String_val(buffer); row_pointers = (png_bytep*)stat_alloc(sizeof(png_bytep) * h); rowbytes= png_get_rowbytes(png_ptr, info_ptr); #if 0 printf("rowbytes= %d width=%d\n", rowbytes, w); #endif if(rowbytes != w && rowbytes != w * 2) { png_destroy_write_struct(&png_ptr, &info_ptr); failwith("png write error (illegal byte/pixel)"); } for(i=0; i< h; i++) { row_pointers[i] = (png_bytep)(buf + rowbytes * i); } png_write_image(png_ptr, row_pointers); stat_free((void*)row_pointers); } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); vres = caml_alloc_string(state.size); memcpy(String_val(vres), state.buffer, state.size); free(state.buffer); CAMLreturn(vres); }
// Method to write raw image into PNG at dest. The raw scanline begins // at the bottom of the image per SecondLife conventions. BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest) { try { S8 numComponents = rawImage->getComponents(); switch (numComponents) { case 1: mColorType = PNG_COLOR_TYPE_GRAY; break; case 2: mColorType = PNG_COLOR_TYPE_GRAY_ALPHA; break; case 3: mColorType = PNG_COLOR_TYPE_RGB; break; case 4: mColorType = PNG_COLOR_TYPE_RGB_ALPHA; break; default: mColorType = -1; } if (mColorType == -1) { throw "Unsupported image: unexpected number of channels"; } mWritePngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &errorHandler, NULL); if (!mWritePngPtr) { throw "Problem creating png write structure"; } mWriteInfoPtr = png_create_info_struct(mWritePngPtr); // Setup write function PngDataInfo dataPtr; dataPtr.mData = dest; dataPtr.mOffset = 0; png_set_write_fn(mWritePngPtr, &dataPtr, &writeDataCallback, &writeFlush); // Setup image params mWidth = rawImage->getWidth(); mHeight = rawImage->getHeight(); mBitDepth = 8; // Fixed to 8-bpp in SL mChannels = numComponents; mInterlaceType = PNG_INTERLACE_NONE; mCompressionType = PNG_COMPRESSION_TYPE_DEFAULT; mFilterMethod = PNG_FILTER_TYPE_DEFAULT; // Write header png_set_IHDR(mWritePngPtr, mWriteInfoPtr, mWidth, mHeight, mBitDepth, mColorType, mInterlaceType, mCompressionType, mFilterMethod); // Get data and compute row size const U8* data = rawImage->getData(); int offset = mWidth * mChannels; // Ready to write, start with the header png_write_info(mWritePngPtr, mWriteInfoPtr); // Write image (sorry, must const-cast for libpng) const U8 * rowPointer; for (U32 i=0; i < mHeight; i++) { rowPointer = &data[(mHeight-1-i)*offset]; png_write_row(mWritePngPtr, const_cast<png_bytep>(rowPointer)); } // Finish up png_write_end(mWritePngPtr, mWriteInfoPtr); mFinalSize = dataPtr.mOffset; } catch (png_const_charp msg) { mErrorMessage = msg; releaseResources(); return (FALSE); } releaseResources(); return TRUE; }
CAMLprim value write_png_file_index(value fd, value buffer, value cmap, value width, value height) { CAMLparam5(fd, buffer, cmap, width, height); FILE *fp; png_structp png_ptr; png_infop info_ptr; int w, h; w = Int_val(width); h = Int_val(height); if ((fp = fdopen(Int_val(fd), "wb")) == NULL ) { failwith("png file open failed"); } if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL ) { fclose(fp); failwith("png_create_write_struct"); } if((info_ptr = png_create_info_struct(png_ptr)) == NULL ) { fclose(fp); png_destroy_write_struct(&png_ptr, (png_infopp)NULL); failwith("png_create_info_struct"); } /* error handling */ if (setjmp(png_jmpbuf(png_ptr))) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); /* If we get here, we had a problem writing the file */ failwith("png write error"); } /* use standard C stream */ png_init_io(png_ptr, fp); /* we use system default compression */ /* png_set_filter(png_ptr, 0, PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_PAETH ); */ /* png_set_compression...() */ png_set_IHDR(png_ptr, info_ptr, w, h, 8 /* fixed */, PNG_COLOR_TYPE_PALETTE, /* fixed */ PNG_INTERLACE_ADAM7, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); { png_colorp palette; int num_palette; PngPalette_val(cmap, &palette, &num_palette ); if(num_palette <= 0 ) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); /* If we get here, we had a problem writing the file */ failwith("png write error (null colormap)"); } png_set_PLTE(png_ptr, info_ptr, palette, num_palette ); } /* infos... */ png_write_info(png_ptr, info_ptr); { int rowbytes, i; png_bytep *row_pointers; char *buf = String_val(buffer); row_pointers = (png_bytep*)stat_alloc(sizeof(png_bytep) * h); rowbytes= png_get_rowbytes(png_ptr, info_ptr); #if 0 printf("rowbytes= %d width=%d\n", rowbytes, w); #endif if(rowbytes != w && rowbytes != w * 2) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); /* If we get here, we had a problem writing the file */ failwith("png write error (illegal byte/pixel)"); } for(i=0; i< h; i++) { row_pointers[i] = (png_bytep)(buf + rowbytes * i); } png_write_image(png_ptr, row_pointers); stat_free((void*)row_pointers); } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); CAMLreturn(Val_unit); }
bool CCImage::_saveImageToPNG(const char * pszFilePath, bool bIsToRGB) { bool bRet = false; do { CC_BREAK_IF(NULL == pszFilePath); FILE *fp; png_structp png_ptr; png_infop info_ptr; png_colorp palette; png_bytep *row_pointers; FILE_STANDARD_INFO fileStandardInfo = { 0 }; HANDLE hFile; std::wstring path = CCUtf8ToUnicode(pszFilePath); CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {0}; extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN; extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS; extendedParams.lpSecurityAttributes = nullptr; extendedParams.hTemplateFile = nullptr; // read the file from hardware hFile = ::CreateFile2(path.c_str(), GENERIC_WRITE, 0, CREATE_ALWAYS, &extendedParams); if (INVALID_HANDLE_VALUE == hFile) { break; } int CrtFileHandle; /* convert OS file handle to CRT file pointer */ if ( (CrtFileHandle=_open_osfhandle ((long)hFile,_O_RDONLY))==-1){ //printf( "_open_osfhandle Failed "); break; } /* Change handle access to stream access. */ if( (fp = _fdopen( CrtFileHandle, "wb")) == NULL ) { //printf( "_fdopen Failed "); break; } CC_BREAK_IF(NULL == fp); png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (NULL == png_ptr) { fclose(fp); break; } info_ptr = png_create_info_struct(png_ptr); if (NULL == info_ptr) { fclose(fp); png_destroy_write_struct(&png_ptr, NULL); break; } #if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA) if (setjmp(png_jmpbuf(png_ptr))) { fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); break; } #endif png_init_io(png_ptr, fp); if (!bIsToRGB && m_bHasAlpha) { png_set_IHDR(png_ptr, info_ptr, m_nWidth, m_nHeight, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); } else { png_set_IHDR(png_ptr, info_ptr, m_nWidth, m_nHeight, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); } palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof (png_color)); png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); png_write_info(png_ptr, info_ptr); png_set_packing(png_ptr); row_pointers = (png_bytep *)malloc(m_nHeight * sizeof(png_bytep)); if(row_pointers == NULL) { fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); break; } if (!m_bHasAlpha) { for (int i = 0; i < (int)m_nHeight; i++) { row_pointers[i] = (png_bytep)m_pData + i * m_nWidth * 3; } png_write_image(png_ptr, row_pointers); free(row_pointers); row_pointers = NULL; } else { if (bIsToRGB) { unsigned char *pTempData = new unsigned char[m_nWidth * m_nHeight * 3]; if (NULL == pTempData) { fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); break; } for (int i = 0; i < m_nHeight; ++i) { for (int j = 0; j < m_nWidth; ++j) { pTempData[(i * m_nWidth + j) * 3] = m_pData[(i * m_nWidth + j) * 4]; pTempData[(i * m_nWidth + j) * 3 + 1] = m_pData[(i * m_nWidth + j) * 4 + 1]; pTempData[(i * m_nWidth + j) * 3 + 2] = m_pData[(i * m_nWidth + j) * 4 + 2]; } } for (int i = 0; i < (int)m_nHeight; i++) { row_pointers[i] = (png_bytep)pTempData + i * m_nWidth * 3; } png_write_image(png_ptr, row_pointers); free(row_pointers); row_pointers = NULL; CC_SAFE_DELETE_ARRAY(pTempData); } else { for (int i = 0; i < (int)m_nHeight; i++) { row_pointers[i] = (png_bytep)m_pData + i * m_nWidth * 4; } png_write_image(png_ptr, row_pointers); free(row_pointers); row_pointers = NULL; } } png_write_end(png_ptr, info_ptr); png_free(png_ptr, palette); palette = NULL; png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); bRet = true; } while (0); return bRet; }
bool PngEncoder::write( const Mat& img, const vector<int>& params ) { png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ); png_infop info_ptr = 0; FILE* f = 0; int y, width = img.cols, height = img.rows; int depth = img.depth(), channels = img.channels(); bool result = false; AutoBuffer<uchar*> buffer; if( depth != CV_8U && depth != CV_16U ) return false; if( png_ptr ) { info_ptr = png_create_info_struct( png_ptr ); if( info_ptr ) { if( setjmp( png_jmpbuf ( png_ptr ) ) == 0 ) { if( m_buf ) { png_set_write_fn(png_ptr, this, (png_rw_ptr)writeDataToBuf, (png_flush_ptr)flushBuf); } else { f = fopen( m_filename.c_str(), "wb" ); if( f ) png_init_io( png_ptr, f ); } int compression_level = -1; // Invalid value to allow setting 0-9 as valid int compression_strategy = Z_RLE; // Default strategy bool isBilevel = false; for( size_t i = 0; i < params.size(); i += 2 ) { if( params[i] == CV_IMWRITE_PNG_COMPRESSION ) { compression_level = params[i+1]; compression_level = MIN(MAX(compression_level, 0), Z_BEST_COMPRESSION); } if( params[i] == CV_IMWRITE_PNG_STRATEGY ) { compression_strategy = params[i+1]; compression_strategy = MIN(MAX(compression_strategy, 0), Z_FIXED); } if( params[i] == CV_IMWRITE_PNG_BILEVEL ) { isBilevel = params[i+1] != 0; } } if( m_buf || f ) { if( compression_level >= 0 ) { png_set_compression_level( png_ptr, compression_level ); } else { // tune parameters for speed // (see http://wiki.linuxquestions.org/wiki/Libpng) png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_SUB); png_set_compression_level(png_ptr, Z_BEST_SPEED); } png_set_compression_strategy(png_ptr, compression_strategy); png_set_IHDR( png_ptr, info_ptr, width, height, depth == CV_8U ? isBilevel?1:8 : 16, channels == 1 ? PNG_COLOR_TYPE_GRAY : channels == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); png_write_info( png_ptr, info_ptr ); if (isBilevel) png_set_packing(png_ptr); png_set_bgr( png_ptr ); if( !isBigEndian() ) png_set_swap( png_ptr ); buffer.allocate(height); for( y = 0; y < height; y++ ) buffer[y] = img.data + y*img.step; png_write_image( png_ptr, buffer ); png_write_end( png_ptr, info_ptr ); result = true; } } } } png_destroy_write_struct( &png_ptr, &info_ptr ); if(f) fclose( f ); return result; }
bool wxPNGHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose ) { wxPNGInfoStruct wxinfo; wxinfo.verbose = verbose; wxinfo.stream.out = &stream; png_structp png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING, NULL, wx_png_error, wx_png_warning ); if (!png_ptr) { if (verbose) wxLogError(_("Couldn't save PNG image.")); return false; } png_infop info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_write_struct( &png_ptr, (png_infopp)NULL ); if (verbose) wxLogError(_("Couldn't save PNG image.")); return false; } if (setjmp(wxinfo.jmpbuf)) { png_destroy_write_struct( &png_ptr, (png_infopp)NULL ); if (verbose) wxLogError(_("Couldn't save PNG image.")); return false; } // NB: please see the comment near wxPNGInfoStruct declaration for // explanation why this line is mandatory png_set_write_fn( png_ptr, &wxinfo, wx_PNG_stream_writer, NULL); const int iColorType = image->HasOption(wxIMAGE_OPTION_PNG_FORMAT) ? image->GetOptionInt(wxIMAGE_OPTION_PNG_FORMAT) : wxPNG_TYPE_COLOUR; const int iBitDepth = image->HasOption(wxIMAGE_OPTION_PNG_BITDEPTH) ? image->GetOptionInt(wxIMAGE_OPTION_PNG_BITDEPTH) : 8; wxASSERT_MSG( iBitDepth == 8 || iBitDepth == 16, _T("PNG bit depth must be 8 or 16") ); bool bHasAlpha = image->HasAlpha(); bool bHasMask = image->HasMask(); bool bUseAlpha = bHasAlpha || bHasMask; int iPngColorType; if ( iColorType==wxPNG_TYPE_COLOUR ) { iPngColorType = bUseAlpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB; } else { iPngColorType = bUseAlpha ? PNG_COLOR_TYPE_GRAY_ALPHA : PNG_COLOR_TYPE_GRAY; } png_set_IHDR( png_ptr, info_ptr, image->GetWidth(), image->GetHeight(), iBitDepth, iPngColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); int iElements; png_color_8 sig_bit; if ( iPngColorType & PNG_COLOR_MASK_COLOR ) { sig_bit.red = sig_bit.green = sig_bit.blue = (png_byte)iBitDepth; iElements = 3; } else // grey { sig_bit.gray = (png_byte)iBitDepth; iElements = 1; } if ( iPngColorType & PNG_COLOR_MASK_ALPHA ) { sig_bit.alpha = (png_byte)iBitDepth; iElements++; } if ( iBitDepth == 16 ) iElements *= 2; png_set_sBIT( png_ptr, info_ptr, &sig_bit ); png_write_info( png_ptr, info_ptr ); png_set_shift( png_ptr, &sig_bit ); png_set_packing( png_ptr ); unsigned char * data = (unsigned char *)malloc( image->GetWidth() * iElements ); if ( !data ) { png_destroy_write_struct( &png_ptr, (png_infopp)NULL ); return false; } unsigned char * pAlpha = (unsigned char *)(bHasAlpha ? image->GetAlpha() : NULL); int iHeight = image->GetHeight(); int iWidth = image->GetWidth(); unsigned char uchMaskRed = 0, uchMaskGreen = 0, uchMaskBlue = 0; if ( bHasMask ) { uchMaskRed = image->GetMaskRed(); uchMaskGreen = image->GetMaskGreen(); uchMaskBlue = image->GetMaskBlue(); } unsigned char *pColors = image->GetData(); for (int y = 0; y != iHeight; ++y) { unsigned char *pData = data; for (int x = 0; x != iWidth; x++) { unsigned char uchRed = *pColors++; unsigned char uchGreen = *pColors++; unsigned char uchBlue = *pColors++; switch ( iColorType ) { default: wxFAIL_MSG( _T("unknown wxPNG_TYPE_XXX") ); // fall through case wxPNG_TYPE_COLOUR: *pData++ = uchRed; if ( iBitDepth == 16 ) *pData++ = 0; *pData++ = uchGreen; if ( iBitDepth == 16 ) *pData++ = 0; *pData++ = uchBlue; if ( iBitDepth == 16 ) *pData++ = 0; break; case wxPNG_TYPE_GREY: { // where do these coefficients come from? maybe we // should have image options for them as well? unsigned uiColor = (unsigned) (76.544*(unsigned)uchRed + 150.272*(unsigned)uchGreen + 36.864*(unsigned)uchBlue); *pData++ = (unsigned char)((uiColor >> 8) & 0xFF); if ( iBitDepth == 16 ) *pData++ = (unsigned char)(uiColor & 0xFF); } break; case wxPNG_TYPE_GREY_RED: *pData++ = uchRed; if ( iBitDepth == 16 ) *pData++ = 0; break; } if ( bUseAlpha ) { unsigned char uchAlpha = 255; if ( bHasAlpha ) uchAlpha = *pAlpha++; if ( bHasMask ) { if ( (uchRed == uchMaskRed) && (uchGreen == uchMaskGreen) && (uchBlue == uchMaskBlue) ) uchAlpha = 0; } *pData++ = uchAlpha; if ( iBitDepth == 16 ) *pData++ = 0; } } png_bytep row_ptr = data; png_write_rows( png_ptr, &row_ptr, 1 ); } free(data); png_write_end( png_ptr, info_ptr ); png_destroy_write_struct( &png_ptr, (png_infopp)&info_ptr ); return true; }
void fr_io_png_dump(fr_t * fr, FILE *fp) { log_debug("png io dump started"); png_structp png_ptr = NULL; png_infop info_ptr = NULL; // Initialize write structure png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { log_error("Couldn't create PNG write struct"); } // Initialize info structure info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { log_error("Couldn't create PNG info struct"); } // Setup Exception handling if (setjmp(png_jmpbuf(png_ptr))) { log_error("Error during PNG creation"); } png_init_io(png_ptr, fp); log_trace("png header writing started"); // Write header (8 bit colour depth) png_set_IHDR(png_ptr, info_ptr, fr->dim.width, fr->dim.height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); log_trace("png header ended started"); char * title = "fractalrender"; // Set title if (title != NULL) { png_text title_text; title_text.compression = PNG_TEXT_COMPRESSION_NONE; title_text.key = "Title"; title_text.text = title; png_set_text(png_ptr, info_ptr, &title_text, 1); } log_trace("png info writing started"); png_write_info(png_ptr, info_ptr); log_trace("png info writing ended"); log_trace("png pixel writing started"); int y; for (y = 0; y < fr->dim.height; y++) { png_write_row(png_ptr, fr->bitmap + 4 * fr->dim.width * y); } log_trace("png pixel writing ended"); // End write png_write_end(png_ptr, NULL); if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); log_debug("png io dump ended"); }
int main( int argc, char *argv[]) { int opt = 0; bool writeToStdout = false; char *pngName = DEFAULT_NAME; int32_t requestedWidth = 0; int32_t requestedHeight = 0; uint32_t displayNumber = DEFAULT_DISPLAY_NUMBER; int compression = Z_DEFAULT_COMPRESSION; int delay = DEFAULT_DELAY; VC_IMAGE_TYPE_T imageType = VC_IMAGE_RGBA32; int8_t dmxBytesPerPixel = 4; int result = 0; program = basename(argv[0]); //------------------------------------------------------------------- char *sopts = "c:d:D:Hh:p:w:s"; struct option lopts[] = { { "compression", required_argument, NULL, 'c' }, { "delay", required_argument, NULL, 'd' }, { "display", required_argument, NULL, 'D' }, { "height", required_argument, NULL, 'h' }, { "help", no_argument, NULL, 'H' }, { "pngname", required_argument, NULL, 'p' }, { "width", required_argument, NULL, 'w' }, { "stdout", no_argument, NULL, 's' }, { NULL, no_argument, NULL, 0 } }; while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { switch (opt) { case 'c': compression = atoi(optarg); if ((compression < 0) || (compression > 9)) { compression = Z_DEFAULT_COMPRESSION; } break; case 'd': delay = atoi(optarg); break; case 'D': displayNumber = atoi(optarg); break; case 'h': requestedHeight = atoi(optarg); break; case 'p': pngName = optarg; break; case 'w': requestedWidth = atoi(optarg); break; case 's': writeToStdout = true; break; case 'H': default: usage(); if (opt == 'H') { exit(EXIT_SUCCESS); } else { exit(EXIT_FAILURE); } break; } } //------------------------------------------------------------------- bcm_host_init(); //------------------------------------------------------------------- // // When the display is rotate (either 90 or 270 degrees) we need to // swap the width and height of the snapshot // char response[1024]; int displayRotated = 0; if (vc_gencmd(response, sizeof(response), "get_config int") == 0) { vc_gencmd_number_property(response, "display_rotate", &displayRotated); } //------------------------------------------------------------------- if (delay) { sleep(delay); } //------------------------------------------------------------------- DISPMANX_DISPLAY_HANDLE_T displayHandle = vc_dispmanx_display_open(displayNumber); if (displayHandle == 0) { fprintf(stderr, "%s: unable to open display %d\n", program, displayNumber); exit(EXIT_FAILURE); } DISPMANX_MODEINFO_T modeInfo; result = vc_dispmanx_display_get_info(displayHandle, &modeInfo); if (result != 0) { fprintf(stderr, "%s: unable to get display information\n", program); exit(EXIT_FAILURE); } int32_t pngWidth = modeInfo.width; int32_t pngHeight = modeInfo.height; if (requestedWidth > 0) { pngWidth = requestedWidth; if (requestedHeight == 0) { double numerator = modeInfo.height * requestedWidth; double denominator = modeInfo.width; pngHeight = (int32_t)ceil(numerator / denominator); } } if (requestedHeight > 0) { pngHeight = requestedHeight; if (requestedWidth == 0) { double numerator = modeInfo.width * requestedHeight; double denominator = modeInfo.height; pngWidth = (int32_t)ceil(numerator / denominator); } } //------------------------------------------------------------------- // only need to check low bit of displayRotated (value of 1 or 3). // If the display is rotated either 90 or 270 degrees (value 1 or 3) // the width and height need to be transposed. int32_t dmxWidth = pngWidth; int32_t dmxHeight = pngHeight; if (displayRotated & 1) { dmxWidth = pngHeight; dmxHeight = pngWidth; } int32_t dmxPitch = dmxBytesPerPixel * ALIGN_TO_16(dmxWidth); void *dmxImagePtr = malloc(dmxPitch * dmxHeight); if (dmxImagePtr == NULL) { fprintf(stderr, "%s: unable to allocated image buffer\n", program); exit(EXIT_FAILURE); } //------------------------------------------------------------------- uint32_t vcImagePtr = 0; DISPMANX_RESOURCE_HANDLE_T resourceHandle; resourceHandle = vc_dispmanx_resource_create(imageType, dmxWidth, dmxHeight, &vcImagePtr); result = vc_dispmanx_snapshot(displayHandle, resourceHandle, DISPMANX_NO_ROTATE); if (result != 0) { vc_dispmanx_resource_delete(resourceHandle); vc_dispmanx_display_close(displayHandle); fprintf(stderr, "%s: vc_dispmanx_snapshot() failed\n", program); exit(EXIT_FAILURE); } VC_RECT_T rect; result = vc_dispmanx_rect_set(&rect, 0, 0, dmxWidth, dmxHeight); if (result != 0) { vc_dispmanx_resource_delete(resourceHandle); vc_dispmanx_display_close(displayHandle); fprintf(stderr, "%s: vc_dispmanx_rect_set() failed\n", program); exit(EXIT_FAILURE); } result = vc_dispmanx_resource_read_data(resourceHandle, &rect, dmxImagePtr, dmxPitch); if (result != 0) { vc_dispmanx_resource_delete(resourceHandle); vc_dispmanx_display_close(displayHandle); fprintf(stderr, "%s: vc_dispmanx_resource_read_data() failed\n", program); exit(EXIT_FAILURE); } vc_dispmanx_resource_delete(resourceHandle); vc_dispmanx_display_close(displayHandle); //------------------------------------------------------------------- // Convert from RGBA (32 bit) to RGB (24 bit) int8_t pngBytesPerPixel = 3; int32_t pngPitch = pngBytesPerPixel * pngWidth; void *pngImagePtr = malloc(pngPitch * pngHeight); int32_t j = 0; for (j = 0 ; j < pngHeight ; j++) { int32_t dmxXoffset = 0; int32_t dmxYoffset = 0; switch (displayRotated & 3) { case 0: // 0 degrees if (displayRotated & 0x20000) // flip vertical { dmxYoffset = (dmxHeight - j - 1) * dmxPitch; } else { dmxYoffset = j * dmxPitch; } break; case 1: // 90 degrees if (displayRotated & 0x20000) // flip vertical { dmxXoffset = j * dmxBytesPerPixel; } else { dmxXoffset = (dmxWidth - j - 1) * dmxBytesPerPixel; } break; case 2: // 180 degrees if (displayRotated & 0x20000) // flip vertical { dmxYoffset = j * dmxPitch; } else { dmxYoffset = (dmxHeight - j - 1) * dmxPitch; } break; case 3: // 270 degrees if (displayRotated & 0x20000) // flip vertical { dmxXoffset = (dmxWidth - j - 1) * dmxBytesPerPixel; } else { dmxXoffset = j * dmxBytesPerPixel; } break; } int32_t i = 0; for (i = 0 ; i < pngWidth ; i++) { uint8_t *pngPixelPtr = pngImagePtr + (i * pngBytesPerPixel) + (j * pngPitch); switch (displayRotated & 3) { case 0: // 0 degrees if (displayRotated & 0x10000) // flip horizontal { dmxXoffset = (dmxWidth - i - 1) * dmxBytesPerPixel; } else { dmxXoffset = i * dmxBytesPerPixel; } break; case 1: // 90 degrees if (displayRotated & 0x10000) // flip horizontal { dmxYoffset = (dmxHeight - i - 1) * dmxPitch; } else { dmxYoffset = i * dmxPitch; } break; case 2: // 180 degrees if (displayRotated & 0x10000) // flip horizontal { dmxXoffset = i * dmxBytesPerPixel; } else { dmxXoffset = (dmxWidth - i - 1) * dmxBytesPerPixel; } break; case 3: // 270 degrees if (displayRotated & 0x10000) // flip horizontal { dmxYoffset = i * dmxPitch; } else { dmxYoffset = (dmxHeight - i - 1) * dmxPitch; } break; } uint8_t *dmxPixelPtr = dmxImagePtr + dmxXoffset + dmxYoffset; memcpy(pngPixelPtr, dmxPixelPtr, 3); } } free(dmxImagePtr); dmxImagePtr = NULL; //------------------------------------------------------------------- png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (pngPtr == NULL) { fprintf(stderr, "%s: unable to allocated PNG write structure\n", program); exit(EXIT_FAILURE); } png_infop infoPtr = png_create_info_struct(pngPtr); if (infoPtr == NULL) { fprintf(stderr, "%s: unable to allocated PNG info structure\n", program); exit(EXIT_FAILURE); } if (setjmp(png_jmpbuf(pngPtr))) { fprintf(stderr, "%s: unable to create PNG\n", program); exit(EXIT_FAILURE); } FILE *pngfp = NULL; if (writeToStdout) { pngfp = stdout; } else { pngfp = fopen(pngName, "wb"); if (pngfp == NULL) { fprintf(stderr, "%s: unable to create %s - %s\n", program, pngName, strerror(errno)); exit(EXIT_FAILURE); } } png_init_io(pngPtr, pngfp); png_set_IHDR( pngPtr, infoPtr, pngWidth, pngHeight, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if (compression != Z_DEFAULT_COMPRESSION) { png_set_compression_level(pngPtr, compression); } png_write_info(pngPtr, infoPtr); int y = 0; for (y = 0; y < pngHeight; y++) { png_write_row(pngPtr, pngImagePtr + (pngPitch * y)); } png_write_end(pngPtr, NULL); png_destroy_write_struct(&pngPtr, &infoPtr); if (pngfp != stdout) { fclose(pngfp); } //------------------------------------------------------------------- free(pngImagePtr); pngImagePtr = NULL; return 0; }
static BOOL SaveBmpToPNGfile(HBITMAP hbmp,LPTSTR file) { BITMAP bmp; FILE * fp = NULL; if(!GetObject(hbmp,sizeof(BITMAP),&bmp))return FALSE; fp = _tfopen(file,TEXT("wb")); if(!fp) { DeleteObject(hbmp); return FALSE; } png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL, user_err_fn,user_err_fn); if(!png_ptr) { DeleteObject(hbmp); return FALSE; } png_infop png_info_ptr = png_create_info_struct(png_ptr); if(!png_info_ptr) { DeleteObject(hbmp); png_destroy_write_struct(&png_ptr,NULL); return FALSE; } if(setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr,&png_info_ptr); fclose(fp); DeleteFile(file); DeleteObject(hbmp); return FALSE; } int color = PNG_COLOR_TYPE_RGB_ALPHA; if(bmp.bmBitsPixel < 32) color = PNG_COLOR_TYPE_RGB; LONG row_length; BYTE * row_bytes; PBYTE * rows_bytes =(PBYTE*) malloc( bmp.bmHeight * sizeof(png_byte *)); row_length =bmp.bmHeight * bmp.bmWidthBytes; row_bytes = (PBYTE) png_malloc(png_ptr,row_length); GetBitmapBits(hbmp,row_length,row_bytes); if(bmp.bmBitsPixel >=24) { for ( LONG i=0 ,j=0; i < bmp.bmHeight ; i ++ ,j +=bmp.bmWidthBytes ) { rows_bytes[i] = row_bytes + j; if(color & PNG_COLOR_MASK_ALPHA) for(LONG k=0; k < bmp.bmWidthBytes ; k+= 4) rows_bytes[i][k+3] = 255; } }else //16 bit { for (int i =0; i < bmp.bmHeight ; i ++) { rows_bytes[i] =(PBYTE) malloc(bmp.bmWidth * 3); for(int j=0,k=0; j < bmp.bmWidthBytes; j+=2, k+=3) { WORD Color;//存16bit的颜色 double Red,Green,Blue; Color = *(PWORD)(row_bytes + i * bmp.bmWidthBytes + j ); Blue=(Color&0xF800)>> 11; Green=(Color&0x7e0)>> 5; Red=(Color&0x1F); rows_bytes[i][k] = (BYTE)(Red * 256 / 32 +0.5); rows_bytes[i][k+1] = (BYTE)(Green * 256 / 64 +0.5); rows_bytes[i][k+2] = (BYTE)(Blue * 256 / 32 +0.5); } } } png_set_IHDR(png_ptr,png_info_ptr,bmp.bmWidth,bmp.bmHeight,8, color, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_init_io(png_ptr,fp); png_set_rows(png_ptr,png_info_ptr,rows_bytes); png_set_bgr(png_ptr); //crc32(0, Z_NULL, 0); png_write_png(png_ptr, png_info_ptr,0,0); png_write_end(png_ptr,png_info_ptr); png_destroy_write_struct(&png_ptr, &png_info_ptr); if(!(color & PNG_COLOR_MASK_ALPHA)) { for(int i = 0; i < bmp.bmHeight ; i++) { free(rows_bytes[i]); } } free(rows_bytes); free(row_bytes); DeleteObject(hbmp); fclose(fp); return TRUE; }
int writePNG(struct opj_res *res, char *title, unsigned xPos, unsigned yPos, unsigned w, unsigned h, unsigned num_comps) { int code = 0; if(w == 0) { w = res->image->comps[0].w; } if(h == 0) { h = res->image->comps[0].h; } if(xPos >= res->image->comps[0].w) { xPos = 0; } if(yPos >= res->image->comps[0].h) { yPos = 0; } if(xPos + w >= res->image->comps[0].w) { w = res->image->comps[0].w - xPos; } if(yPos + h >= res->image->comps[0].h) { h = res->image->comps[0].h - yPos; } png_structp png_ptr; png_infop info_ptr; png_bytep row; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { code = 1; goto finalise; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { code = 1; goto finalise; } if (setjmp(png_jmpbuf(png_ptr))) { code = 1; goto finalise; } png_init_io(png_ptr, stdout); png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if (title != NULL) { png_text title_text; title_text.compression = PNG_TEXT_COMPRESSION_NONE; title_text.key = "Title"; title_text.text = title; png_set_text(png_ptr, info_ptr, &title_text, 1); } png_write_info(png_ptr, info_ptr); row = (png_bytep) malloc(3 * w * sizeof(png_byte)); unsigned x, y; for (y = yPos ; y < yPos + h ; y++) { for (x = xPos ; x < xPos + w ; x++) { int i = y * res->image->comps[0].w + x; if(num_comps < 3) { setRGB(&(row[(x-xPos)*3]), res->image->comps[0].data[i], res->image->comps[0].data[i], res->image->comps[0].data[i]); } else { setRGB(&(row[(x-xPos)*3]), res->image->comps[0].data[i], res->image->comps[1].data[i], res->image->comps[2].data[i]); } } png_write_row(png_ptr, row); } png_write_end(png_ptr, NULL); finalise: if (info_ptr != NULL) { png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); free(info_ptr); } if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); if (row != NULL) free(row); return code; }
/*! * pixWriteStreamPng() * * Input: stream * pix * gamma (use 0.0 if gamma is not defined) * Return: 0 if OK; 1 on error * * Notes: * (1) If called from pixWriteStream(), the stream is positioned * at the beginning of the file. * (2) To do sequential writes of png format images to a stream, * use pixWriteStreamPng() directly. * (3) gamma is an optional png chunk. If no gamma value is to be * placed into the file, use gamma = 0.0. Otherwise, if * gamma > 0.0, its value is written into the header. * (4) The use of gamma in png is highly problematic. For an illuminating * discussion, see: http://hsivonen.iki.fi/png-gamma/ * (5) What is the effect/meaning of gamma in the png file? This * gamma, which we can call the 'source' gamma, is the * inverse of the gamma that was used in enhance.c to brighten * or darken images. The 'source' gamma is supposed to indicate * the intensity mapping that was done at the time the * image was captured. Display programs typically apply a * 'display' gamma of 2.2 to the output, which is intended * to linearize the intensity based on the response of * thermionic tubes (CRTs). Flat panel LCDs have typically * been designed to give a similar response as CRTs (call it * "backward compatibility"). The 'display' gamma is * in some sense the inverse of the 'source' gamma. * jpeg encoders attached to scanners and cameras will lighten * the pixels, applying a gamma corresponding to approximately * a square-root relation of output vs input: * output = input^(gamma) * where gamma is often set near 0.4545 (1/gamma is 2.2). * This is stored in the image file. Then if the display * program reads the gamma, it will apply a display gamma, * typically about 2.2; the product is 1.0, and the * display program produces a linear output. This works because * the dark colors were appropriately boosted by the scanner, * as described by the 'source' gamma, so they should not * be further boosted by the display program. * (6) As an example, with xv and display, if no gamma is stored, * the program acts as if gamma were 0.4545, multiplies this by 2.2, * and does a linear rendering. Taking this as a baseline * brightness, if the stored gamma is: * > 0.4545, the image is rendered lighter than baseline * < 0.4545, the image is rendered darker than baseline * In contrast, gqview seems to ignore the gamma chunk in png. * (7) The only valid pixel depths in leptonica are 1, 2, 4, 8, 16 * and 32. However, it is possible, and in some cases desirable, * to write out a png file using an rgb pix that has 24 bpp. * For example, the open source xpdf SplashBitmap class generates * 24 bpp rgb images. Consequently, we anble writing 24 bpp pix. * To generate such a pix, you can make a 24 bpp pix without data * and assign the data array to the pix; e.g., * pix = pixCreateHeader(w, h, 24); * pixSetData(pix, rgbdata); * See pixConvert32To24() for an example, where we get rgbdata * from the 32 bpp pix. Caution: do not call pixSetPadBits(), * because the alignment is wrong and you may erase part of the * last pixel on each line. */ l_int32 pixWriteStreamPng(FILE *fp, PIX *pix, l_float32 gamma) { char commentstring[] = "Comment"; l_int32 i, j, k; l_int32 wpl, d, cmflag; l_int32 ncolors; l_int32 *rmap, *gmap, *bmap; l_uint32 *data, *ppixel; png_byte bit_depth, color_type; png_uint_32 w, h; png_uint_32 xres, yres; png_bytep *row_pointers; png_bytep rowbuffer; png_structp png_ptr; png_infop info_ptr; png_colorp palette; PIX *pixt; PIXCMAP *cmap; char *text; PROCNAME("pixWriteStreamPng"); if (!fp) return ERROR_INT("stream not open", procName, 1); if (!pix) return ERROR_INT("pix not defined", procName, 1); /* Allocate the 2 data structures */ if ((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL)) == NULL) return ERROR_INT("png_ptr not made", procName, 1); if ((info_ptr = png_create_info_struct(png_ptr)) == NULL) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return ERROR_INT("info_ptr not made", procName, 1); } /* Set up png setjmp error handling */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); return ERROR_INT("internal png error", procName, 1); } png_init_io(png_ptr, fp); /* With best zlib compression (9), get between 1 and 10% improvement * over default (5), but the compression is 3 to 10 times slower. * Our default compression is the zlib default (5). */ png_set_compression_level(png_ptr, var_ZLIB_COMPRESSION); w = pixGetWidth(pix); h = pixGetHeight(pix); d = pixGetDepth(pix); if ((cmap = pixGetColormap(pix))) cmflag = 1; else cmflag = 0; /* Set the color type and bit depth. */ if (d == 32 && var_PNG_WRITE_ALPHA == 1) { bit_depth = 8; color_type = PNG_COLOR_TYPE_RGBA; /* 6 */ cmflag = 0; /* ignore if it exists */ } else if (d == 24 || d == 32) { bit_depth = 8; color_type = PNG_COLOR_TYPE_RGB; /* 2 */ cmflag = 0; /* ignore if it exists */ } else { bit_depth = d; color_type = PNG_COLOR_TYPE_GRAY; /* 0 */ } if (cmflag) color_type = PNG_COLOR_TYPE_PALETTE; /* 3 */ #if DEBUG fprintf(stderr, "cmflag = %d, bit_depth = %d, color_type = %d\n", cmflag, bit_depth, color_type); #endif /* DEBUG */ png_set_IHDR(png_ptr, info_ptr, w, h, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* Store resolution in ppm, if known */ xres = (png_uint_32)(39.37 * (l_float32)pixGetXRes(pix) + 0.5); yres = (png_uint_32)(39.37 * (l_float32)pixGetYRes(pix) + 0.5); if ((xres == 0) || (yres == 0)) png_set_pHYs(png_ptr, info_ptr, 0, 0, PNG_RESOLUTION_UNKNOWN); else png_set_pHYs(png_ptr, info_ptr, xres, yres, PNG_RESOLUTION_METER); if (cmflag) { pixcmapToArrays(cmap, &rmap, &gmap, &bmap); ncolors = pixcmapGetCount(cmap); /* Make and save the palette */ if ((palette = (png_colorp)(CALLOC(ncolors, sizeof(png_color)))) == NULL) return ERROR_INT("palette not made", procName, 1); for (i = 0; i < ncolors; i++) { palette[i].red = (png_byte)rmap[i]; palette[i].green = (png_byte)gmap[i]; palette[i].blue = (png_byte)bmap[i]; } png_set_PLTE(png_ptr, info_ptr, palette, (int)ncolors); FREE(rmap); FREE(gmap); FREE(bmap); } /* 0.4545 is treated as the default by some image * display programs (not gqview). A value > 0.4545 will * lighten an image as displayed by xv, display, etc. */ if (gamma > 0.0) png_set_gAMA(png_ptr, info_ptr, (l_float64)gamma); if ((text = pixGetText(pix))) { png_text text_chunk; text_chunk.compression = PNG_TEXT_COMPRESSION_NONE; text_chunk.key = commentstring; text_chunk.text = text; text_chunk.text_length = strlen(text); #ifdef PNG_ITXT_SUPPORTED text_chunk.itxt_length = 0; text_chunk.lang = NULL; text_chunk.lang_key = NULL; #endif png_set_text(png_ptr, info_ptr, &text_chunk, 1); } /* Write header and palette info */ png_write_info(png_ptr, info_ptr); if ((d != 32) && (d != 24)) { /* not rgb color */ /* Generate a temporary pix with bytes swapped. * For a binary image, there are two conditions in * which you must first invert the data for writing png: * (a) no colormap * (b) colormap with BLACK set to 0 * png writes binary with BLACK = 0, unless contradicted * by a colormap. If the colormap has BLACK = "1" * (typ. about 255), do not invert the data. If there * is no colormap, you must invert the data to store * in default BLACK = 0 state. */ if (d == 1 && (!cmap || (cmap && ((l_uint8 *)(cmap->array))[0] == 0x0))) { pixt = pixInvert(NULL, pix); pixEndianByteSwap(pixt); } else pixt = pixEndianByteSwapNew(pix); if (!pixt) { png_destroy_write_struct(&png_ptr, &info_ptr); return ERROR_INT("pixt not made", procName, 1); } /* Make and assign array of image row pointers */ if ((row_pointers = (png_bytep *)CALLOC(h, sizeof(png_bytep))) == NULL) return ERROR_INT("row-pointers not made", procName, 1); wpl = pixGetWpl(pixt); data = pixGetData(pixt); for (i = 0; i < h; i++) row_pointers[i] = (png_bytep)(data + i * wpl); png_set_rows(png_ptr, info_ptr, row_pointers); /* Transfer the data */ png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); if (cmflag) FREE(palette); FREE(row_pointers); pixDestroy(&pixt); png_destroy_write_struct(&png_ptr, &info_ptr); return 0; } /* For rgb, compose and write a row at a time */ data = pixGetData(pix); wpl = pixGetWpl(pix); if (d == 24) { /* See note 7 above: special case of 24 bpp rgb */ for (i = 0; i < h; i++) { ppixel = data + i * wpl; png_write_rows(png_ptr, (png_bytepp)&ppixel, 1); } } else { /* 32 bpp rgb and rgba */ if ((rowbuffer = (png_bytep)CALLOC(w, 4)) == NULL) return ERROR_INT("rowbuffer not made", procName, 1); for (i = 0; i < h; i++) { ppixel = data + i * wpl; for (j = k = 0; j < w; j++) { rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_RED); rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_GREEN); rowbuffer[k++] = GET_DATA_BYTE(ppixel, COLOR_BLUE); if (var_PNG_WRITE_ALPHA == 1) rowbuffer[k++] = GET_DATA_BYTE(ppixel, L_ALPHA_CHANNEL); ppixel++; } png_write_rows(png_ptr, &rowbuffer, 1); } FREE(rowbuffer); } png_write_end(png_ptr, info_ptr); if (cmflag) FREE(palette); png_destroy_write_struct(&png_ptr, &info_ptr); return 0; }
/** * Write png to file * Return: * 0 OK * negative ERROR */ int write_png(const char *path, const Bitmap_t *mem) { VALIDATE_NOT_NULL2(path, mem); FILE *fp; png_structp png_ptr; png_infop info_ptr; png_colorp palette; fp = fopen(path, "wb"); if (NULL == fp) { LogE("Failed open file\n"); return -1; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (NULL == png_ptr) { fclose (fp); return -1; } info_ptr = png_create_info_struct(png_ptr); if (NULL == info_ptr) { fclose (fp); png_destroy_write_struct(&png_ptr, NULL); return -1; } if (setjmp(png_jmpbuf(png_ptr))) { LogE("write file occur error"); fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); return -1; } int form = PNG_COLOR_TYPE_RGB_ALPHA; int depth = 8; switch (mem->form) { case RGBA32: form = PNG_COLOR_TYPE_RGBA; break; case RGB24: form = PNG_COLOR_TYPE_RGB; break; case GRAY: form = PNG_COLOR_TYPE_GRAY; depth = 1; break; } png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, mem->width, mem->height, depth, form, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); png_bytep row_pointers[mem->height]; int k; for (k = 0; k < mem->height; ++k) { row_pointers[k] = mem->base + k * mem->width * mem->form; } png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); fclose (fp); return 0; }
static GstFlowReturn gst_pngenc_chain (GstPad * pad, GstBuffer * buf) { GstPngEnc *pngenc; gint row_index; gint color_type; png_byte *row_pointers[MAX_HEIGHT]; GstFlowReturn ret = GST_FLOW_OK; GstBuffer *encoded_buf = NULL; pngenc = GST_PNGENC (gst_pad_get_parent (pad)); GST_DEBUG_OBJECT (pngenc, "BEGINNING"); /* initialize png struct stuff */ pngenc->png_struct_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL, user_error_fn, user_warning_fn); if (pngenc->png_struct_ptr == NULL) { gst_buffer_unref (buf); GST_ELEMENT_ERROR (pngenc, LIBRARY, INIT, (NULL), ("Failed to initialize png structure")); ret = GST_FLOW_ERROR; goto done; } pngenc->png_info_ptr = png_create_info_struct (pngenc->png_struct_ptr); if (!pngenc->png_info_ptr) { gst_buffer_unref (buf); png_destroy_write_struct (&(pngenc->png_struct_ptr), (png_infopp) NULL); GST_ELEMENT_ERROR (pngenc, LIBRARY, INIT, (NULL), ("Failed to initialize the png info structure")); ret = GST_FLOW_ERROR; goto done; } /* non-0 return is from a longjmp inside of libpng */ if (setjmp (png_jmpbuf (pngenc->png_struct_ptr)) != 0) { gst_buffer_unref (buf); png_destroy_write_struct (&pngenc->png_struct_ptr, &pngenc->png_info_ptr); GST_ELEMENT_ERROR (pngenc, LIBRARY, FAILED, (NULL), ("returning from longjmp")); ret = GST_FLOW_ERROR; goto done; } png_set_filter (pngenc->png_struct_ptr, 0, PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE); png_set_compression_level (pngenc->png_struct_ptr, pngenc->compression_level); if (pngenc->bpp == 32) color_type = PNG_COLOR_TYPE_RGBA; else if (pngenc->bpp == 8) color_type = PNG_COLOR_TYPE_GRAY; else color_type = PNG_COLOR_TYPE_RGB; png_set_IHDR (pngenc->png_struct_ptr, pngenc->png_info_ptr, pngenc->width, pngenc->height, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_write_fn (pngenc->png_struct_ptr, pngenc, (png_rw_ptr) user_write_data, user_flush_data); for (row_index = 0; row_index < pngenc->height; row_index++) { row_pointers[row_index] = GST_BUFFER_DATA (buf) + (row_index * pngenc->stride); } /* allocate the output buffer */ pngenc->buffer_out = gst_buffer_new_and_alloc (pngenc->height * pngenc->stride); pngenc->written = 0; png_write_info (pngenc->png_struct_ptr, pngenc->png_info_ptr); png_write_image (pngenc->png_struct_ptr, row_pointers); png_write_end (pngenc->png_struct_ptr, NULL); encoded_buf = gst_buffer_create_sub (pngenc->buffer_out, 0, pngenc->written); png_destroy_info_struct (pngenc->png_struct_ptr, &pngenc->png_info_ptr); png_destroy_write_struct (&pngenc->png_struct_ptr, (png_infopp) NULL); gst_buffer_copy_metadata (encoded_buf, buf, GST_BUFFER_COPY_TIMESTAMPS); gst_buffer_unref (buf); gst_buffer_set_caps (encoded_buf, GST_PAD_CAPS (pngenc->srcpad)); if ((ret = gst_pad_push (pngenc->srcpad, encoded_buf)) != GST_FLOW_OK) goto done; if (pngenc->snapshot) { GstEvent *event; GST_DEBUG_OBJECT (pngenc, "snapshot mode, sending EOS"); /* send EOS event, since a frame has been pushed out */ event = gst_event_new_eos (); gst_pad_push_event (pngenc->srcpad, event); ret = GST_FLOW_UNEXPECTED; } done: GST_DEBUG_OBJECT (pngenc, "END, ret:%d", ret); if (pngenc->buffer_out != NULL) { gst_buffer_unref (pngenc->buffer_out); pngenc->buffer_out = NULL; } gst_object_unref (pngenc); return ret; }
/* Dump an image to a Portable Network Graphics (PNG) file. File_name is where the file goes, i_height and i_width are the height and width in pixels of the image. The data for the image is stored as a linear array of one byte for each of red, green, and blue components of an RGB pixel. Thus row[i] will begin at rgb_image + i*(i_width*3) and the blue pixel at image[i][0] would be rgb_image + i*(i_width*3) + 1. */ void write_png(const char *file_name, png_uint_32 i_height, png_uint_32 i_width, void *rgb_image, /*in*/ png_text *text_ptr, int i_text_count ) { FILE *fp; png_structp png_ptr; png_infop info_ptr; png_color_8 sig_bit; png_bytep *row_pointers; unsigned int i,j; /* open the file */ fp = fopen(file_name, "wb"); if (fp == NULL) return; /* 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, (png_voidp) NULL, user_error_fn, user_warning_fn); if (png_ptr == NULL) { fclose(fp); return; } /* 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, (png_infopp)NULL); return; } /* Set error handling. REQUIRED if you aren't supplying your own * error handling functions in the png_create_write_struct() call. */ if (setjmp(png_ptr->jmpbuf)) { /* If we get here, we had a problem writing the file */ fclose(fp); png_destroy_write_struct(&png_ptr, (png_infopp) &info_ptr); return; } /* Set up the output control using standard C streams. This is required. */ png_init_io(png_ptr, fp); /* Set the image information here. i_width and i_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 */ png_set_IHDR(png_ptr, info_ptr, i_width, i_height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* For color images: */ sig_bit.red = 8; sig_bit.green = 8; sig_bit.blue = 8; if (text_ptr) png_set_text(png_ptr, info_ptr, text_ptr, i_text_count); /* Write the file header information. REQUIRED */ png_write_info(png_ptr, info_ptr); /* Once we write out the header, the compression type on the text * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again * at the end. */ /* Shift the pixels up to a legal bit depth and fill in * as appropriate to correctly scale the image. */ png_set_shift(png_ptr, &sig_bit); /* pack pixels into bytes */ png_set_packing(png_ptr); row_pointers = png_malloc(png_ptr, i_height*sizeof(png_bytep *)); for (i=0, j=0; i<i_height; i++, j+=i_width*3) { row_pointers[i] = rgb_image + j; } png_set_rows (png_ptr, info_ptr, row_pointers); png_write_image(png_ptr, row_pointers); /* You can write optional chunks like tEXt, zTXt, and tIME at the end * as well. */ /* It is REQUIRED to call this to finish writing the rest of the file */ png_write_end(png_ptr, info_ptr); /* if you allocated any text comments, free them here */ /* free image data if allocated. */ /* clean up after the write, and free any memory allocated */ png_destroy_info_struct(png_ptr, &info_ptr); /* clean up after the write, and free any memory allocated */ png_destroy_write_struct(&png_ptr, (png_infopp)NULL); fclose(fp); return; }
static void gst_snapshot_chain (GstPad * pad, GstData * _data) { GstBuffer *buf = GST_BUFFER (_data); GstSnapshot *snapshot; guchar *data; gulong size; gint i; png_byte *row_pointers[MAX_HEIGHT]; FILE *fp; g_return_if_fail (pad != NULL); g_return_if_fail (GST_IS_PAD (pad)); g_return_if_fail (buf != NULL); snapshot = GST_SNAPSHOT (GST_OBJECT_PARENT (pad)); data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); GST_DEBUG ("snapshot: have buffer of %d\n", GST_BUFFER_SIZE (buf)); snapshot->cur_frame++; if (snapshot->cur_frame == snapshot->frame || snapshot->snapshot_asked == TRUE) { snapshot->snapshot_asked = FALSE; GST_INFO ("dumpfile : %s\n", snapshot->location); fp = fopen (snapshot->location, "wb"); if (fp == NULL) g_warning (" Can not open %s\n", snapshot->location); else { snapshot->png_struct_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL, user_error_fn, user_warning_fn); if (snapshot->png_struct_ptr == NULL) g_warning ("Failed to initialize png structure"); snapshot->png_info_ptr = png_create_info_struct (snapshot->png_struct_ptr); if (setjmp (snapshot->png_struct_ptr->jmpbuf)) png_destroy_write_struct (&snapshot->png_struct_ptr, &snapshot->png_info_ptr); png_set_filter (snapshot->png_struct_ptr, 0, PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE); png_init_io (snapshot->png_struct_ptr, fp); png_set_compression_level (snapshot->png_struct_ptr, 9); png_set_IHDR (snapshot->png_struct_ptr, snapshot->png_info_ptr, snapshot->width, snapshot->height, snapshot->to_bpp / 3, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); for (i = 0; i < snapshot->height; i++) row_pointers[i] = data + (snapshot->width * i * snapshot->to_bpp / 8); png_write_info (snapshot->png_struct_ptr, snapshot->png_info_ptr); png_write_image (snapshot->png_struct_ptr, row_pointers); png_write_end (snapshot->png_struct_ptr, NULL); png_destroy_info_struct (snapshot->png_struct_ptr, &snapshot->png_info_ptr); png_destroy_write_struct (&snapshot->png_struct_ptr, (png_infopp) NULL); fclose (fp); } } gst_pad_push (snapshot->srcpad, GST_DATA (buf)); }
void GPC_Canvas:: MakeScreenShot( const char* filename ){ png_structp png_ptr; png_infop info_ptr; unsigned char *pixels = 0; png_bytepp row_pointers = 0; int i, bytesperpixel = 3, color_type = PNG_COLOR_TYPE_RGB; FILE *fp = 0; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { std::cout << "Cannot png_create_write_struct." << std::endl; return; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); std::cout << "Cannot png_create_info_struct." << std::endl; return; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); delete [] pixels; delete [] row_pointers; // printf("Aborting\n"); if (fp) { fflush(fp); fclose(fp); } return; } // copy image data pixels = new unsigned char[GetWidth() * GetHeight() * bytesperpixel * sizeof(unsigned char)]; if (!pixels) { std::cout << "Cannot allocate pixels array" << std::endl; return; } glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, pixels); fp = fopen(filename, "wb"); if (!fp) { std::cout << "Couldn't open " << filename << " for writing." << std::endl; longjmp(png_jmpbuf(png_ptr), 1); } png_init_io(png_ptr, fp); /* png_set_filter(png_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| PNG_ALL_FILTERS); png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); */ // png image settings png_set_IHDR(png_ptr, info_ptr, GetWidth(), GetHeight(), 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); // write the file header information png_write_info(png_ptr, info_ptr); // allocate memory for an array of row-pointers row_pointers = new png_bytep [(GetHeight() * sizeof(png_bytep))]; if (!row_pointers) { std::cout << "Cannot allocate row-pointers array" << std::endl; longjmp(png_jmpbuf(png_ptr), 1); } // set the individual row-pointers to point at the correct offsets for (i = 0; i < GetHeight(); i++) { row_pointers[GetHeight()-1-i] = (png_bytep) ((unsigned char *)pixels + (i * GetWidth()) * bytesperpixel * sizeof(unsigned char)); } // write out the entire image data in one call png_write_image(png_ptr, row_pointers); // write the additional chunks to the PNG file (not really needed) png_write_end(png_ptr, info_ptr); // clean up delete [] (pixels); delete [] (row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); if (fp) { fflush(fp); fclose(fp); } }