unsigned char * ReadPNG( FILE *fp, unsigned int &sizeX, unsigned int &sizeY, int &img_depth, int &img_color_type, unsigned char ***row_pointer_ptr ) { png_structp png_ptr; png_bytepp row_pointers; png_infop info_ptr; int interlace_type; png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr) png_cexcept_error, (png_error_ptr) NULL ); if (png_ptr == NULL) { exit( 1 ); return NULL; } info_ptr = png_create_info_struct( png_ptr ); if (info_ptr == NULL) { png_destroy_read_struct( &png_ptr, (png_infopp) NULL, (png_infopp) NULL ); fprintf( stderr, "VSImage ERROR : PNG info_ptr == NULL !!!\n" ); exit( 1 ); return NULL; } if ( setjmp( png_jmpbuf( png_ptr ) ) ) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL ); /* If we get here, we had a problem reading the file */ exit( 1 ); return NULL; } png_init_io( png_ptr, fp ); //png_set_sig_bytes(png_ptr, 8); png_read_info( png_ptr, info_ptr ); /* read all PNG info up to image data */ png_get_IHDR( png_ptr, info_ptr, (png_uint_32*) &sizeX, (png_uint_32*) &sizeY, &img_depth, &img_color_type, &interlace_type, NULL, NULL ); # if __BYTE_ORDER != __BIG_ENDIAN if (img_depth == 16) png_set_swap( png_ptr ); #endif if (img_depth == 16) //for now png_set_strip_16( png_ptr ); if (img_color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb( png_ptr ); if (img_color_type == PNG_COLOR_TYPE_GRAY && img_depth < 8) png_set_expand_gray_1_2_4_to_8( png_ptr ); png_set_expand( png_ptr ); png_read_update_info( png_ptr, info_ptr ); png_get_IHDR( png_ptr, info_ptr, (png_uint_32*) &sizeX, (png_uint_32*) &sizeY, &img_depth, &img_color_type, &interlace_type, NULL, NULL ); row_pointers = (unsigned char**) malloc( sizeof (unsigned char*)*sizeY ); int numchan = 1; if (img_color_type&PNG_COLOR_MASK_COLOR) numchan = 3; if (img_color_type&PNG_COLOR_MASK_PALETTE) numchan = 1; if (img_color_type&PNG_COLOR_MASK_ALPHA) numchan++; unsigned long stride = numchan*sizeof (unsigned char)*img_depth/8; unsigned char *image = (unsigned char*) malloc( stride*sizeX*sizeY ); for (unsigned int i = 0; i < sizeY; i++) row_pointers[i] = &image[i*stride*sizeX]; png_read_image( png_ptr, row_pointers ); unsigned char *result; result = image; //free (row_pointers); *row_pointer_ptr = row_pointers; png_read_end( png_ptr, info_ptr ); png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); return result; }
Error ImageLoaderPNG::_load_image(void *rf_up, png_rw_ptr p_func, Ref<Image> p_image) { png_structp png; png_infop info; //png = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, _png_error_function, _png_warn_function, (png_voidp)NULL, _png_malloc_fn, _png_free_fn); ERR_FAIL_COND_V(!png, ERR_OUT_OF_MEMORY); info = png_create_info_struct(png); if (!info) { png_destroy_read_struct(&png, NULL, NULL); ERR_PRINT("Out of Memory"); return ERR_OUT_OF_MEMORY; } if (setjmp(png_jmpbuf(png))) { png_destroy_read_struct(&png, NULL, NULL); ERR_PRINT("PNG Corrupted"); return ERR_FILE_CORRUPT; } png_set_read_fn(png, (void *)rf_up, p_func); png_uint_32 width, height; int depth, color; png_read_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); //https://svn.gov.pt/projects/ccidadao/repository/middleware-offline/trunk/_src/eidmw/FreeImagePTEiD/Source/FreeImage/PluginPNG.cpp //png_get_text(png,info,) /* printf("Image width:%i\n", width); printf("Image Height:%i\n", height); printf("Bit depth:%i\n", depth); printf("Color type:%i\n", color); */ bool update_info = false; if (depth < 8) { //only bit dept 8 per channel is handled png_set_packing(png); update_info = true; }; if (png_get_color_type(png, info) == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png); update_info = true; } if (depth > 8) { png_set_strip_16(png); update_info = true; } if (png_get_valid(png, info, PNG_INFO_tRNS)) { //png_set_expand_gray_1_2_4_to_8(png); png_set_tRNS_to_alpha(png); update_info = true; } if (update_info) { png_read_update_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); } int components = 0; Image::Format fmt; switch (color) { case PNG_COLOR_TYPE_GRAY: { fmt = Image::FORMAT_L8; components = 1; } break; case PNG_COLOR_TYPE_GRAY_ALPHA: { fmt = Image::FORMAT_LA8; components = 2; } break; case PNG_COLOR_TYPE_RGB: { fmt = Image::FORMAT_RGB8; components = 3; } break; case PNG_COLOR_TYPE_RGB_ALPHA: { fmt = Image::FORMAT_RGBA8; components = 4; } break; default: { ERR_PRINT("INVALID PNG TYPE"); png_destroy_read_struct(&png, &info, NULL); return ERR_UNAVAILABLE; } break; } //int rowsize = png_get_rowbytes(png, info); int rowsize = components * width; PoolVector<uint8_t> dstbuff; dstbuff.resize(rowsize * height); PoolVector<uint8_t>::Write dstbuff_write = dstbuff.write(); uint8_t *data = dstbuff_write.ptr(); uint8_t **row_p = memnew_arr(uint8_t *, height); for (unsigned int i = 0; i < height; i++) { row_p[i] = &data[components * width * i]; } png_read_image(png, (png_bytep *)row_p); memdelete_arr(row_p); p_image->create(width, height, 0, fmt, dstbuff); png_destroy_read_struct(&png, &info, NULL); return OK; }
/* ================= image_png_load ================= */ GNUC_NONNULL static erbool image_png_load (const char *name, image_t *im) { fs_file_t f; int size, r, width, height, inc; png_byte *image = NULL, *p = NULL; png_structp pngst; png_infop info = NULL; png_byte depth, color_type; if (NULL == (f = fs_open(name, FS_RDONLY, &size, false))) return false; if (NULL == (pngst = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, &epng_error, &epng_warn))) { sys_printf("failed to create png read struct\n"); fs_close(f); return false; } if (NULL == (info = png_create_info_struct(pngst))) { sys_printf("failed to create png info struct\n"); goto error; } if (setjmp(png_jmpbuf(pngst))) goto error; png_set_user_limits(pngst, IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT); png_set_read_fn(pngst, f, &epng_read); png_read_info(pngst, info); width = png_get_image_width(pngst, info); height = png_get_image_height(pngst, info); depth = png_get_bit_depth(pngst, info); if (16 == depth) { /* 16 -> 8 */ png_set_strip_16(pngst); depth = 8; } color_type = png_get_color_type(pngst, info); /* 1/2/4 gray -> 8 gray */ if (PNG_COLOR_TYPE_GRAY == color_type && depth < 8) png_set_expand_gray_1_2_4_to_8(pngst); /* gray/palette -> rgb */ if (PNG_COLOR_TYPE_GRAY == color_type || PNG_COLOR_TYPE_GRAY_ALPHA == color_type) png_set_gray_to_rgb(pngst); else if (PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(pngst); /* transparency -> alpha */ if (png_get_valid(pngst, info, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(pngst); } else { /* to rgba */ if (PNG_COLOR_TYPE_RGB_ALPHA != color_type && PNG_COLOR_TYPE_GRAY_ALPHA != color_type) png_set_add_alpha(pngst, 0xff, PNG_FILLER_AFTER); } /* deinterlace */ png_set_interlace_handling(pngst); /* read */ inc = width * 4; p = image = mem_alloc(image_mempool, height * inc); for (r = 0; r < height ;r++, p += inc) png_read_row(pngst, p, NULL); png_read_end(pngst, NULL); png_destroy_read_struct(&pngst, &info, NULL); fs_close(f); im->width = width; im->height = height; im->data = image; return true; error: if (NULL != f) fs_close(f); png_destroy_read_struct(&pngst, NULL != info ? &info : NULL, NULL); if (NULL != image) mem_free(image); return false; }
/* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. Return nonzero (true) if they match */ return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK)); } #ifdef open_file /* prototype 1 */ void read_png(char *file_name) /* We need to open the file */ { png_structp png_ptr; png_infop info_ptr; unsigned int sig_read = 0; png_uint_32 width, height; int bit_depth, color_type, interlace_type; FILE *fp; if ((fp = fopen(file_name, "rb")) == NULL) return (ERROR); #else no_open_file /* prototype 2 */ void read_png(FILE *fp, unsigned int sig_read) /* File is already open */ { png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type; #endif no_open_file /* Only use one prototype! */ /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. REQUIRED */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp user_error_ptr, user_error_fn, user_warning_fn); if (png_ptr == NULL) { fclose(fp); return (ERROR); } /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); return (ERROR); } /* Set error handling if you are using the setjmp/longjmp method (this is * the normal method of doing things with libpng). REQUIRED unless you * set up your own error handlers in the png_create_read_struct() earlier. */ if (setjmp(png_jmpbuf(png_ptr))) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(fp); /* If we get here, we had a problem reading the file */ return (ERROR); } /* One of the following I/O initialization methods is REQUIRED */ #ifdef streams /* PNG file I/O method 1 */ /* Set up the input control if you are using standard C streams */ png_init_io(png_ptr, fp); #else no_streams /* PNG file I/O method 2 */ /* If you are using replacement read functions, instead of calling * png_init_io() here you would call: */ png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); /* where user_io_ptr is a structure you want available to the callbacks */ #endif no_streams /* Use only one I/O method! */ /* If we have already read some of the signature */ png_set_sig_bytes(png_ptr, sig_read); #ifdef hilevel /* * If you have enough memory to read in the entire image at once, * and you need to specify only transforms that can be controlled * with one of the PNG_TRANSFORM_* bits (this presently excludes * dithering, filling, setting background, and doing gamma * adjustment), then you can read the entire image (including * pixels) into the info structure with this call: */ png_read_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL); #else /* OK, you're doing it the hard way, with the lower-level functions */ /* The call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). REQUIRED */ png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL); /* Set up the data transformations you want. Note that these are all * optional. Only call them if you want/need them. Many of the * transformations only work on specific types of images, and many * are mutually exclusive. */ /* Tell libpng to strip 16 bit/color files down to 8 bits/color */ png_set_strip_16(png_ptr); /* Strip alpha bytes from the input data without combining with the * background (not recommended). */ png_set_strip_alpha(png_ptr); /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ png_set_packing(png_ptr); /* Change the order of packed pixels to least significant bit first * (not useful if you are using png_set_packing). */ png_set_packswap(png_ptr); /* Expand paletted colors into true RGB triplets */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); /* Expand paletted or RGB images with transparency to full alpha channels * so the data will be available as RGBA quartets. */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); /* Set the background color to draw transparent and alpha images over. * It is possible to set the red, green, and blue components directly * for paletted images instead of supplying a palette index. Note that * even if the PNG file supplies a background, you are not required to * use it - you should use the (solid) application background if it has one. */ png_color_16 my_background, *image_background; if (png_get_bKGD(png_ptr, info_ptr, &image_background)) png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); else png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); /* Some suggestions as to how to get a screen gamma value * * Note that screen gamma is the display_exponent, which includes * the CRT_exponent and any correction for viewing conditions */ if (/* We have a user-defined screen gamma value */) { screen_gamma = user-defined screen_gamma; } /* This is one way that applications share the same screen gamma value */ else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
Image * readPNG(const char *filename) { FILE *fp; png_structp png_ptr; png_infop info_ptr; png_infop end_info; Image *image; fp = fopen(filename, "rb"); if (!fp) goto no_fp; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) goto no_png; info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); goto no_png; } end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); goto no_png; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); goto no_png; } png_init_io(png_ptr, fp); png_read_info(png_ptr, info_ptr); png_uint_32 width, height; int bit_depth, color_type, interlace_type, compression_type, filter_method; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); image = new Image(width, height); if (!image) goto no_image; /* Convert to RGBA8 */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_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); for (unsigned y = 0; y < height; ++y) { png_bytep row = (png_bytep)(image->pixels + y*width*4); png_read_row(png_ptr, row, NULL); } png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return image; no_image: png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); no_png: fclose(fp); no_fp: return NULL; }
/***************************************************************************** * LoadPNG: loads the PNG logo into memory *****************************************************************************/ static picture_t *LoadPNG( vlc_object_t *p_this ) { picture_t *p_pic; char *psz_filename; vlc_value_t val; FILE *file; int i, j, i_trans; vlc_bool_t b_alpha = VLC_TRUE; png_uint_32 i_width, i_height; int i_color_type, i_interlace_type, i_compression_type, i_filter_type; int i_bit_depth; png_bytep *p_row_pointers; png_structp p_png; png_infop p_info, p_end_info; var_Create( p_this, "logo-file", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Get( p_this, "logo-file", &val ); psz_filename = val.psz_string; if( !psz_filename || !*psz_filename ) { msg_Err( p_this, "logo file not specified" ); return 0; } if( !(file = fopen( psz_filename , "rb" )) ) { msg_Err( p_this, "logo file (%s) not found", psz_filename ); free( psz_filename ); return 0; } free( psz_filename ); p_png = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ); p_info = png_create_info_struct( p_png ); p_end_info = png_create_info_struct( p_png ); png_init_io( p_png, file ); png_read_info( p_png, p_info ); png_get_IHDR( p_png, p_info, &i_width, &i_height, &i_bit_depth, &i_color_type, &i_interlace_type, &i_compression_type, &i_filter_type); if( i_color_type == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb( p_png ); if( i_color_type == PNG_COLOR_TYPE_GRAY || i_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) png_set_gray_to_rgb( p_png ); if( png_get_valid( p_png, p_info, PNG_INFO_tRNS ) ) { png_set_tRNS_to_alpha( p_png ); } else if( !(i_color_type & PNG_COLOR_MASK_ALPHA) ) { b_alpha = VLC_FALSE; } p_row_pointers = malloc( sizeof(png_bytep) * i_height ); for( i = 0; i < (int)i_height; i++ ) p_row_pointers[i] = malloc( 4 * ( i_bit_depth + 7 ) / 8 * i_width ); png_read_image( p_png, p_row_pointers ); png_read_end( p_png, p_end_info ); fclose( file ); png_destroy_read_struct( &p_png, &p_info, &p_end_info ); /* Convert to YUVA */ p_pic = malloc( sizeof(picture_t) ); if( vout_AllocatePicture( p_this, p_pic, VLC_FOURCC('Y','U','V','A'), i_width, i_height, VOUT_ASPECT_FACTOR ) != VLC_SUCCESS ) { for( i = 0; i < (int)i_height; i++ ) free( p_row_pointers[i] ); free( p_row_pointers ); return 0; } var_Create(p_this, "logo-transparency", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT); var_Get( p_this, "logo-transparency", &val ); i_trans = __MAX( __MIN( val.i_int, 255 ), 0 ); for( j = 0; j < (int)i_height ; j++ ) { uint8_t *p = (uint8_t *)p_row_pointers[j]; for( i = 0; i < (int)i_width ; i++ ) { int i_offset = i + j * p_pic->p[Y_PLANE].i_pitch; p_pic->p[Y_PLANE].p_pixels[i_offset] = (p[0] * 257L + p[1] * 504 + p[2] * 98)/1000 + 16; p_pic->p[U_PLANE].p_pixels[i_offset] = (p[2] * 439L - p[0] * 148 - p[1] * 291)/1000 + 128; p_pic->p[V_PLANE].p_pixels[i_offset] = (p[0] * 439L - p[1] * 368 - p[2] * 71)/1000 + 128; p_pic->p[A_PLANE].p_pixels[i_offset] = b_alpha ? (p[3] * i_trans) / 255 : i_trans; p += (b_alpha ? 4 : 3); } } for( i = 0; i < (int)i_height; i++ ) free( p_row_pointers[i] ); free( p_row_pointers ); return p_pic; }
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; }
plMipmap* plPNG::IRead(hsStream* inStream) { plMipmap* newMipmap = NULL; png_structp png_ptr; png_infop info_ptr; png_infop end_info; try { // Check PNG Signature png_byte sig[PNGSIGSIZE]; inStream->Read8Bytes((char*) sig); if (!png_sig_cmp(sig, 0, PNGSIGSIZE)) { // Allocate required structs png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { throw false; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); throw false; } end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); throw false; } // Assign delegate function for reading from hsStream png_set_read_fn(png_ptr, (png_voidp)inStream, pngReadDelegate); // Get PNG Header information png_set_sig_bytes(png_ptr, PNGSIGSIZE); png_read_info(png_ptr, info_ptr); png_uint_32 imgWidth = png_get_image_width(png_ptr, info_ptr); png_uint_32 imgHeight = png_get_image_height(png_ptr, info_ptr); png_uint_32 bitdepth = png_get_bit_depth(png_ptr, info_ptr); png_uint_32 channels = png_get_channels(png_ptr, info_ptr); png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr); // Convert images to RGB color space switch (color_type) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png_ptr); channels = 3; break; case PNG_COLOR_TYPE_GRAY: if (bitdepth < 8) { png_set_expand_gray_1_2_4_to_8(png_ptr); } bitdepth = 8; break; } // Convert transparency (if needed) to a full alpha channel if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); channels += 1; } else if (channels == 3) { // Add an opaque alpha channel if still none exists png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); channels = 4; } // Invert color byte-order as used by plMipmap for DirectX png_set_bgr(png_ptr); /// Construct a new mipmap to hold everything newMipmap = new plMipmap(imgWidth, imgHeight, plMipmap::kARGB32Config, 1, plMipmap::kUncompressed); char* destp = (char*)newMipmap->GetImage(); png_bytep* row_ptrs = new png_bytep[imgHeight]; const unsigned int stride = imgWidth * bitdepth * channels / 8; // Assign row pointers to the appropriate locations in the newly-created Mipmap for (size_t i = 0; i < imgHeight; i++) { row_ptrs[i] = (png_bytep)destp + (i * stride); } png_read_image(png_ptr, row_ptrs); png_read_end(png_ptr, end_info); // Clean up allocated structs png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete [] row_ptrs; } } catch (...) { delete newMipmap; newMipmap = nullptr; } return newMipmap; }
Py::Object _png_module::read_png(const Py::Tuple& args) { args.verify_length(1); std::string fname = Py::String(args[0]); png_byte header[8]; // 8 is the maximum size that can be checked FILE *fp = fopen(fname.c_str(), "rb"); if (!fp) throw Py::RuntimeError(Printf("_image_module::readpng could not open PNG file %s for reading", fname.c_str()).str()); if (fread(header, 1, 8, fp) != 8) throw Py::RuntimeError("_image_module::readpng: error reading PNG header"); if (png_sig_cmp(header, 0, 8)) throw Py::RuntimeError("_image_module::readpng: file not recognized as a PNG file"); /* initialize stuff */ png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) throw Py::RuntimeError("_image_module::readpng: png_create_read_struct failed"); png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) throw Py::RuntimeError("_image_module::readpng: png_create_info_struct failed"); if (setjmp(png_jmpbuf(png_ptr))) throw Py::RuntimeError("_image_module::readpng: error during init_io"); png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); png_uint_32 width = info_ptr->width; png_uint_32 height = info_ptr->height; // convert misc color types to rgb for simplicity if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY || info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); int bit_depth = info_ptr->bit_depth; if (bit_depth == 16) png_set_strip_16(png_ptr); png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); bool rgba = info_ptr->color_type == PNG_COLOR_TYPE_RGBA; if ( (info_ptr->color_type != PNG_COLOR_TYPE_RGB) && !rgba) { std::cerr << "Found color type " << (int)info_ptr->color_type << std::endl; throw Py::RuntimeError("_image_module::readpng: cannot handle color_type"); } /* read file */ if (setjmp(png_jmpbuf(png_ptr))) throw Py::RuntimeError("_image_module::readpng: error during read_image"); png_bytep *row_pointers = new png_bytep[height]; png_uint_32 row; for (row = 0; row < height; row++) row_pointers[row] = new png_byte[png_get_rowbytes(png_ptr,info_ptr)]; png_read_image(png_ptr, row_pointers); int dimensions[3]; dimensions[0] = height; //numrows dimensions[1] = width; //numcols dimensions[2] = 4; PyArrayObject *A = (PyArrayObject *) PyArray_FromDims(3, dimensions, PyArray_FLOAT); for (png_uint_32 y = 0; y < height; y++) { png_byte* row = row_pointers[y]; for (png_uint_32 x = 0; x < width; x++) { png_byte* ptr = (rgba) ? &(row[x*4]) : &(row[x*3]); size_t offset = y*A->strides[0] + x*A->strides[1]; //if ((y<10)&&(x==10)) std::cout << "r = " << ptr[0] << " " << ptr[0]/255.0 << std::endl; *(float*)(A->data + offset + 0*A->strides[2]) = (float)(ptr[0]/255.0f); *(float*)(A->data + offset + 1*A->strides[2]) = (float)(ptr[1]/255.0f); *(float*)(A->data + offset + 2*A->strides[2]) = (float)(ptr[2]/255.0f); *(float*)(A->data + offset + 3*A->strides[2]) = rgba ? (float)(ptr[3]/255.0f) : 1.0f; } } //free the png memory png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); fclose(fp); for (row = 0; row < height; row++) delete [] row_pointers[row]; delete [] row_pointers; return Py::asObject((PyObject*)A); }
ImageData ReadPNG(char* fileName) { ImageData meta; meta.valid = false; // Step 0: Make sure we can open the input file FILE* inFile = fopen(fileName, "rb"); if (!inFile) { abort_("ReadPNG: Can't open %s for reading\n", fileName); } // Step 1: initialize the reader png_structp png = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { abort_("ReadPNG: png_create_read_struct() failed\n"); } png_infop info = png_create_info_struct(png); if (!info) { abort_("ReadPNG: png_create_info_struct() failed\n"); } if (setjmp(png_jmpbuf(png))) { abort_("ReadPNG: Error during initialization.\n"); } png_init_io(png, inFile); png_read_info(png, info); // Step 2: Collect image statistics int width = png_get_image_width(png, info); int height = png_get_image_height(png, info); png_byte color_type = png_get_color_type(png, info); png_byte bit_depth = png_get_bit_depth(png, info); // Make some adjustments if (bit_depth == 16) { png_set_strip_16(png); } if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png); } if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { png_set_expand_gray_1_2_4_to_8(png); } if(png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); // These color_type don't have an alpha channel then fill it with 0xff. if(color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE) { png_set_filler(png, 0xFF, PNG_FILLER_AFTER); } if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png); } png_read_update_info(png, info); // Step 3: Read the data if (setjmp(png_jmpbuf(png))) { abort_("ReadPNG: Error during image data reading.\n"); } png_bytep row_pointers[height]; // This method gives a discontiguous array of rows // Each row is later copied to the destination image, RGB only. // There should be a more streamlined method, but this method works for lena.png for (int y = 0; y < height; y++) { row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png, info)); if (!row_pointers[y]) { abort_("ReadPNG: Couldn't allocate row %d\n", y); } } // Now we can read the image int row_bytes = png_get_rowbytes(png, info); png_read_image(png, row_pointers); // Convert the image from discontiguous rows to contiguous rows, discarding alpha Pixel* image = (Pixel*)malloc(height * width * 3); if (!image) { abort_("ReadPNG: Couldn't allocate image (%d, %d)\n", height, row_bytes); } // Brute force copy, skip over ALPHA channel for (int row = 0; row < height; row++) { for (int pixel = 0; pixel < width; pixel++) { image[(row * width + pixel)] = *(Pixel*)(row_pointers[row] + pixel * 4); } // As we use them, delete the pointers to the image rows. free(row_pointers[row]); } meta.xDim = width; meta.yDim = height; meta.valid = true; meta.pixels = (Pixel*)image; // Step 4: Tidy up. fclose(inFile); // Done. return meta; }
void FPngImageWrapper::UncompressPNGData( const ERGBFormat::Type InFormat, const int32 InBitDepth ) { // thread safety FScopeLock PNGLock(&GPNGSection); check( CompressedData.Num() ); check( Width > 0 ); check( Height > 0 ); // Note that PNGs on PC tend to be BGR check( InFormat == ERGBFormat::BGRA || InFormat == ERGBFormat::RGBA || InFormat == ERGBFormat::Gray ) // Other formats unsupported at present check( InBitDepth == 8 || InBitDepth == 16 ) // Other formats unsupported at present // Reset to the beginning of file so we can use png_read_png(), which expects to start at the beginning. ReadOffset = 0; png_structp png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING, this, FPngImageWrapper::user_error_fn, FPngImageWrapper::user_warning_fn, NULL, FPngImageWrapper::user_malloc, FPngImageWrapper::user_free); check( png_ptr ); png_infop info_ptr = png_create_info_struct( png_ptr ); check( info_ptr ); PNGReadGuard PNGGuard( &png_ptr, &info_ptr ); { if (ColorType == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } if ((ColorType & PNG_COLOR_MASK_COLOR) == 0 && BitDepth < 8) { png_set_expand_gray_1_2_4_to_8(png_ptr); } // Insert alpha channel with full opacity for RGB images without alpha if ((ColorType & PNG_COLOR_MASK_ALPHA) == 0 && (InFormat == ERGBFormat::BGRA || InFormat == ERGBFormat::RGBA)) { // png images don't set PNG_COLOR_MASK_ALPHA if they have alpha from a tRNS chunk, but png_set_add_alpha seems to be safe regardless if ((ColorType & PNG_COLOR_MASK_COLOR) == 0) { png_set_tRNS_to_alpha(png_ptr); } else if (ColorType == PNG_COLOR_TYPE_PALETTE) { png_set_tRNS_to_alpha(png_ptr); } if (InBitDepth == 8) { png_set_add_alpha(png_ptr, 0xff , PNG_FILLER_AFTER); } else if (InBitDepth == 16) { png_set_add_alpha(png_ptr, 0xffff , PNG_FILLER_AFTER); } } // Calculate Pixel Depth const uint32 PixelChannels = (InFormat == ERGBFormat::Gray) ? 1 : 4; const uint32 BytesPerPixel = (InBitDepth * PixelChannels) / 8; const uint32 BytesPerRow = BytesPerPixel * Width; RawData.Empty(Height * BytesPerRow); RawData.AddUninitialized(Height * BytesPerRow); png_set_read_fn( png_ptr, this, FPngImageWrapper::user_read_compressed ); png_bytep* row_pointers = (png_bytep*) png_malloc( png_ptr, Height*sizeof(png_bytep) ); PNGGuard.SetRowPointers(&row_pointers); for (int32 i = 0; i < Height; i++) { row_pointers[i]= &RawData[i * BytesPerRow]; } png_set_rows(png_ptr, info_ptr, row_pointers); uint32 Transform = (InFormat == ERGBFormat::BGRA) ? PNG_TRANSFORM_BGR : PNG_TRANSFORM_IDENTITY; // PNG files store 16-bit pixels in network byte order (big-endian, ie. most significant bits first). #if PLATFORM_LITTLE_ENDIAN // We're little endian so we need to swap if (BitDepth == 16) { Transform |= PNG_TRANSFORM_SWAP_ENDIAN; } #endif // Convert grayscale png to RGB if requested if ((ColorType & PNG_COLOR_MASK_COLOR) == 0 && (InFormat == ERGBFormat::RGBA || InFormat == ERGBFormat::BGRA)) { Transform |= PNG_TRANSFORM_GRAY_TO_RGB; } // Convert RGB png to grayscale if requested if ((ColorType & PNG_COLOR_MASK_COLOR) != 0 && InFormat == ERGBFormat::Gray) { png_set_rgb_to_gray_fixed(png_ptr, 2 /* warn if image is in color */, -1, -1); } // Strip alpha channel if requested output is grayscale if (InFormat == ERGBFormat::Gray) { // this is not necessarily the best option, instead perhaps: // png_color background = {0,0,0}; // png_set_background(png_ptr, &background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); Transform |= PNG_TRANSFORM_STRIP_ALPHA; } // Reduce 16-bit to 8-bit if requested if (BitDepth == 16 && InBitDepth == 8) { #if PNG_LIBPNG_VER >= 10504 check(0); // Needs testing Transform |= PNG_TRANSFORM_SCALE_16; #else Transform |= PNG_TRANSFORM_STRIP_16; #endif } // Increase 8-bit to 16-bit if requested if (BitDepth <= 8 && InBitDepth == 16) { #if PNG_LIBPNG_VER >= 10504 check(0); // Needs testing Transform |= PNG_TRANSFORM_EXPAND_16 #else // Expanding 8-bit images to 16-bit via transform needs a libpng update check(0); #endif } png_read_png(png_ptr, info_ptr, Transform, NULL); } RawFormat = InFormat; RawBitDepth = InBitDepth; }
bool PngDecoder::readData( Mat& img ) { bool result = false; AutoBuffer<uchar*> _buffer(m_height); uchar** buffer = _buffer; int color = img.channels() > 1; uchar* data = img.data; int step = (int)img.step; if( m_png_ptr && m_info_ptr && m_end_info && m_width && m_height ) { png_structp png_ptr = (png_structp)m_png_ptr; png_infop info_ptr = (png_infop)m_info_ptr; png_infop end_info = (png_infop)m_end_info; if( setjmp( png_jmpbuf ( png_ptr ) ) == 0 ) { int y; if( img.depth() == CV_8U && m_bit_depth == 16 ) png_set_strip_16( png_ptr ); else if( !isBigEndian() ) png_set_swap( png_ptr ); if(img.channels() < 4) { /* observation: png_read_image() writes 400 bytes beyond * end of data when reading a 400x118 color png * "mpplus_sand.png". OpenCV crashes even with demo * programs. Looking at the loaded image I'd say we get 4 * bytes per pixel instead of 3 bytes per pixel. Test * indicate that it is a good idea to always ask for * stripping alpha.. 18.11.2004 Axel Walthelm */ png_set_strip_alpha( png_ptr ); } if( m_color_type == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb( png_ptr ); if( m_color_type == PNG_COLOR_TYPE_GRAY && m_bit_depth < 8 ) #if (PNG_LIBPNG_VER_MAJOR*10000 + PNG_LIBPNG_VER_MINOR*100 + PNG_LIBPNG_VER_RELEASE >= 10209) || \ (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR == 0 && PNG_LIBPNG_VER_RELEASE >= 18) png_set_expand_gray_1_2_4_to_8( png_ptr ); #else png_set_gray_1_2_4_to_8( png_ptr ); #endif if( CV_MAT_CN(m_type) > 1 && color ) png_set_bgr( png_ptr ); // convert RGB to BGR else if( color ) png_set_gray_to_rgb( png_ptr ); // Gray->RGB else png_set_rgb_to_gray( png_ptr, 1, 0.299, 0.587 ); // RGB->Gray png_read_update_info( png_ptr, info_ptr ); for( y = 0; y < m_height; y++ ) buffer[y] = data + y*step; png_read_image( png_ptr, buffer ); png_read_end( png_ptr, end_info ); result = true; } } close(); return result; }
int load_png( char *file_name, int stype ) { char buf[PNG_BYTES_TO_CHECK], *mess; unsigned char *rgb, *rgb2, *rgb3; int i, row, do_prog, bit_depth, color_type, interlace_type, width, height; unsigned int sig_read = 0; FILE *fp; png_bytep *row_pointers, trans; png_color_16p trans_rgb; png_structp png_ptr; png_infop info_ptr; png_uint_32 pwidth, pheight; png_colorp png_palette; if ((fp = fopen(file_name, "rb")) == NULL) return -1; i = fread(buf, 1, PNG_BYTES_TO_CHECK, fp); if ( i != PNG_BYTES_TO_CHECK ) goto fail; i = !png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK); if ( i<=0 ) goto fail; rewind( fp ); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) goto fail; info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, NULL, NULL); goto fail; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(fp); return -1; } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, sig_read); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &pwidth, &pheight, &bit_depth, &color_type, &interlace_type, NULL, NULL); width = (int) pwidth; height = (int) pheight; if ( width > MAX_WIDTH || height > MAX_HEIGHT ) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return TOO_BIG; } row_pointers = malloc( sizeof(png_bytep) * height ); if (setjmp(png_jmpbuf(png_ptr))) // If libpng generates an error now, clean up { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); free(row_pointers); return FILE_LIB_ERROR; } rgb = NULL; mess = NULL; if ( width*height > FILE_PROGRESS ) do_prog = 1; else do_prog = 0; if ( stype == 0 ) { mess = _("Loading PNG image"); rgb = mem_image; } if ( stype == 1 ) { mess = _("Loading clipboard image"); rgb = mem_clipboard; if ( rgb != NULL ) free( rgb ); // Lose old clipboard mem_clip_mask_clear(); // Lose old clipboard mask } if ( color_type != PNG_COLOR_TYPE_PALETTE || bit_depth>8 ) // RGB PNG file { png_set_strip_16(png_ptr); png_set_gray_1_2_4_to_8(png_ptr); png_set_palette_to_rgb(png_ptr); png_set_gray_to_rgb(png_ptr); if ( stype == 0 ) { mem_pal_copy( mem_pal, mem_pal_def ); mem_cols = 256; if ( mem_new( width, height, 3 ) != 0 ) goto file_too_huge; rgb = mem_image; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { // Image has a transparent index png_get_tRNS(png_ptr, info_ptr, 0, 0, &trans_rgb); mem_pal[255].red = trans_rgb->red; mem_pal[255].green = trans_rgb->green; mem_pal[255].blue = trans_rgb->blue; if (color_type == PNG_COLOR_TYPE_GRAY) { if ( bit_depth==4 ) i = trans_rgb->gray * 17; if ( bit_depth==8 ) i = trans_rgb->gray; if ( bit_depth==16 ) i = trans_rgb->gray >> (bit_depth-8); mem_pal[255].red = i; mem_pal[255].green = i; mem_pal[255].blue = i; } mem_xpm_trans = 255; } }
GLuint loadPNG(const char * file_name, GLuint tex) { png_byte header[8]; FILE *fp = fopen(file_name, "rb"); if (fp == 0) { perror(file_name); return 0; } // read the header fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) { fprintf(stderr, "error: %s is not a PNG.\n", file_name); fclose(fp); return 0; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fprintf(stderr, "error: png_create_read_struct returned 0.\n"); fclose(fp); return 0; } // create png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(fp); return 0; } // create png info struct png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); fclose(fp); return 0; } // the code in this if statement gets called if libpng encounters an error if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "error from libpng\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return 0; } // init png reading png_init_io(png_ptr, fp); // let libpng know you already read the first 8 bytes png_set_sig_bytes(png_ptr, 8); // read all the info up to the image data png_read_info(png_ptr, info_ptr); // variables to pass to get info int bit_depth, color_type; png_uint_32 temp_width, temp_height; // get info about png png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, NULL, NULL, NULL); GLint format; switch(color_type) { case PNG_COLOR_TYPE_RGB: format = GL_RGB; break; case PNG_COLOR_TYPE_RGB_ALPHA: format = GL_RGBA; break; case PNG_COLOR_TYPE_GRAY: //cout<<"color Type Grey"<<endl; format = GL_RGBA; png_set_gray_to_rgb(png_ptr); png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); break; case PNG_COLOR_TYPE_GRAY_ALPHA: //cout<<"color Type Grey Alpha"<<endl; format = GL_RGBA; png_set_gray_to_rgb(png_ptr); break; case PNG_COLOR_TYPE_PALETTE: //cout<<"color Type Palette"<<endl; format = GL_RGBA; png_set_palette_to_rgb(png_ptr); png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); //return 0; break; default: fprintf(stderr, "%s: Unknown libpng color type %d.\n", file_name, color_type); return 0; } // Update the png info struct. png_read_update_info(png_ptr, info_ptr); // Row size in bytes. int rowbytes = png_get_rowbytes(png_ptr, info_ptr); // glTexImage2d requires rows to be 4-byte aligned rowbytes += 3 - ((rowbytes-1) % 4); // Allocate the image_data as a big block, to be given to opengl png_byte * image_data; //image_data = (png_byte*) malloc(rowbytes * temp_height * sizeof(png_byte)+15); image_data = new png_byte[rowbytes * temp_height]; if (image_data == NULL) { fprintf(stderr, "error: could not allocate memory for PNG image data\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return 0; } // row_pointers is for pointing to image_data for reading the png with libpng //png_bytep * row_pointers = (png_bytep*) malloc(temp_height * sizeof(png_bytep)); png_bytep * row_pointers = new png_bytep[temp_height]; if (row_pointers == NULL) { fprintf(stderr, "error: could not allocate memory for PNG row pointers\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(image_data); fclose(fp); return 0; } // set the individual row_pointers to point at the correct offsets of image_data int i; for (i = 0; i < temp_height; i++) { row_pointers[/*temp_height - 1 - */i] = image_data + i * rowbytes; } // read the png into image_data through row_pointers png_read_image(png_ptr, row_pointers); glBindTexture(GL_TEXTURE_2D, tex); glTexImage2D(GL_TEXTURE_2D, 0, format, temp_width, temp_height, 0, format, GL_UNSIGNED_BYTE, image_data); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // clean up png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete[] image_data; delete[] row_pointers; fclose(fp); return tex; }
static const char * VS_CC check_png(img_hnd_t *ih, int n, FILE *fp, vs_args_t *va) { uint8_t signature[PNG_SIG_LENGTH]; if (fread(signature, 1, PNG_SIG_LENGTH, fp) != PNG_SIG_LENGTH || png_sig_cmp(signature, 0, PNG_SIG_LENGTH)) { return "unsupported format"; } png_structp p_str = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!p_str) { return "failed to create png_read_struct"; } png_infop p_info = png_create_info_struct(p_str); if (!p_info) { png_destroy_read_struct(&p_str, NULL, NULL); return "failed to create png_info_struct"; } png_init_io(p_str, fp); png_set_sig_bytes(p_str, PNG_SIG_LENGTH); png_read_info(p_str, p_info); png_uint_32 width, height; int color_type, bit_depth; png_get_IHDR(p_str, p_info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); if (color_type & PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(p_str); } if (bit_depth < 8) { png_set_packing(p_str); } if (ih->enable_alpha == 0) { if (color_type & PNG_COLOR_MASK_ALPHA) { png_set_strip_alpha(p_str); } } else if ((color_type & PNG_COLOR_MASK_ALPHA) == 0) { png_set_add_alpha(p_str, 0x00, PNG_FILLER_AFTER); } png_read_update_info(p_str, p_info); png_get_IHDR(p_str, p_info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); uint32_t row_size = png_get_rowbytes(p_str, p_info); png_destroy_read_struct(&p_str, &p_info, NULL); ih->src[n].width = width; ih->src[n].height = height; VSPresetFormat pf = get_dst_format(color_type, bit_depth); if (pf == pfNone) { return "unsupported png color type"; } ih->src[n].format = va->vsapi->getFormatPreset(pf, va->core); ih->src[n].read = read_png; ih->src[n].flip = 0; if (row_size > va->max_row_size) { va->max_row_size = row_size; } return NULL; }
void *readpng(const unsigned char *base, size_t size, unsigned *_width, unsigned *_height) { PngReader reader; unsigned char *data = 0; unsigned char **rowptrs = 0; png_structp p = 0; png_infop pi = 0; png_uint_32 width, height; int bitdepth, colortype, imethod, cmethod, fmethod, i; p = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if(p == 0) { LOG("%s: failed to allocate png read struct\n", fn); return 0; } pi = png_create_info_struct(p); if(pi == 0) { LOG("%s: failed to allocate png info struct\n", fn); goto oops; } reader.base = base; reader.end = base + size; reader.cursor = base; if(size < 8 || png_sig_cmp((unsigned char*)base, 0, 8)) { LOG("%s: header is not a PNG header\n", fn); goto oops; } reader.cursor += 8; if(setjmp(png_jmpbuf(p))) { LOG("%s: png library error\n", fn); oops: png_destroy_read_struct(&p, &pi, 0); if(data != 0) free(data); if(rowptrs != 0) free(rowptrs); return 0; } png_set_read_fn (p, &reader, png_reader_read_data); png_set_sig_bytes(p, 8); png_read_info(p, pi); png_get_IHDR(p, pi, &width, &height, &bitdepth, &colortype, &imethod, &cmethod, &fmethod); // printf("PNG: %d x %d (d=%d, c=%d)\n", // width, height, bitdepth, colortype); switch(colortype){ case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(p); break; case PNG_COLOR_TYPE_RGB: if(png_get_valid(p, pi, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(p); } else { png_set_filler(p, 0xff, PNG_FILLER_AFTER); } break; case PNG_COLOR_TYPE_RGB_ALPHA: break; case PNG_COLOR_TYPE_GRAY: if(bitdepth < 8) { png_set_gray_1_2_4_to_8(p); } default: LOG("%s: unsupported (grayscale?) color type\n"); goto oops; } if(bitdepth == 16) { png_set_strip_16(p); } data = (unsigned char*) malloc((width * 4) * height); rowptrs = (unsigned char **) malloc(sizeof(unsigned char*) * height); if((data == 0) || (rowptrs == 0)){ LOG("could not allocate data buffer\n"); goto oops; } for(i = 0; i < height; i++) { rowptrs[i] = data + ((width * 4) * i); } png_read_image(p, rowptrs); png_destroy_read_struct(&p, &pi, 0); if(rowptrs != 0) free(rowptrs); *_width = width; *_height = height; return (void*) data; }
static int VS_CC read_png(img_hnd_t *ih, int n) { FILE *fp = imgr_fopen(ih->src[n].name); if (!fp) { return -1; } png_structp p_str = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!p_str) { fclose(fp); return -1; } png_infop p_info = png_create_info_struct(p_str); if (!p_info) { fclose(fp); png_destroy_read_struct(&p_str, NULL, NULL); return -1; } png_init_io(p_str, fp); png_read_info(p_str, p_info); png_uint_32 width, height; int color_type, bit_depth; png_get_IHDR(p_str, p_info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); if (color_type & PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(p_str); } if (bit_depth < 8) { png_set_packing(p_str); } if (bit_depth > 8) { png_set_swap(p_str); } if (ih->enable_alpha == 0) { if (color_type & PNG_COLOR_MASK_ALPHA) { png_set_strip_alpha(p_str); } } else if ((color_type & PNG_COLOR_MASK_ALPHA) == 0) { png_set_add_alpha(p_str, 0x00, PNG_FILLER_AFTER); } png_read_update_info(p_str, p_info); png_read_image(p_str, ih->png_row_index); fclose(fp); png_destroy_read_struct(&p_str, &p_info, NULL); ih->misc = IMG_ORDER_RGB; ih->row_adjust = 1; switch ((ih->src[n].format->id << 1) | ih->enable_alpha) { case (pfRGB24 << 1 | 0): ih->write_frame = func_write_rgb24; break; case (pfRGB24 << 1 | 1): ih->write_frame = func_write_rgb32; break; case (pfRGB48 << 1 | 0): ih->write_frame = func_write_rgb48; break; case (pfRGB48 << 1 | 1): ih->write_frame = func_write_rgb64; break; case (pfGray8 << 1 | 0): case (pfGray16 << 1 | 0): ih->write_frame = func_write_planar; break; case (pfGray8 << 1 | 1): ih->write_frame = func_write_gray8_a; break; case (pfGray16 << 1 | 1): ih->write_frame = func_write_gray16_a; break; default: break; } return 0; }
gboolean read_png(curlMemoryStructGCS *chunk, unsigned char **raw_image, picSrcImageInfoGCS *info, char *errBuf) { png_structp png_ptr; png_infop info_ptr; /* initialize stuff */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { GST_DEBUG("png_create_read_struct failed"); strcpy(errBuf, "read_png - Error : png_create_read_struct failed"); return FALSE; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { GST_DEBUG("png_create_info_struct failed"); strcpy(errBuf, "read_png - Error : png_create_info_struct failed"); return FALSE; } FILE* memstream = fmemopen((void *)chunk->memory, chunk->size, "rb"); if (!memstream) { GST_DEBUG("fmemopen failed"); strcpy(errBuf, "read_imgheader - Error : fmemopen failed"); return FALSE; } png_init_io(png_ptr, memstream); png_set_error_fn(png_ptr, (png_voidp)NULL, png_error_fn, png_warning_fn); /* read file */ if (setjmp(png_jmpbuf(png_ptr))) { sprintf(errBuf, "read_png - Error : %s", "undetermined"); fclose(memstream); return FALSE; } png_uint_32 imgWidth, imgHeight; int bitdepth, color_type; png_read_info(png_ptr, info_ptr); png_get_IHDR( png_ptr, info_ptr, &imgWidth, &imgHeight, &bitdepth, &color_type, 0, 0, 0 ); //Number of channels int channels = png_get_channels(png_ptr, info_ptr); switch (color_type) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png_ptr); channels = 3; info->colorspace = COLOR_TYPE_GCS_RGB; break; case PNG_COLOR_TYPE_GRAY: if (bitdepth < 8) png_set_gray_1_2_4_to_8(png_ptr); //And the bitdepth info bitdepth = 8; png_set_gray_to_rgb(png_ptr); info->colorspace = COLOR_TYPE_GCS_RGB; break; } /*if the image has a transperancy set.. convert it to a full Alpha channel..*/ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); channels+=1; info->colorspace = COLOR_TYPE_GCS_RGB_ALPHA; } //We don't support 16 bit precision.. so if the image Has 16 bits per channel //precision... round it down to 8. if (bitdepth == 16) png_set_strip_16(png_ptr); info->width = imgWidth; info->height = imgHeight; info->channels = channels; /* read file */ if (setjmp(png_jmpbuf(png_ptr))) { sprintf(errBuf, "read_png - Error : %s", "undetermined"); fclose(memstream); return FALSE; } png_bytep* rowPtrs[imgHeight]; *raw_image = (unsigned char*)malloc(imgWidth * imgHeight * bitdepth * channels / 8); const unsigned int stride = imgWidth * bitdepth * channels / 8; GST_DEBUG("imgWidth:%d, imgHeight:%d, bitdepth:%d, channels:%d, stride:%d", imgWidth,imgHeight,bitdepth,channels, stride ); size_t i; for (i = 0; i < imgHeight; i++) { rowPtrs[i] = (png_bytep*)((png_bytep)(*raw_image) + ( i * stride)); } png_read_image(png_ptr, (png_bytepp)rowPtrs); fclose(memstream); return TRUE; }
/**************************************************************************** * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with a complete compressed frame. ****************************************************************************/ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; picture_t *p_pic = 0; png_uint_32 i_width, i_height; int i_color_type, i_interlace_type, i_compression_type, i_filter_type; int i_bit_depth, i; png_structp p_png; png_infop p_info, p_end_info; png_bytep *p_row_pointers = NULL; if( !pp_block || !*pp_block ) return NULL; p_block = *pp_block; p_sys->b_error = false; if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) { block_Release( p_block ); *pp_block = NULL; return NULL; } p_png = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ); if( p_png == NULL ) { block_Release( p_block ); *pp_block = NULL; return NULL; } p_info = png_create_info_struct( p_png ); if( p_info == NULL ) { png_destroy_read_struct( &p_png, NULL, NULL ); block_Release( p_block ); *pp_block = NULL; return NULL; } p_end_info = png_create_info_struct( p_png ); if( p_end_info == NULL ) { png_destroy_read_struct( &p_png, &p_info, NULL ); block_Release( p_block ); *pp_block = NULL; return NULL; } /* libpng longjmp's there in case of error */ if( setjmp( png_jmpbuf( p_png ) ) ) goto error; png_set_read_fn( p_png, (void *)p_block, user_read ); png_set_error_fn( p_png, (void *)p_dec, user_error, user_warning ); png_read_info( p_png, p_info ); if( p_sys->b_error ) goto error; png_get_IHDR( p_png, p_info, &i_width, &i_height, &i_bit_depth, &i_color_type, &i_interlace_type, &i_compression_type, &i_filter_type); if( p_sys->b_error ) goto error; /* Set output properties */ p_dec->fmt_out.i_codec = VLC_CODEC_RGBA; p_dec->fmt_out.video.i_visible_width = p_dec->fmt_out.video.i_width = i_width; p_dec->fmt_out.video.i_visible_height = p_dec->fmt_out.video.i_height = i_height; p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; p_dec->fmt_out.video.i_rmask = 0x000000ff; p_dec->fmt_out.video.i_gmask = 0x0000ff00; p_dec->fmt_out.video.i_bmask = 0x00ff0000; if( i_color_type == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb( p_png ); if( i_color_type == PNG_COLOR_TYPE_GRAY || i_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) png_set_gray_to_rgb( p_png ); /* Strip to 8 bits per channel */ if( i_bit_depth == 16 ) png_set_strip_16( p_png ); if( png_get_valid( p_png, p_info, PNG_INFO_tRNS ) ) { png_set_tRNS_to_alpha( p_png ); } else if( !(i_color_type & PNG_COLOR_MASK_ALPHA) ) { p_dec->fmt_out.i_codec = VLC_CODEC_RGB24; } /* Get a new picture */ p_pic = decoder_NewPicture( p_dec ); if( !p_pic ) goto error; /* Decode picture */ p_row_pointers = malloc( sizeof(png_bytep) * i_height ); if( !p_row_pointers ) goto error; for( i = 0; i < (int)i_height; i++ ) p_row_pointers[i] = p_pic->p->p_pixels + p_pic->p->i_pitch * i; png_read_image( p_png, p_row_pointers ); if( p_sys->b_error ) goto error; png_read_end( p_png, p_end_info ); if( p_sys->b_error ) goto error; png_destroy_read_struct( &p_png, &p_info, &p_end_info ); free( p_row_pointers ); p_pic->date = p_block->i_pts > VLC_TS_INVALID ? p_block->i_pts : p_block->i_dts; block_Release( p_block ); *pp_block = NULL; return p_pic; error: free( p_row_pointers ); png_destroy_read_struct( &p_png, &p_info, &p_end_info ); block_Release( p_block ); *pp_block = NULL; return NULL; }
static bool loadPng(const uint8_t *inputData, size_t size, Bytes &outputData, Color &color, Alpha &alpha, uint32_t &width, uint32_t &height, uint32_t &stride, const Bitmap::StrideFn &strideFn) { auto png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { log::text("libpng", "fail to create read struct"); return false; } auto info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { log::text("libpng", "fail to create info struct"); png_destroy_read_struct(&png_ptr, NULL, NULL); return false; } if (setjmp(png_jmpbuf(png_ptr))) { log::text("libpng", "error in processing (setjmp return)"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return false; } Bitmap_readState state; state.data = inputData; state.offset = 0; png_set_read_fn(png_ptr,(png_voidp)&state, Bitmap_readDynamicData); 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); png_byte bitdepth = png_get_bit_depth(png_ptr, info_ptr); png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } if (color_type == PNG_COLOR_TYPE_GRAY && bitdepth < 8) { bitdepth = 8; png_set_expand_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 (bitdepth == 16) { png_set_strip_16(png_ptr); } if (bitdepth < 8) { png_set_packing(png_ptr); } png_read_update_info(png_ptr, info_ptr); bitdepth = png_get_bit_depth(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); auto rowbytes = png_get_rowbytes(png_ptr, info_ptr); if (color_type == PNG_COLOR_TYPE_GRAY) { color = (color == Color::A8?Color::A8:Color::I8); } else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { color = Color::IA88; } else if (color_type == PNG_COLOR_TYPE_RGB) { color = Color::RGB888; } else if (color_type == PNG_COLOR_TYPE_RGBA) { color = Color::RGBA8888; } else { width = 0; height = 0; stride = 0; outputData.clear(); log::format("Bitmap", "unsupported color type: %u", (unsigned int)color_type); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return false; } if (strideFn) { stride = max((uint32_t)strideFn(color, width), (uint32_t)rowbytes); } else { stride = (uint32_t)rowbytes; } if (color == Color::I8 || color == Color::RGB888) { alpha = Alpha::Opaque; } else { alpha = Alpha::Unpremultiplied; } // read png data png_bytep* row_pointers = new png_bytep[height]; auto dataLen = stride * height; outputData.resize(dataLen); for (unsigned short i = 0; i < height; ++i) { row_pointers[i] = outputData.data() + i*stride; } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, nullptr); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); delete [] row_pointers; if (!outputData.empty()) { return true; } return false; }
bool Image::initWithPngData(const unsigned char * data, ssize_t dataLen) { #if CC_USE_WIC return decodeWithWIC(data, dataLen); #else // length of bytes to check if it is a valid png file #define PNGSIGSIZE 8 bool ret = false; png_byte header[PNGSIGSIZE] = { 0 }; png_structp png_ptr = 0; png_infop info_ptr = 0; do { // png header len is 8 bytes CC_BREAK_IF(dataLen < PNGSIGSIZE); // check the data is png or not memcpy(header, data, PNGSIGSIZE); CC_BREAK_IF(png_sig_cmp(header, 0, PNGSIGSIZE)); // init png_struct png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); CC_BREAK_IF(!png_ptr); // init png_info info_ptr = png_create_info_struct(png_ptr); CC_BREAK_IF(!info_ptr); #if (PARA_TARGET_PLATFORM != PARA_PLATFORM_BADA && PARA_TARGET_PLATFORM != PARA_PLATFORM_NACL && PARA_TARGET_PLATFORM != PARA_PLATFORM_TIZEN) CC_BREAK_IF(setjmp(png_jmpbuf(png_ptr))); #endif // set the read call back function tImageSource imageSource; imageSource.data = (unsigned char*)data; imageSource.size = dataLen; imageSource.offset = 0; png_set_read_fn(png_ptr, &imageSource, pngReadCallback); // read png header info // read png file info 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); png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr); png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr); //OUTPUT_LOG("color type %u", color_type); // force palette images to be expanded to 24-bit RGB // it may include alpha channel if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } // low-bit-depth grayscale images are to be expanded to 8 bits if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { bit_depth = 8; png_set_expand_gray_1_2_4_to_8(png_ptr); } // expand any tRNS chunk data into a full alpha channel if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); } // reduce images with 16-bit samples to 8 bits if (bit_depth == 16) { png_set_strip_16(png_ptr); } // Expanded earlier for grayscale, now take care of palette and rgb if (bit_depth < 8) { png_set_packing(png_ptr); } // update info png_read_update_info(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); switch (color_type) { case PNG_COLOR_TYPE_GRAY: _renderFormat = Texture2D::PixelFormat::I8; break; case PNG_COLOR_TYPE_GRAY_ALPHA: _renderFormat = Texture2D::PixelFormat::AI88; break; case PNG_COLOR_TYPE_RGB: _renderFormat = Texture2D::PixelFormat::RGB888; break; case PNG_COLOR_TYPE_RGB_ALPHA: _renderFormat = Texture2D::PixelFormat::RGBA8888; break; default: break; } // read png data png_size_t rowbytes; png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * _height); rowbytes = png_get_rowbytes(png_ptr, info_ptr); _dataLen = rowbytes * _height; _data = static_cast<unsigned char*>(malloc(_dataLen * sizeof(unsigned char))); if (!_data) { if (row_pointers != nullptr) { free(row_pointers); } break; } for (unsigned short i = 0; i < _height; ++i) { row_pointers[i] = _data + i*rowbytes; } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, nullptr); // premultiplied alpha for RGBA8888 if (PNG_PREMULTIPLIED_ALPHA_ENABLED && color_type == PNG_COLOR_TYPE_RGB_ALPHA) { premultipliedAlpha(); } if (row_pointers != nullptr) { free(row_pointers); } ret = true; } while (0); if (png_ptr) { png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0); } return ret; #endif }
int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha, Metadata* const metadata) { png_structp png; png_infop info = NULL; png_infop end_info = NULL; int color_type, bit_depth, interlaced; int has_alpha; int num_passes; int p; int ok = 0; png_uint_32 width, height, y; int stride; uint8_t* rgb = NULL; png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (png == NULL) { goto End; } png_set_error_fn(png, 0, error_function, NULL); if (setjmp(png_jmpbuf(png))) { Error: MetadataFree(metadata); png_destroy_read_struct(&png, &info, &end_info); goto End; } info = png_create_info_struct(png); if (info == NULL) goto Error; end_info = png_create_info_struct(png); if (end_info == NULL) goto Error; png_init_io(png, in_file); png_read_info(png, info); if (!png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, &interlaced, NULL, NULL)) goto Error; png_set_strip_16(png); png_set_packing(png); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { if (bit_depth < 8) { png_set_expand_gray_1_2_4_to_8(png); } png_set_gray_to_rgb(png); } if (png_get_valid(png, info, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png); has_alpha = 1; } else { has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA); } if (!keep_alpha) { png_set_strip_alpha(png); has_alpha = 0; } num_passes = png_set_interlace_handling(png); png_read_update_info(png, info); stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb); rgb = (uint8_t*)malloc(stride * height); if (rgb == NULL) goto Error; for (p = 0; p < num_passes; ++p) { for (y = 0; y < height; ++y) { png_bytep row = rgb + y * stride; png_read_rows(png, &row, NULL, 1); } } png_read_end(png, end_info); if (metadata != NULL && !ExtractMetadataFromPNG(png, info, end_info, metadata)) { fprintf(stderr, "Error extracting PNG metadata!\n"); goto Error; } png_destroy_read_struct(&png, &info, &end_info); pic->width = width; pic->height = height; ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, stride) : WebPPictureImportRGB(pic, rgb, stride); if (!ok) { goto Error; } End: free(rgb); return ok; }
/* For little endian systems, ARGB is equivalent to the int32 BGRA. * So, to read the image as RGB */ static SLang_Array_Type *read_image_internal (char *file, int flip, int *color_typep) { Png_Type *p; png_uint_32 width, height, rowbytes; png_struct *png; png_info *info; int bit_depth; int interlace_type; int color_type; unsigned int sizeof_type; SLindex_Type dims[2]; SLtype data_type; png_byte **image_pointers = NULL; png_byte *data = NULL; SLang_Array_Type *at; void (*fixup_array_fun) (SLang_Array_Type *); if (NULL == (p = open_png_file (file))) return NULL; png = p->png; if (setjmp (png_jmpbuf (png))) { free_png_type (p); if (data != NULL) SLfree ((char *) data); free_image_pointers (image_pointers); SLang_verror (SL_Read_Error, "Error encountered during I/O to %s", file); return NULL; } png_init_io (png, p->fp); png_set_sig_bytes (png, 8); info = p->info; png_read_info(png, info); width = png_get_image_width (png, info); height = png_get_image_height (png, info); interlace_type = png_get_interlace_type (png, info); bit_depth = png_get_bit_depth (png, info); if (bit_depth == 16) png_set_strip_16 (png); switch (png_get_color_type (png, info)) { case PNG_COLOR_TYPE_GRAY: #if defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10209) if (bit_depth < 8) png_set_expand_gray_1_2_4_to_8 (png); #else /* deprecated */ if (bit_depth < 8) png_set_gray_1_2_4_to_8 (png); #endif break; case PNG_COLOR_TYPE_GRAY_ALPHA: /* png_set_gray_to_rgb (png); */ break; case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb (png); break; } if (png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); png_read_update_info (png, info); color_type = png_get_color_type (png, info); switch (color_type) { case PNG_COLOR_TYPE_RGBA: sizeof_type = 4; fixup_array_fun = fixup_array_rgba; data_type = SLang_get_int_type (32); break; case PNG_COLOR_TYPE_RGB: sizeof_type = 4; fixup_array_fun = fixup_array_rgb; data_type = SLang_get_int_type (32); break; case PNG_COLOR_TYPE_GRAY_ALPHA: sizeof_type = 2; fixup_array_fun = fixup_array_ga; data_type = SLang_get_int_type (16); break; case PNG_COLOR_TYPE_GRAY: sizeof_type = 1; fixup_array_fun = NULL; data_type = SLANG_UCHAR_TYPE; break; default: SLang_verror (SL_Read_Error, "Unsupported PNG color-type"); free_png_type (p); return NULL; } *color_typep = color_type; /* Use the high-level interface */ rowbytes = png_get_rowbytes (png, info); if (rowbytes > width * sizeof_type) { SLang_verror (SL_INTERNAL_ERROR, "Unexpected value returned from png_get_rowbytes"); free_png_type (p); return NULL; } if (NULL == (data = (png_byte *) SLmalloc (height * width * sizeof_type))) { free_png_type (p); return NULL; } if (NULL == (image_pointers = allocate_image_pointers (height, data, width * sizeof_type, flip))) { SLfree ((char *) data); free_png_type (p); return NULL; } png_read_image(png, image_pointers); dims[0] = height; dims[1] = width; if (NULL == (at = SLang_create_array (data_type, 0, (VOID_STAR) data, dims, 2))) { SLfree ((char *) data); free_image_pointers (image_pointers); free_png_type (p); return NULL; } free_png_type (p); free_image_pointers (image_pointers); if (fixup_array_fun != NULL) (*fixup_array_fun) (at); return at; }
PyObject* _png_module::_read_png(const Py::Object& py_fileobj, const bool float_result, int result_bit_depth) { png_byte header[8]; // 8 is the maximum size that can be checked FILE* fp = NULL; bool close_file = false; bool close_dup_file = false; PyObject *py_file = NULL; if (py_fileobj.isString()) { if ((py_file = npy_PyFile_OpenFile(py_fileobj.ptr(), (char *)"rb")) == NULL) { throw Py::Exception(); } close_file = true; } else { py_file = py_fileobj.ptr(); } if ((fp = npy_PyFile_Dup(py_file, "rb"))) { close_dup_file = true; } else { PyErr_Clear(); PyObject* read_method = PyObject_GetAttrString(py_file, "read"); if (!(read_method && PyCallable_Check(read_method))) { Py_XDECREF(read_method); throw Py::TypeError( "Object does not appear to be a 8-bit string path or a Python " "file-like object"); } Py_XDECREF(read_method); } if (fp) { if (fread(header, 1, 8, fp) != 8) { throw Py::RuntimeError( "_image_module::readpng: error reading PNG header"); } } else { _read_png_data(py_file, header, 8); } if (png_sig_cmp(header, 0, 8)) { throw Py::RuntimeError( "_image_module::readpng: file not recognized as a PNG file"); } /* initialize stuff */ png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { throw Py::RuntimeError( "_image_module::readpng: png_create_read_struct failed"); } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { throw Py::RuntimeError( "_image_module::readpng: png_create_info_struct failed"); } if (setjmp(png_jmpbuf(png_ptr))) { throw Py::RuntimeError( "_image_module::readpng: error during init_io"); } if (fp) { png_init_io(png_ptr, fp); } else { png_set_read_fn(png_ptr, (void*)py_file, &read_png_data); } png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); png_uint_32 width = png_get_image_width(png_ptr, info_ptr); png_uint_32 height = png_get_image_height(png_ptr, info_ptr); int bit_depth = png_get_bit_depth(png_ptr, info_ptr); // Unpack 1, 2, and 4-bit images if (bit_depth < 8) png_set_packing(png_ptr); // If sig bits are set, shift data png_color_8p sig_bit; if ((png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_PALETTE) && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) { png_set_shift(png_ptr, sig_bit); } // Convert big endian to little if (bit_depth == 16) { png_set_swap(png_ptr); } // Convert palletes to full RGB if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); bit_depth = 8; } // If there's an alpha channel convert gray to RGB if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); } png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); /* read file */ if (setjmp(png_jmpbuf(png_ptr))) { throw Py::RuntimeError( "_image_module::readpng: error during read_image"); } png_bytep *row_pointers = new png_bytep[height]; png_uint_32 row; for (row = 0; row < height; row++) { row_pointers[row] = new png_byte[png_get_rowbytes(png_ptr,info_ptr)]; } png_read_image(png_ptr, row_pointers); npy_intp dimensions[3]; dimensions[0] = height; //numrows dimensions[1] = width; //numcols if (png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_ALPHA) { dimensions[2] = 4; //RGBA images } else if (png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_COLOR) { dimensions[2] = 3; //RGB images } else { dimensions[2] = 1; //Greyscale images } //For gray, return an x by y array, not an x by y by 1 int num_dims = (png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_COLOR) ? 3 : 2; PyArrayObject *A = NULL; if (float_result) { double max_value = (1 << bit_depth) - 1; A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, NPY_FLOAT); if (A == NULL) { throw Py::MemoryError("Could not allocate image array"); } for (png_uint_32 y = 0; y < height; y++) { png_byte* row = row_pointers[y]; for (png_uint_32 x = 0; x < width; x++) { size_t offset = y * A->strides[0] + x * A->strides[1]; if (bit_depth == 16) { png_uint_16* ptr = &reinterpret_cast<png_uint_16*>(row)[x * dimensions[2]]; for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++) { *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value; } } else { png_byte* ptr = &(row[x * dimensions[2]]); for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++) { *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value; } } } } } else { if (result_bit_depth < 0) { result_bit_depth = bit_depth; } if (result_bit_depth == 8) { A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, NPY_UBYTE); } else if (result_bit_depth == 16) { A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, NPY_UINT16); } else { throw Py::RuntimeError( "_image_module::readpng: image has unknown bit depth"); } if (A == NULL) { throw Py::MemoryError("Could not allocate image array"); } for (png_uint_32 y = 0; y < height; y++) { png_byte* row = row_pointers[y]; for (png_uint_32 x = 0; x < width; x++) { size_t offset = y * A->strides[0] + x * A->strides[1]; if (bit_depth == 16) { png_uint_16* ptr = &reinterpret_cast<png_uint_16*>(row)[x * dimensions[2]]; if (result_bit_depth == 16) { for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++) { *(png_uint_16*)(A->data + offset + p*A->strides[2]) = ptr[p]; } } else { for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++) { *(png_byte*)(A->data + offset + p*A->strides[2]) = ptr[p] >> 8; } } } else { png_byte* ptr = &(row[x * dimensions[2]]); if (result_bit_depth == 16) { for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++) { *(png_uint_16*)(A->data + offset + p*A->strides[2]) = ptr[p]; } } else { for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++) { *(png_byte*)(A->data + offset + p*A->strides[2]) = ptr[p]; } } } } }
PNGImage LoadImagePNG(const char *path) { PNGImage loadedImage; loadedImage.loadedSuccessfully = GL_FALSE; FILE *PNG_file = fopen(path, "rb"); if (PNG_file == NULL) { printf("Can't open PNG file %s\n", path); return loadedImage; } GLubyte PNG_header[PNG_HEADER_SIZE]; fread(PNG_header, 1, PNG_HEADER_SIZE, PNG_file); if (png_sig_cmp(PNG_header, 0, PNG_HEADER_SIZE) != 0) { printf("%s is not a PNG file\n", path); return loadedImage; } png_structp PNG_reader = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (PNG_reader == NULL) { printf("Can't start reading PNG file %s\n", path); fclose(PNG_file); return loadedImage; } png_infop PNG_info = png_create_info_struct(PNG_reader); if (PNG_info == NULL) { printf("Can't get info for PNG file %s\n", path); png_destroy_read_struct(&PNG_reader, NULL, NULL); fclose(PNG_file); return loadedImage; } png_infop PNG_end_info = png_create_info_struct(PNG_reader); if (PNG_end_info == NULL) { printf("Can't get end info for PNG file %s\n", path); png_destroy_read_struct(&PNG_reader, &PNG_info, NULL); fclose(PNG_file); return loadedImage; } if (setjmp(png_jmpbuf(PNG_reader))) { printf("Can't load PNG file %s\n", path); png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info); fclose(PNG_file); return loadedImage; } png_init_io(PNG_reader, PNG_file); png_set_sig_bytes(PNG_reader, PNG_HEADER_SIZE); png_read_info(PNG_reader, PNG_info); // we have to do a custom transformation to premultiply the alpha of the image png_set_read_user_transform_fn(PNG_reader, png_read_premultiply_alpha); png_uint_32 width, height; int bit_depth, color_type; png_get_IHDR(PNG_reader, PNG_info, &width, &height, &bit_depth, &color_type,NULL, NULL, NULL); if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(PNG_reader); } if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { png_set_expand_gray_1_2_4_to_8(PNG_reader); } if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(PNG_reader); } if (png_get_valid(PNG_reader, PNG_info, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(PNG_reader); } else { png_set_filler(PNG_reader, 0xff, PNG_FILLER_AFTER); } if (bit_depth == 16) { png_set_strip_16(PNG_reader); } png_read_update_info(PNG_reader, PNG_info); png_uint_32 widthPow2, heightPow2; widthPow2 = pow2(width); heightPow2 = pow2(height); png_byte* PNG_image_buffer = (png_byte*)malloc(4 * widthPow2 * heightPow2); memset(PNG_image_buffer,0,4*widthPow2*heightPow2); // clear image buffer png_byte** PNG_rows = (png_byte**)malloc(height * sizeof(png_byte*)); png_uint_32 rowBytes = widthPow2*4; // load the image from the bottom up /* image texture in mem looks like: -------- | | |xxxx | |xxxx | -------- where 'x's represent actual image data and the lines are the image buffer. so the image is aligned at the (0,0) texel coordinate of the image buffer. */ unsigned int row; for (row = 0; row < height; ++row) { PNG_rows[height-1-row] = PNG_image_buffer + (row * rowBytes); } png_read_image(PNG_reader, PNG_rows); free(PNG_rows); png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info); fclose(PNG_file); GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, widthPow2, heightPow2, 0, GL_RGBA, GL_UNSIGNED_BYTE, PNG_image_buffer); free(PNG_image_buffer); loadedImage.width = width; loadedImage.height = height; loadedImage.widthPow2 = widthPow2; loadedImage.heightPow2 = heightPow2; loadedImage.textureId = textureID; loadedImage.loadedSuccessfully = GL_TRUE; return loadedImage; }
unsigned char* load_png_data(char *filename, int *w, int *h) { FILE *fp = fopen(filename, "rb"); if(!fp) { return NULL; } png_byte header[8]; fread(header, 1, 8, fp); if(png_sig_cmp(header, 0, 8)) { return NULL; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) { return NULL; } png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(fp); return NULL; } png_infop end_ptr = png_create_info_struct(png_ptr); if(!end_ptr) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return NULL; } if(setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_ptr); fclose(fp); return NULL; } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); int bit_depth = png_get_bit_depth(png_ptr, info_ptr); switch(png_get_color_type(png_ptr, info_ptr)) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png_ptr); png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); break; case PNG_COLOR_TYPE_GRAY: png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); case PNG_COLOR_TYPE_GRAY_ALPHA: if(bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); if(bit_depth==16) png_set_strip_16(png_ptr); png_set_gray_to_rgb(png_ptr); break; case PNG_COLOR_TYPE_RGB: if(bit_depth < 8 ) png_set_packing(png_ptr); if(bit_depth == 16) png_set_strip_16(png_ptr); png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); break; default: break; } png_read_update_info(png_ptr, info_ptr); *w = png_get_image_width(png_ptr, info_ptr); *h = png_get_image_height(png_ptr, info_ptr); int rowbytes = (int)png_get_rowbytes(png_ptr, info_ptr); png_bytep data = malloc((*h)*rowbytes*sizeof(*data)); png_bytep row_pointers[*h]; int i; for(i=0; i<(*h); ++i) { row_pointers[i] = &data[i*rowbytes]; } png_read_image(png_ptr, row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, &end_ptr); fclose(fp); return data; }
static png_bytepp eiio_png_read_rgb(const void *blob, size_t blob_size, int *width, int *height, int *channels) { png_structp png = NULL; png_infop info = NULL; blob_input_t blob_input; int bit_depth, color_type; png_bytepp rows = NULL; png_uint_32 uwidth, uheight; int i; png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png == NULL){ return NULL; } info = png_create_info_struct(png); if(info == NULL){ png_destroy_read_struct(&png, NULL, NULL); return NULL; } if (setjmp(png_jmpbuf(png))) { png_destroy_read_struct(&png, &info, NULL); eiio_png_rows_free(&rows); return NULL; } blob_input.blob = blob; blob_input.offset = 0; blob_input.blob_size = blob_size; png_set_read_fn(png, &blob_input, read_blob); *width = *height = 0; png_read_info(png, info); png_get_IHDR(png, info, &uwidth, &uheight, &bit_depth, &color_type, NULL, NULL, NULL); if (uwidth > 0x7fffffff || uheight > 0x7fffffff) { png_destroy_read_struct(&png, &info, NULL); eiio_png_rows_free(&rows); return NULL; } *width = (int)uwidth; *height = (int)uheight; if (bit_depth == 16) { png_set_strip_16(png); } if ((color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) && bit_depth < 8) { png_set_expand_gray_1_2_4_to_8(png); //png_set_gray_1_2_4_to_8(png); } if (bit_depth < 8) { png_set_packing(png); } if (color_type & PNG_COLOR_MASK_ALPHA) { *channels = 4; } else { *channels = 3; } if (color_type & PNG_COLOR_MASK_PALETTE) { png_set_palette_to_rgb(png); } if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png); } png_read_update_info(png, info); rows = (png_bytepp)eiio_malloc(sizeof(png_bytep) * (*height + 1)); if (rows == NULL) { png_destroy_read_struct(&png, &info, NULL); return NULL; } for (i = 0; i < *height; ++i) { rows[i] = (png_bytep)eiio_malloc(sizeof(png_byte) * *width * *channels); if (rows[i] == NULL) { png_destroy_read_struct(&png, &info, NULL); eiio_png_rows_free(&rows); return NULL; } } rows[*height] = NULL; /* null terminater */ png_read_image(png, rows); png_read_end(png, info); png_destroy_read_struct(&png, &info, NULL); return rows; }
int read_png(const std::string & file_name, image_t & image) { png_structp png; png_infop info; int color_type, bit_depth, interlaced; int has_alpha; int num_passes; int p; int ok = 0; png_uint_32 width, height, y; int stride; uint8_t* rgb = NULL; FILE * fp; #ifdef LINUX fp = fopen(file_name.c_str(), "rb"); #endif #ifdef WINDOWS fopen_s(&fp, file_name.c_str(), "rb"); #endif if (fp == NULL) throw webp::exception::FileOperationException(); png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (png == NULL) { goto End; } png_set_error_fn(png, 0, error_function, NULL); if (setjmp(png_jmpbuf(png))) { Error: png_destroy_read_struct(&png, NULL, NULL); free(rgb); goto End; } info = png_create_info_struct(png); if (info == NULL) goto Error; png_init_io(png, fp); png_read_info(png, info); if (!png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, &interlaced, NULL, NULL)) goto Error; png_set_strip_16(png); png_set_packing(png); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { if (bit_depth < 8) { png_set_expand_gray_1_2_4_to_8(png); } png_set_gray_to_rgb(png); } if (png_get_valid(png, info, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png); has_alpha = 1; } else { has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA); } num_passes = png_set_interlace_handling(png); png_read_update_info(png, info); stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb); rgb = (uint8_t*)malloc(stride * height); if (rgb == NULL) goto Error; for (p = 0; p < num_passes; ++p) { for (y = 0; y < height; ++y) { png_bytep row = rgb + y * stride; png_read_rows(png, &row, NULL, 1); } } png_read_end(png, info); png_destroy_read_struct(&png, &info, NULL); image.width = width; image.height = height; image.image.realloc(height * width); for(size_t y = 0; y < height; y++) for(size_t x = 0; x < width; x++){ size_t i = y * width + x; if (has_alpha) { *webp::utils::ALPHA(image.image[i]) = rgb[stride * y + x * 4]; *webp::utils::RED(image.image[i]) = rgb[stride * y + x * 4 + 1]; *webp::utils::GREEN(image.image[i]) = rgb[stride * y + x * 4 + 2]; *webp::utils::BLUE(image.image[i]) = rgb[stride * y + x * 4 + 3]; } else{ *webp::utils::ALPHA(image.image[i]) = 0xFF; *webp::utils::RED(image.image[i]) = rgb[stride * y + x * 3]; *webp::utils::GREEN(image.image[i]) = rgb[stride * y + x * 3 + 1]; *webp::utils::BLUE(image.image[i]) = rgb[stride * y + x * 3 + 2]; } } free(rgb); End: fclose(fp); return ok; }
struct ImBuf *imb_loadpng(unsigned char *mem, int size, int flags) { struct ImBuf *ibuf = 0; png_structp png_ptr; png_infop info_ptr; unsigned char *pixels = 0; png_bytepp row_pointers = 0; png_uint_32 width, height; int bit_depth, color_type; PNGReadStruct ps; unsigned char *from, *to; int i, bytesperpixel; if (imb_is_a_png(mem) == 0) return(0); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { printf("Cannot png_create_read_struct\n"); return 0; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); printf("Cannot png_create_info_struct\n"); return 0; } ps.size = size; ps.data = mem; ps.seek = 0; png_set_read_fn(png_ptr, (void *) &ps, ReadData); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); if (pixels) MEM_freeN(pixels); if (row_pointers) MEM_freeN(row_pointers); if (ibuf) IMB_freeImBuf(ibuf); return 0; } // 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); if (bit_depth == 16) { png_set_strip_16(png_ptr); bit_depth = 8; } bytesperpixel = png_get_channels(png_ptr, info_ptr); switch(color_type) { case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: break; case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { bytesperpixel = 4; } else { bytesperpixel = 3; } break; case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY_ALPHA: if (bit_depth < 8) { png_set_expand(png_ptr); bit_depth = 8; } break; default: printf("PNG format not supported\n"); longjmp(png_jmpbuf(png_ptr), 1); } ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0, 0); if (ibuf) { ibuf->ftype = PNG; } else { printf("Couldn't allocate memory for PNG image\n"); } if (ibuf && ((flags & IB_test) == 0)) { imb_addrectImBuf(ibuf); pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels"); if (pixels == NULL) { printf("Cannot allocate pixels array\n"); longjmp(png_jmpbuf(png_ptr), 1); } // allocate memory for an array of row-pointers row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers"); if (row_pointers == NULL) { printf("Cannot allocate row-pointers array\n"); longjmp(png_jmpbuf(png_ptr), 1); } // set the individual row-pointers to point at the correct offsets for (i = 0; i < ibuf->y; i++) { row_pointers[ibuf->y-1-i] = (png_bytep) ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char)); } png_read_image(png_ptr, row_pointers); // copy image data to = (unsigned char *) ibuf->rect; from = pixels; switch (bytesperpixel) { case 4: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; to[3] = from[3]; to += 4; from += 4; } break; case 3: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; to[3] = 0xff; to += 4; from += 3; } break; case 2: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = to[1] = to[2] = from[0]; to[3] = from[1]; to += 4; from += 2; } break; case 1: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = to[1] = to[2] = from[0]; to[3] = 0xff; to += 4; from++; } break; } if (flags & IB_imginfo) { png_text* text_chunks; int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL); for(i = 0; i < count; i++) { IMB_imginfo_add_field(ibuf, text_chunks[i].key, text_chunks[i].text); ibuf->flags |= IB_imginfo; } } png_read_end(png_ptr, info_ptr); } // clean up MEM_freeN(pixels); MEM_freeN(row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return(ibuf); }
ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { struct ImBuf *ibuf = NULL; png_structp png_ptr; png_infop info_ptr; unsigned char *pixels = NULL; unsigned short *pixels16 = NULL; png_bytepp row_pointers = NULL; png_uint_32 width, height; int bit_depth, color_type; PNGReadStruct ps; unsigned char *from, *to; unsigned short *from16; float *to_float; int i, bytesperpixel; if (imb_is_a_png(mem) == 0) return(NULL); /* both 8 and 16 bit PNGs are default to standard byte colorspace */ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { printf("Cannot png_create_read_struct\n"); return NULL; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); printf("Cannot png_create_info_struct\n"); return NULL; } ps.size = size; /* XXX, 4gig limit! */ ps.data = mem; ps.seek = 0; png_set_read_fn(png_ptr, (void *) &ps, ReadData); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); if (pixels) MEM_freeN(pixels); if (pixels16) MEM_freeN(pixels16); if (row_pointers) MEM_freeN(row_pointers); if (ibuf) IMB_freeImBuf(ibuf); return NULL; } // 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); bytesperpixel = png_get_channels(png_ptr, info_ptr); switch (color_type) { case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: break; case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { bytesperpixel = 4; } else { bytesperpixel = 3; } break; case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY_ALPHA: if (bit_depth < 8) { png_set_expand(png_ptr); bit_depth = 8; } break; default: printf("PNG format not supported\n"); longjmp(png_jmpbuf(png_ptr), 1); break; } ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0); if (ibuf) { ibuf->ftype = PNG; if (bit_depth == 16) ibuf->ftype |= PNG_16BIT; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) { int unit_type; png_uint_32 xres, yres; if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type)) if (unit_type == PNG_RESOLUTION_METER) { ibuf->ppm[0] = xres; ibuf->ppm[1] = yres; } } } else { printf("Couldn't allocate memory for PNG image\n"); } if (ibuf && ((flags & IB_test) == 0)) { if (bit_depth == 16) { imb_addrectfloatImBuf(ibuf); png_set_swap(png_ptr); pixels16 = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(png_uint_16), "pixels"); if (pixels16 == NULL) { printf("Cannot allocate pixels array\n"); longjmp(png_jmpbuf(png_ptr), 1); } /* allocate memory for an array of row-pointers */ row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_uint_16p), "row_pointers"); if (row_pointers == NULL) { printf("Cannot allocate row-pointers array\n"); longjmp(png_jmpbuf(png_ptr), 1); } /* set the individual row-pointers to point at the correct offsets */ for (i = 0; i < ibuf->y; i++) { row_pointers[ibuf->y - 1 - i] = (png_bytep) ((png_uint_16 *)pixels16 + (i * ibuf->x) * bytesperpixel); } png_read_image(png_ptr, row_pointers); /* copy image data */ to_float = ibuf->rect_float; from16 = pixels16; switch (bytesperpixel) { case 4: for (i = ibuf->x * ibuf->y; i > 0; i--) { to_float[0] = from16[0] / 65535.0; to_float[1] = from16[1] / 65535.0; to_float[2] = from16[2] / 65535.0; to_float[3] = from16[3] / 65535.0; to_float += 4; from16 += 4; } break; case 3: for (i = ibuf->x * ibuf->y; i > 0; i--) { to_float[0] = from16[0] / 65535.0; to_float[1] = from16[1] / 65535.0; to_float[2] = from16[2] / 65535.0; to_float[3] = 1.0; to_float += 4; from16 += 3; } break; case 2: for (i = ibuf->x * ibuf->y; i > 0; i--) { to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0; to_float[3] = from16[1] / 65535.0; to_float += 4; from16 += 2; } break; case 1: for (i = ibuf->x * ibuf->y; i > 0; i--) { to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0; to_float[3] = 1.0; to_float += 4; from16++; } break; } } else { imb_addrectImBuf(ibuf); pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels"); if (pixels == NULL) { printf("Cannot allocate pixels array\n"); longjmp(png_jmpbuf(png_ptr), 1); } /* allocate memory for an array of row-pointers */ row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers"); if (row_pointers == NULL) { printf("Cannot allocate row-pointers array\n"); longjmp(png_jmpbuf(png_ptr), 1); } /* set the individual row-pointers to point at the correct offsets */ for (i = 0; i < ibuf->y; i++) { row_pointers[ibuf->y - 1 - i] = (png_bytep) ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char)); } png_read_image(png_ptr, row_pointers); /* copy image data */ to = (unsigned char *) ibuf->rect; from = pixels; switch (bytesperpixel) { case 4: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; to[3] = from[3]; to += 4; from += 4; } break; case 3: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; to[3] = 0xff; to += 4; from += 3; } break; case 2: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = to[1] = to[2] = from[0]; to[3] = from[1]; to += 4; from += 2; } break; case 1: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = to[1] = to[2] = from[0]; to[3] = 0xff; to += 4; from++; } break; } } if (flags & IB_metadata) { png_text *text_chunks; int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL); for (i = 0; i < count; i++) { IMB_metadata_add_field(ibuf, text_chunks[i].key, text_chunks[i].text); ibuf->flags |= IB_metadata; } } png_read_end(png_ptr, info_ptr); } /* clean up */ if (pixels) MEM_freeN(pixels); if (pixels16) MEM_freeN(pixels16); if (row_pointers) MEM_freeN(row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return(ibuf); }