errCode genTextures(const char *rootDir, const sFileList *files, sTex ***dynarrTextures){ static const size_t BUFFLEN = 1024; int numTexs=0; int idxFile = files->num; sTex *refTex; if(idxFile <= 0 || rootDir == NULL || rootDir[0] == '\0' || dynarrTextures == NULL) return PROBLEM; size_t lenRootDir = strlen(rootDir); char filePath[BUFFLEN]; FILE *handFile; png_byte header[PNGHEAD_SIZE]; strncpy(filePath, rootDir, 1024); if(lenRootDir>0 && filePath[lenRootDir-1]!='/'){ filePath[lenRootDir] = '/'; lenRootDir += 1; } while(idxFile > 0){ --idxFile; strncpy(&filePath[lenRootDir], files->dynarrFiles[idxFile], 1024 - lenRootDir); handFile = fopen(filePath, "rb"); if(handFile == NULL){ WARN("Can't open file %s", filePath); continue; } if( fread(header, sizeof(png_byte), PNGHEAD_SIZE, handFile) == PNGHEAD_SIZE && png_sig_cmp(header, 0, PNGHEAD_SIZE) == 0 ){ XTRA_LOG("File %s opened as PNG", filePath); }else{ WARN("File %s isn't a PNG", filePath); fclose(handFile); continue; } ++numTexs; (*dynarrTextures) = (sTex**)realloc_chk((*dynarrTextures), (numTexs+1) * sizeof(sTex*)); (*dynarrTextures)[numTexs]=NULL; refTex = (*dynarrTextures)[numTexs-1] = (sTex*)malloc_chk(sizeof(sTex)); memset(refTex, 0, sizeof(sTex)); refTex->pngptrData = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, &myPNGWarnFoo ); if(refTex->pngptrData == NULL){ WARN("Unable to create png struct"); fclose(handFile); continue; } if(setjmp(png_jmpbuf(refTex->pngptrData)) != 0){ /** jumps here on errors. */ cleanupPNGImg( refTex->pngptrData, &refTex->dynarrRows ); png_destroy_read_struct( &(refTex->pngptrData), &(refTex->pngptrInfo), NULL ); refTex->h = refTex->w = 0; }else{ refTex->pngptrInfo = png_create_info_struct( refTex->pngptrData ); if(refTex->pngptrInfo == NULL){ WARN("Unable to create png info struct"); fclose(handFile); continue; } /** setup PNG decode */ png_init_io(refTex->pngptrData, handFile); png_set_sig_bytes(refTex->pngptrData, PNGHEAD_SIZE); png_read_info(refTex->pngptrData, refTex->pngptrInfo); png_byte colorCurrent = png_get_color_type( refTex->pngptrData, refTex->pngptrInfo ); png_set_filler(refTex->pngptrData, 0, PNG_FILLER_AFTER); png_set_packing(refTex->pngptrData); /** if < 8 bits */ { png_color_8p sig_bit; if (png_get_sBIT(refTex->pngptrData, refTex->pngptrInfo, &sig_bit)) png_set_shift(refTex->pngptrData, sig_bit); } switch(colorCurrent){ case PNG_COLOR_TYPE_RGB_ALPHA: /** already good */ break; case PNG_COLOR_TYPE_RGB: png_set_tRNS_to_alpha(refTex->pngptrData); break; case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb( refTex->pngptrData ); png_set_tRNS_to_alpha(refTex->pngptrData); break; case PNG_COLOR_TYPE_GRAY: png_set_expand_gray_1_2_4_to_8( refTex->pngptrData ); png_set_tRNS_to_alpha(refTex->pngptrData); break; default: WARN("unsupported colour"); break; } png_read_update_info(refTex->pngptrData, refTex->pngptrInfo); colorCurrent = png_get_color_type( refTex->pngptrData, refTex->pngptrInfo ); if(colorCurrent != PNG_COLOR_TYPE_RGB_ALPHA){ printf("<warning> %s didn't convert to the right colour type\n", files->dynarrFiles[idxFile]); png_destroy_read_struct(&refTex->pngptrData, &refTex->pngptrInfo, (png_infopp)NULL); fclose(handFile); continue; } refTex->colorType = colorCurrent; const int numPasses = png_set_interlace_handling( refTex->pngptrData ); /** setup other data */ copyString(&refTex->name, files->dynarrFiles[idxFile]); /** setup texture */ unsigned int row; const png_uint_32 sizeRow = png_get_rowbytes( refTex->pngptrData, refTex->pngptrInfo ); refTex->w = png_get_image_width( refTex->pngptrData, refTex->pngptrInfo ); refTex->h = png_get_image_height( refTex->pngptrData, refTex->pngptrInfo ); if(sizeRow/refTex->w != DEFAULT_BYTE_PP){ WARN("%s didn't convert to the right bit depth", refTex->name); png_destroy_read_struct(&refTex->pngptrData, &refTex->pngptrInfo, (png_infopp)NULL); fclose(handFile); continue; } refTex->dynarrRows = calloc_chk((refTex->h +1), sizeof(png_byte*)); refTex->dynarrRows[refTex->h] = NULL; for(row = 0; row < refTex->h; ++row) refTex->dynarrRows[row] = png_malloc(refTex->pngptrData, sizeRow); unsigned int pass; for(pass=0; pass < numPasses; ++pass){ for(row = 0; row < refTex->h; ++row){ png_read_rows( refTex->pngptrData, &refTex->dynarrRows[row], NULL, 1 ); } } png_read_end(refTex->pngptrData, refTex->pngptrInfo); } fclose(handFile); } return NOPROB; }
/* Alternate create PNG structure for reading, and allocate any memory needed. */ png_structp PNGAPI png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn) { #endif /* PNG_USER_MEM_SUPPORTED */ volatile png_structp png_ptr; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD jmp_buf jmpbuf; #endif #endif int i; png_debug(1, "in png_create_read_struct\n"); #ifdef PNG_USER_MEM_SUPPORTED if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr)) == NULL) #else if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL) #endif { return (png_structp)NULL; } #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_ptr->jmpbuf)) #endif { png_free(png_ptr, png_ptr->zbuf); png_ptr->zbuf=NULL; png_destroy_struct(png_ptr); return (png_structp)NULL; } #ifdef USE_FAR_KEYWORD png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf)); #endif #endif #ifdef PNG_USER_MEM_SUPPORTED png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); #endif png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); i=0; do { if(user_png_ver[i] != png_libpng_ver[i]) png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; } while (png_libpng_ver[i++]); if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) { /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so * we must recompile any applications that use any older library version. * For versions after libpng 1.0, we will be compatible, so we need * only check the first digit. */ if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || (user_png_ver[0] == '0' && user_png_ver[2] < '9')) { #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) char msg[80]; if (user_png_ver) { sprintf(msg, "Application was compiled with png.h from libpng-%.20s", user_png_ver); png_warning(png_ptr, msg); } sprintf(msg, "Application is running with png.c from libpng-%.20s", png_libpng_ver); png_warning(png_ptr, msg); #endif #ifdef PNG_ERROR_NUMBERS_SUPPORTED png_ptr->flags=0; #endif png_error(png_ptr, "Incompatible libpng version in application and library"); } /* Libpng 1.0.6 was not binary compatible, due to insertion of the info_ptr->free_me member. Libpng-1.0.1 and earlier were not compatible due to insertion of the user transform function. Note to maintainer: this test can be removed from version 1.2.0 and beyond because the previous test would have already rejected it. */ if (user_png_ver[0] == '1' && user_png_ver[2] == '0' && (user_png_ver[4] < '2' || user_png_ver[4] == '6') && user_png_ver[5] == '\0') { #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) char msg[80]; if (user_png_ver) { sprintf(msg, "Application was compiled with png.h from libpng-%.20s", user_png_ver); png_warning(png_ptr, msg); } sprintf(msg, "Application is running with png.c from libpng-%.20s", png_libpng_ver); png_warning(png_ptr, msg); #endif #ifdef PNG_ERROR_NUMBERS_SUPPORTED png_ptr->flags=0; #endif png_error(png_ptr, "Application must be recompiled; versions <= 1.0.6 were incompatible"); } } /* initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size); png_ptr->zstream.zalloc = png_zalloc; png_ptr->zstream.zfree = png_zfree; png_ptr->zstream.opaque = (voidpf)png_ptr; switch (inflateInit(&png_ptr->zstream)) { case Z_OK: /* Do nothing */ break; case Z_MEM_ERROR: case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break; default: png_error(png_ptr, "Unknown zlib error"); } png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; png_set_read_fn(png_ptr, NULL, NULL); return (png_ptr); }
/** * Write a given canvas to a specific file. */ static int writePNG(char const *filename, Color_t *canvas, int width, int height) { FILE *fp; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_byte ** row_pointers = NULL; int status = -1; int pixel_size = 3; int depth = 8; size_t x, y; fp = fopen(filename, "wb"); if (!fp) abort_("Unable to open file %s\n", filename); png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) abort_("Unable to create PNG write struct.\n"); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) abort_("Unable to create info structure.\n"); if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "Error during PNG creation.\n"); return -1; } 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); 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++) { int index = coord_to_ind(x, y, width); *row++ = canvas[index].red; *row++ = canvas[index].green; *row++ = canvas[index].blue; } } 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); status = 0; for (y = 0; y < height; y++) png_free(png_ptr, row_pointers[y]); png_free(png_ptr, row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return status; }
/* Alternate create PNG structure for reading, and allocate any memory needed. */ png_structp PNGAPI png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn) { #endif /* PNG_USER_MEM_SUPPORTED */ png_structp png_ptr; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD jmp_buf jmpbuf; #endif #endif int i; png_debug(1, "in png_create_read_struct\n"); #ifdef PNG_USER_MEM_SUPPORTED png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); #else png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); #endif if (png_ptr == NULL) return (NULL); #if !defined(PNG_1_0_X) #ifdef PNG_ASSEMBLER_CODE_SUPPORTED png_init_mmx_flags(png_ptr); /* 1.2.0 addition */ #endif #endif /* PNG_1_0_X */ /* added at libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED png_ptr->user_width_max=PNG_USER_WIDTH_MAX; png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; #endif #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_ptr->jmpbuf)) #endif { png_free(png_ptr, png_ptr->zbuf); png_ptr->zbuf=NULL; #ifdef PNG_USER_MEM_SUPPORTED png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, (png_voidp)mem_ptr); #else png_destroy_struct((png_voidp)png_ptr); #endif return (NULL); } #ifdef USE_FAR_KEYWORD png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); #endif #endif #ifdef PNG_USER_MEM_SUPPORTED png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); #endif png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); i=0; do { if(user_png_ver[i] != png_libpng_ver[i]) png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; } while (png_libpng_ver[i++]); if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) { /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so * we must recompile any applications that use any older library version. * For versions after libpng 1.0, we will be compatible, so we need * only check the first digit. */ if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || (user_png_ver[0] == '0' && user_png_ver[2] < '9')) { #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) char msg[80]; if (user_png_ver) { sprintf(msg, "Application was compiled with png.h from libpng-%.20s", user_png_ver); png_warning(png_ptr, msg); } sprintf(msg, "Application is running with png.c from libpng-%.20s", png_libpng_ver); png_warning(png_ptr, msg); #endif #ifdef PNG_ERROR_NUMBERS_SUPPORTED png_ptr->flags=0; #endif png_error(png_ptr, "Incompatible libpng version in application and library"); } } /* initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size); png_ptr->zstream.zalloc = png_zalloc; png_ptr->zstream.zfree = png_zfree; png_ptr->zstream.opaque = (voidpf)png_ptr; switch (inflateInit(&png_ptr->zstream)) { case Z_OK: /* Do nothing */ break; case Z_MEM_ERROR: case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break; default: png_error(png_ptr, "Unknown zlib error"); } png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); #ifdef PNG_SETJMP_SUPPORTED /* Applications that neglect to set up their own setjmp() and then encounter a png_error() will longjmp here. Since the jmpbuf is then meaningless we abort instead of returning. */ #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) PNG_ABORT(); png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); #else if (setjmp(png_ptr->jmpbuf)) PNG_ABORT(); #endif #endif return (png_ptr); }
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; }
bool SavePNG(File* file, Image* image) { COR_GUARD("SavePNG"); if (!image) { return false; } // If the image format isn't supported directly by this function, // clone to a supported format and try to save with that. switch (image->getFormat()) { case PF_R8G8B8A8: case PF_R8G8B8: case PF_I8: break; default: { COR_LOG("Unsupported pixel format... cloning"); std::auto_ptr<Image> cloned(CloneImage(image, PF_R8G8B8A8)); return SavePNG(file, cloned.get()); } } // create write struct png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { return false; } // error handling! if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, NULL); return false; } // create info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_write_struct(&png_ptr, NULL); return false; } int width = image->getWidth(); int height = image->getHeight(); // set image characteristics png_set_write_fn(png_ptr, file, PNG_write, PNG_flush); int color_format = 0; // png output format int color_format_bpp = 0; // png bytes per pixel bool color_format_paletted = false; // png palette needed flag // figure out output format switch (image->getFormat()) { case PF_R8G8B8A8: color_format = PNG_COLOR_TYPE_RGB_ALPHA; color_format_bpp = 4; break; case PF_R8G8B8: color_format = PNG_COLOR_TYPE_RGB; color_format_bpp = 3; break; case PF_I8: color_format = PNG_COLOR_TYPE_PALETTE; color_format_bpp = 1; color_format_paletted = true; break; default: // Unsupported format. This should already be taken care of // by the test at the beginning of this function. return false; } png_set_IHDR( png_ptr, info_ptr, width, height, 8, color_format, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (color_format_paletted) { COR_LOG("Saving palettized image..."); int image_palette_format = image->getPaletteFormat(); // palette format int image_palette_size = image->getPaletteSize(); // palette size // allocate png palette and get pointer to image palette png_color* png_palette = (png_color*)png_malloc( png_ptr, sizeof(png_color) * image_palette_size); byte* image_palette = (byte*)image->getPalette(); if (image_palette_format == PF_R8G8B8) { // 24 bit source palette for (int i = 0; i < image_palette_size; i++) { // copy entry directly png_palette[i].red = *image_palette++; png_palette[i].green = *image_palette++; png_palette[i].blue = *image_palette++; } } else if (image_palette_format == PF_R8G8B8A8) { // 32 bit source palette for (int i = 0; i < image_palette_size; i++) { // copy entry, skip alpha png_palette[i].red = *image_palette++; png_palette[i].green = *image_palette++; png_palette[i].blue = *image_palette++; image_palette++; } } // write palette png_set_PLTE(png_ptr, info_ptr, png_palette, image_palette_size); } byte* pixels = (byte*)image->getPixels(); // build rows void** rows = (void**)png_malloc(png_ptr, sizeof(void*) * height); for (int i = 0; i < height; ++i) { rows[i] = png_malloc(png_ptr, color_format_bpp * width); memcpy(rows[i], pixels, color_format_bpp * width); pixels += width * color_format_bpp; } png_set_rows(png_ptr, info_ptr, (png_bytepp)rows); info_ptr->valid |= PNG_INFO_IDAT; // actually write the image png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); png_destroy_write_struct(&png_ptr, &info_ptr); return true; }
void GenericImage::write_png(const char *filename) { int w = width; int h = height; int c = components; int b = pix_depth; void* p = pixels; FILE *filep = NULL; png_structp writep = NULL; png_infop infop = NULL; png_bytep *bytep = NULL; /* Initialize all PNG import data structures. */ if (!(filep = fopen(filename, "wb"))) fail("can't open file\n"); if (!(writep = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) fail("can't create png write struct\n"); if (!(infop = png_create_info_struct(writep))) fail("can't create png info struct\n"); /* Enable the default PNG error handler. */ if (setjmp(png_jmpbuf(writep)) == 0) { png_init_io (writep, filep); /* 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 */ int color_type; switch (c) { case 1: color_type = PNG_COLOR_TYPE_GRAY; break; case 2: color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; case 3: color_type = PNG_COLOR_TYPE_RGB; break; case 4: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break; default: color_type = PNG_COLOR_TYPE_RGB; } png_set_compression_level(writep, 9); png_set_IHDR(writep, infop, w, h, b*8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(writep, infop); /* pack pixels into bytes */ png_set_packing(writep); bytep = (png_bytep *) png_malloc(writep, h * sizeof (png_bytep)); for (int k = 0; k < h; k++) bytep[k] = (png_bytep)p + k*w*c*b; /* write out the entire image data in one call */ //png_write_image(writep, bytep); /* Write a few rows at a time. */ //png_write_rows(writep, &bytep[first_row], number_of_rows); /* If you are only writing one row at a time, this works */ // for (int y = 0; y < h; y++) // { // png_write_rows(writep, &row_pointers[y], 1); // } // png_write_end(writep, infop); //set rows and write png png_set_rows(writep, infop, bytep); //png_write_png(writep, infop, PNG_TRANSFORM_STRIP_16 | // PNG_TRANSFORM_PACKING, NULL); png_write_png (writep, infop, PNG_TRANSFORM_SWAP_ENDIAN, NULL); free(bytep); } else fail("can't write png data\n"); /* Release all resources. */ png_destroy_write_struct(&writep, &infop); fclose(filep); success("write png file\n"); }
/* Write a VIPS image to PNG. */ static int write_vips( Write *write, int compress, int interlace, const char *profile, VipsForeignPngFilter filter, gboolean strip, gboolean palette, int colours, int Q, double dither ) { VipsImage *in = write->in; int bit_depth; int color_type; int interlace_type; int i, nb_passes; g_assert( in->BandFmt == VIPS_FORMAT_UCHAR || in->BandFmt == VIPS_FORMAT_USHORT ); g_assert( in->Coding == VIPS_CODING_NONE ); g_assert( in->Bands > 0 && in->Bands < 5 ); /* Catch PNG errors. */ if( setjmp( png_jmpbuf( write->pPng ) ) ) return( -1 ); /* Check input image. If we are writing interlaced, we need to make 7 * passes over the image. We advertise ourselves as seq, so to ensure * we only suck once from upstream, switch to WIO. */ if( interlace ) { if( !(write->memory = vips_image_copy_memory( in )) ) return( -1 ); in = write->memory; } else { if( vips_image_pio_input( in ) ) return( -1 ); } if( compress < 0 || compress > 9 ) { vips_error( "vips2png", "%s", _( "compress should be in [0,9]" ) ); return( -1 ); } /* Set compression parameters. */ png_set_compression_level( write->pPng, compress ); /* Set row filter. */ png_set_filter( write->pPng, 0, filter ); bit_depth = in->BandFmt == VIPS_FORMAT_UCHAR ? 8 : 16; switch( in->Bands ) { case 1: color_type = PNG_COLOR_TYPE_GRAY; break; case 2: color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break; case 3: color_type = PNG_COLOR_TYPE_RGB; break; case 4: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break; default: vips_error( "vips2png", _( "can't save %d band image as png" ), in->Bands ); return( -1 ); } #ifdef HAVE_IMAGEQUANT /* Enable image quantisation to paletted 8bpp PNG if colours is set. */ if( palette ) { g_assert( colours >= 2 && colours <= 256 ); bit_depth = 8; color_type = PNG_COLOR_TYPE_PALETTE; } #else if( palette ) g_warning( "%s", _( "ignoring palette (no quantisation support)" ) ); #endif /*HAVE_IMAGEQUANT*/ interlace_type = interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE; png_set_IHDR( write->pPng, write->pInfo, in->Xsize, in->Ysize, bit_depth, color_type, interlace_type, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); /* Set resolution. libpng uses pixels per meter. */ png_set_pHYs( write->pPng, write->pInfo, VIPS_RINT( in->Xres * 1000 ), VIPS_RINT( in->Yres * 1000 ), PNG_RESOLUTION_METER ); /* Set ICC Profile. */ if( profile && !strip ) { if( strcmp( profile, "none" ) != 0 ) { void *data; size_t length; if( !(data = vips__file_read_name( profile, vips__icc_dir(), &length )) ) return( -1 ); #ifdef DEBUG printf( "write_vips: " "attaching %zd bytes of ICC profile\n", length ); #endif /*DEBUG*/ png_set_iCCP( write->pPng, write->pInfo, "icc", PNG_COMPRESSION_TYPE_BASE, data, length ); } } else if( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) && !strip ) { void *data; size_t length; if( vips_image_get_blob( in, VIPS_META_ICC_NAME, &data, &length ) ) return( -1 ); #ifdef DEBUG printf( "write_vips: attaching %zd bytes of ICC profile\n", length ); #endif /*DEBUG*/ png_set_iCCP( write->pPng, write->pInfo, "icc", PNG_COMPRESSION_TYPE_BASE, data, length ); } if( vips_image_get_typeof( in, VIPS_META_XMP_NAME ) ) { const char *str; if( vips_image_get_string( in, VIPS_META_XMP_NAME, &str ) ) return( -1 ); vips__png_set_text( write->pPng, write->pInfo, "XML:com.adobe.xmp", str ); } /* Set any "png-comment-xx-yyy" metadata items. */ if( vips_image_map( in, write_png_comment, write ) ) return( -1 ); #ifdef HAVE_IMAGEQUANT if( palette ) { VipsImage *im_index; VipsImage *im_palette; int palette_count; png_color *png_palette; png_byte *png_trans; int trans_count; if( vips__quantise_image( in, &im_index, &im_palette, colours, Q, dither ) ) return( -1 ); palette_count = im_palette->Xsize; g_assert( palette_count <= PNG_MAX_PALETTE_LENGTH ); png_palette = (png_color *) png_malloc( write->pPng, palette_count * sizeof( png_color ) ); png_trans = (png_byte *) png_malloc( write->pPng, palette_count * sizeof( png_byte ) ); trans_count = 0; for( i = 0; i < palette_count; i++ ) { VipsPel *p = (VipsPel *) VIPS_IMAGE_ADDR( im_palette, i, 0 ); png_color *col = &png_palette[i]; col->red = p[0]; col->green = p[1]; col->blue = p[2]; png_trans[i] = p[3]; if( p[3] != 255 ) trans_count = i + 1; #ifdef DEBUG printf( "write_vips: palette[%d] %d %d %d %d\n", i + 1, p[0], p[1], p[2], p[3] ); #endif /*DEBUG*/ } #ifdef DEBUG printf( "write_vips: attaching %d color palette\n", palette_count ); #endif /*DEBUG*/ png_set_PLTE( write->pPng, write->pInfo, png_palette, palette_count ); if( trans_count ) { #ifdef DEBUG printf( "write_vips: attaching %d alpha values\n", trans_count ); #endif /*DEBUG*/ png_set_tRNS( write->pPng, write->pInfo, png_trans, trans_count, NULL ); } png_free( write->pPng, (void *) png_palette ); png_free( write->pPng, (void *) png_trans ); VIPS_UNREF( im_palette ); VIPS_UNREF( write->memory ); write->memory = im_index; in = write->memory; } #endif /*HAVE_IMAGEQUANT*/ png_write_info( write->pPng, write->pInfo ); /* If we're an intel byte order CPU and this is a 16bit image, we need * to swap bytes. */ if( bit_depth > 8 && !vips_amiMSBfirst() ) png_set_swap( write->pPng ); if( interlace ) nb_passes = png_set_interlace_handling( write->pPng ); else nb_passes = 1; /* Write data. */ for( i = 0; i < nb_passes; i++ ) if( vips_sink_disc( in, write_png_block, write ) ) return( -1 ); /* The setjmp() was held by our background writer: reset it. */ if( setjmp( png_jmpbuf( write->pPng ) ) ) return( -1 ); png_write_end( write->pPng, write->pInfo ); return( 0 ); }
void image_write_png(const char *name, int w, int h, int c, int b, void *p) { png_structp wp = NULL; png_infop ip = NULL; png_bytep *bp = NULL; FILE *fp = NULL; assert(name); assert(p); /* Initialize all PNG export data structures. */ if (!(fp = fopen(name, "wb"))) fail(name, strerror(errno)); if (!(wp = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) fail(name, "Failure to allocate PNG write structure"); if (!(ip = png_create_info_struct(wp))) fail(name, "Failure to allocate PNG info structure"); /* Enable the default PNG error handler. */ if (setjmp(png_jmpbuf(wp)) == 0) { static const int color[] = { 0, PNG_COLOR_TYPE_GRAY, PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_RGB, PNG_COLOR_TYPE_RGB_ALPHA }; /* Initialize the PNG header. */ png_init_io (wp, fp); /* png_set_compression_level(wp, 9); */ png_set_IHDR(wp, ip, w, h, b*8, color[c], PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Allocate and initialize the row pointers. */ if ((bp = (png_bytep *) png_malloc(wp, h * sizeof (png_bytep)))) { int i, j; for (i = 0, j = h - 1; j >= 0; ++i, --j) bp[i] = (png_bytep) p + i * w * c * b; /* Write the PNG image file. */ png_set_rows (wp, ip, bp); png_write_info(wp, ip); png_write_png (wp, ip, PNG_TRANSFORM_SWAP_ENDIAN, NULL); free(bp); } else fail(name, "Failure to allocate PNG row array"); } /* Release all resources. */ png_destroy_write_struct(&wp, &ip); fclose(fp); }
GRAPH * gr_read_png( const char * filename ) { GRAPH * bitmap ; unsigned int n, x ; uint16_t * ptr ; uint32_t * ptr32 ; uint32_t * orig ; uint32_t * row ; uint32_t Rshift, Gshift, Bshift ; uint32_t Rmask, Gmask, Bmask ; png_bytep * rowpointers ; png_structp png_ptr ; png_infop info_ptr, end_info ; png_uint_32 width, height, rowbytes; int depth, color ; /* Abre el fichero y se asegura de que screen está inicializada */ file * png = file_open( filename, "rb" ) ; if ( !png ) return NULL; /* Prepara las estructuras internas */ png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ) ; if ( !png_ptr ) { file_close( png ); return NULL; } info_ptr = png_create_info_struct( png_ptr ) ; end_info = png_create_info_struct( png_ptr ) ; if ( !info_ptr || !end_info ) { png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ; file_close( png ) ; return NULL; } /* Rutina de error */ #if (PNG_LIBPNG_VER>=10500) if ( setjmp( png_jmpbuf( png_ptr ) ) ) #else if ( setjmp( png_ptr->jmpbuf ) ) #endif { png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ; file_close( png ) ; return NULL; } /* Recupera información sobre el PNG */ png_set_read_fn( png_ptr, png, user_read_data ) ; png_read_info( png_ptr, info_ptr ) ; png_get_IHDR( png_ptr, info_ptr, &width, &height, &depth, &color, 0, 0, 0 ) ; row = malloc( sizeof( uint32_t ) * width ); if ( !row ) { png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ; file_close( png ) ; return NULL; } rowpointers = malloc( sizeof( png_bytep ) * height ); if ( !rowpointers ) { png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ; free( row ) ; file_close( png ) ; return NULL; } /* Configura los distintos modos disponibles */ if ( color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA ) { png_set_gray_to_rgb( png_ptr ); if ( color == PNG_COLOR_TYPE_GRAY ) png_set_filler( png_ptr, 0xFF, PNG_FILLER_AFTER ) ; } if ( depth == 16 ) png_set_strip_16( png_ptr ) ; if ( color == PNG_COLOR_TYPE_RGB ) png_set_filler( png_ptr, 0xFF, PNG_FILLER_AFTER ) ; png_set_bgr( png_ptr ) ; /* Recupera el fichero, convirtiendo a 16 bits si es preciso */ rowbytes = png_get_rowbytes( png_ptr, info_ptr ) ; bitmap = bitmap_new( 0, width, height, ( color == PNG_COLOR_TYPE_GRAY ) ? 1 : ( color == PNG_COLOR_TYPE_PALETTE ) ? 8 : ( sys_pixel_format->depth == 16 ? 16 : 32 ) ) ; if ( !bitmap ) { png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ; free( rowpointers ) ; free( row ) ; file_close( png ) ; return NULL; } if ( color == PNG_COLOR_TYPE_GRAY ) { for ( n = 0 ; n < height ; n++ ) { rowpointers[0] = ( void * )(( uint8_t * )bitmap->data ) + n * bitmap->pitch ; png_read_rows( png_ptr, rowpointers, 0, 1 ) ; } } else if ( color == PNG_COLOR_TYPE_PALETTE ) { /* Read the color palette */ png_colorp png_palette = ( png_colorp ) png_malloc( png_ptr, 256 * sizeof( png_color ) ) ; if ( !png_palette ) { png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ; free( rowpointers ) ; free( row ) ; file_close( png ) ; return NULL; } png_get_PLTE( png_ptr, info_ptr, &png_palette, ( int * ) &n ) ; uint8_t colors[256 * 3]; uint8_t * p = colors; for ( n = 0; n < 256 ; n++ ) { * p++ = png_palette[n].red; * p++ = png_palette[n].green; * p++ = png_palette[n].blue; } bitmap->format->palette = pal_new_rgb(( uint8_t * )colors ); pal_refresh( bitmap->format->palette ); if ( !sys_pixel_format->palette ) { sys_pixel_format->palette = pal_new( bitmap->format->palette ); /* pal_use( bitmap->format->palette ); */ palette_changed = 1 ; } for ( n = 0 ; n < height ; n++ ) rowpointers[n] = (( uint8_t* )bitmap->data ) + n * bitmap->pitch ; png_read_image( png_ptr, rowpointers ) ; /* If the depth is less than 8, expand the pixel values */ if ( depth == 4 ) { for ( n = 0; n < height; n++ ) { char * orig, * dest; orig = ( char * ) ( rowpointers[n] ); dest = orig + width - 1; orig += ( width - 1 ) / 2; for ( x = width; x--; ) { *dest-- = ( *orig >> ((( 1 - ( x & 0x01 ) ) << 2 ) ) ) & 0x0F ; if ( !( x & 0x01 ) ) orig--; } } } else if ( depth == 2 )
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; int status=-1; 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) goto png_create_write_struct_failed; info_ptr = png_create_info_struct (png_ptr); if (!info_ptr) goto png_create_info_struct_failed; // Set up error handler for png gen if (setjmp (png_jmpbuf(png_ptr))) { goto png_failure; } 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); 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; pixel_t *pixel = pixel_ptr(bitmap, 0, y); for (x=0; x<bitmap->width; ++x) { *row++=pixel->red; *row++=pixel->green; *row++=pixel->blue; ++pixel; } } 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); 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; }
/* * The function below was taken from http://www.lemoda.net/c/write-png/ * */ int save_png_to_file (_color *bitmap, int screenx, int screeny, 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, screenx, screeny, 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, screeny * sizeof (png_byte *)); for (y = 0; y < screeny; ++y) { png_byte *row = png_malloc (png_ptr, sizeof (uint8_t) * screenx * pixel_size); row_pointers[y] = row; for (x = 0; x < screenx; ++x) { pixel_t pixel; pixel.red = (uint8_t) bitmap[x + y * screenx].r; pixel.green = (uint8_t) bitmap[x + y * screenx].g; pixel.blue = (uint8_t) bitmap[x + y * screenx].b; *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 < screeny; 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; }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { goffset size; FILE *f; png_structp png_ptr; png_infop info_ptr; png_infop end_ptr; png_bytepp row_pointers; guint row; png_uint_32 width, height; gint bit_depth, color_type; gint interlace_type, compression_type, filter_type; const gchar *dlna_profile, *dlna_mimetype, *graph; TrackerSparqlBuilder *preupdate, *metadata; gchar *filename, *uri; GString *where; GFile *file; file = tracker_extract_info_get_file (info); filename = g_file_get_path (file); size = tracker_file_get_size (filename); preupdate = tracker_extract_info_get_preupdate_builder (info); metadata = tracker_extract_info_get_metadata_builder (info); graph = tracker_extract_info_get_graph (info); if (size < 64) { return FALSE; } f = tracker_file_open (filename); g_free (filename); if (!f) { return FALSE; } png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { tracker_file_close (f, FALSE); return FALSE; } info_ptr = png_create_info_struct (png_ptr); if (!info_ptr) { png_destroy_read_struct (&png_ptr, &info_ptr, NULL); tracker_file_close (f, FALSE); return FALSE; } end_ptr = png_create_info_struct (png_ptr); if (!end_ptr) { png_destroy_read_struct (&png_ptr, &info_ptr, NULL); tracker_file_close (f, FALSE); return FALSE; } if (setjmp (png_jmpbuf (png_ptr))) { png_destroy_read_struct (&png_ptr, &info_ptr, &end_ptr); tracker_file_close (f, FALSE); return FALSE; } png_init_io (png_ptr, f); png_read_info (png_ptr, info_ptr); if (!png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type)) { png_destroy_read_struct (&png_ptr, &info_ptr, &end_ptr); tracker_file_close (f, FALSE); return FALSE; } /* Read the image. FIXME We should be able to skip this step and * just get the info from the end. This causes some errors atm. */ row_pointers = g_new0 (png_bytep, height); for (row = 0; row < height; row++) { row_pointers[row] = png_malloc (png_ptr, png_get_rowbytes (png_ptr,info_ptr)); } png_read_image (png_ptr, row_pointers); for (row = 0; row < height; row++) { png_free (png_ptr, row_pointers[row]); } g_free (row_pointers); png_read_end (png_ptr, end_ptr); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nfo:Image"); tracker_sparql_builder_object (metadata, "nmm:Photo"); uri = g_file_get_uri (file); where = g_string_new (""); read_metadata (preupdate, metadata, where, png_ptr, info_ptr, end_ptr, uri, graph); tracker_extract_info_set_where_clause (info, where->str); g_string_free (where, TRUE); g_free (uri); tracker_sparql_builder_predicate (metadata, "nfo:width"); tracker_sparql_builder_object_int64 (metadata, width); tracker_sparql_builder_predicate (metadata, "nfo:height"); tracker_sparql_builder_object_int64 (metadata, height); if (guess_dlna_profile (bit_depth, width, height, &dlna_profile, &dlna_mimetype)) { tracker_sparql_builder_predicate (metadata, "nmm:dlnaProfile"); tracker_sparql_builder_object_string (metadata, dlna_profile); tracker_sparql_builder_predicate (metadata, "nmm:dlnaMime"); tracker_sparql_builder_object_string (metadata, dlna_mimetype); } png_destroy_read_struct (&png_ptr, &info_ptr, &end_ptr); tracker_file_close (f, FALSE); return TRUE; }
void Snapshot(int width, int height) { int i; char file_name[1024]; char randomname[200]; #ifdef USE_WIN //on Windows we have to save a bmp-file (problems with png) SDL_Surface *temp; unsigned char *pixels; /* create file */ get_history(file_name); mkdir(file_name); // every time is not a problem sprintf(randomname,"/screen-%i.bmp",rand()); strcat(file_name,randomname); temp = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0); if (temp == NULL) return; pixels =(png_byte *)malloc(width * height * 3 * sizeof(png_byte)); if (pixels == NULL) { SDL_FreeSurface(temp); return; } glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *)pixels); for (i=0; i<height; i++) memcpy(((char *) temp->pixels) + temp->pitch * i, pixels + 3*width * (height-i-1), width*3); free(pixels); SDL_SaveBMP(temp, file_name); SDL_FreeSurface(temp); return; #else #if COMPILE_PNG_CODE FILE *fp; png_structp png_ptr; png_infop info_ptr; png_colorp palette; png_byte *image; png_bytep *row_pointers; /* create file */ get_history(file_name); #ifdef USE_WIN mkdir(file_name); // every time is not a problem #else mkdir(file_name,0777); // every time is not a problem #endif sprintf(randomname,"/screen-%i.png",rand()); strcat(file_name,randomname); if((fp = fopen(file_name, "wb"))==NULL) { error_print("[write_png_file] File %s could not be opened for writing", file_name); return; } if((png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))==NULL) { error_print("[write_png_file] png_create_write_struct failed",NULL); fclose(fp); remove(file_name); return; } if((info_ptr = png_create_info_struct(png_ptr))==NULL) { error_print("[write_png_file] png_create_info_struct failed",NULL); fclose(fp); remove(file_name); #ifdef png_infopp_NULL png_destroy_write_struct(&png_ptr, png_infopp_NULL); #else png_destroy_write_struct(&png_ptr, (png_infopp)NULL); #endif } if (setjmp(png_jmpbuf(png_ptr))) { fclose(fp); remove(file_name); png_destroy_write_struct(&png_ptr, &info_ptr); return; } 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); palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof (png_color)); png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); png_write_info(png_ptr, info_ptr); png_set_packing(png_ptr); if((image = (png_byte *)malloc(width * height * 3 * sizeof(png_byte)))==NULL) { fclose(fp); remove(file_name); png_destroy_write_struct(&png_ptr, &info_ptr); return; } if((row_pointers = (png_bytep *)malloc(height * sizeof(png_bytep)))==NULL) { fclose(fp); remove(file_name); png_destroy_write_struct(&png_ptr, &info_ptr); free(image); image = NULL; return; } glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *)image); for (i = 0; i < height; i++) { row_pointers[i] = (png_bytep)image + (height - i) * width * 3; } png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); png_free(png_ptr, palette); png_destroy_write_struct(&png_ptr, &info_ptr); free(row_pointers); free(image); fclose(fp); return; #endif // COMPILE_PNG_CODE #endif // USE_WIN }
//--------------------------------------------------------------------------- void __fastcall TDeePNG::SaveToStream(Classes::TStream * Stream) { // SaveToStream method // warning: this method would change the pixelformat to pf24bit // if the pixelformat is pfDevice, pf15bit, pf16bit, or pfCustom. png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_bytep row_buffer = NULL; try { // create png_struct png_ptr = png_create_write_struct_2 (PNG_LIBPNG_VER_STRING, (png_voidp)this, DeePNG_error, DeePNG_warning, (png_voidp)this, DeePNG_malloc, DeePNG_free); // create png_info info_ptr = png_create_info_struct(png_ptr); // set write function png_set_write_fn(png_ptr, (png_voidp)Stream, DeePNG_write_data, DeePNG_flush); // set IHDR if(PixelFormat == pfDevice || PixelFormat == pf15bit || PixelFormat == pf16bit || PixelFormat == pfCustom) PixelFormat = pf24bit; bool grayscale = IsGrayscaleBitmap(this); int colordepth = GetBitmapColorDepth(this); int w = Width; int h = Height; int color_type; if(grayscale) color_type = PNG_COLOR_TYPE_GRAY; else if(colordepth <= 8) color_type = PNG_COLOR_TYPE_PALETTE; else if(colordepth == 32) color_type = PNG_COLOR_TYPE_RGB_ALPHA; else color_type = PNG_COLOR_TYPE_RGB; png_set_IHDR(png_ptr, info_ptr, w, h, colordepth < 8 ? colordepth : 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); // set oFFs if(ofs_set) png_set_oFFs(png_ptr, info_ptr, ofs_x, ofs_y, ofs_unit); // set palette if(color_type == PNG_COLOR_TYPE_PALETTE) { png_color *palette = (png_colorp)png_malloc(png_ptr, 256 * sizeof(png_color)); PALETTEENTRY palentry[256]; int num_palette = GetPaletteEntries(Palette, 0, (1<<colordepth), palentry); for(int i = 0; i < num_palette; i++) { palette[i].red = palentry[i].peRed; palette[i].green = palentry[i].peGreen; palette[i].blue = palentry[i].peBlue; } png_set_PLTE(png_ptr, info_ptr, palette, num_palette); } // write info png_write_info(png_ptr, info_ptr); // write vpAg private chunk if(vpag_set) { png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'}; unsigned char vpag_chunk_data[9]; #define PNG_write_be32(p, a) (\ ((unsigned char *)(p))[0] = (unsigned char)(((a) >>24) & 0xff), \ ((unsigned char *)(p))[1] = (unsigned char)(((a) >>16) & 0xff), \ ((unsigned char *)(p))[2] = (unsigned char)(((a) >> 8) & 0xff), \ ((unsigned char *)(p))[3] = (unsigned char)(((a) ) & 0xff) ) PNG_write_be32(vpag_chunk_data, vpag_w); PNG_write_be32(vpag_chunk_data + 4, vpag_h); vpag_chunk_data[8] = (unsigned char)vpag_unit; png_write_chunk(png_ptr, png_vpAg, vpag_chunk_data, 9); } /* // change RGB order if(color_type = PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_bgr(png_ptr); // ???? why this does not work ? */ // write image if(color_type == PNG_COLOR_TYPE_RGB) { row_buffer = (png_bytep)png_malloc(png_ptr, 3 * w + 6); try { png_bytep row_pointer = row_buffer; for(int i = 0; i < h; i++) { png_bytep in = (png_bytep)ScanLine[i]; png_bytep out = row_buffer; for(int x = 0; x < w; x++) { out[2] = in[0]; out[1] = in[1]; out[0] = in[2]; out += 3; in += 3; } png_write_row(png_ptr, row_pointer); } } catch(...) { png_free(png_ptr, row_buffer); throw; } png_free(png_ptr, row_buffer); } else if(color_type == PNG_COLOR_TYPE_RGB_ALPHA) { row_buffer = (png_bytep)png_malloc(png_ptr, 4 * w + 6); try { png_bytep row_pointer = row_buffer; for(int i = 0; i < h; i++) { png_bytep in = (png_bytep)ScanLine[i]; png_bytep out = row_buffer; for(int x = 0; x < w; x++) { out[2] = in[0]; out[1] = in[1]; out[0] = in[2]; out[3] = in[3]; out += 4; in += 4; } png_write_row(png_ptr, row_pointer); } } catch(...) { png_free(png_ptr, row_buffer); throw; } png_free(png_ptr, row_buffer); } else { for(int i = 0; i < h; i++) { png_bytep row_pointer = (png_bytep)ScanLine[i]; png_write_row(png_ptr, row_pointer); } } // finish writing png_write_end(png_ptr, info_ptr); } catch(...) { png_destroy_write_struct(&png_ptr, &info_ptr); throw; } png_destroy_write_struct(&png_ptr, &info_ptr); }
int ExtractBits(PNG_CONST TCHAR *inname, PNG_CONST TCHAR *outname) { static HANDLE fpin; static HANDLE fpout; /* "static" prevents setjmp corruption */ png_structp read_ptr; png_infop read_info_ptr, end_info_ptr; png_structp write_ptr = NULL; png_infop write_info_ptr = NULL; png_infop write_end_info_ptr = NULL; png_bytep row_buf; png_uint_32 y; png_uint_32 width, height; int num_pass, pass; int bit_depth, color_type; char inbuf[256], outbuf[256]; row_buf = NULL; if ((fpin = CreateFile(inname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) { fprintf(STDERR, "Could not find input file %s\n", inname); return (1); } if ((fpout = CreateFile(outname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE) { fprintf(STDERR, "Could not open output file %s\n", outname); FCLOSE(fpin); return (1); } png_debug(0, "Allocating read and write structures"); read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL); png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, pngtest_warning); png_debug(0, "Allocating read_info, write_info and end_info structures"); read_info_ptr = png_create_info_struct(read_ptr); end_info_ptr = png_create_info_struct(read_ptr); png_debug(0, "Setting jmpbuf for read struct"); if (setjmp(png_jmpbuf(read_ptr))) { fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); png_free(read_ptr, row_buf); row_buf = NULL; png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); FCLOSE(fpin); FCLOSE(fpout); return (1); } png_debug(0, "Initializing input and output streams"); png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); if (status_dots_requested == 1) { png_set_read_status_fn(read_ptr, read_row_callback); } else { png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL); } png_debug(0, "Reading info struct"); png_read_info(read_ptr, read_info_ptr); png_debug(0, "Transferring info struct"); { int interlace_type, compression_type, filter_type; if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type)) { png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, compression_type, filter_type); } } { int intent; if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) png_set_sRGB(write_ptr, write_info_ptr, intent); } { png_colorp palette; int num_palette; if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); } { png_color_8p sig_bit; if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) png_set_sBIT(write_ptr, write_info_ptr, sig_bit); } { png_bytep trans; int num_trans; png_color_16p trans_values; if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans, &trans_values)) { int sample_max = (1 << read_info_ptr->bit_depth); /* libpng doesn't reject a tRNS chunk with out-of-range samples */ if (!((read_info_ptr->color_type == PNG_COLOR_TYPE_GRAY && (int)trans_values->gray > sample_max) || (read_info_ptr->color_type == PNG_COLOR_TYPE_RGB && ((int)trans_values->red > sample_max || (int)trans_values->green > sample_max || (int)trans_values->blue > sample_max)))) png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans, trans_values); } } png_debug(0, "Writing row data"); num_pass = png_set_interlace_handling(read_ptr); for(pass = 0; pass < num_pass; pass++) { png_debug1(0, "Writing row data for pass %d", pass); for(y = 0; y < height; y++) { png_debug2(0, "Allocating row buffer (pass %d, y = %ld)...", pass, y); row_buf = (png_bytep)png_malloc(read_ptr, png_get_rowbytes(read_ptr, read_info_ptr)); png_debug2(0, "0x%08lx (%ld bytes)", (unsigned long)row_buf, png_get_rowbytes(read_ptr, read_info_ptr)); png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1); png_debug2(0, "Freeing row buffer (pass %d, y = %ld)", pass, y); png_free(read_ptr, row_buf); row_buf = NULL; } } png_debug(0, "Reading and writing end_info data"); png_read_end(read_ptr, end_info_ptr); { png_uint_32 iwidth, iheight; iwidth = png_get_image_width(write_ptr, write_info_ptr); iheight = png_get_image_height(write_ptr, write_info_ptr); fprintf(STDERR, "\n Image width = %lu, height = %lu\n", (unsigned long)iwidth, (unsigned long)iheight); } png_debug(0, "Destroying data structs"); png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr"); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); png_debug(0, "Destruction complete."); FCLOSE(fpin); FCLOSE(fpout); png_debug(0, "Opening files for comparison"); if ((fpin = CreateFile(inname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) { fprintf(STDERR, "Could not find file %s\n", inname); return (1); } if ((fpout = CreateFile(outname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) { fprintf(STDERR, "Could not find file %s\n", outname); FCLOSE(fpin); return (1); } for(;;) { DWORD num_in, num_out; READFILE(fpin, inbuf, 1, num_in); READFILE(fpout, outbuf, 1, num_out); if (num_in != num_out) { fprintf(STDERR, "\nFiles %s and %s are of a different size\n", inname, outname); if (wrote_question == 0) { fprintf(STDERR, " Was %s written with the same maximum IDAT chunk size (%d bytes),", inname, PNG_ZBUF_SIZE); fprintf(STDERR, "\n filtering heuristic (libpng default), compression"); fprintf(STDERR, " level (zlib default),\n and zlib version (%s)?\n\n", ZLIB_VERSION); wrote_question = 1; } FCLOSE(fpin); FCLOSE(fpout); return (0); } if (!num_in) break; if (png_memcmp(inbuf, outbuf, num_in)) { fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); if (wrote_question == 0) { fprintf(STDERR, " Was %s written with the same maximum IDAT chunk size (%d bytes),", inname, PNG_ZBUF_SIZE); fprintf(STDERR, "\n filtering heuristic (libpng default), compression"); fprintf(STDERR, " level (zlib default),\n and zlib version (%s)?\n\n", ZLIB_VERSION); wrote_question = 1; } FCLOSE(fpin); FCLOSE(fpout); return (0); } } FCLOSE(fpin); FCLOSE(fpout); return (0); }
void /* PRIVATE */ png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) { if (png_ptr->buffer_size && png_ptr->current_text_left) { png_size_t text_size; if (png_ptr->buffer_size < png_ptr->current_text_left) text_size = png_ptr->buffer_size; else text_size = png_ptr->current_text_left; png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); png_ptr->current_text_left -= text_size; png_ptr->current_text_ptr += text_size; } if (!(png_ptr->current_text_left)) { png_textp text_ptr; png_charp text; png_charp key; int ret; if (png_ptr->buffer_size < 4) { png_push_save_buffer(png_ptr); return; } png_push_crc_finish(png_ptr); #if defined(PNG_MAX_MALLOC_64K) if (png_ptr->skip_length) return; #endif key = png_ptr->current_text; for (text = key; *text; text++) /* empty loop */ ; if (text != key + png_ptr->current_text_size) text++; text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)png_sizeof(png_text)); text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; text_ptr->key = key; #ifdef PNG_iTXt_SUPPORTED text_ptr->lang = NULL; text_ptr->lang_key = NULL; #endif text_ptr->text = text; ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); png_free(png_ptr, key); png_free(png_ptr, text_ptr); png_ptr->current_text = NULL; if (ret) png_warning(png_ptr, "Insufficient memory to store text chunk."); } }
void PNGAPI png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, png_const_bytep chunk_list, int num_chunks_in) { png_bytep new_list; unsigned int num_chunks, old_num_chunks; if (png_ptr == NULL) return; if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST) { png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep"); return; } if (num_chunks_in <= 0) { png_ptr->unknown_default = keep; /* '0' means just set the flags, so stop here */ if (num_chunks_in == 0) return; } if (num_chunks_in < 0) { /* Ignore all unknown chunks and all chunks recognized by * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND */ static PNG_CONST u8 chunks_to_ignore[] = { 98, 75, 71, 68, '\0', /* bKGD */ 99, 72, 82, 77, '\0', /* cHRM */ 103, 65, 77, 65, '\0', /* gAMA */ 104, 73, 83, 84, '\0', /* hIST */ 105, 67, 67, 80, '\0', /* iCCP */ 105, 84, 88, 116, '\0', /* iTXt */ 111, 70, 70, 115, '\0', /* oFFs */ 112, 67, 65, 76, '\0', /* pCAL */ 112, 72, 89, 115, '\0', /* pHYs */ 115, 66, 73, 84, '\0', /* sBIT */ 115, 67, 65, 76, '\0', /* sCAL */ 115, 80, 76, 84, '\0', /* sPLT */ 115, 84, 69, 82, '\0', /* sTER */ 115, 82, 71, 66, '\0', /* sRGB */ 116, 69, 88, 116, '\0', /* tEXt */ 116, 73, 77, 69, '\0', /* tIME */ 122, 84, 88, 116, '\0' /* zTXt */ }; chunk_list = chunks_to_ignore; num_chunks = (sizeof chunks_to_ignore)/5; } else /* num_chunks_in > 0 */ { if (chunk_list == NULL) { /* Prior to 1.6.0 this was silently ignored, now it is an app_error * which can be switched off. */ png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list"); return; } num_chunks = num_chunks_in; } old_num_chunks = png_ptr->num_chunk_list; if (png_ptr->chunk_list == NULL) old_num_chunks = 0; /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow. */ if (num_chunks + old_num_chunks > UINT_MAX/5) { png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks"); return; } /* If these chunks are being reset to the default then no more memory is * required because add_one_chunk above doesn't extend the list if the 'keep' * parameter is the default. */ if (keep != 0) { new_list = png_voidcast(png_bytep, png_malloc(png_ptr, 5 * (num_chunks + old_num_chunks))); if (old_num_chunks > 0) memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks); } else if (old_num_chunks > 0) new_list = png_ptr->chunk_list; else new_list = NULL; /* Add the new chunks together with each one's handling code. If the chunk * already exists the code is updated, otherwise the chunk is added to the * end. (In libpng 1.6.0 order no longer matters because this code enforces * the earlier convention that the last setting is the one that is used.) */ if (new_list != NULL) { png_const_bytep inlist; png_bytep outlist; unsigned int i; for (i=0; i<num_chunks; ++i) old_num_chunks = add_one_chunk(new_list, old_num_chunks, chunk_list+5*i, keep); /* Now remove any spurious 'default' entries. */ num_chunks = 0; for (i=0, inlist=outlist=new_list; i<old_num_chunks; ++i, inlist += 5) if (inlist[4]) { if (outlist != inlist) memcpy(outlist, inlist, 5); outlist += 5; ++num_chunks; } /* This means the application has removed all the specialized handling. */ if (num_chunks == 0) { if (png_ptr->chunk_list != new_list) png_free(png_ptr, new_list); new_list = NULL; } } else num_chunks = 0; png_ptr->num_chunk_list = num_chunks; if (png_ptr->chunk_list != new_list) { if (png_ptr->chunk_list != NULL) png_free(png_ptr, png_ptr->chunk_list); png_ptr->chunk_list = new_list; } }
void /* PRIVATE */ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) { if (png_ptr->buffer_size && png_ptr->current_text_left) { png_size_t text_size; if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) text_size = png_ptr->buffer_size; else text_size = png_ptr->current_text_left; png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); png_ptr->current_text_left -= text_size; png_ptr->current_text_ptr += text_size; } if (!(png_ptr->current_text_left)) { png_textp text_ptr; png_charp text; png_charp key; int ret; png_size_t text_size, key_size; if (png_ptr->buffer_size < 4) { png_push_save_buffer(png_ptr); return; } png_push_crc_finish(png_ptr); key = png_ptr->current_text; for (text = key; *text; text++) /* empty loop */ ; /* zTXt can't have zero text */ if (text == key + png_ptr->current_text_size) { png_ptr->current_text = NULL; png_free(png_ptr, key); return; } text++; if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */ { png_ptr->current_text = NULL; png_free(png_ptr, key); return; } text++; png_ptr->zstream.next_in = (png_bytep )text; png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - (text - key)); png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; key_size = text - key; text_size = 0; text = NULL; ret = Z_STREAM_END; while (png_ptr->zstream.avail_in) { ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); if (ret != Z_OK && ret != Z_STREAM_END) { inflateReset(&png_ptr->zstream); png_ptr->zstream.avail_in = 0; png_ptr->current_text = NULL; png_free(png_ptr, key); png_free(png_ptr, text); return; } if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) { if (text == NULL) { text = (png_charp)png_malloc(png_ptr, (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out + key_size + 1)); png_memcpy(text + key_size, png_ptr->zbuf, png_ptr->zbuf_size - png_ptr->zstream.avail_out); png_memcpy(text, key, key_size); text_size = key_size + png_ptr->zbuf_size - png_ptr->zstream.avail_out; *(text + text_size) = '\0'; } else { png_charp tmp; tmp = text; text = (png_charp)png_malloc(png_ptr, text_size + (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); png_memcpy(text, tmp, text_size); png_free(png_ptr, tmp); png_memcpy(text + text_size, png_ptr->zbuf, png_ptr->zbuf_size - png_ptr->zstream.avail_out); text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; *(text + text_size) = '\0'; } if (ret != Z_STREAM_END) { png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; } } else { break; } if (ret == Z_STREAM_END) break; } inflateReset(&png_ptr->zstream); png_ptr->zstream.avail_in = 0; if (ret != Z_STREAM_END) { png_ptr->current_text = NULL; png_free(png_ptr, key); png_free(png_ptr, text); return; } png_ptr->current_text = NULL; png_free(png_ptr, key); key = text; text += key_size; text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)png_sizeof(png_text)); text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; text_ptr->key = key; #ifdef PNG_iTXt_SUPPORTED text_ptr->lang = NULL; text_ptr->lang_key = NULL; #endif text_ptr->text = text; ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); png_free(png_ptr, key); png_free(png_ptr, text_ptr); if (ret) png_warning(png_ptr, "Insufficient memory to store text chunk."); } }
# endif } } /* Allocate memory. For reasonable files, size should never exceed * 64K. However, zlib may allocate more than 64K if you don't tell * it not to. See zconf.h and png.h for more information. zlib does * need to allocate exactly 64K, so whatever you call here must * have the ability to do that. */ PNG_FUNCTION(png_voidp,PNGAPI png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) { png_voidp ret; ret = png_malloc(png_ptr, size); if (ret != NULL) memset(ret, 0, size); return ret; } /* png_malloc_base, an internal function added at libpng 1.6.0, does the work of * allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED. * Checking and error handling must happen outside this routine; it returns NULL * if the allocation cannot be done (for any reason.) */ PNG_FUNCTION(png_voidp /* PRIVATE */, png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), PNG_ALLOCATED)
void /* PRIVATE */ png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) { if (png_ptr->buffer_size && png_ptr->current_text_left) { png_size_t text_size; if (png_ptr->buffer_size < png_ptr->current_text_left) text_size = png_ptr->buffer_size; else text_size = png_ptr->current_text_left; png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); png_ptr->current_text_left -= text_size; png_ptr->current_text_ptr += text_size; } if (!(png_ptr->current_text_left)) { png_textp text_ptr; png_charp key; int comp_flag; png_charp lang; png_charp lang_key; png_charp text; int ret; if (png_ptr->buffer_size < 4) { png_push_save_buffer(png_ptr); return; } png_push_crc_finish(png_ptr); #if defined(PNG_MAX_MALLOC_64K) if (png_ptr->skip_length) return; #endif key = png_ptr->current_text; for (lang = key; *lang; lang++) /* empty loop */ ; if (lang != key + png_ptr->current_text_size) lang++; comp_flag = *lang++; lang++; /* skip comp_type, always zero */ for (lang_key = lang; *lang_key; lang_key++) /* empty loop */ ; lang_key++; /* skip NUL separator */ for (text = lang_key; *text; text++) /* empty loop */ ; if (text != key + png_ptr->current_text_size) text++; text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)png_sizeof(png_text)); text_ptr->compression = comp_flag + 2; text_ptr->key = key; text_ptr->lang = lang; text_ptr->lang_key = lang_key; text_ptr->text = text; text_ptr->text_length = 0; text_ptr->itxt_length = png_strlen(text); ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); png_ptr->current_text = NULL; png_free(png_ptr, text_ptr); if (ret) png_warning(png_ptr, "Insufficient memory to store iTXt chunk."); } }
/** * Read in a PNG file and return it in a buffer pointer. Make sure to fill * in the w & h parameters with the width & height of the image. Given filename * must point to a PNG file. */ static Color_t *readPNG(char const *filename, int *w, int *h) { int x, y; png_byte color_type; png_structp png_ptr; png_infop info_ptr; png_byte bit_depth; png_bytep *row_pointers; int width, height; char header[8]; FILE *fp; Color_t *buffer; fp = fopen(filename, "rb"); if (!fp) abort_("Unable to open %s.\n", filename); if (fread(header, 1, sizeof(header), fp) != 8) abort_("Read mismatch on header.\n"); if (png_sig_cmp(header, 0, 8)) abort_("File %s is not recognized as a PNG file.\n", filename); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) abort_("Unable to create read struct.\n"); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) abort_("Unable to create info structure.\n"); if (setjmp(png_jmpbuf(png_ptr))) abort_("Error during read IO\n"); png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); png_read_update_info(png_ptr, info_ptr); if (setjmp(png_jmpbuf(png_ptr))) abort_("Error during read_image\n"); row_pointers = png_malloc(png_ptr, sizeof(png_bytep) * height); for (y = 0; y < height; y++) row_pointers[y] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); png_read_image(png_ptr, row_pointers); fclose(fp); if (png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGB) abort_("Expected RGB image.\n"); /* Allocate memory for the buffer. */ buffer = malloc(width * height * sizeof(Color_t)); if (!buffer) abort_("Unable to allocate memory.\n"); for (y = 0; y < height; y++) { png_bytep row = row_pointers[y]; for (x = 0; x < width; x++) { png_bytep px = &(row[x * 3]); Color_t *pColor = &buffer[coord_to_ind(x, y, width)]; pColor->red = px[0]; pColor->green = px[1]; pColor->blue = px[2]; } } for (y = 0; y < height; y++) png_free(png_ptr, row_pointers[y]); png_free(png_ptr, row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (h) *h = height; if (w) *w = width; return buffer; }
/* This function is called when we haven't found a handler for this * chunk. If there isn't a problem with the chunk itself (ie a bad chunk * name or a critical chunk), the chunk is (currently) silently ignored. */ void /* PRIVATE */ png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { png_uint_32 skip=0; png_check_chunk_name(png_ptr, png_ptr->chunk_name); if (!(png_ptr->chunk_name[0] & 0x20)) { #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != PNG_HANDLE_CHUNK_ALWAYS #if defined(PNG_READ_USER_CHUNKS_SUPPORTED) && png_ptr->read_user_chunk_fn == NULL #endif ) #endif png_chunk_error(png_ptr, "unknown critical chunk"); /* to quiet compiler warnings about unused info_ptr */ if (info_ptr == NULL) return; } #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) { png_unknown_chunk chunk; #ifdef PNG_MAX_MALLOC_64K if (length > (png_uint_32)65535L) { png_warning(png_ptr, "unknown chunk too large to fit in memory"); skip = length - (png_uint_32)65535L; length = (png_uint_32)65535L; } #endif png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name); chunk.data = (png_bytep)png_malloc(png_ptr, length); png_crc_read(png_ptr, chunk.data, length); chunk.size = length; #if defined(PNG_READ_USER_CHUNKS_SUPPORTED) if(png_ptr->read_user_chunk_fn != NULL) { /* callback to user unknown chunk handler */ if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0) { if (!(png_ptr->chunk_name[0] & 0x20)) if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != PNG_HANDLE_CHUNK_ALWAYS) png_chunk_error(png_ptr, "unknown critical chunk"); } png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); } else #endif png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1); png_free(png_ptr, chunk.data); } else #endif skip=length; png_push_crc_skip(png_ptr, skip); }
void PNGAPI png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, png_size_t png_struct_size) { #ifdef PNG_SETJMP_SUPPORTED jmp_buf tmp_jmp; /* to save current jump buffer */ #endif int i=0; png_structp png_ptr=*ptr_ptr; do { if(user_png_ver[i] != png_libpng_ver[i]) { #ifdef PNG_LEGACY_SUPPORTED png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; #else png_ptr->warning_fn=NULL; png_warning(png_ptr, "Application uses deprecated png_read_init() and should be recompiled."); break; #endif } } while (png_libpng_ver[i++]); png_debug(1, "in png_read_init_3\n"); #ifdef PNG_SETJMP_SUPPORTED /* save jump buffer and error functions */ png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); #endif if(png_sizeof(png_struct) > png_struct_size) { png_destroy_struct(png_ptr); *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); png_ptr = *ptr_ptr; } /* reset all variables to 0 */ png_memset(png_ptr, 0, png_sizeof (png_struct)); #ifdef PNG_SETJMP_SUPPORTED /* restore jump buffer */ png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); #endif /* added at libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED png_ptr->user_width_max=PNG_USER_WIDTH_MAX; png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; #endif /* initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size); png_ptr->zstream.zalloc = png_zalloc; png_ptr->zstream.zfree = png_zfree; png_ptr->zstream.opaque = (voidpf)png_ptr; switch (inflateInit(&png_ptr->zstream)) { case Z_OK: /* Do nothing */ break; case Z_MEM_ERROR: case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break; case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break; default: png_error(png_ptr, "Unknown zlib error"); } png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); }
void PNGAPI png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, int num_text) { int i; png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ? "text" : (png_const_charp)png_ptr->chunk_name)); if (png_ptr == NULL || info_ptr == NULL || num_text == 0) return; /* Make sure we have enough space in the "text" array in info_struct * to hold all of the incoming text_ptr objects. */ if (info_ptr->num_text + num_text > info_ptr->max_text) { if (info_ptr->text != NULL) { png_textp old_text; int old_max; old_max = info_ptr->max_text; info_ptr->max_text = info_ptr->num_text + num_text + 8; old_text = info_ptr->text; info_ptr->text = (png_textp)png_malloc(png_ptr, (png_uint_32)(info_ptr->max_text * sizeof (png_text))); png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * sizeof(png_text))); png_free(png_ptr, old_text); } else { info_ptr->max_text = num_text + 8; info_ptr->num_text = 0; info_ptr->text = (png_textp)png_malloc(png_ptr, (png_uint_32)(info_ptr->max_text * sizeof (png_text))); #ifdef PNG_FREE_ME_SUPPORTED info_ptr->free_me |= PNG_FREE_TEXT; #endif } png_debug1(3, "allocated %d entries for info_ptr->text\n", info_ptr->max_text); } for (i = 0; i < num_text; i++) { png_size_t text_length,key_len; png_size_t lang_len,lang_key_len; png_textp textp = &(info_ptr->text[info_ptr->num_text]); if (text_ptr[i].key == NULL) continue; key_len = png_strlen(text_ptr[i].key); if(text_ptr[i].compression <= 0) { lang_len = 0; lang_key_len = 0; } else #ifdef PNG_iTXt_SUPPORTED { /* set iTXt data */ if (text_ptr[i].key != NULL) lang_len = png_strlen(text_ptr[i].lang); else lang_len = 0; if (text_ptr[i].lang_key != NULL) lang_key_len = png_strlen(text_ptr[i].lang_key); else lang_key_len = 0; } #else { png_warning(png_ptr, "iTXt chunk not supported."); continue; } #endif if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') { text_length = 0; #ifdef PNG_iTXt_SUPPORTED if(text_ptr[i].compression > 0) textp->compression = PNG_ITXT_COMPRESSION_NONE; else #endif textp->compression = PNG_TEXT_COMPRESSION_NONE; } else { text_length = png_strlen(text_ptr[i].text); textp->compression = text_ptr[i].compression; } textp->key = (png_charp)png_malloc(png_ptr, (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4)); png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n", (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4), (int)textp->key); png_memcpy(textp->key, text_ptr[i].key, (png_size_t)(key_len)); *(textp->key+key_len) = '\0'; #ifdef PNG_iTXt_SUPPORTED if (text_ptr[i].compression > 0) { textp->lang=textp->key + key_len + 1; png_memcpy(textp->lang, text_ptr[i].lang, lang_len); *(textp->lang+lang_len) = '\0'; textp->lang_key=textp->lang + lang_len + 1; png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); *(textp->lang_key+lang_key_len) = '\0'; textp->text=textp->lang_key + lang_key_len + 1; } else #endif { #ifdef PNG_iTXt_SUPPORTED textp->lang=(png_charp)NULL; textp->lang_key=(png_charp)NULL; #endif textp->text=textp->key + key_len + 1; } if(text_length) png_memcpy(textp->text, text_ptr[i].text, (png_size_t)(text_length)); *(textp->text+text_length) = '\0'; #ifdef PNG_iTXt_SUPPORTED if(textp->compression > 0) { textp->text_length = 0; textp->itxt_length = text_length; } else #endif { textp->text_length = text_length; #ifdef PNG_iTXt_SUPPORTED textp->itxt_length = 0; #endif } info_ptr->text[info_ptr->num_text]= *textp; info_ptr->num_text++; png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text); } }
errCode writeSheets( const char *strPath, const char *strManName, sTex **refArrTex, sSheetList *pSheets ){ char buff[128]; size_t s, r, i; FILE *handFile; png_byte **dynarrImg; png_structp pngptrWriteData; png_infop pngptrWriteInfo; png_size_t sizeRow; unsigned int w, h; for(s=0; s < pSheets->num; ++s){ handFile = NULL; dynarrImg = NULL; pngptrWriteData = NULL; pngptrWriteInfo = NULL; w = pSheets->dynarrSheets[s]->w; h = pSheets->dynarrSheets[s]->h; if(w==0 || h==0){ WARN("bad sheet dimensions."); continue; } snprintf(buff, 128, "%s%s%i.png", (strPath!=NULL) ? strPath : "", strManName, (int)s ); handFile = fopen(buff, "wb"); if(handFile == NULL){ WARN("Unable to write to file %s", buff); goto fail_loop_writeSheets; } pngptrWriteData = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, myPNGWarnFoo ); if(pngptrWriteData == NULL){ WARN("Can't make png write data"); goto fail_loop_writeSheets; } pngptrWriteInfo = png_create_info_struct(pngptrWriteData); if(pngptrWriteInfo == NULL){ WARN("Can't make png write info"); goto fail_loop_writeSheets; } if(setjmp (png_jmpbuf (pngptrWriteData))){ goto fail_loop_writeSheets; } png_set_IHDR( pngptrWriteData, pngptrWriteInfo, w, h, DEFAULT_BITDEPTH, DEFAULT_COLOURTYPE, DEFAULT_INTERLACE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); png_set_gamma(pngptrWriteData, 2.2, 1.0/2.2); sizeRow = png_get_rowbytes( pngptrWriteData, pngptrWriteInfo ); dynarrImg = calloc_chk( (h +1), sizeof(png_byte*) ); dynarrImg[h] = NULL; for(r=0; r < h; ++r){ dynarrImg[r] = png_malloc(pngptrWriteData, sizeRow); memset(dynarrImg[r], 0, sizeRow); } for(i=0; i < pSheets->dynarrSheets[s]->num; ++i){ if(readTexToSheet( refArrTex[ pSheets->dynarrSheets[s]->dynarrTexIDs[i] ], dynarrImg, w, h, sizeRow )==PROBLEM) goto fail_loop_writeSheets; } XTRA_LOG("About to write %s\n", buff); png_init_io(pngptrWriteData, handFile); png_set_rows(pngptrWriteData, pngptrWriteInfo, dynarrImg); png_write_info(pngptrWriteData, pngptrWriteInfo); png_write_image(pngptrWriteData, dynarrImg); png_write_end(pngptrWriteData, pngptrWriteInfo); fail_loop_writeSheets: if(pngptrWriteInfo != NULL && pngptrWriteData != NULL){ if(dynarrImg != NULL) cleanupPNGImg(pngptrWriteData, &dynarrImg); png_destroy_write_struct(&pngptrWriteData, &pngptrWriteInfo); } if(handFile != NULL) fclose(handFile); } return NOPROB; }
int /* PRIVATE */ pngx_read_pnm(png_structp png_ptr, png_infop info_ptr, FILE *stream) { pnm_struct pnminfo; unsigned int format, depth, width, height, maxval; unsigned int num_samples, sample_size; unsigned int *pnmrow; size_t row_size; png_bytepp row_pointers; png_color_8 sig_bit; unsigned int i, j; int failed, overflow; /* Read the PNM header. */ if (pnm_fget_header(&pnminfo, stream) != 1) return 0; /* not PNM */ format = pnminfo.format; depth = pnminfo.depth; width = pnminfo.width; height = pnminfo.height; maxval = pnminfo.maxval; if (format > PNM_P6) png_error(png_ptr, "Can't handle PNM formats newer than PPM (\"P6\")"); if (width > (unsigned int)(-1) / depth || width > (size_t)(-1) / sizeof(unsigned int) / depth) png_error(png_ptr, "Can't handle exceedingly large PNM dimensions"); sample_size = 1; row_size = num_samples = depth * width; if (maxval > 65535) png_error(png_ptr, "Can't handle PNM samples larger than 16 bits"); else if (maxval > 255) { sample_size = 2; row_size *= 2; } /* Set the PNG image type. */ png_set_IHDR(png_ptr, info_ptr, width, height, (maxval <= 255) ? 8 : 16, (depth == 1) ? PNG_COLOR_TYPE_GRAY : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); for (i = 1, j = 2; j - 1 < maxval; ++i, j <<= 1) { } if (j - 1 != maxval) png_warning(png_ptr, "Possibly inexact sample conversion from PNM to PNG"); else if (i % 8 != 0 && (depth > 1 || 8 % i != 0)) { sig_bit.red = sig_bit.green = sig_bit.blue = sig_bit.gray = (png_byte)i; sig_bit.alpha = 0; png_set_sBIT(png_ptr, info_ptr, &sig_bit); } /* Allocate memory. */ row_pointers = pngx_malloc_rows(png_ptr, info_ptr, -1); if ((format >= PNM_P4) && (maxval == 255 || maxval == 65535)) pnmrow = NULL; /* can read raw data directly into row_pointers */ else pnmrow = (unsigned int *) png_malloc(png_ptr, num_samples * sizeof(unsigned int)); /* Read the image data. */ failed = 0; overflow = 0; if (pnmrow != NULL) { for (i = 0; i < height; ++i) { if (pnm_fget_values(&pnminfo, pnmrow, 1, stream) <= 0) failed = 1; /* Transfer the samples, even on partial (unsuccessful) reads. */ if (maxval <= 255) { for (j = 0; j < num_samples; ++j) { unsigned int val = pnmrow[j]; if (val > maxval) { val = 255; overflow = 1; } else if (maxval != 255) val = (val * 255 + maxval/2) / maxval; row_pointers[i][j] = (png_byte)val; } } else /* maxval > 255 */ { for (j = 0; j < num_samples; ++j) { png_uint_32 val = pnmrow[j]; if (val > maxval) { val = 65535; overflow = 1; } else if (maxval != 65535) val = (val * 65535 + maxval/2) / maxval; row_pointers[i][2 * j] = (png_byte)(val >> 8); row_pointers[i][2 * j + 1] = (png_byte)(val & 0xff); } } if (failed) break; } } else /* read the raw data directly */ { for (i = 0; i < height; ++i)
void PNGAPI png_read_png(png_structp png_ptr, png_infop info_ptr, int transforms, voidp params) { int row; if (png_ptr == NULL) return; #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED /* Invert the alpha channel from opacity to transparency */ if (transforms & PNG_TRANSFORM_INVERT_ALPHA) png_set_invert_alpha(png_ptr); #endif /* png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). */ png_read_info(png_ptr, info_ptr); if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) png_error(png_ptr, "Image is too high to process with png_read_png()"); /* -------------- image transformations start here ------------------- */ #ifdef PNG_READ_16_TO_8_SUPPORTED /* Tell libpng to strip 16 bit/color files down to 8 bits per color. */ if (transforms & PNG_TRANSFORM_STRIP_16) png_set_strip_16(png_ptr); #endif #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED /* Strip alpha bytes from the input data without combining with * the background (not recommended). */ if (transforms & PNG_TRANSFORM_STRIP_ALPHA) png_set_strip_alpha(png_ptr); #endif #if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ if (transforms & PNG_TRANSFORM_PACKING) png_set_packing(png_ptr); #endif #ifdef PNG_READ_PACKSWAP_SUPPORTED /* Change the order of packed pixels to least significant bit first * (not useful if you are using png_set_packing). */ if (transforms & PNG_TRANSFORM_PACKSWAP) png_set_packswap(png_ptr); #endif #ifdef PNG_READ_EXPAND_SUPPORTED /* Expand paletted colors into true RGB triplets * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel * Expand paletted or RGB images with transparency to full alpha * channels so the data will be available as RGBA quartets. */ if (transforms & PNG_TRANSFORM_EXPAND) if ((png_ptr->bit_depth < 8) || (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) png_set_expand(png_ptr); #endif /* We don't handle background color or gamma transformation or dithering. */ #ifdef PNG_READ_INVERT_SUPPORTED /* Invert monochrome files to have 0 as white and 1 as black */ if (transforms & PNG_TRANSFORM_INVERT_MONO) png_set_invert_mono(png_ptr); #endif #ifdef PNG_READ_SHIFT_SUPPORTED /* If you want to shift the pixel values from the range [0,255] or * [0,65535] to the original [0,7] or [0,31], or whatever range the * colors were originally in: */ if ((transforms & PNG_TRANSFORM_SHIFT) && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) { png_color_8p sig_bit; png_get_sBIT(png_ptr, info_ptr, &sig_bit); png_set_shift(png_ptr, sig_bit); } #endif #ifdef PNG_READ_BGR_SUPPORTED /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ if (transforms & PNG_TRANSFORM_BGR) png_set_bgr(png_ptr); #endif #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ if (transforms & PNG_TRANSFORM_SWAP_ALPHA) png_set_swap_alpha(png_ptr); #endif #ifdef PNG_READ_SWAP_SUPPORTED /* Swap bytes of 16 bit files to least significant byte first */ if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) png_set_swap(png_ptr); #endif /* Added at libpng-1.2.41 */ #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED /* Invert the alpha channel from opacity to transparency */ if (transforms & PNG_TRANSFORM_INVERT_ALPHA) png_set_invert_alpha(png_ptr); #endif /* Added at libpng-1.2.41 */ #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED /* Expand grayscale image to RGB */ if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) png_set_gray_to_rgb(png_ptr); #endif /* We don't handle adding filler bytes */ /* Optional call to gamma correct and add the background to the palette * and update info structure. REQUIRED if you are expecting libpng to * update the palette for you (i.e., you selected such a transform above). */ png_read_update_info(png_ptr, info_ptr); /* -------------- image transformations end here ------------------- */ #ifdef PNG_FREE_ME_SUPPORTED png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); #endif if (info_ptr->row_pointers == NULL) { info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, info_ptr->height * png_sizeof(png_bytep)); png_memset(info_ptr->row_pointers, 0, info_ptr->height * png_sizeof(png_bytep)); #ifdef PNG_FREE_ME_SUPPORTED info_ptr->free_me |= PNG_FREE_ROWS; #endif for (row = 0; row < (int)info_ptr->height; row++) info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); } png_read_image(png_ptr, info_ptr->row_pointers); info_ptr->valid |= PNG_INFO_IDAT; /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); transforms = transforms; /* Quiet compiler warnings */ params = params; }
static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_t *grpatch) { png_structp png_ptr; png_infop png_info_ptr; png_uint_32 width, height; int bit_depth, color_type; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD jmp_buf jmpbuf; #endif #endif png_FILE_p png_FILE; char *pngfilename = va("md2/%s", filename); FIL_ForceExtension(pngfilename, ".png"); png_FILE = fopen(pngfilename, "rb"); if (!png_FILE) { //CONS_Debug(DBG_RENDER, "M_SavePNG: Error on opening %s for loading\n", filename); return 0; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, PNG_error, PNG_warn); if (!png_ptr) { CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n"); fclose(png_FILE); return 0; } png_info_ptr = png_create_info_struct(png_ptr); if (!png_info_ptr) { CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n"); png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(png_FILE); return 0; } #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_jmpbuf(png_ptr))) #endif { //CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename); png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); fclose(png_FILE); Z_Free(grpatch->mipmap.grInfo.data); return 0; } #ifdef USE_FAR_KEYWORD png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); #endif png_init_io(png_ptr, png_FILE); #ifdef PNG_SET_USER_LIMITS_SUPPORTED png_set_user_limits(png_ptr, 2048, 2048); #endif png_read_info(png_ptr, png_info_ptr); png_get_IHDR(png_ptr, png_info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); if (bit_depth == 16) png_set_strip_16(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); else if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); else if (color_type != PNG_COLOR_TYPE_RGB_ALPHA && color_type != PNG_COLOR_TYPE_GRAY_ALPHA) { #if PNG_LIBPNG_VER < 10207 png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); #else png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER); #endif } png_read_update_info(png_ptr, png_info_ptr); { png_uint_32 i, pitch = png_get_rowbytes(png_ptr, png_info_ptr); png_bytep PNG_image = Z_Malloc(pitch*height, PU_HWRCACHE, &grpatch->mipmap.grInfo.data); png_bytepp row_pointers = png_malloc(png_ptr, height * sizeof (png_bytep)); for (i = 0; i < height; i++) row_pointers[i] = PNG_image + i*pitch; png_read_image(png_ptr, row_pointers); png_free(png_ptr, (png_voidp)row_pointers); } png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); fclose(png_FILE); *w = (int)width; *h = (int)height; return GR_RGBA; }