/** * Initialize png reader struct. */ void setup_png_reader(const char* data, size_t length, png_structp* outpng_ptr, png_infop* out_info_ptr) { if (length <= PNG_HEADER_SIZE || !png_check_sig((png_bytep)data, PNG_HEADER_SIZE)) { logstream(LOG_ERROR) << "Invalid PNG signature" << std::endl; throw(std::string("Invalid PNG file")); } // Begin setup // main png read struct png_structp png_ptr = NULL; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_handler, NULL); if(png_ptr == NULL) { logstream(LOG_ERROR) << "Fail allocating PNG reader struct" << std::endl; throw(std::string("Unexpected libpng error")); } // png info struct png_infop info_ptr = NULL; info_ptr = png_create_info_struct(png_ptr); if(info_ptr == NULL) { // libpng must free file info struct memory before we bail png_destroy_read_struct(&png_ptr, NULL, NULL); logstream(LOG_ERROR) << "Fail allocating PNG info struct" << std::endl; throw(std::string("Unexpected libpng error")); } *outpng_ptr = png_ptr; *out_info_ptr = info_ptr; }
bool PngLoader::load( std::string file ) { png_structp png_ptr; png_infop info_ptr; std::ifstream ifile( file.c_str(), std::ios::binary ); if( !ifile.is_open() ) return false; char assinatura[8]; ifile.read( &assinatura[0], 8 * sizeof(char) ); if(!png_check_sig( (png_bytep)assinatura, 8) ) { return false; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if(png_ptr == 0) { return false; } info_ptr = png_create_info_struct( png_ptr ); if( info_ptr == 0 ) { png_destroy_read_struct( &png_ptr, 0, 0 ); return false; } png_set_read_fn( png_ptr, (void*)&ifile, readFileCallback ); png_set_sig_bytes( png_ptr, 8 ); png_read_info( png_ptr, info_ptr ); png_get_IHDR( png_ptr, info_ptr, (png_uint_32*)&width, (png_uint_32*)&height, &depth, &color_type, 0, 0, 0 ); cols = png_get_rowbytes(png_ptr, info_ptr); png_bytepp row_pp = new png_bytep[height]; data = new char[ cols * height ]; for( int i = 0; i < height; ++i ) { row_pp[height - i - 1] = (png_bytep)&data[ i * cols ]; } png_read_image( png_ptr, row_pp ); png_read_end( png_ptr, info_ptr ); png_destroy_read_struct( &png_ptr, &info_ptr, 0 ); delete[] row_pp; return true; }
uint32 readpng_init(FILE *infile) { uint8 sig[8]; /* first do a quick check that the file really is a PNG image; could * have used slightly more general png_sig_cmp() function instead */ fread(sig, 1, 8, infile); if (!png_check_sig(sig, 8)) return 1; /* bad signature */ /* could pass pointers to user-defined error handlers instead of NULLs: */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) return 4; /* out of memory */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return 4; /* out of memory */ } png_init_io(png_ptr, infile); png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ /* OK, that's all we need for now; return happy */ return 0; }
RawImageData get_raw_image_data_from_png(const void* png_data, const int png_data_size) { assert(png_data != NULL && png_data_size > 8); assert(png_check_sig((void*)png_data, 8)); png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); assert(png_ptr != NULL); png_infop info_ptr = png_create_info_struct(png_ptr); assert(info_ptr != NULL); ReadDataHandle png_data_handle = (ReadDataHandle) {{png_data, png_data_size}, 0}; png_set_read_fn(png_ptr, &png_data_handle, read_png_data_callback); if (setjmp(png_jmpbuf(png_ptr))) { CRASH("Error reading PNG file!"); } const PngInfo png_info = read_and_update_info(png_ptr, info_ptr); const DataHandle raw_image = read_entire_png_image(png_ptr, info_ptr, png_info.height); png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return (RawImageData) { png_info.width, png_info.height, raw_image.size, get_gl_color_format(png_info.color_type), raw_image.data }; }
//! returns true if the file maybe is able to be loaded by this class bool CImageLoaderPng::isALoadableFileFormat(engine::io::IReadFile* file) { #ifdef _engine_COMPILE_WITH_LIBPNG_ if (!file) return false; // Read the first few bytes of the PNG file if (file->read(&g_png_load_buffer, 8) != 8) { //os::Printer::log("Not a PNG file: can't read file\n", file->getFileName(), ELL_ERROR); return false; } // CHeck if it really is a PNG file if (!png_check_sig((png_bytep)g_png_load_buffer, 8)) { //os::Printer::log("Not a PNG file: wrong header\n", file->getFileName(),ELL_ERROR); return false; } return true; //if we are here then it must be a png #else return false; #endif // _engine_COMPILE_WITH_LIBPNG_ }
int FilePNG::check_sig(Asset *asset) { FILE *stream = fopen(asset->path, "rb"); if(stream) { //printf("FilePNG::check_sig 1\n"); char test[16]; fread(test, 16, 1, stream); fclose(stream); if(png_check_sig((unsigned char*)test, 8)) { //printf("FilePNG::check_sig 1\n"); return 1; } else if(test[0] == 'P' && test[1] == 'N' && test[2] == 'G' && test[3] == 'L' && test[4] == 'I' && test[5] == 'S' && test[6] == 'T') { //printf("FilePNG::check_sig 1\n"); return 1; } } return 0; }
int readpng_init(FILE *infile, long *pWidth, long *pHeight) { uch sig[8]; /* first do a quick check that the file really is a PNG image; could * have used slightly more general png_sig_cmp() function instead */ fread(sig, 1, 8, infile); if (!png_check_sig(sig, 8)) return 1; /* bad signature */ /* could pass pointers to user-defined error handlers instead of NULLs: */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) return 4; /* out of memory */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return 4; /* out of memory */ } /* we could create a second info struct here (end_info), but it's only * useful if we want to keep pre- and post-IDAT chunk info separated * (mainly for PNG-aware image editors and converters) */ /* setjmp() must be called in every function that calls a PNG-reading * libpng function */ if (setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 2; } png_init_io(png_ptr, infile); png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ /* alternatively, could make separate calls to png_get_image_width(), * etc., but want bit_depth and color_type for later [don't care about * compression_type and filter_type => NULLs] */ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); *pWidth = width; *pHeight = height; /* OK, that's all we need for now; return happy */ return 0; }
virtual bool GetImageInfo(dword header, int limit_size_x, int limit_size_y, C_fixed limit_ratio){ if(!png_check_sig((byte*)&header, 4)) return false; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, this, PNG_Error, PNG_Error); if(!png_ptr) return false; //E_LOADER_RESULT ret = IMGLOAD_READ_ERROR; info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) return false; png_set_bgr(png_ptr); png_set_expand(png_ptr); png_set_palette_to_rgb(png_ptr); png_set_strip_16(png_ptr); png_set_gray_to_rgb(png_ptr); png_set_read_fn(png_ptr, (void*)fl, &ReadFromCache); if(!png_read_info(png_ptr, info_ptr)) return false; bpp = (info_ptr->pixel_depth+7) / 8; if(info_ptr->pixel_depth>32) bpp /= 2; //if(info_ptr->num_palette && info_ptr->bit_depth==8) // pf->bytes_per_pixel = 1; //if 8-bit grayscale, consider it as RGB size_original_x = size_x = info_ptr->width; size_original_y = size_y = info_ptr->height; return true; }
static DFBResult Probe( IDirectFBImageProvider_ProbeContext *ctx ) { if (png_check_sig( ctx->header, 8 )) return DFB_OK; return DFB_UNSUPPORTED; }
int check_for_png (FILE *png_file) { rewind (png_file); if (fread (sigbytes, 1, sizeof(sigbytes), png_file) != sizeof(sigbytes) || (!png_check_sig (sigbytes, sizeof(sigbytes)))) return 0; else return 1; }
bool png_image_get_IHDR(const char *fn, uint32_t *width, uint32_t *height, uint8_t *bpp) { stack_chain_iterate_t sci = { 0 }; BYTE *file_buffer = nullptr; file_buffer_t file = { 0 }; json_t *chain = resolve_chain_game(fn); if (json_array_size(chain)) { log_printf("(PNG) Resolving %s...", json_array_get_string(chain, 0)); while (file_buffer == nullptr && stack_chain_iterate(&sci, chain, SCI_BACKWARDS, nullptr) != 0) { file_buffer = (BYTE*)patch_file_load(sci.patch_info, sci.fn, &file.size); } } if (!file_buffer) { log_print("not found\n"); json_decref(chain); return false; } patch_print_fn(sci.patch_info, sci.fn); log_print("\n"); json_decref(chain); file.buffer = file_buffer; if (!png_check_sig(file.buffer, 8)) { log_print("Bad PNG signature!\n"); free(file_buffer); return false; } file.buffer += 8; file.size -= 8; png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_callback, png_warning_callback); png_infop info_ptr = png_create_info_struct(png_ptr); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); free(file_buffer); return false; } png_set_read_fn(png_ptr, &file, read_bytes); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); int color_type; png_get_IHDR(png_ptr, info_ptr, width, height, NULL, &color_type, NULL, NULL, NULL); if (bpp) { *bpp = (color_type & PNG_COLOR_MASK_ALPHA) ? 32 : 24; } png_destroy_read_struct(&png_ptr, &info_ptr, NULL); free(file_buffer); return true; }
// // Constructor // PNGReader::PNGReader(const QString & ext, MemoryFile & file) : ImageFormatReaderHelper(file) { if (file.size() < 8) return; byte buf[8]; if (!tryReadFile(buf, sizeof(buf))) return; if (png_check_sig((png_bytep)buf, sizeof(buf))) m_IsValid = true; }
bool validate(SprigFile *pngFile) { //Allocate a buffer of 8 bytes, where we can put the file signature. png_byte header[8]; fread(&header, 8, sizeof(png_byte), pngFile->file); rewind(pngFile->file);//rewind to prepare for reading the file if(!png_check_sig(header, 8)) { return false; } return true; }
virtual bool opendata(const unsigned char *data, size_t size) { if (m_png_ptr) return false; if (size < 8) return false; if (png_check_sig(data, 8)){ m_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); m_info_ptr = png_create_info_struct(m_png_ptr); m_data_ptr = new PNGData; m_data_ptr->pdata = (const unsigned char *)data; m_data_ptr->size = size; png_set_read_fn(m_png_ptr, m_data_ptr, data_from_memory); png_read_info(m_png_ptr, m_info_ptr); return true; } return false; }
/* check to see if a file is a png file using png_check_sig() */ int check_png(char * file_name) { FILE *fp; char buf[8]; int ret; fp = fopen(file_name, "rb"); if (!fp) return 0; ret = fread(buf, 1, 8, fp); fclose(fp); if (ret != 8) return 0; ret = png_check_sig(buf, 8); return (ret); }
static int read_image(const char *filename, png24_image *image) { int retval=1; bool using_stdin = false; FILE *fh; unsigned char buffer[8]; if (0 == strcmp("-", filename)) { using_stdin = true; fh = stdin; } else { fh = fopen(filename, "rb"); if (!fh) { return 1; } } setvbuf(fh, (char *)buffer, _IOFBF, 8); // the first read fills the buffer up, but put char back on after int c = fgetc(fh); ungetc(c, fh); // the png number is not really precise but I guess the situation where this would falsely pass is almost equal to 0 if (png_check_sig(buffer, 8)) { /* Reads image into png24_image struct. Returns non-zero on error */ retval = rwpng_read_image24(fh, image, 0); } #ifdef USE_LIBJPEG else { retval=read_image_jpeg(fh,image); } #endif if(!using_stdin) { fclose(fh); } return retval; }
virtual bool openfile(const char *filename) { if (m_png_ptr) return false; FILE *f = fopen(filename, "rb"); if (f){ unsigned char head[8]; fread(head, 1, 8, f); if (png_check_sig(head, 8)){ m_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); m_info_ptr = png_create_info_struct(m_png_ptr); png_init_io(m_png_ptr, f); png_set_sig_bytes(m_png_ptr, 8); png_read_info(m_png_ptr, m_info_ptr); m_file_ptr = f; return true; } fclose(f); } return false; }
static gboolean querypng(FILE *f, int *w, int *h) { png_struct *png_ptr = NULL; png_info *info_ptr = NULL; png_byte buf[8]; png_uint_32 width; png_uint_32 height; int bit_depth; int color_type; /* is it a PNG file? */ if( fread( buf,1,8,f ) != 8 ) return FALSE; if( ! png_check_sig( buf,8 ) ) return FALSE; png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); if( !png_ptr ) return FALSE; info_ptr = png_create_info_struct( png_ptr ); if( !info_ptr ){ png_destroy_read_struct( &png_ptr,NULL,NULL ); return FALSE; } if( setjmp( png_jmpbuf(png_ptr) ) ){ png_destroy_read_struct( &png_ptr,&info_ptr,NULL ); return FALSE; } png_init_io( png_ptr,f ); png_set_sig_bytes( png_ptr,8 ); png_read_info( png_ptr,info_ptr ); png_get_IHDR( png_ptr,info_ptr,&width,&height,&bit_depth, &color_type,NULL,NULL,NULL); *w = width; *h = height; png_destroy_read_struct( &png_ptr,&info_ptr,NULL ); return TRUE; }
void * readpng_init(FILE *infile) { uint8 sig[8]; readpng_structs_t * strs = malloc(sizeof(readpng_structs_t)); memset(strs, 0, sizeof(readpng_structs_t)); /* first do a quick check that the file really is a PNG image; could * have used slightly more general png_sig_cmp() function instead */ fread(sig, 1, 8, infile); if (!png_check_sig(sig, 8)) { free(strs); return NULL; /* bad signature */ } /* could pass pointers to user-defined error handlers instead of NULLs: */ strs->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!strs->png_ptr) { free(strs); return NULL; /* out of memory */ } strs->info_ptr = png_create_info_struct(strs->png_ptr); if (!strs->info_ptr) { png_destroy_read_struct(&strs->png_ptr, NULL, NULL); free(strs); return NULL; /* out of memory */ } png_init_io(strs->png_ptr, infile); png_set_sig_bytes(strs->png_ptr, 8); /* we already read the 8 signature bytes */ png_read_info(strs->png_ptr, strs->info_ptr); /* read all PNG info up to image data */ /* OK, that's all we need for now; return happy */ return (void *)strs; }
int loadimage(char *filename) { infile = fopen(filename, "rb"); unsigned char sig[8]; fread(sig, 1, 8, infile); if (!png_check_sig(sig, 8)) return 1; /* bad signature */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) return 4; /* out of memory */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return 4; /* out of memory */ } if (setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 2; } png_init_io(png_ptr, infile); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); //png_get_IHDR(png_ptr, info_ptr, &pwidth, &pheight, &bit_depth, // &color_type, NULL, NULL, NULL); //*width = pwidth; //*height = pheight; return 0; }
static Bool readPngFileToImage (FILE *file, int *width, int *height, void **data) { unsigned char png_sig[PNG_SIG_SIZE]; int sig_bytes; png_struct *png; png_info *info; Bool status; sig_bytes = fread (png_sig, 1, PNG_SIG_SIZE, file); if (png_check_sig (png_sig, sig_bytes) == 0) return FALSE; png = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) return FALSE; info = png_create_info_struct (png); if (!info) { png_destroy_read_struct (&png, NULL, NULL); return FALSE; } png_init_io (png, file); png_set_sig_bytes (png, sig_bytes); status = readPngData (png, info, data, width, height); png_destroy_read_struct (&png, &info, NULL); return status; }
int gr3_readpngtomemory_(int *pixels, const char *pngfile, int width, int height) { FILE *png_fp; png_structp png_ptr; png_infop info_ptr = NULL; png_infop end_info = NULL; unsigned char sig[8]; png_bytep *row_pointers; int i; png_fp = fopen(pngfile,"rb"); if (!png_fp) { return 1; } i = fread(sig, 1, 8, png_fp); if (!png_check_sig(sig, 8)){ return 2; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { return 3; } 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); return 4; } png_init_io(png_ptr, png_fp); png_set_sig_bytes(png_ptr, 8); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); row_pointers = png_get_rows(png_ptr, info_ptr); for (i = 0; i < height; i++) { memcpy(pixels+(height-1-i)*width,row_pointers[i],width*sizeof(int)); } png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(png_fp); return 0; }
static Bool readPngBuffer (const unsigned char *buffer, char **data, unsigned int *width, unsigned int *height) { unsigned char png_sig[PNG_SIG_SIZE]; png_struct *png; png_info *info; const unsigned char *b = buffer + PNG_SIG_SIZE; Bool status; memcpy (png_sig, buffer, PNG_SIG_SIZE); if (png_check_sig (png_sig, PNG_SIG_SIZE) == 0) return FALSE; png = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) return FALSE; info = png_create_info_struct (png); if (!info) { png_destroy_read_struct (&png, NULL, NULL); return FALSE; } png_set_read_fn (png, (void *) &b, userReadData); png_set_sig_bytes (png, PNG_SIG_SIZE); status = readPngData (png, info, data, width, height); png_destroy_read_struct (&png, &info, NULL); return status; }
static struct gl_texture_t *ReadPNGFromFile (const char *filename) { struct gl_texture_t *texinfo; png_byte magic[8]; png_structp png_ptr; png_infop info_ptr; int bit_depth, color_type; FILE *fp = NULL; png_bytep *row_pointers = NULL; png_uint_32 w, h; int i; /* Open image file */ fp = fopen (filename, "rb"); if (!fp) { fprintf (stderr, "error: couldn't open \"%s\"!\n", filename); return NULL; } /* Read magic number */ fread (magic, 1, sizeof (magic), fp); /* Check for valid magic number */ if (!png_check_sig (magic, sizeof (magic))) { fprintf (stderr, "error: \"%s\" is not a valid PNG image!\n", filename); fclose (fp); return NULL; } /* Create a png read struct */ png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fclose (fp); return NULL; } /* Create a png info struct */ info_ptr = png_create_info_struct (png_ptr); if (!info_ptr) { fclose (fp); png_destroy_read_struct (&png_ptr, NULL, NULL); return NULL; } /* Create our OpenGL texture object */ texinfo = (struct gl_texture_t *) malloc (sizeof (struct gl_texture_t)); /* Initialize the setjmp for returning properly after a libpng error occured */ if (setjmp (png_jmpbuf (png_ptr))) { fclose (fp); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); if (row_pointers) free (row_pointers); if (texinfo) { if (texinfo->texels) free (texinfo->texels); free (texinfo); } return NULL; } /* Setup libpng for using standard C fread() function with our FILE pointer */ png_init_io (png_ptr, fp); /* Tell libpng that we have already read the magic number */ png_set_sig_bytes (png_ptr, sizeof (magic)); /* Read png info */ png_read_info (png_ptr, info_ptr); /* Get some usefull information from header */ bit_depth = png_get_bit_depth (png_ptr, info_ptr); color_type = png_get_color_type (png_ptr, info_ptr); /* Convert index color images to RGB images */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb (png_ptr); /* Convert 1-2-4 bits grayscale images to 8 bits grayscale. */ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8 (png_ptr); if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png_ptr); if (bit_depth == 16) png_set_strip_16 (png_ptr); else if (bit_depth < 8) png_set_packing (png_ptr); /* Update info structure to apply transformations */ png_read_update_info (png_ptr, info_ptr); /* Retrieve updated information */ png_get_IHDR (png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, NULL, NULL, NULL); texinfo->width = w; texinfo->height = h; /* Get image format and components per pixel */ GetPNGtextureInfo (color_type, texinfo); /* We can now allocate memory for storing pixel data */ texinfo->texels = (GLubyte *)malloc (sizeof (GLubyte) * texinfo->width * texinfo->height * texinfo->internalFormat); /* Setup a pointer array. Each one points at the begening of a row. */ row_pointers = (png_bytep *)malloc (sizeof (png_bytep) * texinfo->height); for (i = 0; i < texinfo->height; ++i) { row_pointers[i] = (png_bytep)(texinfo->texels + ((texinfo->height - (i + 1)) * texinfo->width * texinfo->internalFormat)); } /* Read pixel data using row pointers */ png_read_image (png_ptr, row_pointers); /* Finish decompression and release memory */ png_read_end (png_ptr, NULL); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); /* We don't need row pointers anymore */ free (row_pointers); fclose (fp); return texinfo; }
int Read ( const char *filename, byte **data, int *width, int *height ) { // Setup the pointers *data = NULL; *width = 0; *height = 0; // Check and make sure the filename is valid (because you can never be too careful...) if( !filename || !filename[0] ) { ri->Printf( PRINT_ERROR, "PNG read called with invalid filename.\n" ); return 0; } // Copy the filename to the global variable Q_strncpyz( currentPNGFile, filename, sizeof(currentPNGFile) ); // Make sure we're actually reading PNG data. const int SIGNATURE_LEN = 8; byte ident[SIGNATURE_LEN]; memcpy (ident, buf, SIGNATURE_LEN); if ( !png_check_sig (ident, SIGNATURE_LEN) ) { ri->Printf (PRINT_ERROR, "PNG signature not found in %s.\n", currentPNGFile ); return 0; } png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, png_print_error, png_print_warning); if ( png_ptr == NULL ) { ri->Printf (PRINT_ERROR, "PNG: Could not allocate enough memory to load %s\n", currentPNGFile ); return 0; } info_ptr = png_create_info_struct (png_ptr); if ( setjmp (png_jmpbuf (png_ptr)) ) { return 0; } // We've read the signature offset += SIGNATURE_LEN; // Setup reading information, and read header png_set_read_fn (png_ptr, (png_voidp)this, &user_read_data); png_set_sig_bytes (png_ptr, SIGNATURE_LEN); png_read_info (png_ptr, info_ptr); png_uint_32 width_; png_uint_32 height_; int depth; int colortype; png_get_IHDR (png_ptr, info_ptr, &width_, &height_, &depth, &colortype, NULL, NULL, NULL); // While modern OpenGL can handle non-PoT textures, it's faster to handle only PoT // so that the graphics driver doesn't have to fiddle about with the texture when uploading. if ( !IsPowerOfTwo (width_) || !IsPowerOfTwo (height_) ) { ri->Printf (PRINT_ERROR, "PNG: Width or height of %s is not a power-of-two.\n", currentPNGFile ); return 0; } // This function is equivalent to using what used to be LoadPNG32. LoadPNG8 also existed, // but this only seemed to be used by the RMG system which does not work in JKA. If this // does need to be re-implemented, then colortype should be PNG_COLOR_TYPE_PALETTE or // PNG_COLOR_TYPE_GRAY. if ( colortype != PNG_COLOR_TYPE_RGB && colortype != PNG_COLOR_TYPE_RGBA ) { ri->Printf (PRINT_ERROR, "PNG: %s is not 24-bit or 32-bit.\n", currentPNGFile ); return 0; } // Read the png data if ( colortype == PNG_COLOR_TYPE_RGB ) { // Expand RGB -> RGBA png_set_add_alpha (png_ptr, 0xff, PNG_FILLER_AFTER); } png_read_update_info (png_ptr, info_ptr); // We always assume there are 4 channels. RGB channels are expanded to RGBA when read. byte *tempData = (byte *)ri->Z_Malloc (width_ * height_ * 4, TAG_TEMP_PNG, qfalse, 4); if ( !tempData ) { ri->Printf (PRINT_ERROR, "Could not allocate enough memory to load %s.\n", currentPNGFile ); return 0; } // Dynamic array of row pointers, with 'height' elements, initialized to NULL. byte **row_pointers = (byte **)ri->Hunk_AllocateTempMemory (sizeof (byte *) * height_); if ( !row_pointers ) { ri->Printf (PRINT_ERROR, "Could not allocate enough memory to load %s.\n", currentPNGFile ); ri->Z_Free (tempData); return 0; } // Re-set the jmp so that these new memory allocations can be reclaimed if ( setjmp (png_jmpbuf (png_ptr)) ) { ri->Hunk_FreeTempMemory (row_pointers); ri->Z_Free (tempData); return 0; } for ( unsigned int i = 0, j = 0; i < height_; i++, j += 4 ) { row_pointers[i] = tempData + j * width_; } png_read_image (png_ptr, row_pointers); // Finish reading png_read_end (png_ptr, NULL); ri->Hunk_FreeTempMemory (row_pointers); // Finally assign all the parameters *data = tempData; *width = width_; *height = height_; return 1; }
static bool doIsCorrectImageFormat(const byte *fileDataPtr, uint fileSize) { return (fileSize > 8) && png_check_sig(const_cast<byte *>(fileDataPtr), 8); }
int png_load(char *filename) { int i,j,k; FILE *fd; u_char header[NUMBER]; png_structp png_ptr; png_infop info_ptr,end_info; png_uint_32 width,height; int bit_depth,color_type,interlace_type; int compression_type,filter_type; int channels,rowbytes; double gamma; png_colorp palette; int num_palette; png_bytep *row_pointers; char c; int res=0; fd=fopen(filename,"rb"); if(fd==NULL) { VGLEnd(); perror("fopen"); exit(1); } fread(header,1,NUMBER,fd); if(!png_check_sig(header,NUMBER)) { fprintf(stderr,"Not a PNG file.\n"); return(-1); } png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING,(void *)NULL, NULL,NULL); info_ptr=png_create_info_struct(png_ptr); end_info=png_create_info_struct(png_ptr); if(!png_ptr || !info_ptr || !end_info) { VGLEnd(); fprintf(stderr,"failed to allocate needed structs!\n"); png_destroy_read_struct(&png_ptr,&info_ptr,&end_info); return(-1); } png_set_sig_bytes(png_ptr,NUMBER); png_init_io(png_ptr,fd); png_read_info(png_ptr,info_ptr); png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth, &color_type,&interlace_type,&compression_type,&filter_type); png_get_PLTE(png_ptr,info_ptr,&palette,&num_palette); channels=png_get_channels(png_ptr,info_ptr); rowbytes=png_get_rowbytes(png_ptr,info_ptr); if(bit_depth==16) png_set_strip_16(png_ptr); if(color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png_ptr); if(png_get_gAMA(png_ptr,info_ptr,&gamma)) png_set_gamma(png_ptr,screen_gamma,gamma); else png_set_gamma(png_ptr,screen_gamma,0.45); if(res==0) { /* Dither */ if(color_type & PNG_COLOR_MASK_COLOR) { if(png_get_valid(png_ptr,info_ptr,PNG_INFO_PLTE)) { png_uint_16p histogram; png_get_hIST(png_ptr,info_ptr,&histogram); png_set_dither(png_ptr,palette,num_palette,max_screen_colors,histogram,0); } else { png_color std_color_cube[16]={ {0x00,0x00,0x00}, {0x02,0x02,0x02}, {0x04,0x04,0x04}, {0x06,0x06,0x06}, {0x08,0x08,0x08}, {0x0a,0x0a,0x0a}, {0x0c,0x0c,0x0c}, {0x0e,0x0e,0x0e}, {0x10,0x10,0x10}, {0x12,0x12,0x12}, {0x14,0x14,0x14}, {0x16,0x16,0x16}, {0x18,0x18,0x18}, {0x1a,0x1a,0x1a}, {0x1d,0x1d,0x1d}, {0xff,0xff,0xff}, }; png_set_dither(png_ptr,std_color_cube,max_screen_colors,max_screen_colors,NULL,0); } } } png_set_packing(png_ptr); if(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); } png_read_update_info(png_ptr,info_ptr); png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth, &color_type,&interlace_type,&compression_type,&filter_type); png_get_PLTE(png_ptr,info_ptr,&palette,&num_palette); channels=png_get_channels(png_ptr,info_ptr); rowbytes=png_get_rowbytes(png_ptr,info_ptr); row_pointers=malloc(height*sizeof(png_bytep)); for(i=0;i<height;i++) { row_pointers[i]=malloc(rowbytes); } png_read_image(png_ptr,row_pointers); png_read_end(png_ptr,end_info); png_destroy_read_struct(&png_ptr,&info_ptr,&end_info); fclose(fd); /* Set palette */ if(res) k=2; else k=2; for(i=0;i<256;i++) { pal_red[i]=255; pal_green[i]=255; pal_blue[i]=255; } for(i=0;i<num_palette;i++) { pal_red[i]=(palette+i)->red>>k; pal_green[i]=(palette+i)->green>>k; pal_blue[i]=(palette+i)->blue>>k; } pal_colors=num_palette; if(pic.Bitmap!=NULL) free(pic.Bitmap); pic.Bitmap=(byte *)calloc(rowbytes*height,sizeof(byte)); pic.Type=MEMBUF; pic.Xsize=rowbytes; pic.Ysize=height; for(i=0;i<rowbytes;i++) { for(j=0;j<height;j++) { VGLSetXY(&pic, i,j,row_pointers[j][i]); } } a.zoom=1; a.Xshift=(VGLDisplay->Xsize-pic.Xsize)/2; a.Yshift=(VGLDisplay->Ysize-pic.Ysize)/2; a.rotate=0; return(0); }
ImageReaderPNG::ImageType ImageReaderPNG::readData(const std::string& filePath, PNGInfra& infra, bool wantAlpha) { if (filePath.empty()) return eInvalid; infra.pFile = fopen(filePath.c_str(), "rb"); if (!infra.pFile) { fprintf(stderr, "Error opening file: %s\n", filePath.c_str()); return eInvalid; } unsigned char sig[8]; // check the signature fread(sig, 1, 8, infra.pFile); if (!png_check_sig(sig, 8)) { fprintf(stderr, "Cannot open file: %s - not a valid PNG file.\n", filePath.c_str()); fclose(infra.pFile); return eInvalid; } infra.pPNG = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!infra.pPNG) { fclose(infra.pFile); return eInvalid; } infra.pInfo = png_create_info_struct(infra.pPNG); if (!infra.pInfo) { png_destroy_read_struct(&infra.pPNG, NULL, NULL); fclose(infra.pFile); return eInvalid; } if (setjmp(png_jmpbuf(infra.pPNG))) { png_destroy_read_struct(&infra.pPNG, &infra.pInfo, NULL); fclose(infra.pFile); return eInvalid; } png_init_io(infra.pPNG, infra.pFile); png_set_sig_bytes(infra.pPNG, 8); png_read_info(infra.pPNG, infra.pInfo); int colorType; int bitDepth, interlaceType, compressionType; png_get_IHDR(infra.pPNG, infra.pInfo, &infra.width, &infra.height, &bitDepth, &colorType, &interlaceType, &compressionType, NULL); if (colorType == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(infra.pPNG); if (png_get_valid(infra.pPNG, infra.pInfo, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(infra.pPNG); } if (bitDepth == 16) png_set_strip_16(infra.pPNG); ImageType type = eInvalid; if (!wantAlpha) { // add black Alpha if ((colorType & PNG_COLOR_MASK_ALPHA) == 0) png_set_add_alpha(infra.pPNG, 0xFF, PNG_FILLER_AFTER); if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(infra.pPNG); else if (colorType != PNG_COLOR_TYPE_RGB && colorType != PNG_COLOR_TYPE_RGB_ALPHA) return eInvalid; type = eRGBA; } else { if (colorType == PNG_COLOR_TYPE_RGB_ALPHA) type = eRGBA; else if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) type = eA; else return eInvalid; } png_read_update_info(infra.pPNG, infra.pInfo); infra.pRows = new png_bytep[infra.height * png_sizeof(png_bytep)]; png_set_rows(infra.pPNG, infra.pInfo, infra.pRows); for (unsigned int i = 0; i < infra.height; i++) { infra.pRows[i] = new png_byte[png_get_rowbytes(infra.pPNG, infra.pInfo)]; } png_read_image(infra.pPNG, infra.pRows); png_read_end(infra.pPNG, infra.pInfo); return type; }
APNGDATA * loadPng(IPngReader *pSrc) { png_bytep dataFrame; png_uint_32 bytesPerRow; png_uint_32 bytesPerFrame; png_bytepp rowPointers; png_byte sig[8]; png_structp png_ptr_read; png_infop info_ptr_read; pSrc->read(sig,8); if(!png_check_sig(sig,8)) { return NULL; } png_ptr_read = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info_ptr_read = png_create_info_struct(png_ptr_read); if (setjmp(png_jmpbuf(png_ptr_read))) { png_destroy_read_struct(&png_ptr_read, &info_ptr_read, NULL); return NULL; } png_set_read_fn(png_ptr_read,pSrc,mypng_read_data); png_set_sig_bytes(png_ptr_read, 8); if ((png_ptr_read->bit_depth < 8) || (png_ptr_read->color_type == PNG_COLOR_TYPE_PALETTE) || (info_ptr_read->valid & PNG_INFO_tRNS)) png_set_expand(png_ptr_read); png_set_add_alpha(png_ptr_read, 0xff, PNG_FILLER_AFTER); png_set_interlace_handling(png_ptr_read); png_set_gray_to_rgb(png_ptr_read); png_set_strip_16(png_ptr_read); png_read_info(png_ptr_read, info_ptr_read); png_read_update_info(png_ptr_read, info_ptr_read); bytesPerRow = png_ptr_read->width * 4; bytesPerFrame = bytesPerRow * png_ptr_read->height; APNGDATA * apng = (APNGDATA*) malloc(sizeof(APNGDATA)); memset(apng,0,sizeof(APNGDATA)); apng->nWid = png_ptr_read->width; apng->nHei = png_ptr_read->height; //图像帧数据 dataFrame = (png_bytep)malloc(bytesPerRow * apng->nHei); memset(dataFrame,0,bytesPerFrame); //获得扫描行指针 rowPointers = (png_bytepp)malloc(sizeof(png_bytep)* apng->nHei); for(int i=0;i<apng->nHei;i++) rowPointers[i] = dataFrame + bytesPerRow * i; if (!png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_acTL)) {//load png doesn't has this trunk. png_read_image(png_ptr_read,rowPointers); apng->pdata =dataFrame; apng->nFrames =1; }else {//load apng apng->nFrames = png_get_num_frames(png_ptr_read, info_ptr_read);//获取总帧数 png_bytep data = (png_bytep)malloc( bytesPerFrame * apng->nFrames);//为每一帧分配内存 png_bytep curFrame = (png_bytep)malloc(bytesPerFrame); memset(curFrame,0,bytesPerFrame); apng->nLoops = png_get_num_plays(png_ptr_read, info_ptr_read); apng->pDelay = (unsigned short*)malloc(sizeof(unsigned short)*apng->nFrames); for(int iFrame = 0;iFrame<apng->nFrames;iFrame++) { //读帧信息头 png_read_frame_head(png_ptr_read, info_ptr_read); //计算出帧延时信息 if (png_get_valid(png_ptr_read, info_ptr_read, PNG_INFO_fcTL)) { png_uint_16 delay_num = info_ptr_read->next_frame_delay_num, delay_den = info_ptr_read->next_frame_delay_den; if (delay_den==0 || delay_den==100) apng->pDelay[iFrame] = delay_num; else if (delay_den==10) apng->pDelay[iFrame] = delay_num*10; else if (delay_den==1000) apng->pDelay[iFrame] = delay_num/10; else apng->pDelay[iFrame] = delay_num*100/delay_den; }else { apng->pDelay[iFrame] = 0; } //读取PNG帧到dataFrame中,不含偏移数据 png_read_image(png_ptr_read, rowPointers); {//将当前帧数据绘制到当前显示帧中:1)获得绘制的背景;2)计算出绘制位置; 3)使用指定的绘制方式与背景混合 //1)计算出绘制位置 png_bytep lineDst=curFrame+info_ptr_read->next_frame_y_offset*bytesPerRow + 4 * info_ptr_read->next_frame_x_offset; png_bytep lineSour=dataFrame; //2)使用指定的绘制方式与背景混合 switch(info_ptr_read->next_frame_blend_op) { case PNG_BLEND_OP_OVER: { for(unsigned int y=0;y<info_ptr_read->next_frame_height;y++) { png_bytep lineDst1=lineDst; png_bytep lineSour1=lineSour; for(unsigned int x=0;x<info_ptr_read->next_frame_width;x++) { png_byte alpha = lineSour1[3]; *lineDst1++ = ((*lineDst1)*(255-alpha)+(*lineSour1++)*alpha)>>8; *lineDst1++ = ((*lineDst1)*(255-alpha)+(*lineSour1++)*alpha)>>8; *lineDst1++ = ((*lineDst1)*(255-alpha)+(*lineSour1++)*alpha)>>8; *lineDst1++ = ((*lineDst1)*(255-alpha)+(*lineSour1++)*alpha)>>8; } lineDst += bytesPerRow; lineSour+= bytesPerRow; } } break; case PNG_BLEND_OP_SOURCE: { for(unsigned int y=0;y<info_ptr_read->next_frame_height;y++) { memcpy(lineDst,lineSour,info_ptr_read->next_frame_width*4); lineDst += bytesPerRow; lineSour+= bytesPerRow; } } break; default: SASSERT(FALSE); break; } png_bytep targetFrame = data + bytesPerFrame * iFrame; memcpy(targetFrame,curFrame,bytesPerFrame); lineDst=curFrame+info_ptr_read->next_frame_y_offset*bytesPerRow + 4 * info_ptr_read->next_frame_x_offset; //3)处理当前帧绘制区域 switch(info_ptr_read->next_frame_dispose_op) { case PNG_DISPOSE_OP_BACKGROUND://clear background { for(unsigned int y=0;y<info_ptr_read->next_frame_height;y++) { memset(lineDst,0,info_ptr_read->next_frame_width*4); lineDst += bytesPerRow; } } break; case PNG_DISPOSE_OP_PREVIOUS://copy previous frame if(iFrame>0) { memcpy(curFrame,targetFrame-bytesPerFrame,bytesPerFrame); } break; case PNG_DISPOSE_OP_NONE://using current frame, doing nothing break; default: SASSERT(0); break; } } } free(curFrame); free(dataFrame); apng->pdata =data; } free(rowPointers); png_read_end(png_ptr_read,info_ptr_read); png_destroy_read_struct(&png_ptr_read, &info_ptr_read, NULL); return apng; }
main(int argc, char** argv) { char* cmd=argv[0]; char* pngfile=0; char* ppmfile; char* pgmfile; char* ext; char header[8]; FILE *png; FILE *ppm; FILE *pgm; png_structp png_ptr; png_infop info_ptr; png_infop end_info; png_bytep* row_pointers; int h; int crop=0; int hotspot=0; int arg; for (arg=1; arg<argc; arg++) { if (0==strcmp(argv[arg],"-c")) { crop=1; } else if (0==strcmp(argv[arg],"-h")) { hotspot=1; } else { if (!pngfile) { pngfile=argv[arg]; } else { fprintf(stderr,"Usage: %s [-c] [-h] filename.png\n",cmd); fprintf(stderr," Reads filename.png then writes filename.ppm and filename.pgm\n"); fprintf(stderr," filename.ppm is non-alpha image\n"); fprintf(stderr," filename.pgm is alpha image\n"); fprintf(stderr," -c causes auto-cropping to non-transparent rectangle\n"); fprintf(stderr," -h causes HOTSPOT comment in PPM file, center of original\n"); exit(1); } } } ppmfile=strdup(pngfile); ext=strstr(ppmfile,".png"); if (!ext) { fprintf(stderr,"%s: PNG file must have extension .png\n"); exit(1); } strcpy(ext,".ppm"); pgmfile=strdup(pngfile); ext=strstr(pgmfile,".png"); strcpy(ext,".pgm"); ppm = fopen(ppmfile, "wb"); if (!ppm) { perror(ppmfile); exit(1); } pgm = fopen(pgmfile, "wb"); if (!pgm) { perror(pgmfile); exit(1); } /* Boilerplater PNG access code [gee I hate C] */ png = fopen(pngfile, "rb"); if (!png) { perror(pngfile); exit(1); } fread(header, 1, 8, png); if (!png_check_sig(header, 8)) { fprintf(stderr,"%s: %s is not a valid PNG file\n",cmd,pngfile); exit(1); } fseek(png,0,SEEK_SET); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) exit(1); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) exit(1); end_info = png_create_info_struct(png_ptr); if (!end_info) exit(1); png_init_io(png_ptr, png); png_read_info(png_ptr, info_ptr); if (info_ptr->channels!=4) { fprintf(stderr,"%s: found %d channels, expected 4\n",cmd,info_ptr->channels); exit(1); } if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE && info_ptr->bit_depth < 8) png_set_expand(png_ptr); if (info_ptr->valid & PNG_INFO_tRNS) png_set_expand(png_ptr); if (info_ptr->bit_depth == 16) png_set_strip_16(png_ptr); if (info_ptr->bit_depth < 8) png_set_packing(png_ptr); png_read_update_info(png_ptr, info_ptr); row_pointers=(png_bytep*)malloc(sizeof(png_bytep)*info_ptr->height); { int y; for (y=0; y<info_ptr->height; y++) { row_pointers[y]=(unsigned char*)malloc(info_ptr->rowbytes); } } png_read_image(png_ptr, row_pointers); { int top,bottom; int left,right; int opaque=0; int y; if (crop) { for (left=0; left<info_ptr->width*4-4 && !opaque; left+=4) { for (y=0; y<info_ptr->height && !opaque; y++) { if (row_pointers[y][left+3]!=0) opaque=1; } } left-=4; opaque=0; for (right=info_ptr->width*4-4; right>=0 && !opaque; right-=4) { for (y=0; y<info_ptr->height && !opaque; y++) { if (row_pointers[y][right+3]!=0) opaque=1; } } right+=4; opaque=0; for (top=0; top<info_ptr->height && !opaque; top++) { int x; for (x=left; x<=right && !opaque; x+=4) { if (row_pointers[top][x+3]!=0) opaque=1; } } top--; opaque=0; for (bottom=info_ptr->height-1; bottom>=0 && !opaque; bottom--) { int x; for (x=left; x<=right && !opaque; x+=4) { if (row_pointers[bottom][x+3]!=0) opaque=1; } } bottom++; } else { top=left=0; right=info_ptr->width*4-4; bottom=info_ptr->height-1; } if (hotspot) fprintf(ppm,"P6\n# HOTSPOT %d %d\n%d %d\n%d\n", info_ptr->width/2-left/4,info_ptr->height/2-top, right/4-left/4+1,bottom-top+1,255); else fprintf(ppm,"P6\n%d %d\n%d\n", right/4-left/4+1,bottom-top+1,255); fprintf(pgm,"P5\n%d %d\n%d\n",right/4-left/4+1,bottom-top+1,255); for (y=top; y<=bottom; y++) { int x; for (x=left; x<=right; x+=4) { fwrite(row_pointers[y]+x,1,3,ppm); fwrite(row_pointers[y]+x+3,1,1,pgm); } } } fclose(ppm); fclose(pgm); png_read_end(png_ptr, end_info); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); }