void PNGAPI png_read_png(png_structp png_ptr, png_infop info_ptr, int transforms, voidp params) { int row; #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) /* invert the alpha channel from opacity to transparency */ if (transforms & PNG_TRANSFORM_INVERT_ALPHA) png_set_invert_alpha(png_ptr); #endif /* The call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). */ png_read_info(png_ptr, info_ptr); /* -------------- image transformations start here ------------------- */ #if defined(PNG_READ_16_TO_8_SUPPORTED) /* tell libpng to strip 16 bit/color files down to 8 bits/color */ if (transforms & PNG_TRANSFORM_STRIP_16) png_set_strip_16(png_ptr); #endif #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) /* Strip alpha bytes from the input data without combining with the * background (not recommended). */ if (transforms & PNG_TRANSFORM_STRIP_ALPHA) png_set_strip_alpha(png_ptr); #endif #if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ if (transforms & PNG_TRANSFORM_PACKING) png_set_packing(png_ptr); #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED) /* Change the order of packed pixels to least significant bit first * (not useful if you are using png_set_packing). */ if (transforms & PNG_TRANSFORM_PACKSWAP) png_set_packswap(png_ptr); #endif #if defined(PNG_READ_EXPAND_SUPPORTED) /* Expand paletted colors into true RGB triplets * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel * Expand paletted or RGB images with transparency to full alpha * channels so the data will be available as RGBA quartets. */ if (transforms & PNG_TRANSFORM_EXPAND) if ((png_ptr->bit_depth < 8) || (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) png_set_expand(png_ptr); #endif /* We don't handle background color or gamma transformation or dithering. */ #if defined(PNG_READ_INVERT_SUPPORTED) /* invert monochrome files to have 0 as white and 1 as black */ if (transforms & PNG_TRANSFORM_INVERT_MONO) png_set_invert_mono(png_ptr); #endif #if defined(PNG_READ_SHIFT_SUPPORTED) /* If you want to shift the pixel values from the range [0,255] or * [0,65535] to the original [0,7] or [0,31], or whatever range the * colors were originally in: */ if ((transforms & PNG_TRANSFORM_SHIFT) && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) { png_color_8p sig_bit; png_get_sBIT(png_ptr, info_ptr, &sig_bit); png_set_shift(png_ptr, sig_bit); } #endif #if defined(PNG_READ_BGR_SUPPORTED) /* flip the RGB pixels to BGR (or RGBA to BGRA) */ if (transforms & PNG_TRANSFORM_BGR) png_set_bgr(png_ptr); #endif #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ if (transforms & PNG_TRANSFORM_SWAP_ALPHA) png_set_swap_alpha(png_ptr); #endif #if defined(PNG_READ_SWAP_SUPPORTED) /* swap bytes of 16 bit files to least significant byte first */ if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) png_set_swap(png_ptr); #endif /* We don't handle adding filler bytes */ /* Optional call to gamma correct and add the background to the palette * and update info structure. REQUIRED if you are expecting libpng to * update the palette for you (i.e., you selected such a transform above). */ png_read_update_info(png_ptr, info_ptr); /* -------------- image transformations end here ------------------- */ #ifdef PNG_FREE_ME_SUPPORTED png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); #endif if(info_ptr->row_pointers == NULL) { info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, info_ptr->height * sizeof(png_bytep)); #ifdef PNG_FREE_ME_SUPPORTED info_ptr->free_me |= PNG_FREE_ROWS; #endif for (row = 0; row < (int)info_ptr->height; row++) { info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); } } png_read_image(png_ptr, info_ptr->row_pointers); info_ptr->valid |= PNG_INFO_IDAT; /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); if(transforms == 0 || params == NULL) /* quiet compiler warnings */ return; }
/* Read a PNG file. You may want to return an error code if the read * fails (depending upon the failure). There are two "prototypes" given * here - one where we are given the filename, and we need to open the * file, and the other where we are given an open file (possibly with * some or all of the magic bytes read - see comments above). */ #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_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)
int read_header(const char *filename, dt_imageio_png_t *png) { png->f = fopen(filename, "rb"); if(!png->f) return 1; #define NUM_BYTES_CHECK (8) png_byte dat[NUM_BYTES_CHECK]; size_t cnt = fread(dat, 1, NUM_BYTES_CHECK, png->f); if(cnt != NUM_BYTES_CHECK || png_sig_cmp(dat, (png_size_t)0, NUM_BYTES_CHECK)) { fclose(png->f); return 1; } png->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png->png_ptr) { fclose(png->f); return 1; } png->info_ptr = png_create_info_struct(png->png_ptr); if(!png->info_ptr) { fclose(png->f); png_destroy_read_struct(&png->png_ptr, NULL, NULL); return 1; } if(setjmp(png_jmpbuf(png->png_ptr))) { fclose(png->f); png_destroy_read_struct(&png->png_ptr, &png->info_ptr, NULL); return 1; } png_init_io(png->png_ptr, png->f); // we checked some bytes png_set_sig_bytes(png->png_ptr, NUM_BYTES_CHECK); // image info png_read_info(png->png_ptr, png->info_ptr); png->bit_depth = png_get_bit_depth(png->png_ptr, png->info_ptr); png->color_type = png_get_color_type(png->png_ptr, png->info_ptr); // image input transformations // palette => rgb if(png->color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png->png_ptr); // 1, 2, 4 bit => 8 bit if(png->color_type == PNG_COLOR_TYPE_GRAY && png->bit_depth < 8) { png_set_expand_gray_1_2_4_to_8(png->png_ptr); png->bit_depth = 8; } // strip alpha channel if(png->color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png->png_ptr); // grayscale => rgb if(png->color_type == PNG_COLOR_TYPE_GRAY || png->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png->png_ptr); // reflect changes png_read_update_info(png->png_ptr, png->info_ptr); // png->bytespp = 3*bit_depth/8; png->width = png_get_image_width(png->png_ptr, png->info_ptr); png->height = png_get_image_height(png->png_ptr, png->info_ptr); #undef NUM_BYTES_CHECK return 0; }
bool PngImage::Load(FILE *pStream) { if (pStream && !IsValid()) { bool success = false; ubyte aPngHeader[PNG_IMAGE_HEADER_SIZE]; png_structp pPngStruct = NULL; png_infop pPngInfo = NULL; //float gamma = 0.0; uint rowSize; ubyte *pImageData = NULL; png_bytep *pImageRows = NULL; uint offset = 0; png_uint_32 width = 0; png_uint_32 height = 0; int bpp = 0; int colorType = 0; //check png signature if (sizeof(aPngHeader) != fread(aPngHeader, 1, sizeof(aPngHeader), pStream)) { //read failed goto Exit_Load; } if (!png_check_sig(aPngHeader, sizeof(aPngHeader))) { //file is not a png image goto Exit_Load; } //create png read struct pPngStruct = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!pPngStruct) { //png struct allocation failed goto Exit_Load; } //create png info struct pPngInfo = png_create_info_struct(pPngStruct); if (!pPngInfo) { //png info allocation failed goto Exit_Load; } //required for png library use if (setjmp(pPngStruct->jmpbuf)) { //handle png read error goto Exit_Load; } //initialize png io png_init_io(pPngStruct, pStream); //set offset into the file since png header has been already read png_set_sig_bytes(pPngStruct, sizeof(aPngHeader)); //read png image info header png_read_info(pPngStruct, pPngInfo); png_get_IHDR(pPngStruct, pPngInfo, &width, &height, &bpp, &colorType, NULL, NULL, NULL); DbgMessage("Image %ux%ux%ubpp", width, height, bpp); //filter out unsupported images if (bpp < PNG_IMAGE_MIN_BPP || bpp > PNG_IMAGE_MAX_BPP) { goto Exit_Load; } //convert palette images to rgb if (PNG_COLOR_TYPE_PALETTE == colorType) { png_set_expand(pPngStruct); } //convert low-bpp images to 8 bpp if (bpp < IMAGE_BPP_8) { png_set_expand(pPngStruct); } //strip alpha channel if ((colorType & PNG_COLOR_MASK_ALPHA) || png_get_valid(pPngStruct, pPngInfo, PNG_INFO_tRNS)) { png_set_strip_alpha(pPngStruct); } //strip 16 bpp images down to 8 bpp if (IMAGE_BPP_16 == bpp) { png_set_strip_16(pPngStruct); } //convert grayscale images to rgb if (PNG_COLOR_TYPE_GRAY == colorType || PNG_COLOR_TYPE_GRAY_ALPHA == colorType) { //png_set_expand(pPngStruct); png_set_gray_to_rgb(pPngStruct); } //perform gamma correction if gamma is preset /*if (png_get_gAMA(pPngStruct, pPngInfo, &gamma)) { //png_set_gamma(pPngStruct, ???, gamma); }*/ //update image info png_read_update_info(pPngStruct, pPngInfo); //allocate space for image row offsets rowSize = png_get_rowbytes(pPngStruct, pPngInfo); pImageData = new ubyte [height * rowSize]; if (!pImageData) { //allocation failed goto Exit_Load; } //allocate space for image row pointers pImageRows = new png_bytep [height]; if (!pImageRows) { //allocation failed goto Exit_Load; } //set individual row pointers to correct offsets for (uint index = 0; index < height; ++index) { pImageRows[index] = pImageData + offset; offset += rowSize; } //read image data png_read_image(pPngStruct, pImageRows); png_read_end(pPngStruct, NULL); //set image properties m_pImageData = pImageData; m_width = static_cast<uint>(width); m_height = static_cast<uint>(height); m_bpp = static_cast<uint>(bpp); //image successfully loaded success = true; Exit_Load: delete pImageRows; if (pPngStruct && pPngInfo) { //free png struct and png info png_destroy_read_struct(&pPngStruct, &pPngInfo, NULL); } else if (pPngStruct) { //free png struct only png_destroy_read_struct(&pPngStruct, NULL, NULL); } if (!success) { delete pImageData; } return success; } return false; }
static Image * __doOpenImage(char * filename, CSOUND *csound) { #ifdef USE_LIBPNG #define HS (8) FILE *fp; void *fd; unsigned char header[HS]; png_structp png_ptr; png_infop info_ptr; /* png_infop end_ptr; */ int is_png; png_uint_32 width, height, rowbytes; int bit_depth; int color_type; unsigned char *image_data; png_bytepp row_pointers; unsigned int i; Image *img; fd = csound->FileOpen2(csound, &fp, CSFILE_STD, filename, "rb", "SFDIR;SSDIR", CSFTYPE_IMAGE_PNG, 0); if (UNLIKELY(fd == NULL)) { csound->InitError(csound, Str("imageload: cannot open image %s.\n"), filename); return NULL; } if (UNLIKELY(HS!=fread(header, 1, HS, fp))) csound->InitError(csound, Str("imageload: file %s is not in PNG format.\n"), filename); is_png = !png_sig_cmp(header, 0, HS); if (UNLIKELY(!is_png)) { csound->InitError(csound, Str("imageload: file %s is not in PNG format.\n"), filename); csound->FileClose(csound, fd); return NULL; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (UNLIKELY(!png_ptr)) { csound->InitError(csound, Str("imageload: out of memory.\n")); csound->FileClose(csound, fd); return NULL; } info_ptr = png_create_info_struct(png_ptr); if (UNLIKELY(!info_ptr)) { png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); csound->InitError(csound, Str("imageload: out of memory.\n")); csound->FileClose(csound, fd); return NULL; } /* end_ptr = png_create_info_struct(png_ptr); */ /* if (UNLIKELY(!end_ptr)) { */ /* png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); */ /* csound->InitError(csound, Str("imageload: out of memory.\n")); */ /* csound->FileClose(csound, fd); */ /* return NULL; */ /* } */ png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, HS); png_read_info(png_ptr, info_ptr); { png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); } if (color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); if (bit_depth < 8) png_set_packing(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); png_read_update_info(png_ptr, info_ptr); rowbytes = png_get_rowbytes(png_ptr, info_ptr); if (UNLIKELY((image_data = (unsigned char *) malloc(rowbytes * height))==NULL)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); csound->InitError(csound, Str("imageload: out of memory.\n")); return NULL; } row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep)); if (UNLIKELY(row_pointers == NULL)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); free(image_data); image_data = NULL; csound->InitError(csound, Str("imageload: out of memory.\n")); return NULL; } for (i = 0; i < height; i++) row_pointers[i] = image_data + i*rowbytes; png_read_image(png_ptr, row_pointers); free(row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); csound->FileClose(csound, fd); img = malloc(sizeof(Image)); if (UNLIKELY(!img)) { free(image_data); csound->InitError(csound, Str("imageload: out of memory.\n")); return NULL; } img->w = width; img->h = height; img->imageData = image_data; return img; #else Display *disp; ImlibData *id; ImlibImage *im; Image *img; size_t datasize; disp=XOpenDisplay(NULL); id=Imlib_init(disp); im=Imlib_load_image(id, filename); img = malloc(sizeof(Image)); img->w = im->rgb_width; img->h = im->rgb_height; datasize = img->w*img->h*3 * sizeof(unsigned char); img->imageData = malloc(datasize); memcpy(img->imageData, im->rgb_data, datasize); return img; #endif /* SDL */ /* Image *img; size_t datasize; SDL_Surface *srfc; int x,y; int bpp; int indcount = 0; Uint32 *pixel; Uint8 r, g, b; srfc = IMG_Load(filename); if (srfc) { SDL_LockSurface(srfc); img = malloc(sizeof(Image)); img->w = srfc->w; img->h = srfc->h; bpp = srfc->format->BitsPerPixel; datasize = img->w*img->h*3 * sizeof(unsigned char); img->imageData = malloc(datasize); for(y = 0; y < img->h; y++) { for(x = 0; x < img->w; x++) { if (bpp<=8) //need to test on other platforms pixel = srfc->pixels + y * srfc->pitch + x * bpp; else pixel = srfc->pixels + y * srfc->pitch + x * bpp / 8; SDL_GetRGB(*pixel,srfc->format, &r, &g, &b); img->imageData[indcount]= r; img->imageData[indcount+1]= g; img->imageData[indcount+2]= b; indcount += 3; } } SDL_UnlockSurface(srfc); SDL_FreeSurface ( srfc ); return img; } return NULL; */ }
void read_png(unsigned char **block, png_uint_32 *width, png_uint_32 *height, FILE *file) { png_structp png_ptr; png_infop info_ptr; png_bytep *row_pointers; unsigned row, x, y; int rowbytes; char *dst; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); if (png_ptr == NULL) { printf("\nERROR: read_png: Could not create read struct.\n"); exit(1); } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { printf("\nERROR: read_png: Could not create info struct.\n"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); exit(1); } if (setjmp(png_ptr->jmpbuf)) { printf("\nERROR: read_png: fatal error.\n"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_info **)0); /* free pointers before returning, if necessary */ free(png_ptr); free(info_ptr); exit(1); } /* Set up the input control if you are using standard C streams */ png_init_io(png_ptr, file); /* 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, NULL, NULL); // printf("read_png: width=%d, height=%d, bit_depth=%d\n", width, height, bit_depth); // printf("read_png: color_type=%d, interlace_type=%d\n", color_type, interlace_type); // strip alpha information if (color_type & PNG_COLOR_MASK_ALPHA) { png_set_strip_alpha(png_ptr); } // /* tell libpng to strip 16 bit/color files down to 8 bits/color */ // png_set_strip_16(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); /* Expand paletted colors into true RGB triplets */ png_set_expand(png_ptr); png_start_read_image(png_ptr); /* The easiest way to read the image: */ rowbytes = png_get_rowbytes(png_ptr, info_ptr) * 3; row_pointers = (png_bytep *)malloc((*height) * sizeof(*row_pointers)); row_pointers[0] = (png_bytep)malloc(rowbytes * (*height) * 2); for(row = 1; row < (*height); row++) { row_pointers[row] = row_pointers[row - 1] + rowbytes*2; } /* Read the entire image in one go */ png_read_image(png_ptr, row_pointers); // we use fixed height here because block is of limited, fixed size // not fixed any more *block = realloc(*block, *height * *width * 3); // *block = malloc(*height * *width * 6); dst = *block; for(y = 0; y < *height; y++) { for(x = 0; x < *width * 3; x++) { *dst++ = row_pointers[y][x]; // *dst++ = 0; } } free(row_pointers[0]); free(row_pointers); /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); /* At this point you have read the entire image */ /* clean up after the read, and free any memory allocated - REQUIRED */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); }
int int_png_load(const char *name, unsigned char **buffer, int* xp, int* yp, int* bpp, bool alpha) { static const png_color_16 my_background = {0, 0, 0, 0, 0}; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; unsigned int i; int bit_depth, color_type, interlace_type, number_passes, pass, int_bpp; png_byte * fbptr; FILE * fh; if(!(fh=fopen(name,"rb"))) return(FH_ERROR_FILE); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(png_ptr == NULL) { fclose(fh); return(FH_ERROR_FORMAT); } info_ptr = png_create_info_struct(png_ptr); if(info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(fh); return(FH_ERROR_FORMAT); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fh); return(FH_ERROR_FORMAT); } png_init_io(png_ptr,fh); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); if (alpha) { *bpp = png_get_channels(png_ptr, info_ptr); if ((*bpp != 4) || !(color_type & PNG_COLOR_MASK_ALPHA)) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fh); return fh_png_load(name, buffer, xp, yp); } // 24bit PNGs with alpha-channel int_bpp = 4; // png_set_swap_alpha(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); }else // All other PNGs { if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); png_set_background(png_ptr, (png_color_16*)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); /* other possibility for png_set_background: use png_get_bKGD */ } if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); png_set_background(png_ptr, (png_color_16*)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } /* this test does not trigger for 8bit-paletted PNGs with newer libpng (1.2.36 at least), but the data delivered is with alpha channel anyway, so always strip alpha for now */ #if PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR <= 2 && PNG_LIBPNG_VER_RELEASE < 36 if (color_type & PNG_COLOR_MASK_ALPHA) #endif png_set_strip_alpha(png_ptr); if (bit_depth < 8) png_set_packing(png_ptr); int_bpp = 3; } if (bit_depth == 16) png_set_strip_16(png_ptr); number_passes = png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr,info_ptr); unsigned long rowbytes = png_get_rowbytes(png_ptr, info_ptr); if (width * int_bpp != rowbytes) { printf("[png.cpp]: Error processing %s - please report (including image).\n", name); printf(" width: %lu rowbytes: %lu\n", (unsigned long)width, (unsigned long)rowbytes); fclose(fh); return(FH_ERROR_FORMAT); } for (pass = 0; pass < number_passes; pass++) { fbptr = (png_byte *)(*buffer); for (i = 0; i < height; i++, fbptr += width * int_bpp) png_read_row(png_ptr, fbptr, NULL); } png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fh); return(FH_ERROR_OK); }
void write_header( const View& view ) { typedef detail::png_write_support< typename channel_type< typename get_pixel_type< View >::type >::type , typename color_space_type< View >::type > png_rw_info_t; // Set the image information here. Width and height are up to 2^31, // bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on // the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, // PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, // or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or // PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST // currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED png_set_IHDR( get_struct() , get_info() , static_cast< png_image_width::type >( view.width() ) , static_cast< png_image_height::type >( view.height() ) , static_cast< png_bitdepth::type >( png_rw_info_t::_bit_depth ) , static_cast< png_color_type::type >( png_rw_info_t::_color_type ) , _info._interlace_method , _info._compression_type , _info._filter_method ); #ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED if( _info._valid_cie_colors ) { png_set_cHRM( get_struct() , get_info() , _info._white_x , _info._white_y , _info._red_x , _info._red_y , _info._green_x , _info._green_y , _info._blue_x , _info._blue_y ); } if( _info._valid_file_gamma ) { png_set_gAMA( get_struct() , get_info() , _info._file_gamma ); } #else if( _info._valid_cie_colors ) { png_set_cHRM_fixed( get_struct() , get_info() , _info._white_x , _info._white_y , _info._red_x , _info._red_y , _info._green_x , _info._green_y , _info._blue_x , _info._blue_y ); } if( _info._valid_file_gamma ) { png_set_gAMA_fixed( get_struct() , get_info() , _info._file_gamma ); } #endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED if( _info._valid_icc_profile ) { #if PNG_LIBPNG_VER_MINOR >= 5 png_set_iCCP( get_struct() , get_info() , const_cast< png_charp >( _info._icc_name.c_str() ) , _info._iccp_compression_type , reinterpret_cast< png_const_bytep >( _info._profile.c_str() ) , _info._profile_length ); #else png_set_iCCP( get_struct() , get_info() , const_cast< png_charp >( _info._icc_name.c_str() ) , _info._iccp_compression_type , const_cast< png_charp >( _info._profile.c_str() ) , _info._profile_length ); #endif } if( _info._valid_intent ) { png_set_sRGB( get_struct() , get_info() , _info._intent ); } if( _info._valid_palette ) { png_set_PLTE( get_struct() , get_info() , const_cast< png_colorp >( &_info._palette.front() ) , _info._num_palette ); } if( _info._valid_background ) { png_set_bKGD( get_struct() , get_info() , const_cast< png_color_16p >( &_info._background ) ); } if( _info._valid_histogram ) { png_set_hIST( get_struct() , get_info() , const_cast< png_uint_16p >( &_info._histogram.front() ) ); } if( _info._valid_offset ) { png_set_oFFs( get_struct() , get_info() , _info._offset_x , _info._offset_y , _info._off_unit_type ); } if( _info._valid_pixel_calibration ) { std::vector< const char* > params( _info._num_params ); for( std::size_t i = 0; i < params.size(); ++i ) { params[i] = _info._params[ i ].c_str(); } png_set_pCAL( get_struct() , get_info() , const_cast< png_charp >( _info._purpose.c_str() ) , _info._X0 , _info._X1 , _info._cal_type , _info._num_params , const_cast< png_charp >( _info._units.c_str() ) , const_cast< png_charpp >( ¶ms.front() ) ); } if( _info._valid_resolution ) { png_set_pHYs( get_struct() , get_info() , _info._res_x , _info._res_y , _info._phy_unit_type ); } if( _info._valid_significant_bits ) { png_set_sBIT( get_struct() , get_info() , const_cast< png_color_8p >( &_info._sig_bits ) ); } #ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED if( _info._valid_scale_factors ) { png_set_sCAL( get_struct() , get_info() , this->_info._scale_unit , this->_info._scale_width , this->_info._scale_height ); } #else #ifdef BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED if( _info._valid_scale_factors ) { png_set_sCAL_fixed( get_struct() , get_info() , this->_info._scale_unit , this->_info._scale_width , this->_info._scale_height ); } #else if( _info._valid_scale_factors ) { png_set_sCAL_s( get_struct() , get_info() , this->_info._scale_unit , const_cast< png_charp >( this->_info._scale_width.c_str() ) , const_cast< png_charp >( this->_info._scale_height.c_str() ) ); } #endif // BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED #endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED if( _info._valid_text ) { std::vector< png_text > texts( _info._num_text ); for( std::size_t i = 0; i < texts.size(); ++i ) { png_text pt; pt.compression = _info._text[i]._compression; pt.key = const_cast< png_charp >( this->_info._text[i]._key.c_str() ); pt.text = const_cast< png_charp >( this->_info._text[i]._text.c_str() ); pt.text_length = _info._text[i]._text.length(); texts[i] = pt; } png_set_text( get_struct() , get_info() , &texts.front() , _info._num_text ); } if( _info._valid_modification_time ) { png_set_tIME( get_struct() , get_info() , const_cast< png_timep >( &_info._mod_time ) ); } if( _info._valid_transparency_factors ) { int sample_max = ( 1 << _info._bit_depth ); /* libpng doesn't reject a tRNS chunk with out-of-range samples */ if( !( ( _info._color_type == PNG_COLOR_TYPE_GRAY && (int) _info._trans_values[0].gray > sample_max ) || ( _info._color_type == PNG_COLOR_TYPE_RGB &&( (int) _info._trans_values[0].red > sample_max || (int) _info._trans_values[0].green > sample_max || (int) _info._trans_values[0].blue > sample_max ) ) ) ) { //@todo Fix that once reading transparency values works /* png_set_tRNS( get_struct() , get_info() , trans , num_trans , trans_values ); */ } } // Compression Levels - valid values are [0,9] png_set_compression_level( get_struct() , _info._compression_level ); png_set_compression_mem_level( get_struct() , _info._compression_mem_level ); png_set_compression_strategy( get_struct() , _info._compression_strategy ); png_set_compression_window_bits( get_struct() , _info._compression_window_bits ); png_set_compression_method( get_struct() , _info._compression_method ); png_set_compression_buffer_size( get_struct() , _info._compression_buffer_size ); #ifdef BOOST_GIL_IO_PNG_DITHERING_SUPPORTED // Dithering if( _info._set_dithering ) { png_set_dither( get_struct() , &_info._dithering_palette.front() , _info._dithering_num_palette , _info._dithering_maximum_colors , &_info._dithering_histogram.front() , _info._full_dither ); } #endif // BOOST_GIL_IO_PNG_DITHERING_SUPPORTED // Filter if( _info._set_filter ) { png_set_filter( get_struct() , 0 , _info._filter ); } // Invert Mono if( _info._invert_mono ) { png_set_invert_mono( get_struct() ); } // True Bits if( _info._set_true_bits ) { png_set_sBIT( get_struct() , get_info() , &_info._true_bits.front() ); } // sRGB Intent if( _info._set_srgb_intent ) { png_set_sRGB( get_struct() , get_info() , _info._srgb_intent ); } // Strip Alpha if( _info._strip_alpha ) { png_set_strip_alpha( get_struct() ); } // Swap Alpha if( _info._swap_alpha ) { png_set_swap_alpha( get_struct() ); } png_write_info( get_struct() , get_info() ); }
int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha, Metadata* const metadata) { volatile png_structp png; volatile png_infop info = NULL; volatile 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* volatile 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); 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 = (png_bytep)(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; } pic->width = width; pic->height = height; pic->use_argb = 1; ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, stride) : WebPPictureImportRGB(pic, rgb, stride); if (!ok) { goto Error; } End: if (png != NULL) { png_destroy_read_struct((png_structpp)&png, (png_infopp)&info, (png_infopp)&end_info); } free(rgb); return ok; }
int fh_png_load(const char *name, unsigned char *buffer, int x, int y) { static const png_color_16 my_background = {0, 0, 0, 0, 0}; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; unsigned int i; int bit_depth, color_type, interlace_type; int number_passes, pass; png_byte * fbptr; FILE * fh; if (!(fh = fopen(name, "rb"))) return(FH_ERROR_FILE); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) return(FH_ERROR_FORMAT); info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(fh); return(FH_ERROR_FORMAT); } #if (PNG_LIBPNG_VER < 10500) if (setjmp(png_ptr->jmpbuf)) #else if (setjmp(png_jmpbuf(png_ptr))) #endif { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fh); return(FH_ERROR_FORMAT); } png_init_io(png_ptr, fh); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); png_set_background(png_ptr, (png_color_16 *)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); /* other possibility for png_set_background: use png_get_bKGD */ } if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); png_set_background(png_ptr, (png_color_16 *)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } if (color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png_ptr); if (bit_depth < 8) png_set_packing(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); /* on Intel PC ?: if (bit_depth == 16) png_set_swap(png_ptr); */ number_passes = png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); if (width * 3 != png_get_rowbytes(png_ptr, info_ptr)) { printf("[png.cpp]: Error processing %s - please report (including image).\n", name); return(FH_ERROR_FORMAT); } for(pass = 0; pass < number_passes; pass++) { fbptr = (png_byte *)buffer; for (i = 0; i < height; i++, fbptr += width * 3) { png_read_row(png_ptr, fbptr, NULL); } } png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fh); return(FH_ERROR_OK); }
uint8_t* ImageDecoder::decodePNGImpl(png_structp pngPtr, uint32_t* width, uint32_t* height) { png_bytep* rowPtrs = NULL; uint8_t* outData = NULL; png_infop infoPtr = png_create_info_struct(pngPtr); if (!infoPtr) { LOG(LOG_ERROR,"Couldn't initialize png info struct"); png_destroy_read_struct(&pngPtr, (png_infopp)0, (png_infopp)0); return NULL; } if (setjmp(png_jmpbuf(pngPtr))) { png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0); if (rowPtrs != NULL) delete [] rowPtrs; if (outData != NULL) delete [] outData; LOG(LOG_ERROR,"error during reading of the png file"); return NULL; } png_read_info(pngPtr, infoPtr); *width = png_get_image_width(pngPtr, infoPtr); *height = png_get_image_height(pngPtr, infoPtr); //bits per CHANNEL! note: not per pixel! png_uint_32 bitdepth = png_get_bit_depth(pngPtr, infoPtr); //Number of channels png_uint_32 channels = png_get_channels(pngPtr, infoPtr); //Color type. (RGB, RGBA, Luminance, luminance alpha... palette... etc) png_uint_32 color_type = png_get_color_type(pngPtr, infoPtr); // Transform everything into 24 bit RGB switch (color_type) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(pngPtr); // png_set_palette_to_rgb wil convert into 32 // bit, but we don't want the alpha png_set_strip_alpha(pngPtr); break; case PNG_COLOR_TYPE_GRAY: if (bitdepth < 8) png_set_gray_to_rgb(pngPtr); break; } if (bitdepth == 16) { png_set_strip_16(pngPtr); } if (channels > 3) { LOG(LOG_NOT_IMPLEMENTED, "Alpha channel not supported in PNG"); png_set_strip_alpha(pngPtr); } // Update the infoPtr to reflect the transformations set // above. Read new values by calling png_get_* again. png_read_update_info(pngPtr, infoPtr); //bitdepth = png_get_bit_depth(pngPtr, infoPtr); //color_type = png_get_color_type(pngPtr, infoPtr); channels = png_get_channels(pngPtr, infoPtr); if (channels != 3) { // Should never get here because of the // transformations LOG(LOG_NOT_IMPLEMENTED, "Unexpected number of channels in PNG!"); png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0); return NULL; } const unsigned int stride = png_get_rowbytes(pngPtr, infoPtr); outData = new uint8_t[(*height) * stride]; rowPtrs = new png_bytep[(*height)]; for (size_t i = 0; i < (*height); i++) { rowPtrs[i] = (png_bytep)outData + i* stride; } png_read_image(pngPtr, rowPtrs); png_read_end(pngPtr, NULL); png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0); delete[] (png_bytep)rowPtrs; return outData; }
void ZLEwlImageManager::convertImageDirectPng(const std::string &stringData, ZLImageData &data) const { struct s_my_png my_png; my_png.p = (char*)stringData.data(); my_png.size = stringData.length(); png_structp png_ptr = NULL; png_infop info_ptr = NULL; unsigned int *row = NULL; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)&my_png, mypng_error_func, mypng_warning_func); if ( !png_ptr ) return; if (setjmp( png_ptr->jmpbuf )) { data.init(0, 0); if (png_ptr) { png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); } if ( row ) delete row; return; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) mypng_error_func(png_ptr, "cannot create png info struct"); png_set_read_fn(png_ptr, (voidp)&my_png, mypng_read_func); png_read_info( png_ptr, info_ptr ); png_uint_32 width, height; int bit_depth, color_type, interlace_type; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); data.init(width, height); row = new unsigned int[ width ]; // SET TRANSFORMS if (color_type & PNG_COLOR_MASK_PALETTE) png_set_palette_to_rgb(png_ptr); 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); if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_invert_alpha(png_ptr); } else { png_color_16 bg = {0, 0xffff, 0xffff, 0xffff, 0xffff}; png_set_background(png_ptr, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 0.0); png_set_strip_alpha(png_ptr); } if (bit_depth < 8) png_set_packing(png_ptr); //if (color_type == PNG_COLOR_TYPE_RGB) //png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); //if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) // png_set_swap_alpha(png_ptr); if (! (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) png_set_rgb_to_gray(png_ptr, 1, -1, -1); int number_passes = png_set_interlace_handling(png_ptr); //if (color_type == PNG_COLOR_TYPE_RGB_ALPHA || // color_type == PNG_COLOR_TYPE_GRAY_ALPHA) //if (color_type == PNG_COLOR_TYPE_RGB || // color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_bgr(png_ptr); ZLIntegerOption myDitherAlgo(ZLCategoryKey::LOOK_AND_FEEL, "Options", "DitherAlgo", 0); register int dalgo = myDitherAlgo.value(); char *c; for(int pass = 0; pass < number_passes; pass++) { for(unsigned int y = 0; y < height; y++) { png_read_rows(png_ptr, (unsigned char **)&row, png_bytepp_NULL, 1); c = ((ZLEwlImageData&)data).getImageData() + width * y; if ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) { unsigned char *s = (unsigned char*)row; if(dalgo == 1) for(unsigned int i = 0; i < width; i++) *c++ = Dither2BitColor(*(++s)++, i, y); else for(unsigned int i = 0; i < width; i++) *c++ = *(++s)++; } else if(dalgo == 1) { unsigned char *s = (unsigned char*)row; for(unsigned int i = 0; i < width; i++) *c++ = Dither2BitColor(*s++, i, y); } else memcpy(c, (char*)row, width); } } png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); }
/*--------------------------------------------------------------------------- Loads a PNG file. Image : Image will be returned there. Path : Path to image file, relative to the current working directory. Gamma : Display gamma to apply on textures, 2.2 is typical. ---------------------------------------------------------------------------*/ void PNG::Load(Texture &Image, const std::string &Path, float Gamma) { Destroy(); //Important - set class to reading mode Mode = PNG::ModeRead; #if defined (WINDOWS) if (fopen_s(&File, Path.c_str(), "rb") != 0) {throw dexception("Failed to open file: %s.", Path.c_str());} #else File = fopen(Path.c_str(), "rb"); if (File == nullptr) {throw dexception("Failed to open file: %s.", Path.c_str());} #endif uint8 Header[PNG::HeaderSize]; if (fread((png_bytep)Header, 1, PNG::HeaderSize, File) == 0) {throw dexception("fread( ) failed.");} if (!png_check_sig(Header, PNG::HeaderSize)) {throw dexception("Not a valid PNG file.");} PngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (PngPtr == nullptr) {throw dexception("png_create_read_struct( ) failed.");} InfoPtr = png_create_info_struct(PngPtr); if (InfoPtr == nullptr) {throw dexception("png_create_info_struct( ) failed.");} if (setjmp(png_jmpbuf(PngPtr))) {throw dexception("setjmp( ) failed.");} //Read into structures png_init_io(PngPtr, File); png_set_sig_bytes(PngPtr, PNG::HeaderSize); png_read_info(PngPtr, InfoPtr); //Determine image attributes vector2<png_uint_32> Res; int BitDepth, ColourType; png_get_IHDR(PngPtr, InfoPtr, &Res.U, &Res.V, &BitDepth, &ColourType, nullptr, nullptr, nullptr); Texture::TexType Type = Texture::TypeRGB; switch (ColourType) { case PNG_COLOR_TYPE_GRAY : if (BitDepth < 8) { Type = Texture::TypeLum; png_set_expand_gray_1_2_4_to_8(PngPtr); } else if (BitDepth == 16) { Type = Texture::TypeDepth; } break; case PNG_COLOR_TYPE_GRAY_ALPHA : Type = Texture::TypeRGBA; png_set_gray_to_rgb(PngPtr); break; case PNG_COLOR_TYPE_PALETTE : Type = Texture::TypeRGB; png_set_palette_to_rgb(PngPtr); break; case PNG_COLOR_TYPE_RGB : Type = Texture::TypeRGB; png_set_strip_alpha(PngPtr); //If libpng reports RGB, make sure we completely strip alpha break; case PNG_COLOR_TYPE_RGB_ALPHA : Type = Texture::TypeRGBA; break; default : throw dexception("Unknown colour type."); } //Convert palette alpha into a separate alpha channel if (png_get_valid(PngPtr, InfoPtr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(PngPtr); if (ColourType == PNG_COLOR_TYPE_PALETTE) {Type = Texture::TypeRGBA;} } //Force 8 bit per channel if (BitDepth >= 16) { if (Type != Texture::TypeDepth) {png_set_strip_16(PngPtr);} } else if (BitDepth < 8) { png_set_packing(PngPtr); } //Specify display and file gamma (assume 0.45455 for missing file gamma) double FileGamma; if (!png_get_gAMA(PngPtr, InfoPtr, &FileGamma)) {FileGamma = 0.45455;} png_set_gamma(PngPtr, Gamma, FileGamma); //Swap byte order for int16 values on big endian machines if ((BitDepth >= 16) && !Math::MachineLittleEndian()) {png_set_swap(PngPtr);} //Apply the above transformation settings png_read_update_info(PngPtr, InfoPtr); //Allocate image Image.Create(cast_vector2(uint, Res), Type); if (Image.GetBytesPerLine() < (usize)png_get_rowbytes(PngPtr, InfoPtr)) {throw dexception("Incorrect scan line size for allocated image.");} //Populate row pointer array Rows.Create((usize)Res.V); for (uiter I = 0; I < (usize)Res.V; I++) { Rows[I] = Image.Address(0, I); } //Decode png_read_image(PngPtr, Rows.Pointer()); png_read_end(PngPtr, InfoPtr); //Clean up Destroy(); }
int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) { GLint pack, unpack; unsigned char header[8]; png_structp png; png_infop info; png_infop endinfo; png_bytep data, data2; png_bytep *row_p; double fileGamma; png_uint_32 width, height, rw, rh; int depth, color; png_uint_32 i; fread(header, 1, 8, fp); if (!png_check_sig(header, 8)) return 0; png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info = png_create_info_struct(png); endinfo = png_create_info_struct(png); // DH: added following lines if (setjmp(png->jmpbuf)) { png_destroy_read_struct(&png, &info, &endinfo); return 0; } // ~DH png_init_io(png, fp); png_set_sig_bytes(png, 8); png_read_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); if (pinfo != NULL) { pinfo->Width = width; pinfo->Height = height; pinfo->Depth = depth; } if (MaxTextureSize == 0) glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTextureSize); #ifdef SUPPORTS_PALETTE_EXT #ifdef _WIN32 if (PalettedTextures == -1) PalettedTextures = ExtSupported("GL_EXT_paletted_texture") && (strstr((const char *) glGetString(GL_VERSION), "1.1.0 3Dfx Beta") == NULL); if (PalettedTextures) { if (glColorTableEXT == NULL) { glColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT"); if (glColorTableEXT == NULL) PalettedTextures = 0; } } #endif #endif if (PalettedTextures == -1) PalettedTextures = 0; if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); if (color&PNG_COLOR_MASK_ALPHA && trans != PNG_ALPHA) { png_set_strip_alpha(png); color &= ~PNG_COLOR_MASK_ALPHA; } if (!(PalettedTextures && mipmap >= 0 && trans == PNG_SOLID)) if (color == PNG_COLOR_TYPE_PALETTE) png_set_expand(png); /*--GAMMA--*/ checkForGammaEnv(); if (png_get_gAMA(png, info, &fileGamma)) png_set_gamma(png, screenGamma, fileGamma); else png_set_gamma(png, screenGamma, 1.0/2.2); png_read_update_info(png, info); data = (png_bytep) malloc(png_get_rowbytes(png, info)*height); row_p = (png_bytep *) malloc(sizeof(png_bytep)*height); for (i = 0; i < height; i++) { if (StandardOrientation) row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i]; else row_p[i] = &data[png_get_rowbytes(png, info)*i]; } png_read_image(png, row_p); free(row_p); rw = SafeSize(width), rh = SafeSize(height); if (rw != width || rh != height) { const int channels = png_get_rowbytes(png, info)/width; data2 = (png_bytep) malloc(rw*rh*channels); /* Doesn't work on certain sizes */ /* if (gluScaleImage(glformat, width, height, GL_UNSIGNED_BYTE, data, rw, rh, GL_UNSIGNED_BYTE, data2) != 0) return 0; */ Resize(channels, data, width, height, data2, rw, rh); width = rw, height = rh; free(data); data = data2; } { /* OpenGL stuff */ glGetIntegerv(GL_PACK_ALIGNMENT, &pack); glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); #ifdef SUPPORTS_PALETTE_EXT if (PalettedTextures && mipmap >= 0 && trans == PNG_SOLID && color == PNG_COLOR_TYPE_PALETTE) { png_colorp pal; int cols; GLint intf; if (pinfo != NULL) pinfo->Alpha = 0; png_get_PLTE(png, info, &pal, &cols); switch (cols) { case 1<<1: intf = GL_COLOR_INDEX1_EXT; break; case 1<<2: intf = GL_COLOR_INDEX2_EXT; break; case 1<<4: intf = GL_COLOR_INDEX4_EXT; break; case 1<<8: intf = GL_COLOR_INDEX8_EXT; break; case 1<<12: intf = GL_COLOR_INDEX12_EXT; break; case 1<<16: intf = GL_COLOR_INDEX16_EXT; break; default: /*printf("Warning: Colour depth %i not recognised\n", cols);*/ return 0; } glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, cols, GL_RGB, GL_UNSIGNED_BYTE, pal); glTexImage2D(GL_TEXTURE_2D, mipmap, intf, width, height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data); } else #endif if (trans == PNG_SOLID || trans == PNG_ALPHA || trans == PNG_LUMINANCEALPHA || color == PNG_COLOR_TYPE_RGB_ALPHA || color == PNG_COLOR_TYPE_GRAY_ALPHA) { GLenum glformat; GLint glcomponent; switch (color) { case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_PALETTE: glformat = GL_RGB; glcomponent = 3; if (pinfo != NULL) pinfo->Alpha = 0; break; case PNG_COLOR_TYPE_GRAY_ALPHA: case PNG_COLOR_TYPE_RGB_ALPHA: glformat = GL_RGBA; glcomponent = 4; if (pinfo != NULL) pinfo->Alpha = 8; break; default: /*puts("glformat not set");*/ return 0; } if (trans == PNG_LUMINANCEALPHA) glformat = GL_LUMINANCE_ALPHA; if (mipmap == PNG_BUILDMIPMAPS) Build2DMipmaps(glcomponent, width, height, glformat, data, 1); else if (mipmap == PNG_SIMPLEMIPMAPS) Build2DMipmaps(glcomponent, width, height, glformat, data, 0); else glTexImage2D(GL_TEXTURE_2D, mipmap, glcomponent, width, height, 0, glformat, GL_UNSIGNED_BYTE, data); } else { png_bytep p, endp, q; int r, g, b, a; p = data, endp = p+width*height*3; q = data2 = (png_bytep) malloc(sizeof(png_byte)*width*height*4); if (pinfo != NULL) pinfo->Alpha = 8; #define FORSTART \ do { \ r = *p++; /*red */ \ g = *p++; /*green*/ \ b = *p++; /*blue */ \ *q++ = r; \ *q++ = g; \ *q++ = b; #define FOREND \ q++; \ } while (p != endp); #define ALPHA *q switch (trans) { case PNG_CALLBACK: FORSTART ALPHA = AlphaCallback((unsigned char) r, (unsigned char) g, (unsigned char) b); FOREND break; case PNG_STENCIL: FORSTART if (r == StencilRed && g == StencilGreen && b == StencilBlue) ALPHA = 0; else ALPHA = 255; FOREND break; case PNG_BLEND1: FORSTART a = r+g+b; if (a > 255) ALPHA = 255; else ALPHA = a; FOREND break; case PNG_BLEND2: FORSTART a = r+g+b; if (a > 255*2) ALPHA = 255; else ALPHA = a/2; FOREND break; case PNG_BLEND3: FORSTART ALPHA = (r+g+b)/3; FOREND break; case PNG_BLEND4: FORSTART a = r*r+g*g+b*b; if (a > 255) ALPHA = 255; else ALPHA = a; FOREND break; case PNG_BLEND5: FORSTART a = r*r+g*g+b*b; if (a > 255*2) ALPHA = 255; else ALPHA = a/2; FOREND break; case PNG_BLEND6: FORSTART a = r*r+g*g+b*b; if (a > 255*3) ALPHA = 255; else ALPHA = a/3; FOREND break; //HACK: disabling this for now /* case PNG_BLEND7: FORSTART a = r*r+g*g+b*b; if (a > 255*255) ALPHA = 255; else ALPHA = (int) (sqrt(float(a))); FOREND */ break; } #undef FORSTART #undef FOREND #undef ALPHA if (mipmap == PNG_BUILDMIPMAPS) Build2DMipmaps(4, width, height, GL_RGBA, data2, 1); else if (mipmap == PNG_SIMPLEMIPMAPS) Build2DMipmaps(4, width, height, GL_RGBA, data2, 0); else glTexImage2D(GL_TEXTURE_2D, mipmap, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2); free(data2); } glPixelStorei(GL_PACK_ALIGNMENT, pack); glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); } /* OpenGL end */ png_read_end(png, endinfo); png_destroy_read_struct(&png, &info, &endinfo); free(data); return 1; }
static DFBResult load_image (const char *filename, DFBSurfaceDescription *desc) { DFBSurfacePixelFormat dest_format; DFBSurfacePixelFormat src_format; FILE *fp; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; unsigned char *data = NULL; int type; char header[8]; int bytes, pitch; dest_format = (desc->flags & DSDESC_PIXELFORMAT) ? desc->pixelformat : DSPF_UNKNOWN; desc->flags = DSDESC_NONE; desc->preallocated[0].data = NULL; if (!(fp = fopen (filename, "rb"))) { fprintf (stderr, "Failed to open file '%s': %s.\n", filename, strerror (errno)); goto cleanup; } bytes = fread (header, 1, sizeof(header), fp); if (png_sig_cmp ((unsigned char*) header, 0, bytes)) { fprintf (stderr, "File '%s' doesn't seem to be a PNG image file.\n", filename); goto cleanup; } png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) goto cleanup; if (setjmp (png_jmpbuf(png_ptr))) { if (desc->preallocated[0].data) { free (desc->preallocated[0].data); desc->preallocated[0].data = NULL; } /* data might have been clobbered, set it to NULL and leak instead of crashing */ data = NULL; goto cleanup; } info_ptr = png_create_info_struct (png_ptr); if (!info_ptr) goto cleanup; png_init_io (png_ptr, fp); png_set_sig_bytes (png_ptr, bytes); png_read_info (png_ptr, info_ptr); png_get_IHDR (png_ptr, info_ptr, &width, &height, &bytes, &type, NULL, NULL, NULL); if (bytes == 16) png_set_strip_16 (png_ptr); #ifdef WORDS_BIGENDIAN png_set_swap_alpha (png_ptr); #else png_set_bgr (png_ptr); #endif src_format = (type & PNG_COLOR_MASK_ALPHA) ? DSPF_ARGB : DSPF_RGB32; switch (type) { case PNG_COLOR_TYPE_GRAY: if (dest_format == DSPF_A8) { src_format = DSPF_A8; break; } /* fallthru */ case PNG_COLOR_TYPE_GRAY_ALPHA: png_set_gray_to_rgb (png_ptr); // if (rgbformat) // dest_format = rgbformat; break; case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb (png_ptr); /* fallthru */ case PNG_COLOR_TYPE_RGB: // if (rgbformat) // dest_format = rgbformat; case PNG_COLOR_TYPE_RGB_ALPHA: if (dest_format == DSPF_RGB24) { png_set_strip_alpha (png_ptr); src_format = DSPF_RGB24; } break; } switch (src_format) { case DSPF_RGB32: png_set_filler (png_ptr, 0xFF, #ifdef WORDS_BIGENDIAN PNG_FILLER_BEFORE #else PNG_FILLER_AFTER #endif ); break; case DSPF_ARGB: case DSPF_A8: if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png_ptr); break; default: break; } pitch = (DFB_BYTES_PER_LINE( src_format, width ) + 7) & ~7; data = (unsigned char*) malloc (height * pitch); if (!data) { fprintf (stderr, "Failed to allocate %lu bytes.\n", (unsigned long)(height * pitch)); goto cleanup; } { unsigned int i; png_bytep bptrs[height]; for (i = 0; i < height; i++) bptrs[i] = data + i * pitch; png_read_image (png_ptr, bptrs); } if (!dest_format) dest_format = src_format; if (DFB_BYTES_PER_PIXEL(src_format) != DFB_BYTES_PER_PIXEL(dest_format)) { unsigned char *s, *d, *dest; int d_pitch, h; D_ASSERT( DFB_BYTES_PER_PIXEL(src_format) == 4 ); d_pitch = (DFB_BYTES_PER_LINE(dest_format, width) + 7) & ~7; dest = (unsigned char*) malloc (height * d_pitch); if (!dest) { fprintf (stderr, "Failed to allocate %lu bytes.\n", (unsigned long)(height * d_pitch)); goto cleanup; } h = height; switch (dest_format) { case DSPF_RGB16: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_rgb16 ((u32 *) s, (u16 *) d, width); break; case DSPF_ARGB8565: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_argb8565 ((u32 *) s, (u8 *) d, width); break; case DSPF_ARGB1555: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_argb1555 ((u32 *) s, (u16 *) d, width); break; case DSPF_RGBA5551: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_rgba5551 ((u32 *) s, (u16 *) d, width); break; case DSPF_ARGB2554: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_argb2554 ((u32 *) s, (u16 *) d, width); break; case DSPF_ARGB4444: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_argb4444 ((u32 *) s, (u16 *) d, width); break; case DSPF_RGB332: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_rgb332 ((u32 *) s, (u8 *) d, width); break; case DSPF_A8: for (s = data, d = dest; h; h--, s += pitch, d += d_pitch) dfb_argb_to_a8 ((u32 *) s, (u8 *) d, width); break; default: fprintf (stderr, "Sorry, unsupported format conversion.\n"); goto cleanup; } free (data); data = dest; pitch = d_pitch; } desc->flags = (DFBSurfaceDescriptionFlags)(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_PREALLOCATED); desc->width = width; desc->height = height; desc->pixelformat = dest_format; desc->preallocated[0].pitch = pitch; desc->preallocated[0].data = data; data = NULL; cleanup: if (fp) fclose (fp); if (png_ptr) png_destroy_read_struct (&png_ptr, &info_ptr, NULL); if (data) free (data); return ((desc->flags) ? DFB_OK : DFB_FAILURE); }