// // initialize PNG writing // static void s_PngWriteInit(png_structp& png_ptr, png_infop& info_ptr, size_t width, size_t height, size_t depth, CImageIO::ECompress compress) { png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, s_PngWriteErrorHandler, s_PngWarningHandler); if ( !png_ptr ) { NCBI_THROW(CImageException, eWriteError, "CImageIOPng::WriteImage(): png_create_read_struct() failed"); } info_ptr = png_create_info_struct(png_ptr); if ( !info_ptr ) { NCBI_THROW(CImageException, eWriteError, "CImageIOPng::WriteImage(): png_create_info_struct() failed"); } png_byte color_type = PNG_COLOR_TYPE_RGB; if (depth == 4) { color_type = PNG_COLOR_TYPE_RGBA; } png_set_IHDR(png_ptr, info_ptr, width, height, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); // set our compression quality switch (compress) { case CImageIO::eCompress_None: png_set_filter(png_ptr, 0, PNG_FILTER_NONE); png_set_compression_level(png_ptr, Z_NO_COMPRESSION); break; case CImageIO::eCompress_Low: png_set_filter(png_ptr, 0, PNG_FILTER_NONE); png_set_compression_level(png_ptr, Z_BEST_SPEED); break; case CImageIO::eCompress_Medium: png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION); break; case CImageIO::eCompress_High: png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); break; default: LOG_POST_X(26, Error << "unknown compression type: " << (int)compress); break; } }
static size_t rgb2png(ss_t **png, const ss_t *rgb, const struct RGB_Info *ri) { RETURN_IF(!valid_rgbi(ri) ||!rgb, 0); size_t out_size = 0; png_structp s = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); png_infop pi = png_create_info_struct(s); if (png) ss_set_size(*png, 0); png_set_write_fn(s, (png_voidp)png, aux_png_write, NULL); int ctype = (ri->chn > 1 ? PNG_COLOR_MASK_COLOR : 0) | (ri->chn == 2 || ri->chn == 4 ? PNG_COLOR_MASK_ALPHA : 0); png_set_IHDR(s, pi, (png_uint_32)ri->width, (png_uint_32)ri->height, ri->bpc, ctype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_set_filter(s, PNG_FILTER_TYPE_BASE, PNG_ALL_FILTERS); png_set_compression_level(s, Z_BEST_COMPRESSION); png_write_info(s, pi); png_bytep *rows = (png_bytep *)alloca(sizeof(png_bytep) * pi->height); if (aux_png_set_rows(rows, pi, ss_get_buffer_r(rgb))) { png_write_image(s, rows); png_write_end(s, pi); out_size = ss_size(*png); } png_destroy_info_struct(s, &pi); png_destroy_write_struct(&s, &pi); return out_size; }
std::unique_ptr<PNGImageEncoderState> PNGImageEncoderState::create(const IntSize& imageSize, Vector<unsigned char>* output) { if (imageSize.width() <= 0 || imageSize.height() <= 0) return nullptr; png_struct* png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); png_info* info = png_create_info_struct(png); if (!png || !info || setjmp(png_jmpbuf(png))) { png_destroy_write_struct(png ? &png : 0, info ? &info : 0); return nullptr; } // Optimize compression for speed. // The parameters are the same as what libpng uses by default for RGB and RGBA images, except: // The zlib compression level is set to 3 instead of 6, to avoid the lazy Ziv-Lempel match searching. png_set_compression_level(png, 3); // The zlib memory level is set to 8. This actually matches the default, we are just future-proofing. png_set_compression_mem_level(png, 8); // The zlib strategy is set to Z_FILTERED, which does not match the default. // Avoid the zlib strategies Z_HUFFMAN_ONLY or Z_RLE. // Although they are the fastest for poorly-compressible images (e.g. photographs), // they are very slow for highly-compressible images (e.g. text, drawings or business graphics) png_set_compression_strategy(png, Z_FILTERED); // The delta filter is PNG_FILTER_SUB instead of PNG_ALL_FILTERS, to reduce the filter computations. png_set_filter(png, PNG_FILTER_TYPE_BASE, PNG_FILTER_SUB); png_set_write_fn(png, output, writeOutput, 0); png_set_IHDR(png, info, imageSize.width(), imageSize.height(), 8, PNG_COLOR_TYPE_RGB_ALPHA, 0, 0, 0); png_write_info(png, info); return wrapUnique(new PNGImageEncoderState(png, info)); }
static void write_png(const png_bytep rgba, png_uint_32 width, png_uint_32 height, SkWStream& out) { png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); SkASSERT(png != nullptr); png_infop info_ptr = png_create_info_struct(png); SkASSERT(info_ptr != nullptr); if (setjmp(png_jmpbuf(png))) { SkFAIL("png encode error"); } png_set_IHDR(png, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_compression_level(png, 1); png_bytepp rows = (png_bytepp) sk_malloc_throw(height * sizeof(png_byte*)); png_bytep pixels = (png_bytep) sk_malloc_throw(width * height * 3); for (png_size_t y = 0; y < height; ++y) { const png_bytep src = rgba + y * width * 4; rows[y] = pixels + y * width * 3; // convert from RGBA to RGB for (png_size_t x = 0; x < width; ++x) { rows[y][x * 3] = src[x * 4]; rows[y][x * 3 + 1] = src[x * 4 + 1]; rows[y][x * 3 + 2] = src[x * 4 + 2]; } } png_set_filter(png, 0, PNG_NO_FILTERS); png_set_rows(png, info_ptr, &rows[0]); png_set_write_fn(png, &out, write_png_callback, NULL); png_write_png(png, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); png_destroy_write_struct(&png, NULL); sk_free(rows); }
errort WritePNG( FILE * fp , unsigned char * data, unsigned int sizeX, unsigned int sizeY, int img_depth, int img_alpha) { png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,NULL,NULL); if (!png_ptr) return BadFormat; png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return BadFormat; } if (setjmp(png_ptr->jmpbuf)) { png_destroy_write_struct(&png_ptr, &info_ptr); return BadFormat; } png_init_io(png_ptr, fp); png_set_filter(png_ptr, 0, PNG_FILTER_NONE); png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); /* set other zlib parameters */ png_set_compression_mem_level(png_ptr, 8); png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY); png_set_compression_window_bits(png_ptr, 15); png_set_compression_method(png_ptr, 8); png_set_IHDR(png_ptr, info_ptr, sizeX, sizeY, img_depth, img_alpha?PNG_COLOR_TYPE_RGB_ALPHA:PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); # if __BYTE_ORDER != __BIG_ENDIAN if (img_depth==16) { png_set_swap(png_ptr); } #endif int stride = (img_depth/8)*(img_alpha?4:3); png_byte **row_pointers = new png_byte*[sizeY]; for (unsigned int i=0;i<sizeY;i++) { row_pointers[i]= (png_byte *)&data[stride*i*sizeX]; } png_write_image (png_ptr,row_pointers); png_write_end(png_ptr, info_ptr); png_write_flush(png_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); //free (data); delete [] row_pointers; return Ok; }
void write_png(FileSystem::FileSourceFS &fs, const std::string &path, const Uint8 *bytes, int width, int height, int stride, int bytes_per_pixel) { png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) { fprintf(stderr, "Couldn't create png_write_struct\n"); return; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, 0); fprintf(stderr, "Couldn't create png_info_struct\n"); return; } //http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-3.1 if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fprintf(stderr, "Couldn't set png jump buffer\n"); return; } FILE *out = fs.OpenWriteStream(path); if (!out) { png_destroy_write_struct(&png_ptr, &info_ptr); fprintf(stderr, "Couldn't open '%s/%s' for writing\n", fs.GetRoot().c_str(), path.c_str()); return; } int colour_type; switch (bytes_per_pixel) { case 1: colour_type = PNG_COLOR_TYPE_GRAY; break; case 2: colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; case 3: colour_type = PNG_COLOR_TYPE_RGB; break; case 4: colour_type = PNG_COLOR_TYPE_RGB_ALPHA; break; default: assert(0); return; } png_init_io(png_ptr, out); png_set_filter(png_ptr, 0, PNG_FILTER_NONE); png_set_IHDR(png_ptr, info_ptr, width, height, 8, colour_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_bytepp rows = new png_bytep[height]; for (int i = 0; i < height; ++i) { const Uint8 *row = bytes + ((height-i-1) * stride); rows[i] = const_cast<Uint8*>(row); } png_set_rows(png_ptr, info_ptr, rows); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0); png_destroy_write_struct(&png_ptr, &info_ptr); delete[] rows; fclose(out); }
int main(int argc, char **argv) { int i; unsigned char *scanbuf; unsigned char **rows; png_structp png_p; png_infop info_p; if ( !get_args( argc, argv ) ) { (void)fputs(usage, stderr); bu_exit ( 1, NULL ); } /* autosize input? */ if ( fileinput && autosize ) { unsigned long int w, h; if ( fb_common_file_size(&w, &h, file_name, 1) ) { file_width = (long)w; file_height = (long)h; } else { fprintf(stderr, "bw-png: unable to autosize\n"); } } png_p = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); if ( !png_p ) bu_exit( EXIT_FAILURE, "Could not create PNG write structure\n" ); info_p = png_create_info_struct( png_p ); if ( !info_p ) bu_exit( EXIT_FAILURE, "Could not create PNG info structure\n" ); /* allocate space for the image */ scanbuf = (unsigned char *)bu_calloc( SIZE, sizeof( unsigned char ), "scanbuf" ); /* create array of pointers to rows for libpng */ rows = (unsigned char **)bu_calloc( file_height, sizeof( unsigned char *), "rows" ); for ( i=0; i<file_height; i++ ) rows[i] = scanbuf + ((file_height-i-1)*ROWSIZE); /* read the bw file */ if ( fread( scanbuf, SIZE, 1, infp ) != 1 ) bu_exit( EXIT_FAILURE, "bw-png: Short read\n"); png_init_io( png_p, stdout ); png_set_filter( png_p, 0, PNG_FILTER_NONE ); png_set_compression_level( png_p, Z_BEST_COMPRESSION ); png_set_IHDR( png_p, info_p, file_width, file_height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); png_write_info( png_p, info_p ); png_write_image( png_p, rows ); png_write_end( png_p, NULL ); return 0; }
bool CPNGFile::Save(const char *szFilename) { // regular file saving - first, there has to be a buffer if (!pImageData) return false; // open the file fp = fopen(szFilename, "wb"); if (!fp) return false; // clear any previously initialized png-structs (e.g. by reading) ClearPngStructs(); // reinit them for writing fWriteMode=true; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { Clear(); return false; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { Clear(); return false; } // error handling if (setjmp(png_jmpbuf(png_ptr))) { Clear(); return false; } // io initialization png_init_io(png_ptr, fp); // compression stuff 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_set_compression_mem_level(png_ptr, 8); png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY); png_set_compression_window_bits(png_ptr, 15); png_set_compression_method(png_ptr, 8); // set header png_set_IHDR(png_ptr, info_ptr, iWdt, iHgt, iBPC, iClrType, iIntrlcType, iCmprType, iFltrType); // double-check our calculated row size int iRealRowSize=png_get_rowbytes(png_ptr, info_ptr); if (iRealRowSize != iRowSize) { // this won't go well, so better abort Clear(); return false; } // write png header png_write_info(png_ptr, info_ptr); // image data is given as bgr... png_set_bgr(png_ptr); // create row array unsigned char **ppRowBuf = new unsigned char *[iHgt]; unsigned char **ppRows=ppRowBuf; unsigned char *pRow=pImageData; for (unsigned int i=0; i<iHgt; ++i,pRow+=iRowSize) *ppRows++=pRow; // write image png_write_image(png_ptr, ppRowBuf); // free row buffer delete [] ppRowBuf; // write end struct png_write_end(png_ptr, info_ptr); // finally, close the file fclose(fp); fp = NULL; // clear png structs ClearPngStructs(); // success! return true; }
void png_write( const char *myfile, unsigned char *data, unsigned int width, unsigned int height, bool alpha, char bpp ) { FILE *fp = VSFileSystem::vs_open( myfile, "wb" ); png_structp png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING, (png_voidp) NULL, NULL, NULL ); if (!png_ptr) return; png_infop info_ptr = png_create_info_struct( png_ptr ); if (!info_ptr) { png_destroy_write_struct( &png_ptr, (png_infopp) NULL ); return; } if ( setjmp( png_ptr->jmpbuf ) ) { png_destroy_write_struct( &png_ptr, &info_ptr ); VSFileSystem::vs_close( fp ); return; } png_init_io( png_ptr, fp ); png_set_filter( png_ptr, 0, PNG_FILTER_NONE ); png_set_compression_level( png_ptr, Z_BEST_COMPRESSION ); /* set other zlib parameters */ png_set_compression_mem_level( png_ptr, 8 ); png_set_compression_strategy( png_ptr, Z_DEFAULT_STRATEGY ); png_set_compression_window_bits( png_ptr, 15 ); png_set_compression_method( png_ptr, 8 ); png_set_IHDR( png_ptr, info_ptr, width, height, bpp, alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); png_write_info( png_ptr, info_ptr ); # if __BYTE_ORDER != __BIG_ENDIAN if (bpp == 16) png_set_swap( png_ptr ); #endif int stride = (bpp/8)*(alpha ? 4 : 3); png_byte **row_pointers = new png_byte*[height]; for (unsigned int i = 0; i < height; i++) row_pointers[i] = (png_byte*) &data[stride*i*width]; png_write_image( png_ptr, row_pointers ); png_write_end( png_ptr, info_ptr ); png_write_flush( png_ptr ); png_destroy_write_struct( &png_ptr, &info_ptr ); VSFileSystem::vs_close( fp ); free( data ); delete[] row_pointers; }
void PNGImageWriter::beginOfImage(int cols, int rows) { _png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); _info_ptr = png_create_info_struct(_png_ptr); if (!_info_ptr) { png_destroy_write_struct(&_png_ptr, NULL); exit(1); } png_set_IHDR(_png_ptr, _info_ptr, cols, rows, 16, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, NULL/*PNG_COMPRESSION_TYPE_DEFAULT*/, PNG_FILTER_TYPE_DEFAULT); //png_set_filter(_png_ptr, 0, PNG_FILTER_NONE); //png_set_packing(_png_ptr); png_set_compression_level(_png_ptr, 0); // No compression png_set_filter(_png_ptr, 0 /* method */, PNG_NO_FILTERS); png_color_8 sig_bit; sig_bit.gray = 16; sig_bit.red = 0; sig_bit.green = 0; sig_bit.blue = 0; sig_bit.alpha = 0; png_set_sBIT(_png_ptr, _info_ptr, &sig_bit); //png_set_shift(_png_ptr, &sig_bit); //png_set_gamma(_png_ptr, 1., 1.); png_set_strip_16(_png_ptr); //if (lsb) //png_set_swap(_png_ptr); // flush output after every row if (_lineBuffered) png_set_flush(_png_ptr, 1); //png_set_filler(_png_ptr, 0, PNG_FILLER_BEFORE); // Represent black as 1 and white as 0 instead of the PNG default. //png_set_invert_mono(_png_ptr); png_init_io(_png_ptr, _output); /* write the file information */ png_write_info(_png_ptr, _info_ptr); }
void gdImagePng(gdImagePtr im, FILE *out) { int i; png_colorp palette; png_structp png_write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, /* we would need to point to error handlers here to do it properly */ (png_error_ptr)NULL, (png_error_ptr)NULL); png_infop info_ptr = png_create_info_struct(png_write_ptr); if (setjmp(gdPngJmpbufStruct.jmpbuf)) { png_destroy_write_struct(&png_write_ptr, &info_ptr); return; } palette = (png_colorp)png_malloc (png_write_ptr, im->colorsTotal*sizeof(png_color)); if (palette == NULL) { png_destroy_write_struct(&png_write_ptr, &info_ptr); return; } png_init_io(png_write_ptr, out); png_set_write_status_fn(png_write_ptr, NULL); png_set_IHDR(png_write_ptr,info_ptr, im->sx,im->sy,im->colorsTotal > 16 ? 8:4, PNG_COLOR_TYPE_PALETTE, im->interlace ? PNG_INTERLACE_ADAM7: PNG_INTERLACE_NONE , PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); for(i=0; i<im->colorsTotal; i++) { palette[i].red = im->red[i]; palette[i].green = im->green[i]; palette[i].blue = im->blue[i]; } png_set_PLTE(png_write_ptr, info_ptr, palette, im->colorsTotal); /* choose between speed (1) and space (9) optimization */ /* we want to be fast ... */ png_set_compression_level(png_write_ptr,1); png_set_filter(png_write_ptr,PNG_FILTER_TYPE_BASE,PNG_NO_FILTERS); /* store file info */ png_write_info(png_write_ptr, info_ptr); png_set_packing(png_write_ptr); png_write_image(png_write_ptr, im->pixels); png_write_end(png_write_ptr, info_ptr); png_free(png_write_ptr, palette); png_destroy_write_struct(&png_write_ptr, &info_ptr); }
bool PNGOutput::open (const std::string &name, const ImageSpec &userspec, OpenMode mode) { if (mode != Create) { error ("%s does not support subimages or MIP levels", format_name()); return false; } close (); // Close any already-opened file m_spec = userspec; // Stash the spec m_file = Filesystem::fopen (name, "wb"); if (! m_file) { error ("Could not open file \"%s\"", name.c_str()); return false; } std::string s = PNG_pvt::create_write_struct (m_png, m_info, m_color_type, m_spec); if (s.length ()) { close (); error ("%s", s.c_str ()); return false; } png_init_io (m_png, m_file); int compression_level = 6; /* medium speed vs size tradeoff */ // RTT MOD: CVI use incoming compression values const ImageIOParameter *compParameter = m_spec.find_attribute ("CompressionQuality",TypeDesc::INT); if (compParameter) { compression_level = *(const int *)compParameter->data(); compression_level = std::min( std::max( compression_level, 0 ), 9 ); // compression 0-9 } png_set_compression_level (m_png, compression_level); const ImageIOParameter *filterParameter = m_spec.find_attribute ("png:Filters",TypeDesc::INT); if (filterParameter) { int filters = *(const int *)filterParameter->data(); filters &= PNG_ALL_FILTERS; png_set_filter(m_png, 0, filters); } PNG_pvt::write_info (m_png, m_info, m_color_type, m_spec, m_pngtext); return true; }
void CSnapShot::WriteImageToFile(CThread * pThread) { m_threadData.bWriting = true; D3DDISPLAYMODE displayMode; g_pCore->GetGraphics()->GetDevice()->GetDisplayMode(0, &displayMode); UINT uiScreenWidth = displayMode.Width; UINT uiScreenHeight = displayMode.Height; BYTE* mem = new BYTE[SCREEN_SHOT_FORMAT_BYTES_PER_PIXEL * uiScreenWidth * uiScreenWidth]; GetFrontBufferPixels(uiScreenWidth, uiScreenHeight, mem); BYTE** ScreenData = nullptr; ScreenData = new BYTE* [uiScreenHeight]; for (unsigned short y = 0; y < uiScreenHeight; y++) { ScreenData[y] = new BYTE[uiScreenWidth * SCREEN_SHOT_FORMAT_BYTES_PER_PIXEL]; } UINT uiLinePitch = uiScreenWidth * SCREEN_SHOT_FORMAT_BYTES_PER_PIXEL; unsigned long ulLineWidth = uiScreenWidth * SCREEN_SHOT_FORMAT_BYTES_PER_PIXEL; for (unsigned int i = 0; i < uiScreenHeight; i++) { memcpy(ScreenData[i], (BYTE*) mem + i* uiLinePitch, ulLineWidth); for(unsigned int j = 3; j < ulLineWidth; j += SCREEN_SHOT_FORMAT_BYTES_PER_PIXEL) { ScreenData[i][j] = 0xFF; } } CString strPath = GetScreenShotPath(); FILE *file = fopen(strPath, "wb"); png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_info* info_ptr = png_create_info_struct(png_ptr); png_init_io(png_ptr, file); png_set_filter(png_ptr, 0, PNG_FILTER_NONE); png_set_compression_level(png_ptr, 9); png_set_IHDR(png_ptr, info_ptr, uiScreenWidth, uiScreenHeight, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_rows(png_ptr, info_ptr, ScreenData); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR | PNG_TRANSFORM_STRIP_ALPHA, NULL); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(file); for (unsigned short y = 0; y < uiScreenHeight; y++) { delete []ScreenData[y]; } delete []ScreenData; delete []mem; m_threadData.bWriting = false; }
void save_as_png(T1 & file, T2 const& image, png_options const& opts) { png_voidp error_ptr=0; png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, error_ptr,0, 0); if (!png_ptr) return; // switch on optimization only if supported #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) && defined(PNG_MMX_CODE_SUPPORTED) png_uint_32 mask, flags; flags = png_get_asm_flags(png_ptr); mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE); png_set_asm_flags(png_ptr, flags | mask); #endif png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE); png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr,static_cast<png_infopp>(0)); return; } jmp_buf* jmp_context = static_cast<jmp_buf*>(png_get_error_ptr(png_ptr)); if (jmp_context) { png_destroy_write_struct(&png_ptr, &info_ptr); return; } png_set_write_fn (png_ptr, &file, &write_data<T1>, &flush_data<T1>); png_set_compression_level(png_ptr, opts.compression); png_set_compression_strategy(png_ptr, opts.strategy); png_set_compression_buffer_size(png_ptr, 32768); png_set_IHDR(png_ptr, info_ptr,image.width(),image.height(),8, (opts.trans_mode == 0) ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA,PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT); const std::unique_ptr<png_bytep[]> row_pointers(new png_bytep[image.height()]); for (unsigned int i = 0; i < image.height(); i++) { row_pointers[i] = const_cast<png_bytep>(reinterpret_cast<const unsigned char *>(image.get_row(i))); } png_set_rows(png_ptr, info_ptr, row_pointers.get()); png_write_png(png_ptr, info_ptr, (opts.trans_mode == 0) ? PNG_TRANSFORM_STRIP_FILLER_AFTER : PNG_TRANSFORM_IDENTITY, nullptr); png_destroy_write_struct(&png_ptr, &info_ptr); }
void open_png(void) { png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); info_ptr=png_create_info_struct(png_ptr); png_init_io(png_ptr,of); png_set_filter(png_ptr,0,PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_UP |PNG_FILTER_AVG|PNG_FILTER_PAETH); png_set_compression_level(png_ptr,Z_BEST_COMPRESSION); png_set_IHDR(png_ptr,info_ptr,ox,oy,8,PNG_COLOR_TYPE_GRAY,PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT); png_set_gAMA(png_ptr,info_ptr,1.0); png_set_pHYs(png_ptr,info_ptr,ppm,ppm,PNG_RESOLUTION_METER); png_write_info(png_ptr,info_ptr); }
void writePNG (png_bytepp imageBuffer, png_uint_32 width, png_uint_32 height, int iteration) { const char *fname = "out.png"; FILE *fp = fopen(fname, "wb"); if (!fp) return; png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_infop info_ptr = png_create_info_struct(png_ptr); png_init_io(png_ptr, fp); png_set_filter(png_ptr, PNG_FILTER_TYPE_DEFAULT, PNG_FILTER_NONE); png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_rows(png_ptr, info_ptr, imageBuffer); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); }
static bool encodePixels(IntSize imageSize, const unsigned char* inputPixels, bool premultiplied, Vector<unsigned char>* output) { if (imageSize.width() <= 0 || imageSize.height() <= 0) return false; Vector<unsigned char> row; png_struct* png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); png_info* info = png_create_info_struct(png); if (!png || !info || setjmp(png_jmpbuf(png))) { png_destroy_write_struct(png ? &png : 0, info ? &info : 0); return false; } // Optimize compression for speed. // The parameters are the same as what libpng uses by default for RGB and RGBA images, except: // - the zlib compression level is 3 instead of 6, to avoid the lazy Ziv-Lempel match searching; // - the delta filter is 1 ("sub") instead of 5 ("all"), to reduce the filter computations. // The zlib memory level (8) and strategy (Z_FILTERED) will be set inside libpng. // // Avoid the zlib strategies Z_HUFFMAN_ONLY or Z_RLE. // Although they are the fastest for poorly-compressible images (e.g. photographs), // they are very slow for highly-compressible images (e.g. text, drawings or business graphics). png_set_compression_level(png, 3); png_set_filter(png, PNG_FILTER_TYPE_BASE, PNG_FILTER_SUB); png_set_write_fn(png, output, writeOutput, 0); png_set_IHDR(png, info, imageSize.width(), imageSize.height(), 8, PNG_COLOR_TYPE_RGB_ALPHA, 0, 0, 0); png_write_info(png, info); unsigned char* pixels = const_cast<unsigned char*>(inputPixels); row.resize(imageSize.width() * sizeof(SkPMColor)); const size_t pixelRowStride = imageSize.width() * 4; for (int y = 0; y < imageSize.height(); ++y) { if (premultiplied) { preMultipliedBGRAtoRGBA(pixels, imageSize.width(), row.data()); png_write_row(png, row.data()); } else png_write_row(png, pixels); pixels += pixelRowStride; } png_write_end(png, info); png_destroy_write_struct(&png, &info); return true; }
// Callback for threaded save // Static function DWORD CScreenShot::ThreadProc ( LPVOID lpdwThreadParam ) { unsigned long ulScreenHeight = ms_ScreenSize.bottom - ms_ScreenSize.top; unsigned long ulScreenWidth = ms_ScreenSize.right - ms_ScreenSize.left; // Create the screen data buffer BYTE** ppScreenData = NULL; ppScreenData = new BYTE* [ ulScreenHeight ]; for ( unsigned short y = 0; y < ulScreenHeight; y++ ) { ppScreenData[y] = new BYTE [ ulScreenWidth * 4 ]; } // Copy the surface data into a row-based buffer for libpng #define BYTESPERPIXEL 4 unsigned long ulLineWidth = ulScreenWidth * 4; for ( unsigned int i = 0; i < ulScreenHeight; i++ ) { memcpy ( ppScreenData[i], (BYTE*) ms_pBits + i* ms_ulPitch, ulLineWidth ); for ( unsigned int j = 3; j < ulLineWidth; j += BYTESPERPIXEL ) { ppScreenData[i][j] = 0xFF; } } FILE *file = fopen (ms_strFileName, "wb"); png_struct* png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); png_info* info_ptr = png_create_info_struct ( png_ptr ); png_init_io ( png_ptr, file ); png_set_filter ( png_ptr, 0, PNG_FILTER_NONE ); png_set_compression_level ( png_ptr, 1 ); png_set_IHDR ( png_ptr, info_ptr, ulScreenWidth, ulScreenHeight, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); png_set_rows ( png_ptr, info_ptr, ppScreenData ); png_write_png ( png_ptr, info_ptr, PNG_TRANSFORM_BGR | PNG_TRANSFORM_STRIP_ALPHA, NULL ); png_write_end ( png_ptr, info_ptr ); png_destroy_write_struct ( &png_ptr, &info_ptr ); fclose(file); // Clean up the screen data buffer if ( ppScreenData ) { for ( unsigned short y = 0; y < ulScreenHeight; y++ ) { delete [] ppScreenData[y]; } delete [] ppScreenData; } ms_bIsSaving = false; return 0; }
void save_as_png(T1 & file , T2 const& image, int compression = Z_DEFAULT_COMPRESSION, int strategy = Z_DEFAULT_STRATEGY) { png_voidp error_ptr=0; png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, error_ptr,0, 0); if (!png_ptr) return; // switch on optimization only if supported #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) && defined(PNG_MMX_CODE_SUPPORTED) png_uint_32 mask, flags; flags = png_get_asm_flags(png_ptr); mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE); png_set_asm_flags(png_ptr, flags | mask); #endif png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE); png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr,(png_infopp)0); return; } jmp_buf* jmp_context = (jmp_buf*) png_get_error_ptr(png_ptr); if (jmp_context) { png_destroy_write_struct(&png_ptr, &info_ptr); return; } png_set_write_fn (png_ptr, &file, &write_data<T1>, &flush_data<T1>); png_set_compression_level(png_ptr, compression); png_set_compression_strategy(png_ptr, strategy); png_set_compression_buffer_size(png_ptr, 32768); png_set_IHDR(png_ptr, info_ptr,image.width(),image.height(),8, PNG_COLOR_TYPE_RGB_ALPHA,PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); for (unsigned i=0;i<image.height();i++) { png_write_row(png_ptr,(png_bytep)image.getRow(i)); } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); }
int png_write_data(const char *filename, uint8 *data, uint32 width, uint32 height) { FILE *fp; uint32_t i; fp = fopen(filename, "wb"); if (!fp) return -1; png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); if (!png_ptr) return false; png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr,(png_infopp)NULL); return false; } png_init_io(png_ptr, fp); png_set_filter(png_ptr, 0, PNG_FILTER_VALUE_NONE); png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_bytepp row_pointers = (png_bytepp)malloc(sizeof(png_bytep)*height); for(i = 0; i < height; i++) row_pointers[i] = &data[3*i*width]; png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); png_destroy_write_struct(&png_ptr, &info_ptr); free(row_pointers); fclose(fp); return 0; }
/* * Encodes an image to a PNG file stream. */ int opng_encode_image(struct opng_codec_context *context, int filtered, FILE *stream, const char *fname, int level) { const char * volatile err_msg; /* volatile is required by cexcept */ context->libpng_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, opng_write_error, opng_write_warning); context->info_ptr = png_create_info_struct(context->libpng_ptr); if (!context->libpng_ptr || !context->info_ptr) { opng_error(0, "Out of memory"); png_destroy_write_struct(&context->libpng_ptr, &context->info_ptr); exit(1); } struct opng_encoding_stats * stats = context->stats; opng_init_stats(stats); context->stream = stream; context->fname = fname; Try { png_set_filter(context->libpng_ptr, PNG_FILTER_TYPE_BASE, filtered ? PNG_ALL_FILTERS : PNG_FILTER_NONE); if (level != 6) { png_set_compression_level(context->libpng_ptr, level); } png_set_compression_mem_level(context->libpng_ptr, 8); png_set_compression_window_bits(context->libpng_ptr, 15); png_set_compression_strategy(context->libpng_ptr, 0); png_set_keep_unknown_chunks(context->libpng_ptr, PNG_HANDLE_CHUNK_ALWAYS, 0, 0); opng_store_image(context->image, context->libpng_ptr, context->info_ptr); /* Write the PNG stream. */ png_set_write_fn(context->libpng_ptr, context, opng_write_data, 0); png_write_png(context->libpng_ptr, context->info_ptr, 0, 0); } Catch (err_msg) { stats->idat_size = OPTK_INT64_MAX; opng_error(fname, err_msg); return -1; } png_data_freer(context->libpng_ptr, context->info_ptr, PNG_USER_WILL_FREE_DATA, PNG_FREE_ALL); png_destroy_write_struct(&context->libpng_ptr, &context->info_ptr); return 0; }
pngquant_error rwpng_write_image8(FILE *outfile, png8_image *mainprog_ptr) { png_structp png_ptr; png_infop info_ptr; pngquant_error retval = rwpng_write_image_init((png_image*)mainprog_ptr, &png_ptr, &info_ptr, outfile); if (retval) return retval; // Palette images generally don't gain anything from filtering png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_VALUE_NONE); rwpng_set_gamma(info_ptr, png_ptr, mainprog_ptr->gamma); /* set the image parameters appropriately */ int sample_depth; if (mainprog_ptr->num_palette <= 2) sample_depth = 1; else if (mainprog_ptr->num_palette <= 4) sample_depth = 2; else if (mainprog_ptr->num_palette <= 16) sample_depth = 4; else sample_depth = 8; png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height, sample_depth, PNG_COLOR_TYPE_PALETTE, 0, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_BASE); png_set_PLTE(png_ptr, info_ptr, &mainprog_ptr->palette[0], mainprog_ptr->num_palette); if (mainprog_ptr->num_trans > 0) png_set_tRNS(png_ptr, info_ptr, mainprog_ptr->trans, mainprog_ptr->num_trans, NULL); png_bytepp row_pointers = rwpng_create_row_pointers(info_ptr, png_ptr, mainprog_ptr->indexed_data, mainprog_ptr->height, mainprog_ptr->width); rwpng_write_end(&info_ptr, &png_ptr, row_pointers); free(row_pointers); return SUCCESS; }
pngquant_error rwpng_write_image_init(png_image *mainprog_ptr, png_structpp png_ptr_p, png_infopp info_ptr_p, FILE *outfile) { /* could also replace libpng warning-handler (final NULL), but no need: */ *png_ptr_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr, rwpng_error_handler, NULL); if (!(*png_ptr_p)) { return LIBPNG_INIT_ERROR; /* out of memory */ } *info_ptr_p = png_create_info_struct(*png_ptr_p); if (!(*info_ptr_p)) { png_destroy_write_struct(png_ptr_p, NULL); return LIBPNG_INIT_ERROR; /* out of memory */ } /* setjmp() must be called in every function that calls a PNG-writing * libpng function, unless an alternate error handler was installed-- * but compatible error handlers must either use longjmp() themselves * (as in this program) or exit immediately, so here we go: */ if (setjmp(mainprog_ptr->jmpbuf)) { png_destroy_write_struct(png_ptr_p, info_ptr_p); return LIBPNG_INIT_ERROR; /* libpng error (via longjmp()) */ } png_init_io(*png_ptr_p, outfile); png_set_compression_level(*png_ptr_p, Z_BEST_COMPRESSION); // Palette images generally don't gain anything from filtering png_set_filter(*png_ptr_p, PNG_FILTER_TYPE_BASE, PNG_FILTER_VALUE_NONE); if (mainprog_ptr->png8.gamma > 0.0) { png_set_gAMA(*png_ptr_p, *info_ptr_p, mainprog_ptr->png8.gamma); } return SUCCESS; }
// Note: Calls req.Respond(). Other data can be added afterward. static bool StreamBufferToDataURI(DebuggerRequest &req, const GPUDebugBuffer &buf, bool includeAlpha, int stackWidth) { #ifdef USING_QT_UI req.Fail("Not supported on Qt yet, pull requests accepted"); return false; #else u8 *flipbuffer = nullptr; u32 w = (u32)-1; u32 h = (u32)-1; const u8 *buffer = ConvertBufferToScreenshot(buf, includeAlpha, flipbuffer, w, h); if (!buffer) { req.Fail("Internal error converting buffer for PNG encode"); return false; } if (stackWidth > 0) { u32 totalPixels = w * h; w = stackWidth; while ((totalPixels % w) != 0) --w; h = totalPixels / w; } png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (!png_ptr) { req.Fail("Internal error setting up PNG encoder (png_ptr)"); return false; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, nullptr); req.Fail("Internal error setting up PNG encoder (info_ptr)"); return false; } // Speed. Wireless N should give 35 KB/ms. For most devices, zlib/filters will cost more. png_set_compression_strategy(png_ptr, Z_RLE); png_set_compression_level(png_ptr, 1); png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE); auto &json = req.Respond(); json.writeInt("width", w); json.writeInt("height", h); // Start a value... json.writeRaw("uri", ""); req.Flush(); // Now we'll write it directly to the stream. req.ws->AddFragment(false, "\"data:image/png;base64,"); struct Context { DebuggerRequest *req; uint8_t buf[3]; size_t bufSize; }; Context ctx = { &req, {}, 0 }; auto write = [](png_structp png_ptr, png_bytep data, png_size_t length) { auto ctx = (Context *)png_get_io_ptr(png_ptr); auto &req = *ctx->req; // If we buffered some bytes, fill to 3 bytes for a clean base64 encode. // This way we don't have padding. while (length > 0 && ctx->bufSize > 0 && ctx->bufSize != 3) { ctx->buf[ctx->bufSize++] = data[0]; data++; length--; } if (ctx->bufSize == 3) { req.ws->AddFragment(false, Base64Encode(ctx->buf, ctx->bufSize)); ctx->bufSize = 0; } assert(ctx->bufSize == 0 || length == 0); // Save bytes that would result in padding for next time. size_t toBuffer = length % 3; for (size_t i = 0; i < toBuffer; ++i) { ctx->buf[i] = data[length - toBuffer + i]; ctx->bufSize++; } if (length > toBuffer) { req.ws->AddFragment(false, Base64Encode(data, length - toBuffer)); } }; auto flush = [](png_structp png_ptr) { // Nothing, just here to prevent stdio flush. }; png_bytep *row_pointers = new png_bytep[h]; u32 stride = includeAlpha ? w * 4 : w * 3; for (u32 i = 0; i < h; ++i) { row_pointers[i] = (u8 *)buffer + stride * i; } png_set_write_fn(png_ptr, &ctx, write, flush); int colorType = includeAlpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB; png_set_IHDR(png_ptr, info_ptr, w, h, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr); png_destroy_write_struct(&png_ptr, &info_ptr); delete [] row_pointers; delete [] flipbuffer; if (ctx.bufSize > 0) { req.ws->AddFragment(false, Base64Encode(ctx.buf, ctx.bufSize)); ctx.bufSize = 0; } // End the string. req.ws->AddFragment(false, "\""); return true; #endif }
void Screendump(const char* destFile, const int width, const int height) { std::string dir = FileSystem::GetUserDir("screenshots"); FileSystem::rawFileSystem.MakeDirectory(dir); std::string fname = FileSystem::JoinPathBelow(dir, destFile); // pad rows to 4 bytes, which is the default row alignment for OpenGL const int stride = (3*width + 3) & ~3; std::vector<png_byte> pixel_data(stride * height); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glPixelStorei(GL_PACK_ALIGNMENT, 4); // never trust defaults glReadBuffer(GL_FRONT); glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, &pixel_data[0]); glFinish(); png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) { fprintf(stderr, "Couldn't create png_write_struct\n"); return; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, 0); fprintf(stderr, "Couldn't create png_info_struct\n"); return; } //http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-3.1 if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fprintf(stderr, "Couldn't set png jump buffer\n"); return; } FILE *out = fopen(fname.c_str(), "wb"); if (!out) { png_destroy_write_struct(&png_ptr, &info_ptr); fprintf(stderr, "Couldn't open %s for writing\n", fname.c_str()); return; } png_init_io(png_ptr, out); png_set_filter(png_ptr, 0, PNG_FILTER_NONE); png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_bytepp rows = new png_bytep[height]; for (int i = 0; i < height; ++i) { rows[i] = reinterpret_cast<png_bytep>(&pixel_data[(height-i-1) * stride]); } png_set_rows(png_ptr, info_ptr, rows); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0); png_destroy_write_struct(&png_ptr, &info_ptr); delete[] rows; fclose(out); printf("Screenshot %s saved\n", fname.c_str()); }
void save_as_png(T & file, std::vector<mapnik::rgb> const& palette, mapnik::image_gray8 const& image, unsigned width, unsigned height, unsigned color_depth, std::vector<unsigned> const&alpha, png_options const& opts) { png_voidp error_ptr=0; png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, error_ptr,0, 0); if (!png_ptr) { return; } // switch on optimization only if supported #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) && defined(PNG_MMX_CODE_SUPPORTED) png_uint_32 mask, flags; flags = png_get_asm_flags(png_ptr); mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE); png_set_asm_flags(png_ptr, flags | mask); #endif png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE); png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr,static_cast<png_infopp>(0)); return; } jmp_buf* jmp_context = static_cast<jmp_buf*>(png_get_error_ptr(png_ptr)); if (jmp_context) { png_destroy_write_struct(&png_ptr, &info_ptr); return; } png_set_write_fn (png_ptr, &file, &write_data<T>, &flush_data<T>); png_set_compression_level(png_ptr, opts.compression); png_set_compression_strategy(png_ptr, opts.strategy); png_set_compression_buffer_size(png_ptr, 32768); png_set_IHDR(png_ptr, info_ptr,width,height,color_depth, PNG_COLOR_TYPE_PALETTE,PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT); png_color* pal = const_cast<png_color*>(reinterpret_cast<const png_color*>(&palette[0])); png_set_PLTE(png_ptr, info_ptr, pal, static_cast<unsigned>(palette.size())); // make transparent lowest indexes, so tRNS is small if (alpha.size()>0) { std::vector<png_byte> trans(alpha.size()); unsigned alphaSize=0;//truncate to nonopaque values for(unsigned i=0; i < alpha.size(); i++) { trans[i]=alpha[i]; if (alpha[i]<255) { alphaSize = i+1; } } if (alphaSize>0) { png_set_tRNS(png_ptr, info_ptr, static_cast<png_bytep>(&trans[0]), alphaSize, 0); } } png_write_info(png_ptr, info_ptr); for (unsigned i=0;i<height;i++) { png_write_row(png_ptr,const_cast<png_bytep>(image.get_row(i))); } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); }
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; }
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, PNG_RESOLUTION_METER); } // 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_const_bytep)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 (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 begin(char* base_file_name, unsigned char *png_buf, long long png_length) { MY_PNG_READ_OFFSET = 0; PNG_LENGTH = png_length; ENTIRE_PNG_BUF = png_buf; if (png_sig_cmp(ENTIRE_PNG_BUF, 0, 8) != 0) { error(-1, "png_sig_cmp", E_INVALID); return -1; } DEBUG_PRINT(("Initial png size is %lld bytes\n", PNG_LENGTH)); my_png_meta *pm = calloc(1, sizeof(my_png_meta)); my_init_libpng(pm); //If libpng errors, we end up here if (setjmp(png_jmpbuf(pm->read_ptr))) { DEBUG_PRINT(("libpng called setjmp!\n")); my_deinit_libpng(pm); free(ENTIRE_PNG_BUF); error(-1, "libpng", "libpng encountered an error\n"); return -1; } //Normally a file, but instead make it our buffer void *read_io_ptr = png_get_io_ptr(pm->read_ptr); png_set_read_fn(pm->read_ptr, read_io_ptr, my_png_read_fn); //Transform all PNG image types to RGB int transforms = PNG_TRANSFORM_GRAY_TO_RGB | PNG_TRANSFORM_STRIP_ALPHA | PNG_TRANSFORM_EXPAND; png_read_png(pm->read_ptr, pm->info_ptr, transforms, NULL); //Now that it was read and transformed, its size will differ PNG_LENGTH = 0; //Lets collect our metadata struct ihdr_infos_s ihdr_infos; ihdr_infos.bit_depth = png_get_bit_depth(pm->read_ptr, pm->info_ptr); ihdr_infos.color_type = png_get_color_type(pm->read_ptr, pm->info_ptr); ihdr_infos.filter_method = png_get_filter_type(pm->read_ptr, pm->info_ptr); ihdr_infos.compression_type = png_get_compression_type(pm->read_ptr, pm->info_ptr); ihdr_infos.interlace_type = png_get_interlace_type(pm->read_ptr, pm->info_ptr); ihdr_infos.height = png_get_image_height(pm->read_ptr, pm->info_ptr); ihdr_infos.width = png_get_image_width(pm->read_ptr, pm->info_ptr); if (ihdr_infos.color_type != 2) { DEBUG_PRINT((E_INVALID)); free(ENTIRE_PNG_BUF); my_deinit_libpng(pm); DEBUG_PRINT(("Looks like libpng could not correctly convert to RGB\n")); return -1; } //Just in case we want to enable alpha, etc switch(ihdr_infos.color_type) { case 0: //greyscale case 3: //indexed ihdr_infos.bytes_per_pixel = 1; break; case 4: ihdr_infos.bytes_per_pixel = 2; break; //greyscale w/ alpha case 2: ihdr_infos.bytes_per_pixel = 3; break; //Truecolour (RGB) case 6: ihdr_infos.bytes_per_pixel = 4; break; //Truecolour w/ alpha default: error_fatal(1, "ihdr_infos", "Unknown image type"); //should never happen } ihdr_infos.scanline_len = (ihdr_infos.bytes_per_pixel * ihdr_infos.width) + 1; DEBUG_PRINT(("HEIGHT: %u\n", ihdr_infos.height)); DEBUG_PRINT(("WIDTH: %u\n", ihdr_infos.width)); DEBUG_PRINT(("BIT_DEPTH: %u\n", ihdr_infos.bit_depth)); // Don't compress, since we are merely copying it to memory, // we will be decompressing it again anyway png_set_compression_level(pm->write_ptr, Z_NO_COMPRESSION); void *write_io_ptr = png_get_io_ptr(pm->write_ptr); png_set_write_fn(pm->write_ptr, write_io_ptr, my_png_write_fn, my_png_dummy_flush); //Make sure we use all filters png_set_filter(pm->write_ptr, 0, PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | PNG_FILTER_UP | PNG_FILTER_VALUE_UP | PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG | PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH); //Set our comment struct png_text_struct comment_struct; comment_struct.compression = -1; comment_struct.key = " Glitched by pnglitch.xyz "; comment_struct.text = NULL; comment_struct.text_length = 0; png_set_text(pm->write_ptr, pm->info_ptr, &comment_struct, 1); //Buffer is Written using callback my_png_write_fn to buffer //ENTIRE_PNG_BUF. PNG_LENGTH will be updated automatically by it png_write_png(pm->write_ptr, pm->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); my_deinit_libpng(pm); DEBUG_PRINT(("libpng output buf is %lld bytes\n", PNG_LENGTH)); //Now that libpng has converted the image //and we have it in a buffer, we process it by hand with zlib struct z_stream_s inflate_stream; my_init_zlib(&inflate_stream); inflateInit(&inflate_stream); //Pointer to keep track of where we are unsigned char *pngp = ENTIRE_PNG_BUF; //Skip PNG Signature pngp += 8; //Get Header unsigned char ihdr_bytes_buf[4+4+13+4]; // size + label + content + crc buf_read(ihdr_bytes_buf, &pngp, 4+4+13+4); //When we run into non-idat chunks, we will want to preserve them. //The spec says there's no chunk that needs to go after IDAT, //so we can simply concatenate all of these chunks into a buffer //then write them all at once after the IHDR //ancillary chunks, eg comments unsigned char *ancil_chunks_buf = calloc(1,1); long long ancil_chunks_len = 0; unsigned char *unzip_idats_buf = calloc(1, 1); long unzip_buf_len = 1; long unzip_buf_offset = 0; long long zipped_idats_len = 0; //Length of all idats as we read them unsigned long accum_png_len = 8 + (4+4+13+4); int chunk_count = 0; printf("Uncompressing image data...\n"); while (1) { unsigned char chunk_label[4]; unsigned char chunk_len_buf[4]; buf_read(chunk_len_buf, &pngp, 4); //first 4 bytes are the length of data section long chunk_len = four_bytes_to_int(chunk_len_buf); accum_png_len += chunk_len + 4 + 4 + 4; // plus len, crc, label DEBUG_PRINT(("at %lu --> %lld\n", accum_png_len, PNG_LENGTH)); //leave at end of buffer if (accum_png_len >= PNG_LENGTH) break; //read the chunk label (name of this header) buf_read(chunk_label, &pngp, 4); DEBUG_PRINT(("Reading chunk %d with label '%c%c%c%c', size %ld\n", chunk_count, chunk_label[0], chunk_label[1], chunk_label[2], chunk_label[3], chunk_len)); chunk_count += 1; if (memcmp(chunk_label, "IDAT", 4) == 0) { zipped_idats_len += chunk_len; //read the chunk's data section unsigned char *raw_chunk_buf = calloc(chunk_len, 1); buf_read(raw_chunk_buf, &pngp, chunk_len); //Tell inflate to uncompress it inflate_stream.next_in = raw_chunk_buf; inflate_stream.avail_in = chunk_len; //Now uncompress it (resizes buffer automatically) unsigned char *check_uncompress = uncompress_buffer(&inflate_stream, unzip_idats_buf, &unzip_buf_len, &unzip_buf_offset); //Stop if error if (check_uncompress == NULL) { DEBUG_PRINT((E_GLITCH)); free(ancil_chunks_buf); free(raw_chunk_buf); free(unzip_idats_buf); free(ENTIRE_PNG_BUF); return -1; } //Moving on unzip_idats_buf = check_uncompress; free(raw_chunk_buf); pngp += 4; // skip CRC } else { //This is not an idat ancil_chunks_buf = realloc(ancil_chunks_buf, ancil_chunks_len + 4 + 4 + chunk_len + 4); //make room for new data //append length and label bytes append_bytes(ancil_chunks_buf, chunk_len_buf, &ancil_chunks_len, 4); append_bytes(ancil_chunks_buf, chunk_label, &ancil_chunks_len, 4); //append chunk data unsigned char *raw_chunk_buf = calloc(chunk_len, 1); buf_read(raw_chunk_buf, &pngp, chunk_len); append_bytes(ancil_chunks_buf, raw_chunk_buf, &ancil_chunks_len, chunk_len ); //append chunk crc unsigned char chunk_crc_buf[4]; buf_read(chunk_crc_buf, &pngp, 4); append_bytes(ancil_chunks_buf, chunk_crc_buf, &ancil_chunks_len, 4); free(raw_chunk_buf); DEBUG_PRINT(("ancillary chunks length: %lld\n", ancil_chunks_len)); } } //buf contains all idats uncompressed, concatenated unsigned long unzipped_idats_len = inflate_stream.total_out; unzip_idats_buf = realloc(unzip_idats_buf, unzipped_idats_len); //we already have ancillary chunks and idats, don't need the original free(ENTIRE_PNG_BUF); inflateEnd(&inflate_stream); printf("Uncompressed %lld bytes to %ld bytes\n", zipped_idats_len, unzipped_idats_len); printf("Glitching image data...\n"); for (int g=0;g<NUM_OUTPUT_FILES;g++) { //do glitches switch(g) { case 5: glitch_random(unzip_idats_buf, unzipped_idats_len, ihdr_infos.scanline_len, 0.0005); break; case 6: glitch_random_filter(unzip_idats_buf, unzipped_idats_len, ihdr_infos.scanline_len); break; default: glitch_filter(unzip_idats_buf, unzipped_idats_len, ihdr_infos.scanline_len, g); } //recompress so we can write them to file long long glitched_idats_len = 0; unsigned char *glitched_idats = zip_idats(unzip_idats_buf, unzipped_idats_len, &glitched_idats_len); if (glitched_idats == NULL) { DEBUG_PRINT((E_GLITCH)); free (unzip_idats_buf); free (ancil_chunks_buf); return -1; } char path[MAX_PATH_LENGTH]; bzero(path, MAX_PATH_LENGTH); snprintf(path, MAX_PATH_LENGTH, "%s%s%s-%d.png", OUTPUT_DIRECTORY, DIR_SEP, base_file_name, g); DEBUG_PRINT(("Output file name is %s\n", path)); FILE *outfp = fopen(path, "wb"); write_glitched_image(glitched_idats, glitched_idats_len, ihdr_bytes_buf, ancil_chunks_buf, ancil_chunks_len, outfp); printf("%s\n", path); fflush(stdout); fclose(outfp); free(glitched_idats); } free(ancil_chunks_buf); free(unzip_idats_buf); return 0; }
void write_header( const View& view ) { using png_rw_info_t = detail::png_write_support < typename channel_type<typename get_pixel_type<View>::type>::type, typename color_space_type<View>::type >; // 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 png_set_IHDR( get_struct() , get_info() , static_cast< png_image_width::type >( view.width() ) , static_cast< png_image_height::type >( view.height() ) , static_cast< png_bitdepth::type >( png_rw_info_t::_bit_depth ) , static_cast< png_color_type::type >( png_rw_info_t::_color_type ) , _info._interlace_method , _info._compression_type , _info._filter_method ); #ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED if( _info._valid_cie_colors ) { png_set_cHRM( get_struct() , get_info() , _info._white_x , _info._white_y , _info._red_x , _info._red_y , _info._green_x , _info._green_y , _info._blue_x , _info._blue_y ); } if( _info._valid_file_gamma ) { png_set_gAMA( get_struct() , get_info() , _info._file_gamma ); } #else if( _info._valid_cie_colors ) { png_set_cHRM_fixed( get_struct() , get_info() , _info._white_x , _info._white_y , _info._red_x , _info._red_y , _info._green_x , _info._green_y , _info._blue_x , _info._blue_y ); } if( _info._valid_file_gamma ) { png_set_gAMA_fixed( get_struct() , get_info() , _info._file_gamma ); } #endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED if( _info._valid_icc_profile ) { #if PNG_LIBPNG_VER_MINOR >= 5 png_set_iCCP( get_struct() , get_info() , const_cast< png_charp >( _info._icc_name.c_str() ) , _info._iccp_compression_type , reinterpret_cast< png_const_bytep >( & (_info._profile.front ()) ) , _info._profile_length ); #else png_set_iCCP( get_struct() , get_info() , const_cast< png_charp >( _info._icc_name.c_str() ) , _info._iccp_compression_type , const_cast< png_charp >( & (_info._profile.front()) ) , _info._profile_length ); #endif } if( _info._valid_intent ) { png_set_sRGB( get_struct() , get_info() , _info._intent ); } if( _info._valid_palette ) { png_set_PLTE( get_struct() , get_info() , const_cast< png_colorp >( &_info._palette.front() ) , _info._num_palette ); } if( _info._valid_background ) { png_set_bKGD( get_struct() , get_info() , const_cast< png_color_16p >( &_info._background ) ); } if( _info._valid_histogram ) { png_set_hIST( get_struct() , get_info() , const_cast< png_uint_16p >( &_info._histogram.front() ) ); } if( _info._valid_offset ) { png_set_oFFs( get_struct() , get_info() , _info._offset_x , _info._offset_y , _info._off_unit_type ); } if( _info._valid_pixel_calibration ) { std::vector< const char* > params( _info._num_params ); for( std::size_t i = 0; i < params.size(); ++i ) { params[i] = _info._params[ i ].c_str(); } png_set_pCAL( get_struct() , get_info() , const_cast< png_charp >( _info._purpose.c_str() ) , _info._X0 , _info._X1 , _info._cal_type , _info._num_params , const_cast< png_charp >( _info._units.c_str() ) , const_cast< png_charpp >( ¶ms.front() ) ); } if( _info._valid_resolution ) { png_set_pHYs( get_struct() , get_info() , _info._res_x , _info._res_y , _info._phy_unit_type ); } if( _info._valid_significant_bits ) { png_set_sBIT( get_struct() , get_info() , const_cast< png_color_8p >( &_info._sig_bits ) ); } #ifndef BOOST_GIL_IO_PNG_1_4_OR_LOWER #ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED if( _info._valid_scale_factors ) { png_set_sCAL( get_struct() , get_info() , this->_info._scale_unit , this->_info._scale_width , this->_info._scale_height ); } #else #ifdef BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED if( _info._valid_scale_factors ) { png_set_sCAL_fixed( get_struct() , get_info() , this->_info._scale_unit , this->_info._scale_width , this->_info._scale_height ); } #else if( _info._valid_scale_factors ) { png_set_sCAL_s( get_struct() , get_info() , this->_info._scale_unit , const_cast< png_charp >( this->_info._scale_width.c_str() ) , const_cast< png_charp >( this->_info._scale_height.c_str() ) ); } #endif // BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED #endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED #endif // BOOST_GIL_IO_PNG_1_4_OR_LOWER if( _info._valid_text ) { std::vector< png_text > texts( _info._num_text ); for( std::size_t i = 0; i < texts.size(); ++i ) { png_text pt; pt.compression = _info._text[i]._compression; pt.key = const_cast< png_charp >( this->_info._text[i]._key.c_str() ); pt.text = const_cast< png_charp >( this->_info._text[i]._text.c_str() ); pt.text_length = _info._text[i]._text.length(); texts[i] = pt; } png_set_text( get_struct() , get_info() , &texts.front() , _info._num_text ); } if( _info._valid_modification_time ) { png_set_tIME( get_struct() , get_info() , const_cast< png_timep >( &_info._mod_time ) ); } if( _info._valid_transparency_factors ) { int sample_max = ( 1u << _info._bit_depth ); /* libpng doesn't reject a tRNS chunk with out-of-range samples */ if( !( ( _info._color_type == PNG_COLOR_TYPE_GRAY && (int) _info._trans_values[0].gray > sample_max ) || ( _info._color_type == PNG_COLOR_TYPE_RGB &&( (int) _info._trans_values[0].red > sample_max || (int) _info._trans_values[0].green > sample_max || (int) _info._trans_values[0].blue > sample_max ) ) ) ) { //@todo Fix that once reading transparency values works /* png_set_tRNS( get_struct() , get_info() , trans , num_trans , trans_values ); */ } } // Compression Levels - valid values are [0,9] png_set_compression_level( get_struct() , _info._compression_level ); png_set_compression_mem_level( get_struct() , _info._compression_mem_level ); png_set_compression_strategy( get_struct() , _info._compression_strategy ); png_set_compression_window_bits( get_struct() , _info._compression_window_bits ); png_set_compression_method( get_struct() , _info._compression_method ); png_set_compression_buffer_size( get_struct() , _info._compression_buffer_size ); #ifdef BOOST_GIL_IO_PNG_DITHERING_SUPPORTED // Dithering if( _info._set_dithering ) { png_set_dither( get_struct() , &_info._dithering_palette.front() , _info._dithering_num_palette , _info._dithering_maximum_colors , &_info._dithering_histogram.front() , _info._full_dither ); } #endif // BOOST_GIL_IO_PNG_DITHERING_SUPPORTED // Filter if( _info._set_filter ) { png_set_filter( get_struct() , 0 , _info._filter ); } // Invert Mono if( _info._invert_mono ) { png_set_invert_mono( get_struct() ); } // True Bits if( _info._set_true_bits ) { png_set_sBIT( get_struct() , get_info() , &_info._true_bits.front() ); } // sRGB Intent if( _info._set_srgb_intent ) { png_set_sRGB( get_struct() , get_info() , _info._srgb_intent ); } // Strip Alpha if( _info._strip_alpha ) { png_set_strip_alpha( get_struct() ); } // Swap Alpha if( _info._swap_alpha ) { png_set_swap_alpha( get_struct() ); } png_write_info( get_struct() , get_info() ); }