//saves the given SDL structure into a given filename. void save_image(surface surf, const std::string &filename) { //opens the actual file const util::scoped_FILE file(fopen(filename.c_str(),"wb")); //initializes PNG write structures //TODO: review whether providing NULL error handlers is something //sensible png_struct* png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, reinterpret_cast<png_voidp>(png_voidp_NULL), png_error_ptr_NULL, png_error_ptr_NULL); if(!png_ptr) throw exploder_failure("Unable to initialize the png write structure"); png_info* info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_write_struct(&png_ptr, static_cast<png_infopp>(NULL)); throw exploder_failure("Unable to initialize the png info structure"); } //instructs the PNG library to use the open file png_init_io(png_ptr, file); //sets compression level to the maximum png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); //configures the header png_set_IHDR(png_ptr, info_ptr, surf->w, surf->h, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); //puts the actual image data in the row_pointers array png_byte **row_pointers = new png_byte *[surf->h]; surface_lock lock(surf); //converts the data to the RGBA format. We cannot pass SDL data //directly to the png lib, even if we know its pixel format, because of //endianness problems. util::scoped_array<rgba> rgba_data(new rgba[surf->w * surf->h]); Uint32 *surf_data = lock.pixels(); int pos = 0; for(int y = 0; y < surf->h; ++y) { row_pointers[y] = reinterpret_cast<png_byte*>(rgba_data + pos); for(int x = 0; x < surf->w; ++x) { Uint8 red, green, blue, alpha; SDL_GetRGBA(*surf_data, surf->format, &red, &green, &blue, &alpha); rgba_data[pos].r = red; rgba_data[pos].g = green; rgba_data[pos].b = blue; rgba_data[pos].a = alpha; pos++; surf_data++; } } png_set_rows(png_ptr, info_ptr, row_pointers); //writes the actual image data png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); //cleans everything png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); delete [] row_pointers; }
/* Save the two dimensional array as a png image */ int save_png(double *data, const int nx, const int ny, const char *fname) { FILE *fp; png_structp pngstruct_ptr = NULL; png_infop pnginfo_ptr = NULL; png_byte **row_pointers = NULL; int i, j; /* Default return status is failure */ int status = -1; int pixel_size = 3; int depth = 8; if ((fp = fopen(fname, "wb")) != NULL) { pngstruct_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (pngstruct_ptr != NULL) { pnginfo_ptr = png_create_info_struct(pngstruct_ptr); if (pnginfo_ptr != NULL) { if (!setjmp(png_jmpbuf(pngstruct_ptr))) { png_set_IHDR(pngstruct_ptr, pnginfo_ptr, (size_t) ny, (size_t) nx, depth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); row_pointers = png_malloc(pngstruct_ptr, ny * sizeof(png_byte *)); for (i = 0; i < nx; i++) { png_byte *row = png_malloc(pngstruct_ptr, sizeof(uint8_t) * ny * pixel_size); row_pointers[i] = row; for (j = 0; j < ny; j++) { pixel_t pixel; // Scale the values so that values between // 0 and 100 degrees are mapped to values // between 0 and 255 cmap(data[j + i * ny], 2.55, 0.0, &pixel); *row++ = pixel.red; *row++ = pixel.green; *row++ = pixel.blue; } } png_init_io(pngstruct_ptr, fp); png_set_rows(pngstruct_ptr, pnginfo_ptr, row_pointers); png_write_png(pngstruct_ptr, pnginfo_ptr, PNG_TRANSFORM_IDENTITY, NULL); status = 0; for (i = 0; i < ny; i++) { png_free(pngstruct_ptr, row_pointers[i]); } png_free(pngstruct_ptr, row_pointers); } } png_destroy_write_struct(&pngstruct_ptr, &pnginfo_ptr); } fclose(fp); } return status; }
//void save_png(GLfloat* pix) void save_png(GLuint* pix, int width, int height) { FILE * fp; png_structp png_ptr = NULL; png_infop info_ptr = NULL; size_t x, y; png_byte ** row_pointers = NULL; /* "status" contains the return value of this function. At first it is set to a value which means 'failure'. When the routine has finished its work, it is set to a value which means 'success'. */ int status = -1; /* The following number is set by trial and error only. I cannot see where it it is documented in the libpng manual. */ int pixel_size = 3; int depth = 8; fp = fopen ("testdepth.png", "wb"); if (! fp) { printf("cannot open\n"); return; } png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { printf("error 0\n"); return; } info_ptr = png_create_info_struct (png_ptr); if (info_ptr == NULL) { printf("error 1\n"); return; } /* Set up error handling. */ if (setjmp (png_jmpbuf (png_ptr))) { printf("error 2\n"); return; } /* Set image attributes. */ //int width = 1200; //int height = 400; png_set_IHDR (png_ptr, info_ptr, width, height, depth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Initialize rows of PNG. */ row_pointers = png_malloc (png_ptr, height * sizeof (png_byte *)); for (y = 0; y < height; ++y) { png_byte *row = png_malloc (png_ptr, sizeof (uint8_t) * width * pixel_size); row_pointers[y] = row; for (x = 0; x < width; ++x) { //float f = pix[y*width +x]*255; //float f = (pix[y*width +x]>>8) / 16777215.0f * 255.0f ; //float f = (pix[y*width +x]>>8); //float f = (pix[y*width +x]>>8) / 65536.0f * 255.0f ; float f = (pix[y*width +x]&0xff)*255; //float f = (pix[y*width +x]&0xff); uint32_t utest = (pix[y*width +x]&0xff); if (y*width +x == 0) { //printf(" the value u : %u \n", pix[0]&0xff); printf(" the value f : %f \n", f); printf(" the value utest : %x \n", utest); } pixel_t yep = { f,f,f}; pixel_t * pixel = &yep; *row++ = pixel->red; *row++ = pixel->green; *row++ = pixel->blue; } } /* Write the image data to "fp". */ png_init_io (png_ptr, fp); png_set_rows (png_ptr, info_ptr, row_pointers); png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); /* The routine has successfully written the file, so we set "status" to a value which indicates success. */ status = 0; for (y = 0; y < height; y++) { png_free (png_ptr, row_pointers[y]); } png_free (png_ptr, row_pointers); return; }
/** 保存指定图像的Mipmap @Param 要保存图像文件的路径 @Param 指向图像对象的指针 @Param 指定的Mipmap层级 */ void F3DPNGCodec::SaveMipmap( const char* filename,F3DImage* image,size_t level ) { FBYTE* destBuf; EPixelFormat destFormat; size_t destSize,pxSize; // 创建一个PNG文件 FVFile file; if( file.Open(filename,FVFile::VFILE_CREATENEW|FVFile::VFILE_BINARY) ) { FLOG_WARNINGF( "F3DPNGCodec::SaveMipMap, Create the PNG file (%s) failed!",filename ); return; } // 分配一个PNG写对象 png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); // 分配一个PNG信息结构体 png_infop info_ptr = png_create_info_struct( png_ptr ); if( setjmp(png_jmpbuf(png_ptr)) ) { png_destroy_write_struct( &png_ptr,&info_ptr ); FLOG_ERROR("F3DPNGCodec::SaveMipmap, An error occurs when writing..."); return; } // 设置PNG的写入回调函数 png_set_write_fn( png_ptr,&file,PNGWriteFunc,NULL ); // 获取源图像的一些信息 size_t width = image->GetWidth( level ); size_t height = image->GetHeight( level ); EPixelFormat srcFormat = image->GetPixelFormat(); if( F3D_HaveAlpha(srcFormat) ) destFormat = PFT_A8R8G8B8; else destFormat = PFT_R8G8B8; // 将数据转换为指定像素格式 pxSize = F3D_PixelSize( destFormat ); destSize = width*height*pxSize; destBuf = new FBYTE[destSize]; F3D_ConvertPixelFormat( image->GetImageData(level),srcFormat,destBuf,destFormat,width,height ); // 设置PNG图像的信息 if( destFormat == PFT_A8R8G8B8 ) { png_set_IHDR( png_ptr,info_ptr,(png_uint_32)image->GetWidth(level), (png_uint_32)image->GetHeight(level),8,PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT ); } else { png_set_IHDR( png_ptr,info_ptr,(png_uint_32)image->GetWidth(level), (png_uint_32)image->GetHeight(level),8,PNG_COLOR_TYPE_RGB,PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT ); } FBYTE** row_pointers = new png_bytep[height]; FBYTE* data = destBuf; for( size_t i=0;i<height;i++ ) { row_pointers[i] = data; data += width * pxSize; } if( setjmp(png_jmpbuf(png_ptr)) ) { png_destroy_write_struct( &png_ptr,&info_ptr ); delete[] row_pointers; delete[] destBuf; FLOG_ERROR("F3DPNGCodec::SaveMipmap, An error occurs when writing..."); return; } png_set_rows( png_ptr,info_ptr,row_pointers ); if( destFormat == PFT_A8R8G8B8 ) png_write_png( png_ptr,info_ptr,PNG_TRANSFORM_BGR,NULL ); else png_write_png( png_ptr,info_ptr,PNG_TRANSFORM_IDENTITY,NULL ); // 关闭PNG文件 png_destroy_write_struct( &png_ptr,&info_ptr ); file.Close(); delete[] row_pointers; delete[] destBuf; }
bool CImageWriterPNG::writeImage(io::IWriteFile* file, IImage* image,u32 param) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ if (!file || !image) return false; // Allocate the png write struct png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)png_cpexcept_error, NULL); if (!png_ptr) { os::Printer::log("PNGWriter: Internal PNG create write struct failure\n", file->getFileName(), ELL_ERROR); return false; } // Allocate the png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { os::Printer::log("PNGWriter: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR); png_destroy_write_struct(&png_ptr, NULL); return false; } // for proper error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); return false; } png_set_write_fn(png_ptr, file, user_write_data_fcn, NULL); // Set info switch(image->getColorFormat()) { case ECF_A8R8G8B8: case ECF_A1R5G5B5: png_set_IHDR(png_ptr, info_ptr, image->getDimension().Width, image->getDimension().Height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); break; default: png_set_IHDR(png_ptr, info_ptr, image->getDimension().Width, image->getDimension().Height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } s32 lineWidth=image->getDimension().Width; switch(image->getColorFormat()) { case ECF_R8G8B8: case ECF_R5G6B5: lineWidth*=3; break; case ECF_A8R8G8B8: case ECF_A1R5G5B5: lineWidth*=4; break; } u8* tmpImage = new u8[image->getDimension().Height*lineWidth]; if (!tmpImage) { os::Printer::log("PNGWriter: Internal PNG create image failure\n", file->getFileName(), ELL_ERROR); png_destroy_write_struct(&png_ptr, &info_ptr); return false; } u8* data = (u8*)image->lock(); switch(image->getColorFormat()) { case ECF_R8G8B8: CColorConverter::convert_R8G8B8toR8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage); break; case ECF_A8R8G8B8: CColorConverter::convert_A8R8G8B8toA8R8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage); break; case ECF_R5G6B5: CColorConverter::convert_R5G6B5toR8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage); break; case ECF_A1R5G5B5: CColorConverter::convert_A1R5G5B5toA8R8G8B8(data,image->getDimension().Height*image->getDimension().Width,tmpImage); break; } image->unlock(); // Create array of pointers to rows in image data //Used to point to image rows u8** RowPointers = new png_bytep[image->getDimension().Height]; if (!RowPointers) { os::Printer::log("PNGWriter: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR); png_destroy_write_struct(&png_ptr, &info_ptr); delete [] tmpImage; return false; } data=tmpImage; // Fill array of pointers to rows in image data for (u32 i=0; i<image->getDimension().Height; ++i) { RowPointers[i]=data; data += lineWidth; } // for proper error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); delete [] RowPointers; delete [] tmpImage; return false; } png_set_rows(png_ptr, info_ptr, RowPointers); if (image->getColorFormat()==ECF_A8R8G8B8 || image->getColorFormat()==ECF_A1R5G5B5) png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, NULL); else { png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); } delete [] RowPointers; delete [] tmpImage; png_destroy_write_struct(&png_ptr, &info_ptr); return true; #else return false; #endif }
// lecture de l'image... void VideoGen::read_image() { char filename[1024]; //grmpf, il vaudrait mieux faire un malloc... FILE *file; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type; png_bytep *row_pointers; unsigned int i; // Calcul du nom de la prochaine image. // Si ce nom ne correspond a aucun fichier, on remet l'index a zero sprintf(filename, "%s%02d.png", base_name, current_image_number); // on désalloue l'espace mémoire occupé par l'image précédente if (image.pixel) free(image.pixel); image.pixel = NULL; // on ouvre l'image file = fopen(filename, "rb"); if(file == NULL) { // On reessaye la première image current_image_number = 0; sprintf(filename, "%s%02d.png", base_name, current_image_number); file = fopen(filename, "rb"); // Si la première image n'existe pas on quite if(file == NULL) { cerr << name() << " read_image : impossible d'ouvrir l'image source " << filename << endl; exit(-1); } } // Les structures de l'image png png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); assert((png_ptr != NULL) && "png_create_read_struct..."); info_ptr = png_create_info_struct(png_ptr); assert((info_ptr != NULL) && "png_create_info_struct..."); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(file); exit(-1); } png_init_io(png_ptr, file); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); assert((bit_depth == 8) && "bit_depth!=8"); if(color_type != PNG_COLOR_TYPE_GRAY) { cerr << name() << " Erreur sur le format de l'image d'entrée" << endl << "Le seul format PNG supporté est : " << "niveaux de gris, 8bpp, sans canal alpha" << endl; png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(file); exit(-1); } // on recupère la taille de l'image if(( width != p_WIDTH ) || ( height != p_HEIGHT )) { cerr << name() << " l'image " << filename << " n'a pas les bonnes dimensions (" << p_WIDTH << "x" << p_HEIGHT << ")"<< endl; exit(-1); } image.width = width; image.height = height; // on alloue l'espace necessaire à l'image image.pixel = (unsigned char *)malloc(width * height * sizeof(unsigned char)); assert( (image.pixel != NULL) && "alloc image failed"); row_pointers = (png_bytep*) png_malloc(png_ptr, height * sizeof(png_bytep)); assert((row_pointers != NULL) && "row_pointer"); for (i = 0; i < height; i++) row_pointers[i] = (png_bytep)(&image.pixel[i*width]); png_set_rows(png_ptr, info_ptr, row_pointers); png_read_image(png_ptr, row_pointers); png_free(png_ptr, row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); #ifdef SOCLIB_MODULE_DEBUG cout << name() << " Lecture de l'image " << filename << endl; #endif fclose(file); }
/*! * 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 void internal_saveImage_PNG(const char *fileName, const iV_Image *image, int color_type) { unsigned char** scanlines = NULL; png_infop info_ptr = NULL; png_structp png_ptr = NULL; PHYSFS_file* fileHandle; ASSERT(image->depth != 0, "Bad depth"); fileHandle = PHYSFS_openWrite(fileName); if (fileHandle == NULL) { debug(LOG_ERROR, "pie_PNGSaveFile: PHYSFS_openWrite failed (while opening file %s) with error: %s\n", fileName, PHYSFS_getLastError()); return; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { debug(LOG_ERROR, "pie_PNGSaveFile: Unable to create png struct\n"); PNGWriteCleanup(&info_ptr, &png_ptr, fileHandle); return; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { debug(LOG_ERROR, "pie_PNGSaveFile: Unable to create png info struct\n"); PNGWriteCleanup(&info_ptr, &png_ptr, fileHandle); return; } // If libpng encounters an error, it will jump into this if-branch if (setjmp(png_jmpbuf(png_ptr))) { debug(LOG_ERROR, "pie_PNGSaveFile: Error encoding PNG data\n"); } else { unsigned int channelsPerPixel = 3; unsigned int currentRow, row_stride; if (color_type == PNG_COLOR_TYPE_GRAY) { channelsPerPixel = 1; } row_stride = image->width * channelsPerPixel * image->depth / 8; scanlines = (unsigned char **)malloc(sizeof(unsigned char *) * image->height); if (scanlines == NULL) { debug(LOG_ERROR, "pie_PNGSaveFile: Couldn't allocate memory\n"); PNGWriteCleanup(&info_ptr, &png_ptr, fileHandle); return; } png_set_write_fn(png_ptr, fileHandle, wzpng_write_data, wzpng_flush_data); // Set the compression level of ZLIB // Right now we stick with the default, since that one is the // fastest which still produces acceptable filesizes. // The highest compression level hardly produces smaller files than default. // // Below are some benchmarks done while taking screenshots at 1280x1024 // Z_NO_COMPRESSION: // black (except for GUI): 398 msec // 381, 391, 404, 360 msec // // Z_BEST_SPEED: // black (except for GUI): 325 msec // 611, 406, 461, 608 msec // // Z_DEFAULT_COMPRESSION: // black (except for GUI): 374 msec // 1154, 1121, 627, 790 msec // // Z_BEST_COMPRESSION: // black (except for GUI): 439 msec // 1600, 1078, 1613, 1700 msec // Not calling this function is equal to using the default // so to spare some CPU cycles we comment this out. // png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION); png_set_IHDR(png_ptr, info_ptr, image->width, image->height, image->depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); // Create an array of scanlines for (currentRow = 0; currentRow < image->height; ++currentRow) { // We're filling the scanline from the bottom up here, // otherwise we'd have a vertically mirrored image. scanlines[currentRow] = &image->bmp[row_stride * (image->height - currentRow - 1)]; } png_set_rows(png_ptr, info_ptr, (png_bytepp)scanlines); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); } free(scanlines); PNGWriteCleanup(&info_ptr, &png_ptr, fileHandle); }
/* Dump an image to a Portable Network Graphics (PNG) file. File_name is where the file goes, i_height and i_width are the height and width in pixels of the image. The data for the image is stored as a linear array of one byte for each of red, green, and blue components of an RGB pixel. Thus row[i] will begin at rgb_image + i*(i_width*3) and the blue pixel at image[i][0] would be rgb_image + i*(i_width*3) + 1. */ void write_png(const char *file_name, png_uint_32 i_height, png_uint_32 i_width, void *rgb_image, /*in*/ png_text *text_ptr, int i_text_count ) { FILE *fp; png_structp png_ptr; png_infop info_ptr; png_color_8 sig_bit; png_bytep *row_pointers; unsigned int i,j; /* open the file */ fp = fopen(file_name, "wb"); if (fp == NULL) return; /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also check that * the library version is compatible with the one used at compile time, * in case we are using dynamically linked libraries. REQUIRED. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, user_error_fn, user_warning_fn); if (png_ptr == NULL) { fclose(fp); return; } /* Allocate/initialize the image information data. REQUIRED */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return; } /* Set error handling. REQUIRED if you aren't supplying your own * error handling functions in the png_create_write_struct() call. */ if (setjmp(png_ptr->jmpbuf)) { /* If we get here, we had a problem writing the file */ fclose(fp); png_destroy_write_struct(&png_ptr, (png_infopp) &info_ptr); return; } /* Set up the output control using standard C streams. This is required. */ png_init_io(png_ptr, fp); /* Set the image information here. i_width and i_height are up to 2^31, * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED */ png_set_IHDR(png_ptr, info_ptr, i_width, i_height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* For color images: */ sig_bit.red = 8; sig_bit.green = 8; sig_bit.blue = 8; if (text_ptr) png_set_text(png_ptr, info_ptr, text_ptr, i_text_count); /* Write the file header information. REQUIRED */ png_write_info(png_ptr, info_ptr); /* Once we write out the header, the compression type on the text * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again * at the end. */ /* Shift the pixels up to a legal bit depth and fill in * as appropriate to correctly scale the image. */ png_set_shift(png_ptr, &sig_bit); /* pack pixels into bytes */ png_set_packing(png_ptr); row_pointers = png_malloc(png_ptr, i_height*sizeof(png_bytep *)); for (i=0, j=0; i<i_height; i++, j+=i_width*3) { row_pointers[i] = rgb_image + j; } png_set_rows (png_ptr, info_ptr, row_pointers); png_write_image(png_ptr, row_pointers); /* You can write optional chunks like tEXt, zTXt, and tIME at the end * as well. */ /* It is REQUIRED to call this to finish writing the rest of the file */ png_write_end(png_ptr, info_ptr); /* if you allocated any text comments, free them here */ /* free image data if allocated. */ /* clean up after the write, and free any memory allocated */ png_destroy_info_struct(png_ptr, &info_ptr); /* clean up after the write, and free any memory allocated */ png_destroy_write_struct(&png_ptr, (png_infopp)NULL); fclose(fp); return; }
int writepng(const void * buffer, char * filename, int width, int height) { // Open a file to write the png for FILE * fp = fopen(filename, "wb"); if (!fp) { fprintf(stderr, "capture: Couln't open output file \"%s\"", filename); return 1; } // Initialize PNG write structure png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fprintf(stderr, "capture: Can't initialize png_ptr"); return 1; } // Initialize PNG info pointer png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp) NULL); fprintf(stderr, "capture: Can't initialze info_ptr"); return 1; } // Initialize PNG error jump if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); fprintf(stderr, "capture: Unknown error"); return 1; } // Give PNG the file handle png_init_io(png_ptr, fp); // Set PNG Header png_set_IHDR(png_ptr, info_ptr, width, // Width height, // Height 8, // Bit depth PNG_COLOR_TYPE_RGB_ALPHA, // Color type PNG_INTERLACE_NONE, // Interlacing PNG_COMPRESSION_TYPE_DEFAULT, // Compression PNG_FILTER_TYPE_DEFAULT); // Filter method // Allocate a pointer to an array of png_byte pointers png_bytep * row_pointers = png_malloc(png_ptr, height * png_sizeof(png_bytep)); // OpenGL stores pixel data in row major format, from bottom of image to top. // PNG's are stored row major, top to bottom. int i; for (i = 0; i < height; ++i) row_pointers[i] = &((png_bytep) buffer)[(height - i - 1) * width * 4]; // Set the rows png_set_rows(png_ptr, info_ptr, row_pointers); // Write the png png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); free(row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return 0; } // writepng()
void Metafile::toPNG(PMEMPNG accum, int width, int height, const char *px){ bitmap_t bmStore; bitmap_t *bitmap = &bmStore; accum->buffer=NULL; // PNG constructed in memory will end up here, caller must free(). accum->size=0; bitmap->pixels=(pixel_t *)px; bitmap->width = width; bitmap->height = height; png_structp png_ptr = NULL; png_infop info_ptr = NULL; size_t x, y; png_byte ** row_pointers = NULL; /* The following number is set by trial and error only. I cannot see where it it is documented in the libpng manual. */ int pixel_size = 3; int depth = 8; png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL){ accum->buffer=NULL; return; } info_ptr = png_create_info_struct (png_ptr); if (info_ptr == NULL){ png_destroy_write_struct (&png_ptr, &info_ptr); accum->buffer=NULL; return; } /* Set up error handling. */ if (setjmp (png_jmpbuf (png_ptr))) { png_destroy_write_struct (&png_ptr, &info_ptr); accum->buffer=NULL; return; } /* Set image attributes. */ png_set_IHDR ( png_ptr, info_ptr, bitmap->width, bitmap->height, depth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); /* Initialize rows of PNG. */ row_pointers = (png_byte **) png_malloc (png_ptr, bitmap->height * sizeof (png_byte *)); for (y = 0; y < bitmap->height; ++y) { png_byte *row = (png_byte *) png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size); row_pointers[bitmap->height - y - 1] = row; // Row order in EMF is reversed. for (x = 0; x < bitmap->width; ++x) { pixel_t * pixel = pixel_at (bitmap, x, y); *row++ = pixel->red; // R & B channels were set correctly by DIB_to_RGB *row++ = pixel->green; *row++ = pixel->blue; } } /* Write the image data to memory */ png_set_rows (png_ptr, info_ptr, row_pointers); png_set_write_fn(png_ptr, accum, my_png_write_data, NULL); png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); for (y = 0; y < bitmap->height; y++) { png_free (png_ptr, row_pointers[y]); } png_free (png_ptr, row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); }
void impl_save_png ( const std::string& file_name, std::vector<unsigned char*>& row_pointers, const long width, const png_type type, const int bit_depth ) { FILE *fp; png_structp png_ptr; png_infop info_ptr; /* Open the file */ fp = fopen(file_name.c_str(), "wb"); if (fp == NULL) throw image_save_error("Unable to open " + file_name + " for writing."); /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also check that * the library version is compatible with the one used at compile time, * in case we are using dynamically linked libraries. REQUIRED. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &png_reader_user_error_fn_silent, &png_reader_user_warning_fn_silent); if (png_ptr == NULL) { fclose(fp); throw image_save_error("Error while writing PNG file " + file_name); } /* Allocate/initialize the image information data. REQUIRED */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_write_struct(&png_ptr, NULL); throw image_save_error("Error while writing PNG file " + file_name); } /* Set error handling. REQUIRED if you aren't supplying your own * error handling functions in the png_create_write_struct() call. */ if (setjmp(png_jmpbuf(png_ptr))) { /* If we get here, we had a problem writing the file */ fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); throw image_save_error("Error while writing PNG file " + file_name); } int color_type = 0; switch(type) { case png_type_rgb: color_type = PNG_COLOR_TYPE_RGB; break; case png_type_rgb_alpha: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break; case png_type_gray: color_type = PNG_COLOR_TYPE_GRAY; break; default: { fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); throw image_save_error("Invalid color type"); } } /* Set up the output control if you are using standard C streams */ png_init_io(png_ptr, fp); int png_transforms = PNG_TRANSFORM_IDENTITY; byte_orderer bo; if (bo.host_is_little_endian()) png_transforms |= PNG_TRANSFORM_SWAP_ENDIAN; const long height = row_pointers.size(); png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_rows(png_ptr, info_ptr, &row_pointers[0]); png_write_png(png_ptr, info_ptr, png_transforms, NULL); /* Clean up after the write, and free any memory allocated */ png_destroy_write_struct(&png_ptr, &info_ptr); /* Close the file */ fclose(fp); }
int filter_png(struct media_info const *info, int out_fd, int in_fd) { FILE *fp = fdopen(out_fd, "wb"); struct png_struct_def *png_ptr = NULL; struct png_info_def *png_info = NULL; volatile int rc = EX_SOFTWARE; png_bytep row_pointers[info->height]; void * volatile raw_data = NULL; void * volatile rgb_data = NULL; size_t rgb_stride = info->width * ((info->bpp + 7) / 8) * 3; if (!fp) { perror("fdopen()"); return EX_OSERR; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) goto out; if (setjmp(png_jmpbuf(png_ptr))) goto out; /* allocate memory for raw (YCbCr) image data */ raw_data = png_malloc(png_ptr, info->stride * info->height); if (!raw_data) goto out; rgb_data = png_malloc(png_ptr, rgb_stride * info->height); if (!rgb_data) goto out; for (size_t y = 0; y < info->height; ++y) row_pointers[y] = rgb_data + y * rgb_stride; png_info = png_create_info_struct(png_ptr); if (!png_info) goto out; png_init_io(png_ptr, fp); png_set_user_limits(png_ptr, info->width, info->height); png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); /* atm, only 8bpp support is implemented */ assert(info->bpp == 8); for (;;) { bool eof = false; if (read_all(in_fd, raw_data, info->stride * info->height, &eof)) ; /* noop */ else if (!eof) goto out; else break; convert_yuv422_rgb888(rgb_data, raw_data, info->bpp, info->width, info->height); png_set_rows(png_ptr, png_info, row_pointers); png_set_IHDR(png_ptr, png_info, info->width, info->height, info->bpp, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_png(png_ptr, png_info, PNG_TRANSFORM_IDENTITY, NULL); fflush(fp); break; } rc = 0; out: png_free(png_ptr, rgb_data); png_free(png_ptr, raw_data); png_destroy_write_struct(&png_ptr, &png_info); fclose(fp); return rc; }
int main(int argc, char **argv) { extern int optind; extern char *optarg; int i; char *outfile = NULL; int de = 0; while ((i = getopt(argc, argv, "o:d")) != -1) { switch (i) { case 'o': outfile = optarg; break; case 'd': de = 1; break; default: usage(argv); exit(EXIT_FAILURE); } } if (argc - optind != 1) { usage(argv); exit(EXIT_FAILURE); } if (outfile == NULL && isatty(1)) { fprintf(stderr, "Didn't specify -o and standard output is a terminal\n"); exit(EXIT_FAILURE); } FILE *outfp = stdout; if (outfile != NULL) { outfp = fopen(outfile, "wb"); if (outfp == NULL) { perror(outfile); exit(EXIT_FAILURE); } } int width, height; unsigned char *buf; { { { char *url = argv[optind]; CURL *curl = curl_easy_init(); if (curl == NULL) { fprintf(stderr, "Curl won't start\n"); exit(EXIT_FAILURE); } struct data data; data.buf = NULL; data.len = 0; data.nalloc = 0; curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_receive); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { fprintf(stderr, "Can't retrieve %s: %s\n", url, curl_easy_strerror(res)); exit(EXIT_FAILURE); } struct image *i; if (data.len >= 4 && memcmp(data.buf, "\x89PNG", 4) == 0) { i = read_png(data.buf, data.len); } else if (data.len >= 2 && memcmp(data.buf, "\xFF\xD8", 2) == 0) { i = read_jpeg(data.buf, data.len); } else { fprintf(stderr, "Don't recognize file format\n"); free(data.buf); curl_easy_cleanup(curl); exit(EXIT_FAILURE); } free(data.buf); curl_easy_cleanup(curl); width = i->width; height = i->height; buf = malloc(i->width * i->height * 4); int x, y; for (y = 0; y < i->height; y++) { for (x = 0; x < i->width; x++) { if (i->depth == 4) { double as = buf[((y) * width + x) * 4 + 3] / 255.0; double rs = buf[((y) * width + x) * 4 + 0] / 255.0 * as; double gs = buf[((y) * width + x) * 4 + 1] / 255.0 * as; double bs = buf[((y) * width + x) * 4 + 2] / 255.0 * as; double ad = i->buf[(y * i->width + x) * 4 + 3] / 255.0; double rd = i->buf[(y * i->width + x) * 4 + 0] / 255.0 * ad; double gd = i->buf[(y * i->width + x) * 4 + 1] / 255.0 * ad; double bd = i->buf[(y * i->width + x) * 4 + 2] / 255.0 * ad; // https://code.google.com/p/pulpcore/wiki/TutorialBlendModes double ar = as * (1 - ad) + ad; double rr = rs * (1 - ad) + rd; double gr = gs * (1 - ad) + gd; double br = bs * (1 - ad) + bd; buf[((y) * width + x) * 4 + 3] = ar * 255.0; buf[((y) * width + x) * 4 + 0] = rr / ar * 255.0; buf[((y) * width + x) * 4 + 1] = gr / ar * 255.0; buf[((y) * width + x) * 4 + 2] = br / ar * 255.0; } else if (i->depth == 3) { buf[((y) * width + x) * 4 + 0] = i->buf[(y * i->width + x) * 3 + 0]; buf[((y) * width + x) * 4 + 1] = i->buf[(y * i->width + x) * 3 + 1]; buf[((y) * width + x) * 4 + 2] = i->buf[(y * i->width + x) * 3 + 2]; buf[((y) * width + x) * 4 + 3] = 255; } else { buf[((y) * width) * 4 + 0] = i->buf[(y * i->width + x) * i->depth + 0]; buf[((y) * width) * 4 + 1] = i->buf[(y * i->width + x) * i->depth + 0]; buf[((y) * width) * 4 + 2] = i->buf[(y * i->width + x) * i->depth + 0]; buf[((y) * width) * 4 + 3] = 255; } } } free(i->buf); free(i); } } } unsigned char *rows[height]; for (i = 0; i < height; i++) { rows[i] = buf + i * (4 * width); } convert(buf, width, height, de); png_structp png_ptr; png_infop info_ptr; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, fail, fail, fail); if (png_ptr == NULL) { fprintf(stderr, "PNG failure (write struct)\n"); exit(EXIT_FAILURE); } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_write_struct(&png_ptr, NULL); fprintf(stderr, "PNG failure (info struct)\n"); exit(EXIT_FAILURE); } png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_rows(png_ptr, info_ptr, rows); png_init_io(png_ptr, outfp); png_write_png(png_ptr, info_ptr, 0, NULL); png_destroy_write_struct(&png_ptr, &info_ptr); if (outfile != NULL) { fclose(outfp); } return 0; }
int main(int argc, char **argv) { if (argc != 4) { fprintf(stderr, "usage: %s <input.png> <output_basename> <jpeg-quality>\n", *argv); return 1; } const char *infile = argv[1]; const char *outfile = argv[2]; int jpeg_quality = atoi(argv[3]); FILE *fpin = fopen(infile, "rb"); if (!fpin) { perror(infile); return 1; } unsigned char header[8]; fread(header, 1, 8, fpin); if (png_sig_cmp(header, 0, 8)) { fprintf(stderr, "this is not a PNG file\n"); fclose(fpin); return 1; } png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); assert(png_ptr); png_infop info_ptr = png_create_info_struct(png_ptr); assert(info_ptr); png_infop end_info = png_create_info_struct(png_ptr); assert (end_info); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fpin); fprintf(stderr, "failed.\n"); return 1; } png_init_io(png_ptr, fpin); png_set_sig_bytes(png_ptr, 8); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0); png_bytep * row_pointers = png_get_rows(png_ptr, info_ptr); png_uint_32 width, height; int bit_depth, color_type; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) { fprintf(stderr, "input PNG must be RGB+Alpha\n"); fclose(fpin); return 1; } if (bit_depth != 8) { fprintf(stderr, "input bit depth must be 8bit!\n"); fclose(fpin); return 1; } printf("png is %ldx%ld\n", width, height); int channels = png_get_channels(png_ptr, info_ptr); if (channels != 4) { fprintf(stderr, "channels must be 4.\n"); fclose(fpin); return 1; } fclose(fpin); /* now write jpeg */ struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW jrow_pointer[1]; FILE *outfp; char filename[strlen(outfile) + 10]; strcpy(filename, outfile); strcat(filename, ".rgb.jpg"); outfp = fopen(filename, "wb"); if (!outfp) { perror(filename); return 1; } cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, outfp); cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, jpeg_quality, 1); jpeg_start_compress(&cinfo, 1); unsigned char *row = malloc(width * 3); while (cinfo.next_scanline < cinfo.image_height) { int x; jrow_pointer[0] = row; unsigned char *source = row_pointers[cinfo.next_scanline]; for (x = 0; x < width; ++x) { row[x * 3 + 0] = source[0]; row[x * 3 + 1] = source[1]; row[x * 3 + 2] = source[2]; source += 4; } jpeg_write_scanlines(&cinfo, jrow_pointer, 1); } jpeg_finish_compress(&cinfo); fclose(outfp); jpeg_destroy_compress(&cinfo); /* and write png */ strcpy(filename, outfile); strcat(filename, ".a.png"); outfp = fopen(filename, "wb"); if (!outfp) { perror(filename); return 1; } png_structp png_ptr_w = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); png_infop info_ptr_w = png_create_info_struct(png_ptr_w); if (setjmp(png_jmpbuf(png_ptr_w))) { png_destroy_write_struct(&png_ptr_w, &info_ptr_w); fclose(outfp); return 1; } png_init_io(png_ptr_w, outfp); png_set_IHDR(png_ptr_w, info_ptr_w, width, height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* turn RGBA into A, in-place */ int x, y; for (y=0; y < height; ++y) { unsigned char *source = row_pointers[y]; unsigned char *dst = source; for (x=0; x < width; ++x) { *dst++ = source[3]; source += 4; } } png_set_rows(png_ptr_w, info_ptr_w, row_pointers); png_write_png(png_ptr_w, info_ptr_w, PNG_TRANSFORM_IDENTITY, 0); png_write_end(png_ptr_w, info_ptr_w); png_destroy_write_struct(&png_ptr_w, &info_ptr_w); fclose(outfp); return 0; }
void image_read(Image * image, char *filename) { FILE *file; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type; png_bytep *row_pointers; int i; if(image->pixel) free(image->pixel); image->pixel = NULL; file = fopen(filename, "rb"); assert(file != NULL); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); assert(png_ptr != NULL); info_ptr = png_create_info_struct(png_ptr); assert(info_ptr != NULL); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(file); exit(-1); } png_init_io(png_ptr, file); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); assert(bit_depth == 8); if(color_type != PNG_COLOR_TYPE_GRAY) { fprintf(stderr, "Erreur sur le format de l'image d'entrée.\n"); fprintf(stderr, "Le seul format PNG supporté est : niveaux de gris, 8bpp, sans canal alpha\n"); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(file); exit(-1); } image->width = width; image->height = height; image->pixel = (unsigned char *)malloc(width * height * sizeof(unsigned char)); assert(image->pixel != NULL); row_pointers = png_malloc(png_ptr, height * sizeof(png_bytep)); assert(row_pointers != NULL); for (i = 0; i < height; i++) row_pointers[i] = (png_bytep)(&image->pixel[i*width]); png_set_rows(png_ptr, info_ptr, row_pointers); png_read_image(png_ptr, row_pointers); png_free(png_ptr, row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(file); }
bool StreamerPNG::saveBitmap(const Bitmap & bitmap, std::ostream & output) { volatile int colorType = 0; // volatile is needed because of the setjmp later on. volatile int transforms = 0; const PixelFormat & pixelFormat = bitmap.getPixelFormat(); if(pixelFormat == PixelFormat::RGBA) { colorType = PNG_COLOR_TYPE_RGB_ALPHA; transforms = PNG_TRANSFORM_IDENTITY; } else if(pixelFormat == PixelFormat::BGRA) { colorType = PNG_COLOR_TYPE_RGB_ALPHA; transforms = PNG_TRANSFORM_BGR; } else if(pixelFormat == PixelFormat::RGB) { colorType = PNG_COLOR_TYPE_RGB; transforms = PNG_TRANSFORM_IDENTITY; } else if(pixelFormat == PixelFormat::BGR) { colorType = PNG_COLOR_TYPE_RGB; transforms = PNG_TRANSFORM_BGR; } else if(pixelFormat == PixelFormat::MONO) { colorType = PNG_COLOR_TYPE_GRAY; transforms = PNG_TRANSFORM_IDENTITY; } else if(pixelFormat == PixelFormat::MONO_FLOAT) { Reference<Bitmap> tmp = BitmapUtils::convertBitmap(bitmap, PixelFormat::MONO); return saveBitmap(*tmp.get(), output); } else { WARN("Unable to save PNG file. Unsupported color type."); return false; } // Set up the necessary structures for libpng. png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (!png_ptr) { return false; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, nullptr); return false; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); return false; } struct PNGFunctions { static void writeData(png_structp write_ptr, png_bytep data, png_size_t length) { std::ostream * out = reinterpret_cast<std::ostream *>(png_get_io_ptr(write_ptr)); out->write(reinterpret_cast<const char*>(data), static_cast<std::streamsize>(length)); } static void flushData(png_structp flush_ptr) { std::ostream * out = reinterpret_cast<std::ostream *>(png_get_io_ptr(flush_ptr)); out->flush(); } }; png_set_write_fn(png_ptr, reinterpret_cast<png_voidp>(&output), PNGFunctions::writeData, PNGFunctions::flushData); const uint32_t width = bitmap.getWidth(); const uint32_t height = bitmap.getHeight(); png_set_IHDR(png_ptr, info_ptr, width, height, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); // Write the image. std::vector<png_bytep> row_pointers; row_pointers.reserve(height); const uint8_t bytes = pixelFormat.getBytesPerPixel(); for (uint_fast32_t row = 0; row < height; ++row) { // Take over rows in the same order. row_pointers.push_back(reinterpret_cast<png_bytep>(const_cast<uint8_t *>(bitmap.data()) + row * width * bytes)); } png_set_rows(png_ptr, info_ptr, row_pointers.data()); png_write_png(png_ptr, info_ptr, transforms, nullptr); // Clean up. png_destroy_write_struct(&png_ptr, &info_ptr); return true; }
void saveCorePNG (FILE * writer, GLuint texture, int w, int h) { GLint tw, th; glBindTexture (GL_TEXTURE_2D, texture); getTextureDimensions(texture, &tw, &th); GLubyte* image = new GLubyte [tw*th*4]; if (! checkNew (image)) return; glPixelStorei (GL_PACK_ALIGNMENT, 1); // glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, image); #ifdef HAVE_GLES2 GLuint old_fbo, new_fbo; GLint old_vp[4]; glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&old_fbo); glGetIntegerv(GL_VIEWPORT, old_vp); glGenFramebuffers(1, &new_fbo); glBindFramebuffer(GL_FRAMEBUFFER, new_fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); glViewport(0, 0, tw, th); glReadPixels(0, 0, tw, th, GL_RGBA, GL_UNSIGNED_BYTE, image); glBindFramebuffer(GL_FRAMEBUFFER, old_fbo); glViewport(old_vp[0], old_vp[1], old_vp[2], old_vp[3]); glDeleteFramebuffers(1, &new_fbo); #else setPixelCoords (true); //glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const GLfloat texCoords[] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f }; int xoffset = 0; while (xoffset < tw) { int w = (tw-xoffset < viewportWidth) ? tw-xoffset : viewportWidth; int yoffset = 0; while (yoffset < th) { int h = (th-yoffset < viewportHeight) ? th-yoffset : viewportHeight; glClear(GL_COLOR_BUFFER_BIT); // Clear The Screen const GLfloat vertices[] = { (GLfloat)-xoffset, (GLfloat)-yoffset, 0., (GLfloat)tw-xoffset, (GLfloat)-yoffset, 0., (GLfloat)-xoffset, (GLfloat)-yoffset+th, 0., (GLfloat)tw-xoffset, (GLfloat)-yoffset+th, 0. }; glUseProgram(shader.texture); setPMVMatrix(shader.texture); drawQuad(shader.texture, vertices, 1, texCoords); glUseProgram(0); for (int i = 0; i<h; i++) { glReadPixels(viewportOffsetX, viewportOffsetY+i, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, image+xoffset*4+(yoffset+i)*4*tw); } yoffset += viewportHeight; } xoffset += viewportWidth; } setPixelCoords (false); #endif png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fatal ("Error saving image!"); return; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr){ png_destroy_write_struct(&png_ptr, (png_infopp)NULL); fatal ("Error saving image!"); return; } png_init_io(png_ptr, writer); png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); unsigned char * row_pointers[h]; for (int i = 0; i < h; i++) { row_pointers[i] = image + 4*i*tw; } png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); delete [] image; image = NULL; }
int RE_SavePNG( const char *filename, byte *buf, size_t width, size_t height, int byteDepth ) { fileHandle_t fp; png_structp png_ptr = NULL; png_infop info_ptr = NULL; unsigned int x, y; png_byte ** row_pointers = NULL; /* "status" contains the return value of this function. At first it is set to a value which means 'failure'. When the routine has finished its work, it is set to a value which means 'success'. */ int status = -1; /* The following number is set by trial and error only. I cannot see where it it is documented in the libpng manual. */ int depth = 8; fp = ri->FS_FOpenFileWrite( filename, qtrue ); if ( !fp ) { goto fopen_failed; } png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { goto png_create_write_struct_failed; } info_ptr = png_create_info_struct (png_ptr); if (info_ptr == NULL) { goto png_create_info_struct_failed; } /* Set up error handling. */ if (setjmp (png_jmpbuf (png_ptr))) { goto png_failure; } /* Set image attributes. */ png_set_IHDR (png_ptr, info_ptr, width, height, depth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Initialize rows of PNG. */ row_pointers = (png_byte **)png_malloc (png_ptr, height * sizeof (png_byte *)); for ( y=0; y<height; ++y ) { png_byte *row = (png_byte *)png_malloc (png_ptr, sizeof (uint8_t) * width * byteDepth); row_pointers[height-y-1] = row; for (x = 0; x < width; ++x) { byte *px = buf + (width * y + x)*3; *row++ = px[0]; *row++ = px[1]; *row++ = px[2]; } } /* Write the image data to "fp". */ // png_init_io (png_ptr, fp); png_set_write_fn( png_ptr, (png_voidp)&fp, user_write_data, user_flush_data ); png_set_rows (png_ptr, info_ptr, row_pointers); png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); /* The routine has successfully written the file, so we set "status" to a value which indicates success. */ status = 0; for (y = 0; y < height; y++) { png_free (png_ptr, row_pointers[y]); } png_free (png_ptr, row_pointers); png_failure: png_create_info_struct_failed: png_destroy_write_struct (&png_ptr, &info_ptr); png_create_write_struct_failed: ri->FS_FCloseFile( fp ); fopen_failed: return status; }
static BOOL SaveBmpToPNGfile(HBITMAP hbmp,LPTSTR file) { BITMAP bmp; FILE * fp = NULL; if(!GetObject(hbmp,sizeof(BITMAP),&bmp))return FALSE; fp = _tfopen(file,TEXT("wb")); if(!fp) { DeleteObject(hbmp); return FALSE; } png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL, user_err_fn,user_err_fn); if(!png_ptr) { DeleteObject(hbmp); return FALSE; } png_infop png_info_ptr = png_create_info_struct(png_ptr); if(!png_info_ptr) { DeleteObject(hbmp); png_destroy_write_struct(&png_ptr,NULL); return FALSE; } if(setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr,&png_info_ptr); fclose(fp); DeleteFile(file); DeleteObject(hbmp); return FALSE; } int color = PNG_COLOR_TYPE_RGB_ALPHA; if(bmp.bmBitsPixel < 32) color = PNG_COLOR_TYPE_RGB; LONG row_length; BYTE * row_bytes; PBYTE * rows_bytes =(PBYTE*) malloc( bmp.bmHeight * sizeof(png_byte *)); row_length =bmp.bmHeight * bmp.bmWidthBytes; row_bytes = (PBYTE) png_malloc(png_ptr,row_length); GetBitmapBits(hbmp,row_length,row_bytes); if(bmp.bmBitsPixel >=24) { for ( LONG i=0 ,j=0; i < bmp.bmHeight ; i ++ ,j +=bmp.bmWidthBytes ) { rows_bytes[i] = row_bytes + j; if(color & PNG_COLOR_MASK_ALPHA) for(LONG k=0; k < bmp.bmWidthBytes ; k+= 4) rows_bytes[i][k+3] = 255; } }else //16 bit { for (int i =0; i < bmp.bmHeight ; i ++) { rows_bytes[i] =(PBYTE) malloc(bmp.bmWidth * 3); for(int j=0,k=0; j < bmp.bmWidthBytes; j+=2, k+=3) { WORD Color;//存16bit的颜色 double Red,Green,Blue; Color = *(PWORD)(row_bytes + i * bmp.bmWidthBytes + j ); Blue=(Color&0xF800)>> 11; Green=(Color&0x7e0)>> 5; Red=(Color&0x1F); rows_bytes[i][k] = (BYTE)(Red * 256 / 32 +0.5); rows_bytes[i][k+1] = (BYTE)(Green * 256 / 64 +0.5); rows_bytes[i][k+2] = (BYTE)(Blue * 256 / 32 +0.5); } } } png_set_IHDR(png_ptr,png_info_ptr,bmp.bmWidth,bmp.bmHeight,8, color, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_init_io(png_ptr,fp); png_set_rows(png_ptr,png_info_ptr,rows_bytes); png_set_bgr(png_ptr); //crc32(0, Z_NULL, 0); png_write_png(png_ptr, png_info_ptr,0,0); png_write_end(png_ptr,png_info_ptr); png_destroy_write_struct(&png_ptr, &png_info_ptr); if(!(color & PNG_COLOR_MASK_ALPHA)) { for(int i = 0; i < bmp.bmHeight ; i++) { free(rows_bytes[i]); } } free(rows_bytes); free(row_bytes); DeleteObject(hbmp); fclose(fp); return TRUE; }
/** * @short Writes an image as png to the response object * * @param image flat buffer with all pixels * @param Bpp Bytes per pixel: 1 grayscale, 2 grayscale with alpha, 3 RGB, 4 RGB with alpha. Negative if in BGR format (cairo) * @param width The width of the image * @param height The height of the image * @param res where to write the image, it sets the necessary structs */ int onion_png_response(unsigned char *image, int Bpp, int width, int height, onion_response *res){ // Many copied from example.c from libpng source code. png_structp png_ptr; png_infop info_ptr; /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also check that * the library version is compatible with the one used at compile time, * in case we are using dynamically linked libraries. REQUIRED. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, error, warning); if (png_ptr == NULL) { return OCS_INTERNAL_ERROR; } /* Allocate/initialize the image information data. REQUIRED */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_write_struct(&png_ptr, NULL); return OCS_INTERNAL_ERROR; } onion_png_data opd; opd.res=res; opd.sent=0; png_set_write_fn(png_ptr, (void *)&opd, onion_png_write, onion_png_flush); /* where user_io_ptr is a structure you want available to the callbacks */ onion_response_set_header(res, "Content-Type", "image/png"); if (onion_response_write_headers(res)==OR_SKIP_CONTENT) // Maybe it was HEAD. return OCS_PROCESSED; /* 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 (Bpp<0){ png_set_bgr(png_ptr); Bpp=-Bpp; } switch(Bpp){ case 1: png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); break; case 2: png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_GRAY_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); break; case 3: 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); break; case 4: 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); break; default: png_error(png_ptr, "Wrong bytes per pixel"); break; } png_uint_32 k; png_bytep row_pointers[height]; if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) png_error (png_ptr, "Image is too tall to process in memory"); for (k = 0; k < height; k++) row_pointers[k] = (png_byte *) (image + k*width*Bpp); // Sets the rows to save at the image png_set_rows(png_ptr, info_ptr, row_pointers); // If header already sent, then there was an error. if (opd.sent){ return OCS_PROCESSED; } opd.sent=1; // Finally WRITE the image. Uses the onion_response_write via onion_png_write helper. png_write_png(png_ptr, info_ptr, 0, NULL); /* Clean up after the write, and free any memory allocated */ png_destroy_write_struct(&png_ptr, &info_ptr); /* That's it */ return OCS_PROCESSED; }
int png_utils_write_png_image(const char *filename, unsigned char *pixels, int w, int h, int has_alpha, int invert) { png_structp png_ptr; png_infop info_ptr; png_byte **row; int x, y, rc, colordepth = 8; int bytes_per_pixel = has_alpha ? 4 : 3; FILE *f; f = fopen(filename, "w"); if (!f) { fprintf(stderr, "fopen: %s:%s\n", filename, strerror(errno)); return -1; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) goto cleanup1; info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) goto cleanup2; if (setjmp(png_jmpbuf(png_ptr))) /* oh libpng, you're old as dirt, aren't you. */ goto cleanup2; png_set_IHDR(png_ptr, info_ptr, (size_t) w, (size_t) h, colordepth, has_alpha ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); row = png_malloc(png_ptr, h * sizeof(*row)); if (!invert) { for (y = 0; y < h; y++) { row[y] = png_malloc(png_ptr, w * bytes_per_pixel); for (x = 0; x < w; x++) { unsigned char *r = (unsigned char *) row[y]; unsigned char *src = (unsigned char *) &pixels[y * w * bytes_per_pixel + x * bytes_per_pixel]; unsigned char *dest = &r[x * bytes_per_pixel]; memcpy(dest, src, bytes_per_pixel); } } } else { for (y = 0; y < h; y++) { row[h - y - 1] = png_malloc(png_ptr, w * bytes_per_pixel); for (x = 0; x < w; x++) { unsigned char *r = (unsigned char *) row[h - y - 1]; unsigned char *src = (unsigned char *) &pixels[y * w * bytes_per_pixel + x * bytes_per_pixel]; unsigned char *dest = &r[x * bytes_per_pixel]; memcpy(dest, src, bytes_per_pixel); } } } png_init_io(png_ptr, f); png_set_rows(png_ptr, info_ptr, row); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING, NULL); for (y = 0; y < h; y++) png_free(png_ptr, row[y]); png_free(png_ptr, row); rc = 0; cleanup2: png_destroy_write_struct(&png_ptr, &info_ptr); cleanup1: fclose(f); return rc; }
int main(int argc, char *argv[]) { if (argc != 3) { fprintf(stderr, "Usage: %s file_in.dat result.png\n", argv[0]); return 1; } char *file_in = argv[1]; char *file_out = argv[2]; int bytes = 256 * 256 * sizeof(int); unsigned int *points = (unsigned int *)calloc(1, bytes); FILE *fhi = fopen(file_in, "rb"); if (!fhi) { fprintf(stderr, "Failed to open %s\n", file_in); return 1; } FILE *fho = fopen(file_out, "wb"); if (!fho) { fprintf(stderr, "Failed to create %s\n", file_out); return 1; } while(!feof(fhi)) { int x = fgetc(fhi); int y = fgetc(fhi); if (x < 0 || y < 0) // EOF probably break; points[y * 256 + x]++; } fclose(fhi); unsigned int c_max = 0, c_min = 1 << 31; for(int index=0; index<(256*256); index++) { if (points[index] > c_max) c_max = points[index]; if (points[index] < c_min) c_min = points[index]; } double div = double(c_max) - double(c_min); bytes = 256 * 256 * 3; unsigned char *result = (unsigned char *)calloc(1, bytes); for(int y=0; y<256; y++) { for(int x=0; x<256; x++) { if (points[y * 256 + x] == 0) continue; double val = double(points[y * 256 + x] - c_min) / div; result[y * 256 * 3 + x * 3 + 0] = result[y * 256 * 3 + x * 3 + 2] = 0; result[y * 256 * 3 + x * 3 + 1] = (unsigned char)maxval(minval(255.0, val * 255.0), 0.0); } } 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_set_IHDR (png_ptr, info_ptr, 256, 256, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); unsigned char *row_pointers[256]; for(int y=0; y<256; y++) row_pointers[y] = &result[y * 256 * 3]; png_init_io(png_ptr, fho); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); fclose(fho); return 0; }
int enc_png(char *data,g2int width,g2int height,g2int nbits,char *pngbuf) { int color_type; g2int j,bytes,pnglen,bit_depth; png_structp png_ptr; png_infop info_ptr; // png_bytep *row_pointers[height]; png_bytep **row_pointers; png_stream write_io_ptr; /* create and initialize png_structs */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); if (!png_ptr) return (-1); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr,(png_infopp)NULL); return (-2); } /* Set Error callback */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); return (-3); } /* Initialize info for writing PNG stream to memory */ write_io_ptr.stream_ptr=(png_voidp)pngbuf; write_io_ptr.stream_len=0; /* Set new custom write functions */ png_set_write_fn(png_ptr,(voidp)&write_io_ptr,(png_rw_ptr)user_write_data, (png_flush_ptr)user_flush_data); /* png_init_io(png_ptr, fptr); */ /* png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); */ /* Set the image size, colortype, filter type, etc... */ /* printf("SAGTsettingIHDR %d %d %d\n",width,height,bit_depth); */ bit_depth=nbits; color_type=PNG_COLOR_TYPE_GRAY; if (nbits == 24 ) { bit_depth=8; color_type=PNG_COLOR_TYPE_RGB; } else if (nbits == 32 ) { bit_depth=8; color_type=PNG_COLOR_TYPE_RGB_ALPHA; } png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Put image data into the PNG info structure */ /*bytes=bit_depth/8;*/ bytes=nbits/8; row_pointers=malloc(height*sizeof(png_bytep)); for (j=0;j<height;j++) row_pointers[j]=(png_bytep *)(data+(j*width*bytes)); png_set_rows(png_ptr, info_ptr, (png_bytepp)row_pointers); /* Do the PNG encoding, and write out PNG stream */ png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); /* Clean up */ png_destroy_write_struct(&png_ptr, &info_ptr); free(row_pointers); pnglen=write_io_ptr.stream_len; return pnglen; }
void write( Image& img, const char* filename ) { if ( !( img.get_width() > 0 && img.get_height() > 0 && img.get_num_channels() > 0 ) ) { throw std::exception( "This is not a valid image to write." ); } FILE* fp = fopen( filename, "wb" ); if ( !fp ) { throw std::exception( "Failed to open file." ); } boost::shared_ptr<void> fp_cleanup( static_cast<void*>(0), boost::bind( fclose, fp ) ); png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); if (!png_ptr) { throw std::exception( "png_create_write_struct failed." ); } png_infop info_ptr = 0; boost::shared_ptr<void> png_cleanup( static_cast<void*>(0), boost::bind( png_destroy_write_struct, &png_ptr, &info_ptr ) ); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { throw std::exception( "png_create_info_struct failed." ); } if ( setjmp(png_jmpbuf(png_ptr)) ) { throw std::exception( "libpng returned an error." ); } png_init_io(png_ptr, fp); // optional: call png_set_filter to control compression // fill png_info structure typedef boost::scoped_array< Image::channel* > Channel_array; Channel_array row_pointers( new Image::channel* [ img.get_height() ] ); for ( int row = 0; row < img.get_height(); ++row ) { row_pointers[ row ] = img.get_row_ptr( row ); } png_set_rows( png_ptr, info_ptr, row_pointers.get() ); png_set_IHDR( png_ptr, info_ptr, img.get_width(), img.get_height(), 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); png_write_png( png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL ); }
static int save_png_to_file (bitmap_t *bitmap, const char *path) { FILE * fp; png_structp png_ptr = NULL; png_infop info_ptr = NULL; size_t x, y; png_byte ** row_pointers = NULL; /* "status" contains the return value of this function. At first it is set to a value which means 'failure'. When the routine has finished its work, it is set to a value which means 'success'. */ int status = -1; /* The following number is set by trial and error only. I cannot see where it it is documented in the libpng manual. */ int pixel_size = 3; int depth = 8; fp = fopen (path, "wb"); if (! fp) { goto fopen_failed; } png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { goto png_create_write_struct_failed; } info_ptr = png_create_info_struct (png_ptr); if (info_ptr == NULL) { goto png_create_info_struct_failed; } /* Set up error handling. */ if (setjmp (png_jmpbuf (png_ptr))) { goto png_failure; } /* Set image attributes. */ png_set_IHDR (png_ptr, info_ptr, bitmap->width, bitmap->height, depth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Initialize rows of PNG. */ row_pointers = png_malloc (png_ptr, bitmap->height * sizeof (png_byte *)); for (y = 0; y < bitmap->height; ++y) { png_byte *row = png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size); row_pointers[y] = row; for (x = 0; x < bitmap->width; ++x) { pixel_t * pixel = pixel_at (bitmap, x, y); *row++ = pixel->red; *row++ = pixel->green; *row++ = pixel->blue; } } /* Write the image data to "fp". */ png_init_io (png_ptr, fp); png_set_rows (png_ptr, info_ptr, row_pointers); png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); /* The routine has successfully written the file, so we set "status" to a value which indicates success. */ status = 0; for (y = 0; y < bitmap->height; y++) { png_free (png_ptr, row_pointers[y]); } png_free (png_ptr, row_pointers); png_failure: png_create_info_struct_failed: png_destroy_write_struct (&png_ptr, &info_ptr); png_create_write_struct_failed: fclose (fp); fopen_failed: return status; }
void TCOD_sys_write_png(const SDL_Surface *surf, const char *filename) { png_structp png_ptr; png_infop info_ptr; png_bytep *row_pointers; int y,x; FILE *fp=fopen(filename,"wb"); if (!fp) return; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); return; } /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_write_struct(&png_ptr, png_infopp_NULL); return; } if (setjmp(png_jmpbuf(png_ptr))) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(fp); /* If we get here, we had a problem reading the file */ return; } png_init_io(png_ptr, fp); png_set_IHDR(png_ptr,info_ptr,surf->w, surf->h, 8,PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); // get row data row_pointers=(png_bytep *)malloc(sizeof(png_bytep)*surf->h); for (y=0; y< surf->h; y++ ) { // TODO : we should be able to use directly the surface data... // row_pointers[y]=(png_bytep)(Uint8 *)(surf->pixels) + y * surf->pitch; row_pointers[y]=(png_bytep)malloc(sizeof(png_byte)*surf->w*3); for (x=0; x < surf->w; x++ ) { Uint8 *pixel=(Uint8 *)(surf->pixels) + y * surf->pitch + x * surf->format->BytesPerPixel; row_pointers[y][x*3]=*((pixel)+surf->format->Rshift/8); row_pointers[y][x*3+1]=*((pixel)+surf->format->Gshift/8); row_pointers[y][x*3+2]=*((pixel)+surf->format->Bshift/8); } } png_set_rows(png_ptr,info_ptr,row_pointers); png_write_png(png_ptr,info_ptr,PNG_TRANSFORM_IDENTITY,NULL); fclose(fp); /* clean up, and free any memory allocated - REQUIRED */ png_destroy_write_struct(&png_ptr, &info_ptr); for (y=0; y< surf->h; y++ ) { free(row_pointers[y]); } free(row_pointers); }
void save_as_png(T1 & file, T2 const& image, png_options const& opts) { if (opts.use_miniz) { MiniZ::PNGWriter writer(opts.compression,opts.strategy); if (opts.trans_mode == 0) { writer.writeIHDR(image.width(), image.height(), 24); writer.writeIDATStripAlpha(image); } else { writer.writeIHDR(image.width(), image.height(), 32); writer.writeIDAT(image); } writer.writeIEND(); writer.toStream(file); return; } png_voidp error_ptr=0; png_structp png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, error_ptr,0, 0); if (!png_ptr) return; // switch on optimization only if supported #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) && defined(PNG_MMX_CODE_SUPPORTED) png_uint_32 mask, flags; flags = png_get_asm_flags(png_ptr); mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE); png_set_asm_flags(png_ptr, flags | mask); #endif png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE); png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr,(png_infopp)0); return; } jmp_buf* jmp_context = (jmp_buf*) png_get_error_ptr(png_ptr); if (jmp_context) { png_destroy_write_struct(&png_ptr, &info_ptr); return; } png_set_write_fn (png_ptr, &file, &write_data<T1>, &flush_data<T1>); png_set_compression_level(png_ptr, 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] = (png_bytep)image.getRow(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); }
bool ScreenshotManager::encode_png(std::shared_ptr<uint8_t> pxdata, coord::viewport_delta size) { std::FILE *fout = NULL; coord::pixel_t width = size.x, height = size.y; auto warn_fn = [] (png_structp /*png_ptr*/, png_const_charp message) { log::log(MSG(err) << "Creating screenshot failed: libpng error: " << message); }; auto err_fn = [] (png_structp png_ptr, png_const_charp message) { log::log(MSG(err) << "Creating screenshot failed: libpng error: " << message); longjmp(png_jmpbuf(png_ptr), 1); }; png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, err_fn, warn_fn); 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; } if (setjmp(png_jmpbuf(png_ptr))) { std::fclose(fout); png_destroy_write_struct(&png_ptr, &info_ptr); return false; } std::string filename = this->gen_next_filename(); fout = std::fopen(filename.c_str(), "wb"); if (fout == NULL) { png_destroy_write_struct(&png_ptr, &info_ptr); log::log(MSG(err) << "Could not open '"<< filename << "': " << std::string(strerror(errno))); return false; } png_init_io(png_ptr, fout); 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); // Put image row pointer into info_ptr so that we can use the high-level // write interface. std::vector<png_bytep> row_ptrs; // Invert rows. row_ptrs.reserve(height); for (int i = 1; i <= height; i++) { row_ptrs.push_back(pxdata.get() + (height - i) * 4 * width); } png_set_rows(png_ptr, info_ptr, &row_ptrs[0]); //TODO: print ingame message. log::log(MSG(info) << "Saving screenshot to '" << filename << "'."); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_FILLER_AFTER, NULL); std::fclose(fout); png_destroy_write_struct(&png_ptr, &info_ptr); return true; }
void PngEncoder::write(const char *name) { FILE * file = NULL; unsigned char ** rows = 0; unsigned char * cmap = 0; short numOfColors = (1<<depth); short bit_depth = 4; long i = 0; long j = 0; png_structp png_ptr; png_infop info_ptr; char user_error_ptr[] = "PngEncoder"; png_colorp png_palette; png_byte ti[1]; png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, user_error_fn, user_warning_fn); if (!png_ptr) { err("Can not allocate writing structure!\n"); return; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); err("Can not allocate writing structure!\n"); return; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); return; } else { png_palette = (png_colorp) png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH*sizeof(png_color)); memset(png_palette,0,PNG_MAX_PALETTE_LENGTH*sizeof(png_color)); for (i=0; i<numOfColors; i++) { png_palette[i].red = palette[i].red; png_palette[i].green = palette[i].green; png_palette[i].blue = palette[i].blue; } png_set_PLTE(png_ptr, info_ptr, png_palette, numOfColors); png_set_IHDR( png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE ); free(png_palette); ti[0] = transIndex; png_set_tRNS(png_ptr,info_ptr,ti,1,NULL); rows = (unsigned char **) calloc(sizeof(unsigned char*),height); rows[0] = (unsigned char *) calloc(sizeof(unsigned char),height*width); for (i=1; i<height; i++) { rows[i] = rows[i-1] + width; } for (i=0, dataPtr=data; i<height; i++) { for (j=0; j<width; j++) { if (j%2) { rows[i][j/2] = ( rows[i][j/2] | *dataPtr ); } else { rows[i][j/2] = (*dataPtr) << 4; } dataPtr++; } } png_set_rows(png_ptr,info_ptr,rows); file = fopen(name,"wb"); if (file==0) { err("Error opening png file %s for writing: %s!\n",name,strerror(errno)); } else { png_init_io(png_ptr,file); png_write_png(png_ptr,info_ptr,PNG_TRANSFORM_IDENTITY,NULL); } } png_destroy_write_struct(&png_ptr, &info_ptr); if (file) { fclose (file); } if (cmap) { free(cmap); } if (rows) { if (rows[0]) { free(rows[0]); } free(rows); } return; }