bool DeferredPNGWriter::begin( GFXFormat format, S32 width, S32 height, Stream &stream, U32 compressionLevel ) { // ONLY RGB bitmap writing supported at this time! AssertFatal( format == GFXFormatR8G8B8 || format == GFXFormatR8G8B8A8 || format == GFXFormatR8G8B8X8 || format == GFXFormatA8 || format == GFXFormatR5G6B5, "_writePNG: ONLY RGB bitmap writing supported at this time."); if ( format != GFXFormatR8G8B8 && format != GFXFormatR8G8B8A8 && format != GFXFormatR8G8B8X8 && format != GFXFormatA8 && format != GFXFormatR5G6B5 ) return false; mData->png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, pngFatalErrorFn, pngWarningFn, NULL, pngRealMallocFn, pngRealFreeFn); if (mData->png_ptr == NULL) return (false); mData->info_ptr = png_create_info_struct(mData->png_ptr); if (mData->info_ptr == NULL) { png_destroy_write_struct(&mData->png_ptr, (png_infopp)NULL); return false; } png_set_write_fn(mData->png_ptr, &stream, pngWriteDataFn, pngFlushDataFn); // Set the compression level and image filters png_set_compression_window_bits(mData->png_ptr, 15); png_set_compression_level(mData->png_ptr, compressionLevel); png_set_filter(mData->png_ptr, 0, PNG_ALL_FILTERS); // 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 if (format == GFXFormatR8G8B8) { png_set_IHDR(mData->png_ptr, mData->info_ptr, width, height, // the width & height 8, PNG_COLOR_TYPE_RGB, // bit_depth, color_type, NULL, // no interlace NULL, // compression type NULL); // filter type } else if (format == GFXFormatR8G8B8A8 || format == GFXFormatR8G8B8X8) { png_set_IHDR(mData->png_ptr, mData->info_ptr, width, height, // the width & height 8, PNG_COLOR_TYPE_RGB_ALPHA, // bit_depth, color_type, NULL, // no interlace NULL, // compression type NULL); // filter type } else if (format == GFXFormatA8) { png_set_IHDR(mData->png_ptr, mData->info_ptr, width, height, // the width & height 8, PNG_COLOR_TYPE_GRAY, // bit_depth, color_type, NULL, // no interlace NULL, // compression type NULL); // filter type } else if (format == GFXFormatR5G6B5) { png_set_IHDR(mData->png_ptr, mData->info_ptr, width, height, // the width & height 16, PNG_COLOR_TYPE_GRAY, // bit_depth, color_type, PNG_INTERLACE_NONE, // no interlace PNG_COMPRESSION_TYPE_DEFAULT, // compression type PNG_FILTER_TYPE_DEFAULT); // filter type png_color_8_struct sigBit = { 0 }; sigBit.gray = 16; png_set_sBIT(mData->png_ptr, mData->info_ptr, &sigBit ); png_set_swap( mData->png_ptr ); } png_write_info(mData->png_ptr, mData->info_ptr); mActive = true; return true; }
/* TextureToPng Inputs: data : This is an array of RGBA with 8 bits per channel. 4 bytes for each pixel. row_stride: Determines the amount of bytes per row of pixels. */ bool TextureToPng(u8* data, int row_stride, const std::string filename, int width, int height, bool saveAlpha) { bool success = false; if (!data) return false; char title[] = "Dolphin Screenshot"; char title_key[] = "Title"; png_structp png_ptr = NULL; png_infop info_ptr = NULL; // Open file for writing (binary mode) File::IOFile fp(filename, "wb"); if (!fp.IsOpen()) { PanicAlert("Screenshot failed: Could not open file %s %d\n", filename.c_str(), errno); goto finalise; } // Initialize write structure png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { PanicAlert("Screenshot failed: Could not allocate write struct\n"); goto finalise; } // Initialize info structure info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { PanicAlert("Screenshot failed: Could not allocate info struct\n"); goto finalise; } // Setup Exception handling if (setjmp(png_jmpbuf(png_ptr))) { PanicAlert("Screenshot failed: Error during png creation\n"); goto finalise; } png_init_io(png_ptr, fp.GetHandle()); // Write header (8 bit colour depth) 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); png_text title_text; title_text.compression = PNG_TEXT_COMPRESSION_NONE; title_text.key = title_key; title_text.text = title; png_set_text(png_ptr, info_ptr, &title_text, 1); png_write_info(png_ptr, info_ptr); // Write image data for (auto y = 0; y < height; ++y) { u8* row_ptr = (u8*)data + y * row_stride; u8* ptr = row_ptr; for (auto x = 0; x < row_stride / 4; ++x) { if (!saveAlpha) ptr[3] = 0xff; ptr += 4; } png_write_row(png_ptr, row_ptr); } // End write png_write_end(png_ptr, NULL); success = true; finalise: 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); return success; }
PyObject * save_png_fast_progressive (char *filename, int w, int h, bool has_alpha, PyObject *data_generator, bool write_legacy_png) { png_structp png_ptr = NULL; png_infop info_ptr = NULL; PyObject * result = NULL; int bpc; FILE * fp = NULL; PyObject *iterator = NULL; /* TODO: try if this silliness helps #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) 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 */ bpc = 8; fp = fopen(filename, "wb"); if (!fp) { PyErr_SetFromErrno(PyExc_IOError); //PyErr_Format(PyExc_IOError, "Could not open PNG file for writing: %s", filename); goto cleanup; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, png_write_error_callback, NULL); if (!png_ptr) { PyErr_SetString(PyExc_MemoryError, "png_create_write_struct() failed"); goto cleanup; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { PyErr_SetString(PyExc_MemoryError, "png_create_info_struct() failed"); goto cleanup; } if (setjmp(png_jmpbuf(png_ptr))) { goto cleanup; } png_init_io(png_ptr, fp); png_set_IHDR (png_ptr, info_ptr, w, h, bpc, has_alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if (! write_legacy_png) { // Internal data is sRGB by the time it gets here. // Explicitly save with the recommended chunks to advertise that fact. png_set_sRGB_gAMA_and_cHRM (png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL); } // default (all filters enabled): 1350ms, 3.4MB //png_set_filter(png_ptr, 0, PNG_FILTER_NONE); // 790ms, 3.8MB //png_set_filter(png_ptr, 0, PNG_FILTER_PAETH); // 980ms, 3.5MB png_set_filter(png_ptr, 0, PNG_FILTER_SUB); // 760ms, 3.4MB //png_set_compression_level(png_ptr, 0); // 0.49s, 32MB //png_set_compression_level(png_ptr, 1); // 0.98s, 9.6MB png_set_compression_level(png_ptr, 2); // 1.08s, 9.4MB //png_set_compression_level(png_ptr, 9); // 18.6s, 9.3MB png_write_info(png_ptr, info_ptr); if (!has_alpha) { // input array format format is rgbu png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); } { iterator = PyObject_GetIter(data_generator); if (!iterator) goto cleanup; int y = 0; while (y < h) { int rows; PyObject * arr = PyIter_Next(iterator); if (PyErr_Occurred()) goto cleanup; assert(arr); // iterator should have data assert(PyArray_ISALIGNED(arr)); assert(PyArray_NDIM(arr) == 3); assert(PyArray_DIM(arr, 1) == w); assert(PyArray_DIM(arr, 2) == 4); // rgbu assert(PyArray_TYPE(arr) == NPY_UINT8); assert(PyArray_STRIDE(arr, 1) == 4); assert(PyArray_STRIDE(arr, 2) == 1); rows = PyArray_DIM(arr, 0); assert(rows > 0); y += rows; png_bytep p = (png_bytep)PyArray_DATA(arr); for (int row=0; row<rows; row++) { png_write_row (png_ptr, p); p += PyArray_STRIDE(arr, 0); } Py_DECREF(arr); } assert(y == h); PyObject * obj = PyIter_Next(iterator); assert(!obj); // iterator should be finished if (PyErr_Occurred()) goto cleanup; } png_write_end (png_ptr, NULL); result = Py_BuildValue("{}"); cleanup: if (iterator) Py_DECREF(iterator); if (info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr); if (fp) fclose(fp); return result; }
static int save_png(SDL_Surface* surface, char *path) { int w = surface->w; int h = surface->h; unsigned char * pix = (unsigned char *)surface->pixels; unsigned char writeBuffer[1024 * 3]; FILE *f = fopen(path,"wb"); if(!f) return 0; png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) { fclose(f); return 0; } png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_write_struct(&png_ptr,NULL); fclose(f); return 0; } png_init_io(png_ptr,f); png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr,info_ptr); unsigned char *b = writeBuffer; int sizeX = w; int sizeY = h; int y; int x; unsigned short *p = (unsigned short *)pix; for(y = 0; y < sizeY; y++) { for(x = 0; x < sizeX; x++) { unsigned short v = p[x]; *b++ = ((v & systemRedMask ) >> systemRedShift ) << 3; // R *b++ = ((v & systemGreenMask) >> systemGreenShift) << 2; // G *b++ = ((v & systemBlueMask ) >> systemBlueShift ) << 3; // B } p += surface->pitch / 2; png_write_row(png_ptr,writeBuffer); b = writeBuffer; } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(f); return 1; }
void WritePng(char *path, struct Image *image) { FILE *fp = fopen(path, "wb"); if (fp == NULL) FATAL_ERROR("Failed to open \"%s\" for writing.\n", path); png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) FATAL_ERROR("Failed to create PNG write struct.\n"); png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) FATAL_ERROR("Failed to create PNG info struct.\n"); if (setjmp(png_jmpbuf(png_ptr))) FATAL_ERROR("Failed to init I/O for writing \"%s\".\n", path); png_init_io(png_ptr, fp); if (setjmp(png_jmpbuf(png_ptr))) FATAL_ERROR("Error writing header for \"%s\".\n", path); int color_type = image->hasPalette ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_GRAY; png_set_IHDR(png_ptr, info_ptr, image->width, image->height, image->bitDepth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if (image->hasPalette) { SetPngPalette(png_ptr, info_ptr, &image->palette); if (image->hasTransparency) { png_byte trans = 0; png_set_tRNS(png_ptr, info_ptr, &trans, 1, 0); } } png_write_info(png_ptr, info_ptr); png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep)); if (row_pointers == NULL) FATAL_ERROR("Failed to allocate row pointers.\n"); int rowbytes = png_get_rowbytes(png_ptr, info_ptr); for (int i = 0; i < image->height; i++) row_pointers[i] = (png_bytep)(image->pixels + (i * rowbytes)); if (setjmp(png_jmpbuf(png_ptr))) FATAL_ERROR("Error writing \"%s\".\n", path); png_write_image(png_ptr, row_pointers); if (setjmp(png_jmpbuf(png_ptr))) FATAL_ERROR("Error ending write of \"%s\".\n", path); png_write_end(png_ptr, NULL); fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); free(row_pointers); }
/*! * 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; }
static DVector<uint8_t> _lossless_pack_png(const Image& p_image) { Image img = p_image; if (img.get_format() > Image::FORMAT_INDEXED_ALPHA) img.decompress(); ERR_FAIL_COND_V(img.get_format() > Image::FORMAT_INDEXED_ALPHA, DVector<uint8_t>()); png_structp png_ptr; png_infop info_ptr; png_bytep * row_pointers; /* initialize stuff */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); ERR_FAIL_COND_V(!png_ptr,DVector<uint8_t>()); info_ptr = png_create_info_struct(png_ptr); ERR_FAIL_COND_V(!info_ptr,DVector<uint8_t>()); if (setjmp(png_jmpbuf(png_ptr))) { ERR_FAIL_V(DVector<uint8_t>()); } DVector<uint8_t> ret; ret.push_back('P'); ret.push_back('N'); ret.push_back('G'); ret.push_back(' '); png_set_write_fn(png_ptr,&ret,_write_png_data,NULL); /* write header */ if (setjmp(png_jmpbuf(png_ptr))) { ERR_FAIL_V(DVector<uint8_t>()); } int pngf=0; int pngb=8; int cs=0; switch(img.get_format()) { case Image::FORMAT_GRAYSCALE: { pngf=PNG_COLOR_TYPE_GRAY; cs=1; } break; case Image::FORMAT_GRAYSCALE_ALPHA: { pngf=PNG_COLOR_TYPE_GRAY_ALPHA; cs=2; } break; case Image::FORMAT_RGB: { pngf=PNG_COLOR_TYPE_RGB; cs=3; } break; case Image::FORMAT_RGBA: { pngf=PNG_COLOR_TYPE_RGB_ALPHA; cs=4; } break; default: { if (img.detect_alpha()) { img.convert(Image::FORMAT_RGBA); pngf=PNG_COLOR_TYPE_RGB_ALPHA; cs=4; } else { img.convert(Image::FORMAT_RGB); pngf=PNG_COLOR_TYPE_RGB; cs=3; } } } int w = img.get_width(); int h = img.get_height(); png_set_IHDR(png_ptr, info_ptr, w,h, 8, pngf, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); /* write bytes */ if (setjmp(png_jmpbuf(png_ptr))) { ERR_FAIL_V(DVector<uint8_t>()); } DVector<uint8_t>::Read r = img.get_data().read(); row_pointers = (png_bytep*)memalloc(sizeof(png_bytep)*h); for(int i=0;i<h;i++) { row_pointers[i]=(png_bytep)&r[i*w*cs]; } png_write_image(png_ptr, row_pointers); memfree(row_pointers); /* end write */ if (setjmp(png_jmpbuf(png_ptr))) { ERR_FAIL_V(DVector<uint8_t>()); } png_write_end(png_ptr, NULL); return ret; }
static gboolean ico_write_png (FILE *fp, gint32 layer, gint32 depth) { png_structp png_ptr; png_infop info_ptr; png_byte **row_pointers; gint i, rowstride; gint width, height; gint num_colors_used; guchar *palette; guchar *buf; row_pointers = NULL; palette = NULL; buf = NULL; width = gimp_drawable_width (layer); height = gimp_drawable_height (layer); png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if ( !png_ptr ) return FALSE; info_ptr = png_create_info_struct (png_ptr); if ( !info_ptr ) { png_destroy_write_struct (&png_ptr, NULL); return FALSE; } if (setjmp (png_jmpbuf (png_ptr))) { png_destroy_write_struct (&png_ptr, &info_ptr); if ( row_pointers ) g_free (row_pointers); if (palette) g_free (palette); if (buf) g_free (buf); return FALSE; } ico_image_get_reduced_buf (layer, depth, &num_colors_used, &palette, &buf); png_init_io (png_ptr, fp); png_set_IHDR (png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info (png_ptr, info_ptr); rowstride = ico_rowstride (width, 32); row_pointers = g_new (png_byte*, height); for (i = 0; i < height; i++) { row_pointers[i] = buf + rowstride * i; } png_write_image (png_ptr, row_pointers); row_pointers = NULL; png_write_end (png_ptr, info_ptr); png_destroy_write_struct (&png_ptr, &info_ptr); g_free (row_pointers); g_free (palette); g_free (buf); return TRUE; }
int writepng_init(mainprog_info *mainprog_ptr) { AMJU_CALL_STACK; png_structp png_ptr; /* note: temporary variables! */ png_infop info_ptr; int color_type, interlace_type; /* could also replace libpng warning-handler (final NULL), but no need: */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr, writepng_error_handler, NULL); if (!png_ptr) return 4; /* out of memory */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, NULL); return 4; /* 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, &info_ptr); return 2; } /* make sure outfile is (re)opened in BINARY mode */ png_init_io(png_ptr, mainprog_ptr->outfile); /* set the compression levels--in general, always want to leave filtering * turned on (except for palette images) and allow all of the filters, * which is the default; want 32K zlib window, unless entire image buffer * is 16K or smaller (unknown here)--also the default; usually want max * compression (NOT the default); and remaining compression flags should * be left alone */ png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); /* >> this is default for no filtering; Z_FILTERED is default otherwise: png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY); >> these are all defaults: png_set_compression_mem_level(png_ptr, 8); png_set_compression_window_bits(png_ptr, 15); png_set_compression_method(png_ptr, 8); */ /* set the image parameters appropriately */ if (mainprog_ptr->pnmtype == 5) color_type = PNG_COLOR_TYPE_GRAY; else if (mainprog_ptr->pnmtype == 6) color_type = PNG_COLOR_TYPE_RGB; else if (mainprog_ptr->pnmtype == 8) color_type = PNG_COLOR_TYPE_RGB_ALPHA; else { png_destroy_write_struct(&png_ptr, &info_ptr); return 11; } interlace_type = mainprog_ptr->interlaced? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE; png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height, mainprog_ptr->sample_depth, color_type, interlace_type, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (mainprog_ptr->gamma > 0.0) png_set_gAMA(png_ptr, info_ptr, mainprog_ptr->gamma); if (mainprog_ptr->have_bg) { /* we know it's RGBA, not gray+alpha */ png_color_16 background; background.red = mainprog_ptr->bg_red; background.green = mainprog_ptr->bg_green; background.blue = mainprog_ptr->bg_blue; png_set_bKGD(png_ptr, info_ptr, &background); } if (mainprog_ptr->have_time) { png_time modtime; png_convert_from_time_t(&modtime, mainprog_ptr->modtime); png_set_tIME(png_ptr, info_ptr, &modtime); } if (mainprog_ptr->have_text) { png_text text[6]; int num_text = 0; if (mainprog_ptr->have_text & TEXT_TITLE) { text[num_text].compression = PNG_TEXT_COMPRESSION_NONE; text[num_text].key = (char*)"Title"; text[num_text].text = mainprog_ptr->title; ++num_text; } if (mainprog_ptr->have_text & TEXT_AUTHOR) { text[num_text].compression = PNG_TEXT_COMPRESSION_NONE; text[num_text].key = (char*)"Author"; text[num_text].text = mainprog_ptr->author; ++num_text; } if (mainprog_ptr->have_text & TEXT_DESC) { text[num_text].compression = PNG_TEXT_COMPRESSION_NONE; text[num_text].key = (char*)"Description"; text[num_text].text = mainprog_ptr->desc; ++num_text; } if (mainprog_ptr->have_text & TEXT_COPY) { text[num_text].compression = PNG_TEXT_COMPRESSION_NONE; text[num_text].key = (char*)"Copyright"; text[num_text].text = mainprog_ptr->copyright; ++num_text; } if (mainprog_ptr->have_text & TEXT_EMAIL) { text[num_text].compression = PNG_TEXT_COMPRESSION_NONE; text[num_text].key = (char*)"E-mail"; text[num_text].text = mainprog_ptr->email; ++num_text; } if (mainprog_ptr->have_text & TEXT_URL) { text[num_text].compression = PNG_TEXT_COMPRESSION_NONE; text[num_text].key = (char*)"URL"; text[num_text].text = mainprog_ptr->url; ++num_text; } png_set_text(png_ptr, info_ptr, text, num_text); } /* write all chunks up to (but not including) first IDAT */ png_write_info(png_ptr, info_ptr); /* if we wanted to write any more text info *after* the image data, we * would set up text struct(s) here and call png_set_text() again, with * just the new data; png_set_tIME() could also go here, but it would * have no effect since we already called it above (only one tIME chunk * allowed) */ /* set up the transformations: for now, just pack low-bit-depth pixels * into bytes (one, two or four pixels per byte) */ png_set_packing(png_ptr); /* png_set_shift(png_ptr, &sig_bit); to scale low-bit-depth values */ /* make sure we save our pointers for use in writepng_encode_image() */ mainprog_ptr->png_ptr = png_ptr; mainprog_ptr->info_ptr = info_ptr; /* OK, that's all we need to do for now; return happy */ return 0; }
bool PngEncoder::write( const Mat& img, const vector<int>& params ) { int compression_level = 0; 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), MAX_MEM_LEVEL); } } 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 ); } if( m_buf || f ) { if( compression_level > 0 ) { png_set_compression_mem_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, Z_HUFFMAN_ONLY); png_set_IHDR( png_ptr, info_ptr, width, height, depth == CV_8U ? 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 ); 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 abiword_document::garble_png( void*& data, size_t& size ) { png_bytep * dib; png_uint_32 width; png_uint_32 height; int compression_type; int filter_type; int interlace_type; int bit_depth; int color_type; png_uint_32 rowbytes; // read PNG data { png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (void*) NULL, NULL, NULL ); if (!png_ptr) return false; png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct( &png_ptr, (png_infopp)NULL, (png_infopp)NULL ); return false; } png_read_data _png_read_data = { data, size, 0 }; png_set_read_fn( png_ptr, (void*)&_png_read_data, &_png_read ); png_read_info( png_ptr, info_ptr ); png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type ); png_set_packing( png_ptr ); png_set_expand( png_ptr ); png_set_strip_16( png_ptr ); png_set_gray_to_rgb( png_ptr ); png_set_strip_alpha( png_ptr ); png_set_interlace_handling( png_ptr ); png_set_bgr( png_ptr ); rowbytes = png_get_rowbytes(png_ptr, info_ptr); png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); } // we don't care about the image data itself, we just want a random garbled // image of the same size dib = (png_bytep*) malloc( sizeof(png_bytep) * height ); for (size_t i=0; i<height; ++i) { dib[i] = (png_byte*) malloc( rowbytes ); garble_image_line( reinterpret_cast<char*>( dib[i] ), rowbytes ); } bool result = false; { // write it back png_structp png_ptrw = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); if (png_ptrw) { png_infop info_ptrw = png_create_info_struct( png_ptrw ); png_set_IHDR( png_ptrw, info_ptrw, width, height, bit_depth, color_type, interlace_type, compression_type, filter_type ); string newdata; png_set_write_fn( png_ptrw, (void*)&newdata, &_png_write, NULL ); png_write_info( png_ptrw, info_ptrw ); png_write_image( png_ptrw, dib ); png_write_end( png_ptrw, NULL ); png_destroy_write_struct( &png_ptrw, NULL ); free(data); size = newdata.size(); data = malloc( size ); memcpy( data, &newdata[0], size ); result = true; } } // cleanup for (size_t i=0; i<height; i++) free( dib[i] ); free( dib ); return result; }
/** * Write PNG image data * @param buffer Image data * @param filename A filename of the PNG image to save * @param width Image width in pixels * @param height Image height in pixels * @param depth The bit depth of the image. * Valid values shall include 1, 2, 4, 8, 16. * @return TRUE if it completed successfully or FALSE otherwise */ static bool png_create (char *buffer, const char *filename, Uint32 width, Uint32 height, Sint32 depth) { Uint32 i; FILE *out; LOG_DBG ("Write %s", filename); if (buffer == NULL) { LOG_ERR ("image_to_buffer() failed! (filename = %s)", filename); return FALSE; } out = fopen_data (filename, "w"); if (out == NULL) { LOG_ERR ("can't open \"%s\"", filename); return FALSE; } /* allocate and initialize png_ptr struct for writing */ png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, /* error_ptr */ (png_voidp) NULL, /* error_fn */ NULL, /* warn_fn */ NULL); if (png_ptr == NULL) { LOG_ERR ("png_create_write_struct() failed"); return FALSE; } /* allocate and initialize the info structure */ png_infop info_ptr = png_create_info_struct (png_ptr); if (png_ptr == NULL) { LOG_ERR ("png_create_info_struct() failed"); return FALSE; } /* initialize input/output for PNG file to the default functions */ png_init_io (png_ptr, out); /* set library compression level */ png_set_IHDR (png_ptr, info_ptr, /* width */ width, /* height */ height, /* bit depth */ depth, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_compression_level (png_ptr, Z_BEST_COMPRESSION); png_set_text (png_ptr, info_ptr, text, sizeof text / sizeof text[0]); png_color_16 background; background.red = 0; background.green = 0; background.blue = 0; png_set_bKGD (png_ptr, info_ptr, &background); png_write_info (png_ptr, info_ptr); for (i = 0; i < height; i++) { { png_write_row (png_ptr, (png_byte *) & buffer[i * width * 4]); } } png_write_end (png_ptr, info_ptr); png_destroy_write_struct (&png_ptr, &info_ptr); fclose (out); return TRUE; }
int writeBmpBuffToPng(const char *fileName, unsigned char *bmpBuff, unsigned int bmpWidth, unsigned int bmpHeight, int upSideDown) { int ERROR = 0; int OK = 1; FILE *fp = NULL; png_structp png_ptr; png_infop info_ptr; fp = fopen(fileName, "wb"); if (fp == NULL) { DEBUG_LOG("error in open %s\n", fileName); return (ERROR); } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); DEBUG_LOG("error in png_create_write_struct \n"); return (ERROR); } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_write_struct(&png_ptr, NULL); DEBUG_LOG("error png_create_info_struct \n"); return (ERROR); } /* Set error handling. REQUIRED if you aren't supplying your own * error handling functions in the png_create_write_struct() call. */ if (setjmp(png_jmpbuf(png_ptr))) { /* If we get here, we had a problem writing the file */ fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); DEBUG_LOG("error png_create_info_struct \n"); return (ERROR); } png_init_io(png_ptr, fp); /* This is the easy way. Use it if you already have all the * image info living in the structure. You could "|" many * PNG_TRANSFORM flags into the png_transforms integer here. */ // png_write_png(png_ptr, info_ptr, png_transforms, NULL); png_set_IHDR(png_ptr, info_ptr, bmpWidth, bmpHeight, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); /* Flip BGR pixels to RGB */ // png_set_bgr(png_ptr); { /* Set up pointers into your "image" byte array */ png_bytep *row_pointers = (png_bytep *)malloc(bmpHeight * sizeof(png_byte)); if (upSideDown) { unsigned int k = 0; for (; k < bmpHeight; k++) { row_pointers[k] = bmpBuff + (bmpHeight - 1 - k) * bmpWidth * 4; } } else { unsigned int k = 0; for (; k < bmpHeight; k++) { row_pointers[k] = bmpBuff + k * bmpWidth * 4; } } png_write_image(png_ptr, row_pointers); free(row_pointers); } /* Similarly, if you png_malloced any data that you passed in with * png_set_something(), such as a hist or trans array, free it here, * when you can be sure that libpng is through with it. */ // png_free(png_ptr, trans); // trans = NULL; /* Clean up after the write, and free any memory allocated */ png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return (OK); }
static void png_save(BPGDecoderContext *img, const char *filename, int bit_depth) { BPGImageInfo img_info_s, *img_info = &img_info_s; FILE *f; png_structp png_ptr; png_infop info_ptr; png_bytep row_pointer; int y, color_type, bpp; BPGDecoderOutputFormat out_fmt; if (bit_depth != 8 && bit_depth != 16) { fprintf(stderr, "Only bit_depth = 8 or 16 are supported for PNG output\n"); exit(1); } bpg_decoder_get_info(img, img_info); f = fopen(filename, "wb"); if (!f) { fprintf(stderr, "%s: I/O error\n", filename); exit(1); } png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, /* error */ NULL, /* warning */ NULL, NULL, NULL); info_ptr = png_create_info_struct(png_ptr); png_set_write_fn(png_ptr, (png_voidp)f, &png_write_data, NULL); if (setjmp(png_jmpbuf(png_ptr)) != 0) { fprintf(stderr, "PNG write error\n"); exit(1); } if (img_info->has_alpha) color_type = PNG_COLOR_TYPE_RGB_ALPHA; else color_type = PNG_COLOR_TYPE_RGB; png_set_IHDR(png_ptr, info_ptr, img_info->width, img_info->height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); #if __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ if (bit_depth == 16) { png_set_swap(png_ptr); } #endif if (bit_depth == 16) { if (img_info->has_alpha) out_fmt = BPG_OUTPUT_FORMAT_RGBA64; else out_fmt = BPG_OUTPUT_FORMAT_RGB48; } else { if (img_info->has_alpha) out_fmt = BPG_OUTPUT_FORMAT_RGBA32; else out_fmt = BPG_OUTPUT_FORMAT_RGB24; } bpg_decoder_start(img, out_fmt); bpp = (3 + img_info->has_alpha) * (bit_depth / 8); row_pointer = (png_bytep)png_malloc(png_ptr, img_info->width * bpp); for (y = 0; y < img_info->height; y++) { bpg_decoder_get_line(img, row_pointer); png_write_row(png_ptr, row_pointer); } png_free(png_ptr, row_pointer); png_write_end(png_ptr, NULL); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(f); }
int icns_image_to_png(icns_image_t *image, icns_size_t *dataSizeOut, icns_byte_t **dataPtrOut) { int width = 0; int height = 0; int image_channels = 0; int image_pixel_depth = 0; int mask_channels = 0; png_structp png_ptr; png_infop info_ptr; png_bytep *row_pointers; int i, j; if(image == NULL) { icns_print_err("icns_image_to_png: Image is NULL!\n"); return ICNS_STATUS_NULL_PARAM; } if(dataSizeOut == NULL) { icns_print_err("icns_image_to_png: Data size NULL!\n"); return ICNS_STATUS_NULL_PARAM; } if(dataPtrOut == NULL) { icns_print_err("icns_image_to_png: Data ref is NULL!\n"); return ICNS_STATUS_NULL_PARAM; } if (image->pngFilename) { FILE *fp = fopen(image->pngFilename, "rb"); if (fp) { fseek(fp, 0, SEEK_END); *dataSizeOut = ftell(fp); fseek(fp, 0, SEEK_SET); *dataPtrOut = malloc(*dataSizeOut); if (fread(*dataPtrOut, 1, *dataSizeOut, fp)) { return ICNS_STATUS_OK; } } } #ifdef ICNS_DEBUG printf("Encoding PNG image...\n"); #endif width = image->imageWidth; height = image->imageHeight; image_channels = image->imageChannels; image_pixel_depth = image->imagePixelDepth; png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fprintf (stderr, "PNG error: cannot allocate libpng main struct\n"); return ICNS_STATUS_NO_MEMORY; } info_ptr = png_create_info_struct (png_ptr); if (info_ptr == NULL) { fprintf (stderr, "PNG error: cannot allocate libpng info struct\n"); png_destroy_write_struct (&png_ptr, (png_infopp) NULL); return ICNS_STATUS_NO_MEMORY; } icns_png_io_ref io_data = { NULL, 0, 0 }; png_set_write_fn(png_ptr, (void *)&io_data, &icns_png_write_memory, NULL); png_set_filter(png_ptr, 0, PNG_FILTER_NONE); png_set_IHDR (png_ptr, info_ptr, width, height, image_pixel_depth, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info (png_ptr, info_ptr); if(image_pixel_depth < 8) png_set_packing (png_ptr); row_pointers = (png_bytep*)malloc(sizeof(png_bytep)*height); if (row_pointers == NULL) { fprintf (stderr, "PNG error: unable to allocate row_pointers\n"); } else { for (i = 0; i < height; i++) { if ((row_pointers[i] = (png_bytep)malloc(width*image_channels)) == NULL) { fprintf (stderr, "PNG error: unable to allocate rows\n"); for (j = 0; j < i; j++) free(row_pointers[j]); free(row_pointers); return ICNS_STATUS_NO_MEMORY; } for(j = 0; j < width; j++) { icns_uint32_t *src_pixel = (icns_uint32_t*)&(image->imageData[i*width*image_channels+j*image_channels]); icns_uint32_t *dst_pixel = (icns_uint32_t*)&(row_pointers[i][j*image_channels]); *dst_pixel = *src_pixel; } } } png_write_image (png_ptr,row_pointers); png_write_end (png_ptr, info_ptr); *dataSizeOut = io_data.offset; *dataPtrOut = io_data.data; png_destroy_write_struct (&png_ptr, &info_ptr); for (j = 0; j < height; j++) free(row_pointers[j]); free(row_pointers); return ICNS_STATUS_OK; }
RADRT_API bool RADRT_CALL Encode(const Image &in, const Mipmap &mip, bool interlaced, void *&outData, AddrSize &outSize) { RAD_ASSERT(in.format == Format_A8 || in.format == Format_RGB888 || in.format == Format_RGBA8888); if (in.format != Format_A8 && in.format != Format_RGB888 && in.format != Format_RGBA8888) return false; png_structp png; png_infop info; png = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, 0, PNGErrorHandler, PNGWarningHandler, 0, PNGMalloc, PNGFree); if (!png) return false; info = png_create_info_struct(png); if (!info) { png_destroy_write_struct(&png, 0); return false; } stream::DynamicMemOutputBuffer ob(ZImageCodec); stream::OutputStream os(ob); png_set_write_fn(png, &os, PNGWrite, PNGFlush); png_set_IHDR(png, info, mip.width, mip.height, 8, (in.format == Format_A8) ? PNG_COLOR_TYPE_GRAY : (in.format == Format_RGB888) ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA, interlaced ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_color_8 sig; memset(&sig, 0, sizeof(sig)); if (in.format == Format_A8) { sig.gray = 8; } else { sig.red = 8; sig.green = 8; sig.blue = 8; sig.alpha = (in.format == Format_RGBA8888) ? 8 : 0; } png_set_sBIT(png, info, &sig); try { png_write_info(png, info); } catch (PNGException&) { png_destroy_write_struct(&png, &info); return false; } png_set_shift(png, &sig); int passes = 1; if (interlaced) { passes = png_set_interlace_handling(png); } for (int pass = 0; pass < passes; ++pass) { png_bytep src = (png_bytep)mip.data; for (int y = 0; y < mip.height; ++y) { png_write_rows(png, (png_bytepp)&src, 1); src += mip.stride; } } png_write_end(png, info); png_destroy_write_struct(&png, &info); outData = ob.OutputBuffer().Ptr(); outSize = ob.OutputBuffer().Size(); ob.OutputBuffer().Set(0, 0); // don't let the output buffer release the memory. return true; }
void take_screenshot(FILE *fb_in, FILE *fb_out) { int fb; char imgbuf[0x10000]; struct fb_var_screeninfo vinfo; png_structp png; png_infop info; unsigned int r,c,rowlen; unsigned int bytespp,offset; fb = fileno(fb_in); if(fb < 0) { ALOGE("failed to open framebuffer\n"); return; } fb_in = fdopen(fb, "r"); if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) { ALOGE("failed to get framebuffer info\n"); return; } fcntl(fb, F_SETFD, FD_CLOEXEC); png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png == NULL) { ALOGE("failed png_create_write_struct\n"); fclose(fb_in); return; } png_init_io(png, fb_out); info = png_create_info_struct(png); if (info == NULL) { ALOGE("failed png_create_info_struct\n"); png_destroy_write_struct(&png, NULL); fclose(fb_in); return; } if (setjmp(png_jmpbuf(png))) { ALOGE("failed png setjmp\n"); png_destroy_write_struct(&png, NULL); fclose(fb_in); return; } bytespp = vinfo.bits_per_pixel / 8; png_set_IHDR(png, info, vinfo.xres, vinfo.yres, vinfo.bits_per_pixel / 4, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png, info); rowlen=vinfo.xres * bytespp; if (rowlen > sizeof(imgbuf)) { ALOGE("crazy rowlen: %d\n", rowlen); png_destroy_write_struct(&png, NULL); fclose(fb_in); return; } offset = vinfo.xoffset * bytespp + vinfo.xres * vinfo.yoffset * bytespp; fseek(fb_in, offset, SEEK_SET); for(r=0; r<vinfo.yres; r++) { int len = fread(imgbuf, 1, rowlen, fb_in); if (len <= 0) break; png_write_row(png, (png_bytep)imgbuf); } png_write_end(png, info); fclose(fb_in); png_destroy_write_struct(&png, NULL); }
bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, const QString &description, int off_x_in, int off_y_in) { QPoint offset = image.offset(); int off_x = off_x_in + offset.x(); int off_y = off_y_in + offset.y(); png_structp png_ptr; png_infop info_ptr; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { return false; } png_set_error_fn(png_ptr, 0, 0, qt_png_warning); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, 0); return false; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); return false; } int quality = quality_in; if (quality >= 0) { if (quality > 9) { qWarning("PNG: Quality %d out of range", quality); quality = 9; } png_set_compression_level(png_ptr, quality); } png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn); int color_type = 0; if (image.colorCount()) { if (image.isGrayscale()) color_type = PNG_COLOR_TYPE_GRAY; else color_type = PNG_COLOR_TYPE_PALETTE; } else if (image.format() == QImage::Format_Grayscale8) color_type = PNG_COLOR_TYPE_GRAY; else if (image.hasAlphaChannel()) color_type = PNG_COLOR_TYPE_RGB_ALPHA; else color_type = PNG_COLOR_TYPE_RGB; png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(), image.depth() == 1 ? 1 : 8, // per channel color_type, 0, 0, 0); // sets #channels if (gamma != 0.0) { png_set_gAMA(png_ptr, info_ptr, 1.0/gamma); } if (image.format() == QImage::Format_MonoLSB) png_set_packswap(png_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) { // Paletted int num_palette = qMin(256, image.colorCount()); png_color palette[256]; png_byte trans[256]; int num_trans = 0; for (int i=0; i<num_palette; i++) { QRgb rgba=image.color(i); palette[i].red = qRed(rgba); palette[i].green = qGreen(rgba); palette[i].blue = qBlue(rgba); trans[i] = qAlpha(rgba); if (trans[i] < 255) { num_trans = i+1; } } png_set_PLTE(png_ptr, info_ptr, palette, num_palette); if (num_trans) { png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0); } } // Swap ARGB to RGBA (normal PNG format) before saving on // BigEndian machines if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { png_set_swap_alpha(png_ptr); } // Qt==ARGB==Big(ARGB)==Little(BGRA). But RGB888 is RGB regardless if (QSysInfo::ByteOrder == QSysInfo::LittleEndian && image.format() != QImage::Format_RGB888) { png_set_bgr(png_ptr); } if (off_x || off_y) { png_set_oFFs(png_ptr, info_ptr, off_x, off_y, PNG_OFFSET_PIXEL); } if (frames_written > 0) png_set_sig_bytes(png_ptr, 8); if (image.dotsPerMeterX() > 0 || image.dotsPerMeterY() > 0) { png_set_pHYs(png_ptr, info_ptr, image.dotsPerMeterX(), image.dotsPerMeterY(), PNG_RESOLUTION_METER); } set_text(image, png_ptr, info_ptr, description); png_write_info(png_ptr, info_ptr); if (image.depth() != 1) png_set_packing(png_ptr); if (color_type == PNG_COLOR_TYPE_RGB && image.format() != QImage::Format_RGB888) png_set_filler(png_ptr, 0, QSysInfo::ByteOrder == QSysInfo::BigEndian ? PNG_FILLER_BEFORE : PNG_FILLER_AFTER); if (looping >= 0 && frames_written == 0) { uchar data[13] = "NETSCAPE2.0"; // 0123456789aBC data[0xB] = looping%0x100; data[0xC] = looping/0x100; png_write_chunk(png_ptr, const_cast<png_bytep>((const png_byte *)"gIFx"), data, 13); } if (ms_delay >= 0 || disposal!=Unspecified) { uchar data[4]; data[0] = disposal; data[1] = 0; data[2] = (ms_delay/10)/0x100; // hundredths data[3] = (ms_delay/10)%0x100; png_write_chunk(png_ptr, const_cast<png_bytep>((const png_byte *)"gIFg"), data, 4); } int height = image.height(); int width = image.width(); switch (image.format()) { case QImage::Format_Mono: case QImage::Format_MonoLSB: case QImage::Format_Indexed8: case QImage::Format_Grayscale8: case QImage::Format_RGB32: case QImage::Format_ARGB32: case QImage::Format_RGB888: { png_bytep* row_pointers = new png_bytep[height]; for (int y=0; y<height; y++) row_pointers[y] = const_cast<png_bytep>(image.constScanLine(y)); png_write_image(png_ptr, row_pointers); delete [] row_pointers; } break; default: { QImage::Format fmt = image.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32; QImage row; png_bytep row_pointers[1]; for (int y=0; y<height; y++) { row = image.copy(0, y, width, 1).convertToFormat(fmt); row_pointers[0] = const_cast<png_bytep>(row.constScanLine(0)); png_write_rows(png_ptr, row_pointers, 1); } } break; } png_write_end(png_ptr, info_ptr); frames_written++; png_destroy_write_struct(&png_ptr, &info_ptr); return true; }
void Mesh::generateHeightmap(const char* filename) { // Shoot rays down from a point just above the max Y position of the mesh. // Compute ray-triangle intersection tests against the ray and this mesh to // generate heightmap data. Vector3 rayOrigin(0, bounds.max.y + 10, 0); Vector3 rayDirection(0, -1, 0); Vector3 intersectionPoint; int minX = (int)ceil(bounds.min.x); int maxX = (int)floor(bounds.max.x); int minZ = (int)ceil(bounds.min.z); int maxZ = (int)floor(bounds.max.z); int width = maxX - minX + 1; int height = maxZ - minZ + 1; float* heights = new float[width * height]; int index = 0; float minHeight = FLT_MAX; float maxHeight = FLT_MIN; for (int z = minZ; z <= maxZ; z++) { rayOrigin.z = (float)z; for (int x = minX; x <= maxX; x++) { float h; rayOrigin.x = (float)x; if (intersect(rayOrigin, rayDirection, vertices, parts, &intersectionPoint)) { h = intersectionPoint.y; } else { h = 0; fprintf(stderr, "Warning: Heightmap triangle intersection failed for (%d, %d).\n", x, z); } if (h < minHeight) minHeight = h; if (h > maxHeight) maxHeight = h; heights[index++] = h; } } // Normalize the max height value maxHeight = maxHeight - minHeight; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_bytep row = NULL; FILE* fp = fopen(filename, "wb"); if (fp == NULL) { fprintf(stderr, "Error: Failed to open file for writing: %s\n", filename); goto error; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fprintf(stderr, "Error: Write struct creation failed: %s\n", filename); goto error; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "Error: Info struct creation failed: %s\n", filename); goto error; } png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); // Allocate memory for a single row of image data row = (png_bytep)malloc(3 * width * sizeof(png_byte)); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // Write height value normalized between 0-255 (between min and max height) float h = heights[y*width + x]; float nh = (h - minHeight) / maxHeight; png_byte b = (png_byte)(nh * 255.0f); int pos = x*3; row[pos] = row[pos+1] = row[pos+2] = b; } png_write_row(png_ptr, row); } png_write_end(png_ptr, NULL); DEBUGPRINT_VARG("> Saved heightmap: %s\n", filename); error: if (heights) delete[] heights; if (fp) fclose(fp); if (row) free(row); if (info_ptr) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); if (png_ptr) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); }
/************************************************************************** Save given buffer type to file. **************************************************************************/ bool savePngInternal(const char *filename, unsigned char *pixels, int w, int h, int bitdepth, int color_type) { png_structp pngp; png_infop infop; int y; FILE *fp; png_bytep *row_pointers; int const bytes = bitdepth / 8; if (filename == NULL || *filename == '\0' || pixels == NULL) { return false; } if (!(fp = fopen(filename, "wb"))) { debug(LOG_ERROR, "%s won't open for writing!", filename); return false; } pngp = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!pngp) { debug(LOG_ERROR, "fgl_save_pixmap: Failed to create PNG write struct"); fclose(fp); return false; } infop = png_create_info_struct(pngp); if (!infop) { debug(LOG_ERROR, "fgl_save_pixmap: Failed to create PNG info struct"); fclose(fp); png_destroy_write_struct(&pngp, NULL); return false; } if (setjmp(png_jmpbuf(pngp))) { debug(LOG_ERROR, "fgl_save_pixmap: Failed to initialize IO during PNG save"); fclose(fp); png_destroy_write_struct(&pngp, NULL); return false; } png_init_io(pngp, fp); /* write header */ if (setjmp(png_jmpbuf(pngp))) { debug(LOG_ERROR, "fgl_save_pixmap: Failed to write PNG header"); fclose(fp); png_destroy_write_struct(&pngp, NULL); return false; } png_set_IHDR(pngp, infop, w, h, bitdepth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(pngp, infop); /* Create pointers to each row of the data, as libpng wants it */ row_pointers = malloc(sizeof(png_bytep) * h); for (y = 0; y < h; y++) { row_pointers[y] = pixels + (y * w * bytes); } if (setjmp(png_jmpbuf(pngp))) { debug(LOG_ERROR, "fgl_save_pixmap: Failed to write PNG body"); fclose(fp); png_destroy_write_struct(&pngp, NULL); return false; } png_write_image(pngp, row_pointers); if (setjmp(png_jmpbuf(pngp))) { debug(LOG_ERROR, "fgl_save_pixmap: Failed to finalize PNG"); fclose(fp); png_destroy_write_struct(&pngp, NULL); return false; } png_write_end(pngp, NULL); free(row_pointers); fclose(fp); png_destroy_write_struct(&pngp, NULL); return true; }
int GImageWrite_Png(GImage *gi, FILE *fp, int progressive) { struct _GImage *base = gi->list_len==0?gi->u.image:gi->u.images[0]; png_structp png_ptr; png_infop info_ptr; png_byte **rows; int i; int bit_depth; int color_type; int num_palette; png_bytep trans_alpha = NULL; png_color_16p trans_color = NULL; png_colorp palette = NULL; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (void *)NULL, user_error_fn, user_warning_fn); if (!png_ptr) { return(false); } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return(false); } #if (PNG_LIBPNG_VER < 10500) if (setjmp(png_ptr->jmpbuf)) #else if (setjmp(*png_set_longjmp_fn(png_ptr, longjmp, sizeof (jmp_buf)))) #endif { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return(false); } png_init_io(png_ptr, fp); bit_depth = 8; num_palette = base->clut==NULL?2:base->clut->clut_len; if ( base->image_type==it_index || base->image_type==it_bitmap ) { color_type = PNG_COLOR_TYPE_PALETTE; if ( num_palette<=2 ) bit_depth=1; else if ( num_palette<=4 ) bit_depth=2; else if ( num_palette<=16 ) bit_depth=4; } else { color_type = PNG_COLOR_TYPE_RGB; if ( base->image_type == it_rgba ) color_type = PNG_COLOR_TYPE_RGB_ALPHA; } png_set_IHDR(png_ptr, info_ptr, base->width, base->height, bit_depth, color_type, progressive, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if ( base->image_type==it_index || base->image_type==it_bitmap ) { palette = (png_color *) galloc(num_palette*sizeof(png_color)); if ( base->clut==NULL ) { palette[0].red = palette[0].green = palette[0].blue = 0; palette[1].red = palette[1].green = palette[1].blue = 0xff; } else { for ( i=0; i<num_palette; ++i ) { long col = base->clut->clut[i]; palette[i].red = COLOR_RED(col); palette[i].green = COLOR_GREEN(col); palette[i].blue = COLOR_BLUE(col); } } png_set_PLTE(png_ptr, info_ptr, palette, num_palette); if ( num_palette<=16 ) png_set_packing(png_ptr); if ( base->trans!=-1 ) { trans_alpha = (png_bytep) galloc(1); trans_alpha[0] = base->trans; } } else { if ( base->trans!=-1 ) { trans_color = (png_color_16p) galloc(sizeof(png_color_16)); trans_color->red = COLOR_RED(base->trans); trans_color->green = COLOR_GREEN(base->trans); trans_color->blue = COLOR_BLUE(base->trans); } } if ( base->trans!=-1 ) { png_set_tRNS(png_ptr, info_ptr, trans_alpha, 1, trans_color); } png_write_info(png_ptr, info_ptr); if (color_type == PNG_COLOR_TYPE_RGB) png_set_filler(png_ptr, '\0', PNG_FILLER_BEFORE); rows = (png_byte **) galloc(base->height*sizeof(png_byte *)); for ( i=0; i<base->height; ++i ) rows[i] = (png_byte *) (base->data + i*base->bytes_per_line); png_write_image(png_ptr,rows); png_write_end(png_ptr, info_ptr); if ( trans_alpha!=NULL ) gfree(trans_alpha); if ( trans_color!=NULL ) gfree(trans_color); if ( palette!=NULL ) gfree(palette); png_destroy_write_struct(&png_ptr, &info_ptr); gfree(rows); return( 1 ); }
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; png_set_sRGB_gAMA_and_cHRM (png, info, PNG_sRGB_INTENT_RELATIVE); } 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; }
template<typename T> void encodeImageToPNG (typename std::vector<T>& image_arg, size_t width_arg, size_t height_arg, int image_format_arg, typename std::vector<uint8_t>& pngData_arg, int png_level_arg) { png_structp png_ptr; png_infop info_ptr; volatile int channels; if (image_arg.size () ==0) return; // Get amount of channels switch (image_format_arg) { case PNG_COLOR_TYPE_GRAY: channels = 1; break; case PNG_COLOR_TYPE_GRAY_ALPHA: channels = 2; break; case PNG_COLOR_TYPE_RGB: channels = 3; break; case PNG_COLOR_TYPE_RGB_ALPHA: channels = 4; break; default: channels = 0; break; } // Ensure valid input array assert (image_arg.size () == width_arg*height_arg*channels); // Initialize write structure png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); assert (png_ptr && "creating png_create_write_structpng_create_write_struct failed"); // Initialize info structure info_ptr = png_create_info_struct (png_ptr); assert (info_ptr && "Could not allocate info struct"); // Setup Exception handling setjmp(png_jmpbuf(png_ptr)); // reserve memory for output data (300kB) pngData_arg.clear (); pngData_arg.reserve (300 * 1024); // Define I/O methods png_set_write_fn (png_ptr, reinterpret_cast<void*> (&pngData_arg), user_write_data, user_flush_data); // Define zlib compression level if (png_level_arg >= 0) { png_set_compression_level (png_ptr, png_level_arg); } else { png_set_compression_level (png_ptr, Z_DEFAULT_COMPRESSION); } // Write header png_set_IHDR (png_ptr, info_ptr, width_arg, height_arg, sizeof(T) * 8, image_format_arg, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info (png_ptr, info_ptr); // Write image data size_t y; for (y = 0; y < height_arg; y++) { png_write_row (png_ptr, reinterpret_cast<png_bytep> (&image_arg[y * width_arg * channels])); } // End write png_write_end (png_ptr, 0); if (info_ptr) png_free_data (png_ptr, info_ptr, PNG_FREE_ALL, -1); if (png_ptr) png_destroy_write_struct (&png_ptr, 0); }
int write_PNG(char *filename, int interlace, char borfb) { //hardcore theft from fbgrab.c /* * fbgrab - takes screenshots using the framebuffer. * * (C) Gunnar Monell <*****@*****.**> 2002 * * This program is free Software, see the COPYING file * and is based on Stephan Beyer's <*****@*****.**> FBShot * (C) 2000. * * For features and differences, read the manual page. * * This program has been checked with "splint +posixlib" without * warnings. Splint is available from http://www.splint.org/ . * Patches and enhancements of fbgrab have to fulfill this too. */ png_uint_32 i; int bit_depth=0, color_type; png_uint_32 uheight, uwidth; uheight = (png_uint_32)height; uwidth = (png_uint_32)width; png_bytep row_pointers[uheight]; png_structp png_ptr; png_infop info_ptr; FILE *outfile = fopen(filename, "wb"); interlace = PNG_INTERLACE_NONE; //printf ("%d, %d\n", uheight, uwidth); //well, either from the buffer or the framebuffer... //yih, gotta clean this one up, reallyyyyy // if (borfb == 0) for (i=0; i<uheight; i++) row_pointers[i] = (unsigned char *)(fbp + (BPP*Ox) + (Oy + i) * 1 * (finfo.line_length/*uwidth+10*/)); if (borfb == 1) for (i=0; i<uheight; i++) row_pointers[i] = (unsigned char *)(tmp_buf + (BPP*Ox) + (Oy + i) * 1 * (finfo.line_length/*uwidth+10*/)); if (!outfile){ fprintf (stderr, "Error: Couldn't fopen %s.\n", filename); return -1; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, (png_error_ptr) NULL, (png_error_ptr) NULL); if (!png_ptr){ fprintf(stderr,"Error: Couldn't create PNG write struct."); return -1; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr){ png_destroy_write_struct(&png_ptr, (png_infopp) NULL); fprintf(stderr, "Error: Couldn't create PNG info struct."); return -1; } if (setjmp(png_jmpbuf(png_ptr))){ fclose(outfile); png_destroy_write_struct(&png_ptr, &info_ptr); return -2; } png_init_io(png_ptr, outfile); //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); bit_depth = 8; color_type = PNG_COLOR_TYPE_RGB_ALPHA; png_set_IHDR(png_ptr, info_ptr, uwidth, uheight, bit_depth, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); //png_set_packing(png_ptr); png_set_invert_alpha(png_ptr); // //png_set function must be after set_IHDR //according to libpng-manual png_set_filter(png_ptr, 0, PNG_FILTER_NONE); png_set_filler(png_ptr, 0 , PNG_FILLER_BEFORE); png_set_bgr(png_ptr); png_write_info(png_ptr, info_ptr); //printf ("Now writing PNG file\n"); png_write_image(png_ptr, row_pointers); //png_write_rows(png_ptr, row_pointers, uheight); png_write_end(png_ptr, info_ptr); //puh, done, now freeing memory... png_destroy_write_struct(&png_ptr, &info_ptr); if (outfile != NULL) (void) fclose(outfile); //printf("Done writing...\n"); return 0; }
void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags, float fps, Bit8u * data, Bit8u * pal) { #if (C_SSHOT) Bitu i; Bit8u doubleRow[SCALER_MAXWIDTH*4]; Bitu countWidth = width; if (flags & CAPTURE_FLAG_DBLH) height *= 2; if (flags & CAPTURE_FLAG_DBLW) width *= 2; if (height > SCALER_MAXHEIGHT) return; if (width > SCALER_MAXWIDTH) return; if (CaptureState & CAPTURE_IMAGE) { png_structp png_ptr; png_infop info_ptr; png_color palette[256]; CaptureState &= ~CAPTURE_IMAGE; /* Open the actual file */ FILE * fp=OpenCaptureFile("Screenshot",".png"); if (!fp) goto skip_shot; /* First try to allocate the png structures */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL); if (!png_ptr) goto skip_shot; info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr,(png_infopp)NULL); goto skip_shot; } /* Finalize the initing of png library */ png_init_io(png_ptr, fp); 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_compression_buffer_size(png_ptr, 8192); if (bpp==8) { png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); for (i=0;i<256;i++) { palette[i].red=pal[i*4+0]; palette[i].green=pal[i*4+1]; palette[i].blue=pal[i*4+2]; } png_set_PLTE(png_ptr, info_ptr, palette,256); } else { png_set_bgr( png_ptr ); 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); } #ifdef PNG_TEXT_SUPPORTED int fields = 1; png_text text[1]; const char* text_s = "DOSBox " VERSION; size_t strl = strlen(text_s); char* ptext_s = new char[strl + 1]; strcpy(ptext_s, text_s); char software[9] = { 'S','o','f','t','w','a','r','e',0}; text[0].compression = PNG_TEXT_COMPRESSION_NONE; text[0].key = software; text[0].text = ptext_s; png_set_text(png_ptr, info_ptr, text, fields); #endif png_write_info(png_ptr, info_ptr); #ifdef PNG_TEXT_SUPPORTED delete [] ptext_s; #endif for (i=0;i<height;i++) { void *rowPointer; void *srcLine; if (flags & CAPTURE_FLAG_DBLH) srcLine=(data+(i >> 1)*pitch); else srcLine=(data+(i >> 0)*pitch); rowPointer=srcLine; switch (bpp) { case 8: if (flags & CAPTURE_FLAG_DBLW) { for (Bitu x=0;x<countWidth;x++) doubleRow[x*2+0] = doubleRow[x*2+1] = ((Bit8u *)srcLine)[x]; rowPointer = doubleRow; } break; case 15: if (flags & CAPTURE_FLAG_DBLW) { for (Bitu x=0;x<countWidth;x++) { Bitu pixel = ((Bit16u *)srcLine)[x]; doubleRow[x*6+0] = doubleRow[x*6+3] = ((pixel& 0x001f) * 0x21) >> 2; doubleRow[x*6+1] = doubleRow[x*6+4] = ((pixel& 0x03e0) * 0x21) >> 7; doubleRow[x*6+2] = doubleRow[x*6+5] = ((pixel& 0x7c00) * 0x21) >> 12; } } else { for (Bitu x=0;x<countWidth;x++) { Bitu pixel = ((Bit16u *)srcLine)[x]; doubleRow[x*3+0] = ((pixel& 0x001f) * 0x21) >> 2; doubleRow[x*3+1] = ((pixel& 0x03e0) * 0x21) >> 7; doubleRow[x*3+2] = ((pixel& 0x7c00) * 0x21) >> 12; } } rowPointer = doubleRow; break; case 16: if (flags & CAPTURE_FLAG_DBLW) { for (Bitu x=0;x<countWidth;x++) { Bitu pixel = ((Bit16u *)srcLine)[x]; doubleRow[x*6+0] = doubleRow[x*6+3] = ((pixel& 0x001f) * 0x21) >> 2; doubleRow[x*6+1] = doubleRow[x*6+4] = ((pixel& 0x07e0) * 0x41) >> 9; doubleRow[x*6+2] = doubleRow[x*6+5] = ((pixel& 0xf800) * 0x21) >> 13; } } else { for (Bitu x=0;x<countWidth;x++) {
int convertToPNG(AbstractFile* imageWrapper, const unsigned int* key, const unsigned int* iv, const char* png) { AbstractFile* imageFile; FILE *fp = fopen(png, "wb"); if(!fp) return -1; if(key != NULL) { imageFile = openAbstractFile2(imageWrapper, key, iv); } else { imageFile = openAbstractFile(imageWrapper); } InfoIBootIM* info = (InfoIBootIM*) (imageFile->data); png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, pngError, pngWarn); if (!png_ptr) { return -1; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return -1; } png_init_io(png_ptr, fp); int color_type; int bytes_per_pixel; if(info->header.format == IBOOTIM_ARGB) { XLOG(3, "ARGB"); color_type = PNG_COLOR_TYPE_RGB_ALPHA; bytes_per_pixel = 4; } else if(info->header.format == IBOOTIM_GREY) { XLOG(3, "Grayscale"); color_type = PNG_COLOR_TYPE_GRAY_ALPHA; bytes_per_pixel = 2; } else { XLOG(3, "Unknown color type!"); } png_set_IHDR(png_ptr, info_ptr, info->header.width, info->header.height, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_bgr(png_ptr); png_set_invert_alpha(png_ptr); png_write_info(png_ptr, info_ptr); void* imageBuffer = malloc(imageFile->getLength(imageFile)); imageFile->read(imageFile, imageBuffer, imageFile->getLength(imageFile)); png_bytepp row_pointers = (png_bytepp) malloc(sizeof(png_bytep) * info->header.height); int i; for(i = 0; i < png_get_image_height(png_ptr, info_ptr); i++) { row_pointers[i] = imageBuffer + (info->header.width * bytes_per_pixel * i); } png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, NULL); free(imageBuffer); return 0; }
UT_Error IE_ImpGraphic_BMP::Convert_BMP(UT_ByteBuf* pBB) { /* Reset error handling for libpng */ if (setjmp(png_jmpbuf(m_pPNG))) { png_destroy_write_struct(&m_pPNG, &m_pPNGInfo); return UT_ERROR; } png_write_info(m_pPNG,m_pPNGInfo); const UT_Byte* row_data; UT_sint32 row; UT_uint32 position; UT_uint32 row_width = m_iWidth * m_iBitsPerPlane / 8; while ((row_width & 3) != 0) row_width++; UT_Byte* row_transformed_data = new UT_Byte[row_width]; switch (m_iBitsPerPlane) { case 1: case 4: case 8: case 16: for (row=m_iHeight-1; row >= 0; row--) { /* Calculating the start of each row */ position=m_iOffset + row*row_width; row_data = reinterpret_cast<const unsigned char *>(pBB->getPointer(position)); png_write_rows(m_pPNG,const_cast<png_byte **>(reinterpret_cast<const png_byte **>(&row_data)),1); } break; case 24: case 48: for (row=m_iHeight-1; row >= 0; row--) { /* Calculating the start of each row */ position=m_iOffset + row*row_width; /* Transforming the b/r to r/b */ for (UT_sint32 i=0, col=0; i < m_iWidth; i++,col+=3) { row_transformed_data[col+0] = (UT_Byte)*pBB->getPointer(position+col+2); row_transformed_data[col+1] = (UT_Byte)*pBB->getPointer(position+col+1); row_transformed_data[col+2] = (UT_Byte)*pBB->getPointer(position+col+0); } png_write_rows(m_pPNG,&row_transformed_data,1); } break; case 32: case 64: for (row=m_iHeight-1; row >= 0; row--) { /* Calculating the start of each row */ position=m_iOffset + row*row_width; /* Transforming the b/r to r/b */ for (UT_sint32 i=0, col=0; i < m_iWidth; i++,col+=4) { row_transformed_data[col+0] = (UT_Byte)*pBB->getPointer(position+col+2); row_transformed_data[col+1] = (UT_Byte)*pBB->getPointer(position+col+1); row_transformed_data[col+2] = (UT_Byte)*pBB->getPointer(position+col+0); row_transformed_data[col+3] = (UT_Byte)*pBB->getPointer(position+col+3); } png_write_rows(m_pPNG,&row_transformed_data,1); } break; default: return UT_IE_BOGUSDOCUMENT; break; } delete [] row_transformed_data; png_write_end(m_pPNG,m_pPNGInfo); return UT_OK; }
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); }
void write_png( ImgGray *img, const char *filename ) { int width = img->Width(); int height = img->Height(); int bit_depth = 8; int color_type = PNG_COLOR_TYPE_GRAY; // to be changed to the correct value! /* create file */ FILE *fp = fopen(filename, "wb"); if (!fp) { dbg(DBG_ERROR,"[write_png_file] File %s could not be opened for writing", filename); return; } /* initialize stuff */ png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { dbg(DBG_ERROR,"[write_png_file] png_create_write_struct failed"); return; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { dbg(DBG_ERROR,"[write_png_file] png_create_info_struct failed"); return; } if (setjmp(png_jmpbuf(png_ptr))) dbg(DBG_ERROR,"[write_png_file] Error during init_io"); png_init_io(png_ptr, fp); /* write header */ if (setjmp(png_jmpbuf(png_ptr))) dbg(DBG_ERROR,"[write_png_file] Error during writing header"); png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); int x,y; png_bytep *row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height); for (y=0; y<height; y++) { row_pointers[y] = (png_byte*) malloc(width*sizeof(png_byte)); for (x=0;x<width;x++) { row_pointers[y][x] = (png_byte)(img->GetPixel(x,y)); } } /* write bytes */ if (setjmp(png_jmpbuf(png_ptr))) dbg(DBG_ERROR,"[write_png_file] Error during writing bytes"); png_write_image(png_ptr, row_pointers); /* end write */ if (setjmp(png_jmpbuf(png_ptr))) dbg(DBG_ERROR,"[write_png_file] Error during end of write"); png_write_end(png_ptr, NULL); /* cleanup heap allocation */ for (y=0; y<height; y++) { free( row_pointers[y]); } free( row_pointers ); fclose(fp); }
//-------------------------------------------------------------------------- static bool _writePNG(GBitmap *bitmap, Stream &stream, U32 compressionLevel, U32 strategy, U32 filter) { GFXFormat format = bitmap->getFormat(); // ONLY RGB bitmap writing supported at this time! AssertFatal( format == GFXFormatR8G8B8 || format == GFXFormatR8G8B8A8 || format == GFXFormatR8G8B8X8 || format == GFXFormatA8 || format == GFXFormatR5G6B5, "_writePNG: ONLY RGB bitmap writing supported at this time."); if ( format != GFXFormatR8G8B8 && format != GFXFormatR8G8B8A8 && format != GFXFormatR8G8B8X8 && format != GFXFormatA8 && format != GFXFormatR5G6B5 ) return false; png_structp png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, pngFatalErrorFn, pngWarningFn, NULL, pngMallocFn, pngFreeFn); if (png_ptr == NULL) 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); return false; } png_set_write_fn(png_ptr, &stream, pngWriteDataFn, pngFlushDataFn); // Set the compression level and image filters png_set_compression_window_bits(png_ptr, 15); png_set_compression_level(png_ptr, compressionLevel); png_set_filter(png_ptr, 0, filter); // 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 U32 width = bitmap->getWidth(); U32 height = bitmap->getHeight(); if (format == GFXFormatR8G8B8) { png_set_IHDR(png_ptr, info_ptr, width, height, // the width & height 8, PNG_COLOR_TYPE_RGB, // bit_depth, color_type, NULL, // no interlace NULL, // compression type NULL); // filter type } else if (format == GFXFormatR8G8B8A8 || format == GFXFormatR8G8B8X8) { png_set_IHDR(png_ptr, info_ptr, width, height, // the width & height 8, PNG_COLOR_TYPE_RGB_ALPHA, // bit_depth, color_type, NULL, // no interlace NULL, // compression type NULL); // filter type } else if (format == GFXFormatA8) { png_set_IHDR(png_ptr, info_ptr, width, height, // the width & height 8, PNG_COLOR_TYPE_GRAY, // bit_depth, color_type, NULL, // no interlace NULL, // compression type NULL); // filter type } else if (format == GFXFormatR5G6B5) { png_set_IHDR(png_ptr, info_ptr, width, height, // the width & height 16, PNG_COLOR_TYPE_GRAY, // bit_depth, color_type, PNG_INTERLACE_NONE, // no interlace PNG_COMPRESSION_TYPE_DEFAULT, // compression type PNG_FILTER_TYPE_DEFAULT); // filter type png_color_8_struct sigBit = { 0 }; sigBit.gray = 16; png_set_sBIT(png_ptr, info_ptr, &sigBit ); png_set_swap( png_ptr ); } png_write_info(png_ptr, info_ptr); FrameAllocatorMarker marker; png_bytep* row_pointers = (png_bytep*)marker.alloc( height * sizeof( png_bytep ) ); for (U32 i=0; i<height; i++) row_pointers[i] = const_cast<png_bytep>(bitmap->getAddress(0, i)); png_write_image(png_ptr, row_pointers); // Write S3TC data if present... // Write FXT1 data if present... png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return true; }