// Do transformations to normalize the input to 8-bpp RGBA void LLPngWrapper::normalizeImage() { // 1. Expand any palettes // 2. Convert grayscales to RGB // 3. Create alpha layer from transparency // 4. Ensure 8-bpp for all images // 5. Apply background matte if any // 6. Set (or guess) gamma if (mColorType == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(mReadPngPtr); } if (mColorType == PNG_COLOR_TYPE_GRAY && mBitDepth < 8) { png_set_gray_1_2_4_to_8(mReadPngPtr); } if (mColorType == PNG_COLOR_TYPE_GRAY || mColorType == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(mReadPngPtr); } if (png_get_valid(mReadPngPtr, mReadInfoPtr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(mReadPngPtr); } if (mBitDepth < 8) { png_set_packing(mReadPngPtr); } else if (mBitDepth == 16) { png_set_strip_16(mReadPngPtr); } mHasBKGD = png_get_bKGD(mReadPngPtr, mReadInfoPtr, &mBackgroundColor); if (mHasBKGD) { png_set_background(mReadPngPtr, mBackgroundColor, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); } #if LL_DARWIN const F64 SCREEN_GAMMA = 1.8; #else const F64 SCREEN_GAMMA = 2.2; #endif if (png_get_gAMA(mReadPngPtr, mReadInfoPtr, &mGamma)) { png_set_gamma(mReadPngPtr, SCREEN_GAMMA, mGamma); } else { png_set_gamma(mReadPngPtr, SCREEN_GAMMA, 1/SCREEN_GAMMA); } }
// // Load a texture from a png image // bool PngLoader::loadImageIntoBuffer() { DEBUG_ENTER_FUNC(); if (!basicImageLoad()) { png_destroy_read_struct(&_pngPtr, &_infoPtr, png_infopp_NULL); return false; } png_set_strip_16(_pngPtr); // Strip off 16 bit channels in case they occur if (_paletteSize) { // Copy the palette png_colorp srcPal = _infoPtr->palette; for (int i = 0; i < _infoPtr->num_palette; i++) { unsigned char alphaVal = (i < _infoPtr->num_trans) ? _infoPtr->trans[i] : 0xFF; // Load alpha if it's there _palette->setSingleColorRGBA(i, srcPal->red, srcPal->green, srcPal->blue, alphaVal); srcPal++; } } else { // Not a palettized image if (_colorType == PNG_COLOR_TYPE_GRAY && _bitDepth < 8) png_set_gray_1_2_4_to_8(_pngPtr); // Round up grayscale images if (png_get_valid(_pngPtr, _infoPtr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(_pngPtr); // Convert trans channel to alpha for 32 bits png_set_add_alpha(_pngPtr, 0xff, PNG_FILLER_AFTER); // Filler for alpha if none exists } uint32 rowBytes = png_get_rowbytes(_pngPtr, _infoPtr); // there seems to be a bug in libpng where it doesn't increase the rowbytes or the // channel even after we add the alpha channel if (_channels == 3 && (rowBytes / _width) == 3) { _channels = 4; rowBytes = _width * _channels; } PSP_DEBUG_PRINT("rowBytes[%d], channels[%d]\n", rowBytes, _channels); unsigned char *line = (unsigned char*) malloc(rowBytes); if (!line) { png_destroy_read_struct(&_pngPtr, png_infopp_NULL, png_infopp_NULL); PSP_ERROR("Couldn't allocate line\n"); return false; } for (size_t y = 0; y < _height; y++) { png_read_row(_pngPtr, line, png_bytep_NULL); _buffer->copyFromRect(line, rowBytes, 0, y, _width, 1); // Copy into buffer } free(line); png_read_end(_pngPtr, _infoPtr); png_destroy_read_struct(&_pngPtr, &_infoPtr, png_infopp_NULL); return true; }
//============================================================================= // load_png //============================================================================= int load_png(PKLImage pkl, FILE *image) { png_structp png_ptr; png_infop info_ptr; int i; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) return(1); info_ptr = png_create_info_struct(png_ptr); if(!info_ptr){ png_destroy_read_struct(&png_ptr, NULL, NULL); return(1); } if( setjmp(png_jmpbuf(png_ptr)) ){ png_destroy_info_struct(png_ptr, &info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return(1); } png_init_io(png_ptr, image); png_read_info(png_ptr, info_ptr); pkl->width = info_ptr->width; pkl->height = info_ptr->height; pkl->color = color_pn2pk(info_ptr->color_type); pkl->channel = pkl_png_channels(pkl->color); pkl->resh = resolution_p2p(info_ptr->phys_unit_type, info_ptr->x_pixels_per_unit); pkl->resv = resolution_p2p(info_ptr->phys_unit_type, info_ptr->y_pixels_per_unit); if(pkl->color == PKL_UNKNOWN) return(1); pkl->image = malloc(pkl->width * pkl->height * pkl->channel); if(!pkl->image) return(1); if(info_ptr->color_type==PNG_COLOR_TYPE_RGB_ALPHA || info_ptr->color_type==PNG_COLOR_TYPE_GRAY_ALPHA || info_ptr->num_trans) png_set_strip_alpha(png_ptr); if(info_ptr->bit_depth<8 && info_ptr->color_type==PNG_COLOR_TYPE_GRAY) png_set_gray_1_2_4_to_8(png_ptr); if(info_ptr->bit_depth==16) png_set_strip_16(png_ptr); if(info_ptr->color_type==PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); for(i=0; i<pkl->height; i++) png_read_row(png_ptr, &pkl->image[i*pkl->width*pkl->channel], NULL); png_destroy_info_struct(png_ptr, &info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return(0); }
void _gTexLoadPNG(FILE* fp, gImage* tex) { 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, x, y; u32* line; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); png_set_error_fn(png_ptr,NULL,NULL,NULL); info_ptr = png_create_info_struct(png_ptr); 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,&width,&height,&bit_depth,&color_type, &interlace_type,NULL,NULL); png_set_strip_16(png_ptr); png_set_packing(png_ptr); 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_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); png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); tex->w = width; tex->h = height; tex->tw = _getNextPower2(width); tex->th = _getNextPower2(height); tex->ratio = (float)width / height; tex->data = memalign(16, tex->tw * tex->th * sizeof(gColor)); line = malloc(width * 4); for (y = 0; y < height; y++) { png_read_row(png_ptr, (u8*) line, png_bytep_NULL); for (x = 0; x < width; x++) { u32 color = line[x]; tex->data[x + y * tex->tw] = color; } } free(line); png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); }
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; }
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; } }
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; }
void PNGImage_load(PNGImage *self) { png_structp png_ptr; png_infop info_ptr; int bit_depth; int color_type; int interlace_type; png_uint_32 w; png_uint_32 h; int palleteComponents = 3; int number_passes, row; FILE *fp = fopen(self->path, "rb"); PNGImage_error_(self, ""); if (!fp) { PNGImage_error_(self, "file not found"); return; } /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also 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, NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); PNGImage_error_(self, "unable to read png from file"); return; } /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_read_struct(&(png_ptr), png_infopp_NULL, png_infopp_NULL); PNGImage_error_(self, "error allocating png struct"); return; } /* 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); PNGImage_error_(self, self->path); return; } /* Set up the input control if you are using standard C streams */ png_init_io(png_ptr, fp); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &w, &h, &(bit_depth), &(color_type), &(interlace_type), int_p_NULL, int_p_NULL); self->width = w; self->height = h; /* 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 */ /* if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_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); palleteComponents = 4; } /* swap bytes of 16 bit files to least significant byte first */ /*png_set_swap(png_ptr);*/ /* Add filler (or alpha) byte (before/after each RGB triplet) */ /*png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);*/ /* Turn on interlace handling. REQUIRED if you are not using * png_read_image(). To see how to handle interlacing passes, * see the png_read_row() method below: */ number_passes = png_set_interlace_handling(png_ptr); /* Allocate the memory to hold the image using the fields of info_ptr. */ /* The easiest way to read the image: */ { /*png_bytep row_pointers[height];*/ png_bytep *row_pointers = (png_bytep *)malloc(self->height*sizeof(void *)); for (row = 0; row < self->height; row++) { /*int bpr = png_get_rowbytes(png_ptr, info_ptr);*/ int bpr = png_get_rowbytes(png_ptr, info_ptr) * 4; row_pointers[row] = png_malloc(png_ptr, bpr); } /* Now it's time to read the image. One of these methods is REQUIRED */ png_read_image(png_ptr, row_pointers); { int bytesPerRow; switch(color_type) { case PNG_COLOR_TYPE_GRAY: self->components = 1; break; case PNG_COLOR_TYPE_PALETTE: self->components = palleteComponents; break; case PNG_COLOR_TYPE_RGB: self->components = 3; break; case PNG_COLOR_TYPE_RGB_ALPHA: self->components = 4; break; case PNG_COLOR_TYPE_GRAY_ALPHA: self->components = 2; break; } bytesPerRow = self->width * self->components; UArray_setSize_(self->byteArray, self->width * self->height * self->components); for (row = 0; row < self->height; row++) { int i = row*(self->width*self->components); memcpy((uint8_t *)UArray_bytes(self->byteArray) + i, row_pointers[row], bytesPerRow); free(row_pointers[row]); } } 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); fclose(fp); return; }
// ###################################################################### PngParser::PngParser(const char* filename) : rep(new Rep(filename)) { errno = 0; rep->file = fopen(filename, "rb"); if (rep->file == 0) rep->onError("couldn't open file for png reading"); const size_t nheader = 8; png_byte header[nheader]; if (fread(header, 1, nheader, rep->file) != nheader) rep->onError("short read on png file header"); int is_png = !png_sig_cmp(header, 0, nheader); if (!is_png) rep->onError("file was not a png image file"); rep->pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (rep->pngPtr == 0) rep->onError("png_create_read_struct failed"); rep->infoPtr = png_create_info_struct(rep->pngPtr); if (rep->infoPtr == 0) rep->onError("png_create_info_struct failed"); rep->endPtr = png_create_info_struct(rep->pngPtr); if (rep->endPtr == 0) rep->onError("png_create_info_struct failed"); png_init_io(rep->pngPtr, rep->file); png_set_sig_bytes(rep->pngPtr, nheader); png_read_info(rep->pngPtr, rep->infoPtr); rep->bitDepth = png_get_bit_depth(rep->pngPtr, rep->infoPtr); rep->colorType = png_get_color_type(rep->pngPtr, rep->infoPtr); if (rep->bitDepth == 16) png_set_strip_16(rep->pngPtr); else if (rep->bitDepth < 8 && (rep->colorType == PNG_COLOR_TYPE_GRAY)) png_set_gray_1_2_4_to_8(rep->pngPtr); else if (rep->bitDepth != 8 && (rep->colorType != PNG_COLOR_TYPE_PALETTE)) rep->onError(sformat("invalid bit-depth(%d)/color-mode(%d) " "combination", rep->bitDepth, rep->colorType)); // Strip out the alpha channel, if present if (rep->colorType & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(rep->pngPtr); if (rep->colorType & PNG_COLOR_MASK_PALETTE) png_set_palette_to_rgb(rep->pngPtr); // This must come after any+all transformations are specified png_read_update_info(rep->pngPtr, rep->infoPtr); // These calls must come after png_read_update_info, so that we get // values that reflect any transformations rep->width = png_get_image_width(rep->pngPtr, rep->infoPtr); rep->height = png_get_image_height(rep->pngPtr, rep->infoPtr); rep->rowBytes = png_get_rowbytes(rep->pngPtr, rep->infoPtr); rep->numChannels = png_get_channels(rep->pngPtr, rep->infoPtr); ASSERT(rep->rowBytes = rep->width*rep->numChannels); // run-time mmx PNG optimizations (nate) #if defined(HAVE_PNG_ASM_FLAGS) const png_uint_32 flags = png_get_asm_flags(rep->pngPtr); const png_uint_32 mask = png_get_asm_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE); png_set_asm_flags(rep->pngPtr, flags | mask); #endif }
static GstFlowReturn gst_pngdec_caps_create_and_set (GstPngDec * pngdec) { GstFlowReturn ret = GST_FLOW_OK; GstCaps *caps = NULL, *res = NULL; GstPadTemplate *templ = NULL; gint bpc = 0, color_type; png_uint_32 width, height; g_return_val_if_fail (GST_IS_PNGDEC (pngdec), GST_FLOW_ERROR); /* Get bits per channel */ bpc = png_get_bit_depth (pngdec->png, pngdec->info); /* We don't handle 16 bits per color, strip down to 8 */ if (bpc == 16) { GST_LOG_OBJECT (pngdec, "this is a 16 bits per channel PNG image, strip down to 8 bits"); png_set_strip_16 (pngdec->png); } /* Get Color type */ color_type = png_get_color_type (pngdec->png, pngdec->info); #if 0 /* We used to have this HACK to reverse the outgoing bytes, but the problem * that originally required the hack seems to have been in ffmpegcolorspace's * RGBA descriptions. It doesn't seem needed now that's fixed, but might * still be needed on big-endian systems, I'm not sure. J.S. 6/7/2007 */ if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_bgr (pngdec->png); #endif /* Gray scale converted to RGB and upscaled to 8 bits */ if ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) || (color_type == PNG_COLOR_TYPE_GRAY)) { GST_LOG_OBJECT (pngdec, "converting grayscale png to RGB"); png_set_gray_to_rgb (pngdec->png); if (bpc < 8) { /* Convert to 8 bits */ GST_LOG_OBJECT (pngdec, "converting grayscale image to 8 bits"); png_set_gray_1_2_4_to_8 (pngdec->png); } } /* Palette converted to RGB */ if (color_type == PNG_COLOR_TYPE_PALETTE) { GST_LOG_OBJECT (pngdec, "converting palette png to RGB"); png_set_palette_to_rgb (pngdec->png); } /* Update the info structure */ png_read_update_info (pngdec->png, pngdec->info); /* Get IHDR header again after transformation settings */ png_get_IHDR (pngdec->png, pngdec->info, &width, &height, &bpc, &pngdec->color_type, NULL, NULL, NULL); pngdec->width = width; pngdec->height = height; GST_LOG_OBJECT (pngdec, "this is a %dx%d PNG image", pngdec->width, pngdec->height); switch (pngdec->color_type) { case PNG_COLOR_TYPE_RGB: GST_LOG_OBJECT (pngdec, "we have no alpha channel, depth is 24 bits"); pngdec->bpp = 24; break; case PNG_COLOR_TYPE_RGB_ALPHA: GST_LOG_OBJECT (pngdec, "we have an alpha channel, depth is 32 bits"); pngdec->bpp = 32; break; default: GST_ELEMENT_ERROR (pngdec, STREAM, NOT_IMPLEMENTED, (NULL), ("pngdec does not support this color type")); ret = GST_FLOW_NOT_SUPPORTED; goto beach; } caps = gst_caps_new_simple ("video/x-raw-rgb", "width", G_TYPE_INT, pngdec->width, "height", G_TYPE_INT, pngdec->height, "bpp", G_TYPE_INT, pngdec->bpp, "framerate", GST_TYPE_FRACTION, pngdec->fps_n, pngdec->fps_d, NULL); templ = gst_static_pad_template_get (&gst_pngdec_src_pad_template); res = gst_caps_intersect (caps, gst_pad_template_get_caps (templ)); gst_caps_unref (caps); gst_object_unref (templ); if (!gst_pad_set_caps (pngdec->srcpad, res)) ret = GST_FLOW_NOT_NEGOTIATED; GST_DEBUG_OBJECT (pngdec, "our caps %" GST_PTR_FORMAT, res); gst_caps_unref (res); /* Push a newsegment event */ if (pngdec->need_newsegment) { gst_pad_push_event (pngdec->srcpad, gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0)); pngdec->need_newsegment = FALSE; } beach: return ret; }
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_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; }
bool PNGImageFileType::read( Image *OSG_PNG_ARG(pImage ), std::istream &OSG_PNG_ARG(is ), const std::string &OSG_PNG_ARG(mimetype)) { #ifdef OSG_WITH_PNG bool retCode; Image::PixelFormat pixelFormat = OSG::Image::OSG_INVALID_PF; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, wc, height, h, i, res_x, res_y; png_byte bit_depth, channels, color_type; png_bytep *row_pointers, base; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if(!png_ptr) return false; png_set_error_fn(png_ptr, 0, &errorOutput, &warningOutput); info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr, 0, 0); return false; } if(setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, 0); return false; } png_set_read_fn(png_ptr, &is, &isReadFunc); 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); bit_depth = png_get_bit_depth(png_ptr, info_ptr); res_x = png_get_x_pixels_per_meter(png_ptr, info_ptr); res_y = png_get_y_pixels_per_meter(png_ptr, info_ptr); channels = png_get_channels(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); // Convert paletted images to RGB if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); channels = 3; bit_depth = 8; } // Convert < 8 bit to 8 bit if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { png_set_gray_1_2_4_to_8(png_ptr); bit_depth = 8; } #if BYTE_ORDER == LITTLE_ENDIAN if (bit_depth == 16) png_set_swap(png_ptr); #endif // Add a full alpha channel if there is transparency // information in a tRNS chunk if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); ++channels; } Int32 dataType; switch (bit_depth) { case 8: dataType = Image::OSG_UINT8_IMAGEDATA; break; case 16: dataType = Image::OSG_UINT16_IMAGEDATA; break; default: FWARNING (( "Invalid bit_depth: %d, can not read png-data\n", bit_depth )); return false; } switch(channels) { case 1: pixelFormat = Image::OSG_L_PF; break; case 2: pixelFormat = Image::OSG_LA_PF; break; case 3: pixelFormat = Image::OSG_RGB_PF; break; case 4: pixelFormat = Image::OSG_RGBA_PF; break; }; if(pImage->set(pixelFormat, width, height, 1, 1, 1, 0.0, 0, dataType)) { // set resolution png supports only pixel per meter, // so we do a conversion to dpi with some rounding. res_x = png_uint_32((Real32(res_x) / 39.37007874f) < 0.0f ? (Real32(res_x) / 39.37007874f) - 0.5f : (Real32(res_x) / 39.37007874f) + 0.5f); res_y = png_uint_32((Real32(res_y) / 39.37007874f) < 0.0f ? (Real32(res_y) / 39.37007874f) - 0.5f : (Real32(res_y) / 39.37007874f) + 0.5f); pImage->setResX(Real32(res_x)); pImage->setResY(Real32(res_y)); pImage->setResUnit(Image::OSG_RESUNIT_INCH); // Calculate the row pointers row_pointers = new png_bytep[height]; wc = width * channels * (bit_depth / 8); h = height - 1; base = pImage->editData(); for(i = 0; i < height; ++i) row_pointers[i] = base + (h - i) * wc; // Read the image data png_read_image(png_ptr, row_pointers); delete[] row_pointers; retCode = true; } else { retCode = false; } png_destroy_read_struct(&png_ptr, &info_ptr, 0); return retCode; #else SWARNING << getMimeType() << " read is not compiled into the current binary " << std::endl; return false; #endif }
UInt64 PNGImageFileType::restoreData( Image *OSG_PNG_ARG (pImage ), const UChar8 *OSG_PNG_ARG (buffer ), Int32 OSG_CHECK_ARG(memSize)) { #ifdef OSG_WITH_PNG UInt64 retCode; Image::PixelFormat pixelFormat = Image::OSG_INVALID_PF; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, wc, height, h, i; png_byte bit_depth, channels, color_type; png_bytep *row_pointers, base; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if(!png_ptr) { return 0; } png_set_error_fn(png_ptr, 0, &errorOutput, &warningOutput); info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr, 0, 0); return 0; } if(setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, 0); return 0; } BufferInfo bufferInfo; bufferInfo.buffer = const_cast<UChar8 *>(buffer); bufferInfo.length = 0; png_set_read_fn(png_ptr, static_cast<void *>(&bufferInfo), user_read_data); 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); bit_depth = png_get_bit_depth(png_ptr, info_ptr); channels = png_get_channels(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); // Convert paletted images to RGB if(color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); channels = 3; bit_depth = 8; } // Convert < 8 bit to 8 bit if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { png_set_gray_1_2_4_to_8(png_ptr); bit_depth = 8; } #if BYTE_ORDER == LITTLE_ENDIAN if (bit_depth == 16) png_set_swap(png_ptr); #endif // Add a full alpha channel if there is transparency // information in a tRNS chunk if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); ++channels; } Int32 dataType; switch (bit_depth) { case 8: dataType = Image::OSG_UINT8_IMAGEDATA; break; case 16: dataType = Image::OSG_UINT16_IMAGEDATA; break; default: FWARNING (( "Invalid bit_depth: %d, can not read png-data\n", bit_depth )); return false; } switch(channels) { case 1: pixelFormat = Image::OSG_L_PF; break; case 2: pixelFormat = Image::OSG_LA_PF; break; case 3: pixelFormat = Image::OSG_RGB_PF; break; case 4: pixelFormat = Image::OSG_RGBA_PF; break; }; if(pImage->set(pixelFormat, width, height, 1, 1, 1, 0.0, 0, dataType)) { // Calculate the row pointers row_pointers = new png_bytep[height]; wc = width * channels * (bit_depth / 8); h = height - 1; base = pImage->editData(); for(i = 0; i < height; ++i) row_pointers[i] = base + (h - i) * wc; // Read the image data png_read_image(png_ptr, row_pointers); delete[] row_pointers; retCode = bufferInfo.length; } else { retCode = 0; } png_destroy_read_struct(&png_ptr, &info_ptr, 0); return retCode; #else SWARNING << getMimeType() << " restoreData is not compiled into the current binary " << std::endl; return 0; #endif }
static RGBAImagePtr LoadPNGBuff (unsigned char* fbuffer) { png_byte** row_pointers; png_bytep p_fbuffer; p_fbuffer = fbuffer; // the reading glue // http://www.libpng.org/pub/png/libpng-manual.html png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, user_error_fn, user_warning_fn); if (!png_ptr) { rError() << "libpng error: png_create_read_struct\n"; return RGBAImagePtr(); } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); rError() << "libpng error: png_create_info_struct (info_ptr)" << std::endl; return RGBAImagePtr(); } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); rError() << "libpng error: png_create_info_struct (end_info)" << std::endl; return RGBAImagePtr(); } // configure the read function png_set_read_fn(png_ptr, (png_voidp)&p_fbuffer, (png_rw_ptr)&user_read_data); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return RGBAImagePtr(); } png_read_info(png_ptr, info_ptr); int bit_depth = png_get_bit_depth(png_ptr, info_ptr); int color_type = png_get_color_type(png_ptr, info_ptr); // we want to treat all images the same way // The following code transforms grayscale images of less than 8 to 8 bits, // changes paletted images to RGB, and adds a full alpha channel if there is // transparency information in a tRNS chunk. if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { #if PNG_LIBPNG_VER < 10400 png_set_gray_1_2_4_to_8(png_ptr); #else png_set_expand_gray_1_2_4_to_8(png_ptr); #endif } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); } if (!(color_type & PNG_COLOR_MASK_ALPHA)) { // Set the background color to draw transparent and alpha images over. 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); } // Add alpha byte after each RGB triplet png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); } // read the sucker in one chunk png_read_update_info(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); int width = png_get_image_width(png_ptr, info_ptr); int height = png_get_image_height(png_ptr, info_ptr); // allocate the pixel buffer, and the row pointers RGBAImagePtr image(new RGBAImage(width, height)); row_pointers = (png_byte**) malloc((height) * sizeof(png_byte*)); for (int i = 0; i < height; i++) { row_pointers[i] = (png_byte*)(image->getMipMapPixels(0)) + i * 4 * (width); } // actual read png_read_image(png_ptr, row_pointers); /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); /* free up the memory structure */ png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); free(row_pointers); return image; }
/** Our implementation of libPNG callbacks */ void haveInfo() { int bitDepth, colorType, interlaceType; png_get_IHDR(pngReadStruct, pngInfoStruct, &width, &height, &bitDepth, &colorType, &interlaceType, 0, 0); if (!ImageManager::isAcceptableSize(width, height)) { libPngError = true; return; } //Ask libPNG to change bit depths we don't support if (bitDepth < 8) #if PNG_LIBPNG_VER < 10400 png_set_gray_1_2_4_to_8(pngReadStruct); #else png_set_expand_gray_1_2_4_to_8(pngReadStruct); #endif if (bitDepth > 8) png_set_strip_16 (pngReadStruct); //Some images (basically, only paletted ones) may have alpha //included as part of a tRNS chunk. We want to convert that to regular alpha //channel.. bool haveTRNS = false; if (png_get_valid(pngReadStruct, pngInfoStruct, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(pngReadStruct); haveTRNS = true; if (colorType == PNG_COLOR_TYPE_RGB) colorType = PNG_COLOR_TYPE_RGB_ALPHA; //Paranoia.. else if (colorType == PNG_COLOR_TYPE_GRAY) colorType = PNG_COLOR_TYPE_GRAY_ALPHA; } ImageFormat imFrm; //Prepare for mapping from colorType to our format descriptors. switch (colorType) { case PNG_COLOR_TYPE_GRAY: imFrm.greyscaleSetup(); break; case PNG_COLOR_TYPE_GRAY_ALPHA: //We don't natively support 8-bit plus alpha, so ask libPNG to expand it out to RGB png_set_gray_to_rgb(pngReadStruct); imFrm.type = ImageFormat::Image_ARGB_32; break; case PNG_COLOR_TYPE_PALETTE: //For now, we handle paletted images as RGB or ARGB //### TODO: handle non-alpha paletted images with a sufficiently small palette as //paletted imFrm.type = haveTRNS ? ImageFormat::Image_ARGB_32 : ImageFormat::Image_RGB_32; png_set_palette_to_rgb(pngReadStruct); break; case PNG_COLOR_TYPE_RGB: imFrm.type = ImageFormat::Image_RGB_32; break; case PNG_COLOR_TYPE_RGB_ALPHA: imFrm.type = ImageFormat::Image_ARGB_32; break; default: //Huh? libPngError = true; return; } //Configure padding/byte swapping if need be (32-bit images) //We want a 32-bit value with ARGB. //This means that for little-endian, in memory we should have BGRA, //and for big-endian, well, ARGB if (imFrm.type == ImageFormat::Image_RGB_32) { //Need fillers, plus perhaps BGR swapping for non-alpha #if Q_BYTE_ORDER == Q_BIG_ENDIAN || defined(__BIG_ENDIAN__) png_set_filler(pngReadStruct, 0xff, PNG_FILLER_BEFORE); #else png_set_filler(pngReadStruct, 0xff, PNG_FILLER_AFTER); png_set_bgr (pngReadStruct); #endif } else if (imFrm.type == ImageFormat::Image_ARGB_32) { #if Q_BYTE_ORDER == Q_BIG_ENDIAN || defined(__BIG_ENDIAN__) png_set_swap_alpha(pngReadStruct); //ARGB, not RGBA #else png_set_bgr (pngReadStruct); //BGRA #endif } //Remember depth, for our own use depth = imFrm.depth(); //handle interlacing if (interlaceType != PNG_INTERLACE_NONE) { interlaced = true; scanlineBuf = new unsigned char[depth * width]; png_set_interlace_handling(pngReadStruct); // Give up on premultiply in this case.. if (imFrm.type == ImageFormat::Image_ARGB_32) imFrm.type = ImageFormat::Image_ARGB_32_DontPremult; } notifySingleFrameImage(width, height, imFrm); //OK, time to start input png_read_update_info(pngReadStruct, pngInfoStruct); }
Bool readPng (const char *filename, char **data, unsigned int *width, unsigned int *height) { static const int PNG_SIG_SIZE = 8; unsigned char png_sig[PNG_SIG_SIZE]; FILE *file; int sig_bytes; png_struct *png; png_info *info; png_uint_32 png_width, png_height; int depth, color_type, interlace, i; unsigned int pixel_size; png_byte **row_pointers; file = fopen (filename, "r"); if (!file) { char *home, *imagedir; home = getenv ("HOME"); if (home) { imagedir = malloc (strlen (home) + strlen (HOME_IMAGEDIR) + strlen (filename) + 3); if (imagedir) { sprintf (imagedir, "%s/%s/%s", home, HOME_IMAGEDIR, filename); file = fopen (imagedir, "r"); free (imagedir); } } if (!file) { imagedir = malloc (strlen (IMAGEDIR) + strlen (filename) + 2); if (imagedir) { sprintf (imagedir, "%s/%s", IMAGEDIR, filename); file = fopen (imagedir, "r"); free (imagedir); } if (!file) return FALSE; } } sig_bytes = fread (png_sig, 1, PNG_SIG_SIZE, file); if (png_check_sig (png_sig, sig_bytes) == 0) { fclose (file); return FALSE; } png = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { fclose (file); return FALSE; } info = png_create_info_struct (png); if (info == NULL) { fclose (file); png_destroy_read_struct (&png, NULL, NULL); return FALSE; } png_init_io (png, file); png_set_sig_bytes (png, sig_bytes); png_read_info (png, info); png_get_IHDR (png, info, &png_width, &png_height, &depth, &color_type, &interlace, NULL, NULL); *width = png_width; *height = png_height; /* convert palette/gray image to rgb */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb (png); /* expand gray bit depth if needed */ if (color_type == PNG_COLOR_TYPE_GRAY && depth < 8) png_set_gray_1_2_4_to_8 (png); /* transform transparency to alpha */ if (png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png); if (depth == 16) png_set_strip_16 (png); if (depth < 8) png_set_packing (png); /* convert grayscale to RGB */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb (png); if (interlace != PNG_INTERLACE_NONE) png_set_interlace_handling (png); png_set_bgr (png); png_set_filler (png, 0xff, PNG_FILLER_AFTER); png_set_read_user_transform_fn (png, premultiplyData); png_read_update_info (png, info); pixel_size = 4; *data = (char *) malloc (png_width * png_height * pixel_size); if (*data == NULL) { fclose (file); return FALSE; } row_pointers = (png_byte **) malloc (png_height * sizeof (char *)); for (i=0; i < png_height; i++) row_pointers[i] = (png_byte *) (*data + i * png_width * pixel_size); png_read_image (png, row_pointers); png_read_end (png, info); free (row_pointers); fclose (file); png_destroy_read_struct (&png, &info, NULL); return TRUE; }
// load in the image data IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const { #ifdef _IRR_COMPILE_WITH_LIBPNG_ if (!file) return 0; video::IImage* image = 0; //Used to point to image rows u8** RowPointers = 0; png_byte buffer[8]; // Read the first few bytes of the PNG file if( file->read(buffer, 8) != 8 ) { os::Printer::log("LOAD PNG: can't read file\n", file->getFileName(), ELL_ERROR); return 0; } // Check if it really is a PNG file if( png_sig_cmp(buffer, 0, 8) ) { os::Printer::log("LOAD PNG: not really a png\n", file->getFileName(), ELL_ERROR); return 0; } // Allocate the png read struct png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)png_cpexcept_error, NULL); if (!png_ptr) { os::Printer::log("LOAD PNG: Internal PNG create read struct failure\n", file->getFileName(), ELL_ERROR); return 0; } // Allocate the png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { os::Printer::log("LOAD PNG: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR); png_destroy_read_struct(&png_ptr, NULL, NULL); return 0; } // for proper error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (RowPointers) delete [] RowPointers; return 0; } // changed by zola so we don't need to have public FILE pointers png_set_read_fn(png_ptr, file, user_read_data_fcn); png_set_sig_bytes(png_ptr, 8); // Tell png that we read the signature png_read_info(png_ptr, info_ptr); // Read the info section of the png file u32 Width; u32 Height; s32 BitDepth; s32 ColorType; { // Use temporary variables to avoid passing casted pointers png_uint_32 w,h; // Extract info png_get_IHDR(png_ptr, info_ptr, &w, &h, &BitDepth, &ColorType, NULL, NULL, NULL); Width=w; Height=h; } // Convert palette color to true color if (ColorType==PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); // Convert low bit colors to 8 bit colors if (BitDepth < 8) { if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA) #if (PNG_LIBPNG_VER_MAJOR > 1) || (PNG_LIBPNG_VER_MINOR > 3) png_set_expand_gray_1_2_4_to_8(png_ptr); #else png_set_gray_1_2_4_to_8(png_ptr); #endif else png_set_packing(png_ptr); }
bool SkPNGImageDecoder::onDecodeInit(SkStream* sk_stream, png_structp *png_ptrp, png_infop *info_ptrp) { /* 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. */ png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, sk_error_fn, NULL); // png_voidp user_error_ptr, user_error_fn, user_warning_fn); if (png_ptr == NULL) { return false; } *png_ptrp = png_ptr; /* Allocate/initialize the memory for image information. */ png_infop info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); return false; } *info_ptrp = info_ptr; /* 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))) { return false; } /* If you are using replacement read functions, instead of calling * png_init_io() here you would call: */ png_set_read_fn(png_ptr, (void *)sk_stream, sk_read_fn); png_set_seek_fn(png_ptr, sk_seek_fn); /* where user_io_ptr is a structure you want available to the callbacks */ /* If we have already read some of the signature */ // png_set_sig_bytes(png_ptr, 0 /* sig_read */ ); // hookup our peeker so we can see any user-chunks the caller may be interested in png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"", 0); if (this->getPeeker()) { png_set_read_user_chunk_fn(png_ptr, (png_voidp)this->getPeeker(), sk_read_user_chunk); } /* 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); png_uint_32 origWidth, origHeight; int bit_depth, color_type, interlace_type; png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL); /* tell libpng to strip 16 bit/color files down to 8 bits/color */ if (bit_depth == 16) { 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). */ if (bit_depth < 8) { png_set_packing(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); } /* Make a grayscale image into RGB. */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); } return true; }
/* 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; }
static Bool readPngData (png_struct *png, png_info *info, void **data, int *width, int *height) { png_uint_32 png_width, png_height; int depth, color_type, interlace, i; unsigned int pixel_size; png_byte **row_pointers; char *d; png_read_info (png, info); png_get_IHDR (png, info, &png_width, &png_height, &depth, &color_type, &interlace, NULL, NULL); *width = (int) png_width; *height = (int) png_height; /* convert palette/gray image to rgb */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb (png); /* expand gray bit depth if needed */ if (color_type == PNG_COLOR_TYPE_GRAY && depth < 8) png_set_gray_1_2_4_to_8 (png); /* transform transparency to alpha */ if (png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png); if (depth == 16) png_set_strip_16 (png); if (depth < 8) png_set_packing (png); /* convert grayscale to RGB */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb (png); if (interlace != PNG_INTERLACE_NONE) png_set_interlace_handling (png); png_set_bgr (png); png_set_filler (png, 0xff, PNG_FILLER_AFTER); png_set_read_user_transform_fn (png, premultiplyData); png_read_update_info (png, info); pixel_size = 4; d = (char *) malloc (png_width * png_height * pixel_size); if (!d) return FALSE; *data = d; row_pointers = (png_byte **) malloc (png_height * sizeof (char *)); if (!row_pointers) { free (d); return FALSE; } for (i = 0; i < png_height; i++) row_pointers[i] = (png_byte *) (d + i * png_width * pixel_size); png_read_image (png, row_pointers); png_read_end (png, info); free (row_pointers); return TRUE; }
/* 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_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)
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; }
void png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) { png_set_gray_1_2_4_to_8(png_ptr); }
static GstFlowReturn gst_pngdec_caps_create_and_set (GstPngDec * pngdec) { GstFlowReturn ret = GST_FLOW_OK; gint bpc = 0, color_type; png_uint_32 width, height; GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN; g_return_val_if_fail (GST_IS_PNGDEC (pngdec), GST_FLOW_ERROR); /* Get bits per channel */ bpc = png_get_bit_depth (pngdec->png, pngdec->info); /* Get Color type */ color_type = png_get_color_type (pngdec->png, pngdec->info); /* Add alpha channel if 16-bit depth, but not for GRAY images */ if ((bpc > 8) && (color_type != PNG_COLOR_TYPE_GRAY)) { png_set_add_alpha (pngdec->png, 0xffff, PNG_FILLER_BEFORE); png_set_swap (pngdec->png); } #if 0 /* We used to have this HACK to reverse the outgoing bytes, but the problem * that originally required the hack seems to have been in videoconvert's * RGBA descriptions. It doesn't seem needed now that's fixed, but might * still be needed on big-endian systems, I'm not sure. J.S. 6/7/2007 */ if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_bgr (pngdec->png); #endif /* Gray scale with alpha channel converted to RGB */ if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { GST_LOG_OBJECT (pngdec, "converting grayscale png with alpha channel to RGB"); png_set_gray_to_rgb (pngdec->png); } /* Gray scale converted to upscaled to 8 bits */ if ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) || (color_type == PNG_COLOR_TYPE_GRAY)) { if (bpc < 8) { /* Convert to 8 bits */ GST_LOG_OBJECT (pngdec, "converting grayscale image to 8 bits"); #if PNG_LIBPNG_VER < 10400 png_set_gray_1_2_4_to_8 (pngdec->png); #else png_set_expand_gray_1_2_4_to_8 (pngdec->png); #endif } } /* Palette converted to RGB */ if (color_type == PNG_COLOR_TYPE_PALETTE) { GST_LOG_OBJECT (pngdec, "converting palette png to RGB"); png_set_palette_to_rgb (pngdec->png); } png_set_interlace_handling (pngdec->png); /* Update the info structure */ png_read_update_info (pngdec->png, pngdec->info); /* Get IHDR header again after transformation settings */ png_get_IHDR (pngdec->png, pngdec->info, &width, &height, &bpc, &pngdec->color_type, NULL, NULL, NULL); GST_LOG_OBJECT (pngdec, "this is a %dx%d PNG image", (gint) width, (gint) height); switch (pngdec->color_type) { case PNG_COLOR_TYPE_RGB: GST_LOG_OBJECT (pngdec, "we have no alpha channel, depth is 24 bits"); if (bpc == 8) format = GST_VIDEO_FORMAT_RGB; break; case PNG_COLOR_TYPE_RGB_ALPHA: GST_LOG_OBJECT (pngdec, "we have an alpha channel, depth is 32 or 64 bits"); if (bpc == 8) format = GST_VIDEO_FORMAT_RGBA; else if (bpc == 16) format = GST_VIDEO_FORMAT_ARGB64; break; case PNG_COLOR_TYPE_GRAY: GST_LOG_OBJECT (pngdec, "We have an gray image, depth is 8 or 16 (be) bits"); if (bpc == 8) format = GST_VIDEO_FORMAT_GRAY8; else if (bpc == 16) format = GST_VIDEO_FORMAT_GRAY16_BE; break; default: break; } if (format == GST_VIDEO_FORMAT_UNKNOWN) { GST_ELEMENT_ERROR (pngdec, STREAM, NOT_IMPLEMENTED, (NULL), ("pngdec does not support this color type")); ret = GST_FLOW_NOT_SUPPORTED; goto beach; } /* Check if output state changed */ if (pngdec->output_state) { GstVideoInfo *info = &pngdec->output_state->info; if (width == GST_VIDEO_INFO_WIDTH (info) && height == GST_VIDEO_INFO_HEIGHT (info) && GST_VIDEO_INFO_FORMAT (info) == format) { goto beach; } gst_video_codec_state_unref (pngdec->output_state); } pngdec->output_state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (pngdec), format, width, height, pngdec->input_state); gst_video_decoder_negotiate (GST_VIDEO_DECODER (pngdec)); GST_DEBUG ("Final %d %d", GST_VIDEO_INFO_WIDTH (&pngdec->output_state->info), GST_VIDEO_INFO_HEIGHT (&pngdec->output_state->info)); beach: return ret; }
Load_SBit_Png( FT_GlyphSlot slot, FT_Int x_offset, FT_Int y_offset, FT_Int pix_bits, TT_SBit_Metrics metrics, FT_Memory memory, FT_Byte* data, FT_UInt png_len, FT_Bool populate_map_and_metrics ) { FT_Bitmap *map = &slot->bitmap; FT_Error error = FT_Err_Ok; FT_StreamRec stream; png_structp png; png_infop info; png_uint_32 imgWidth, imgHeight; int bitdepth, color_type, interlace; FT_Int i; png_byte* *rows = NULL; /* pacify compiler */ if ( x_offset < 0 || y_offset < 0 ) { error = FT_THROW( Invalid_Argument ); goto Exit; } if ( !populate_map_and_metrics && ( x_offset + metrics->width > map->width || y_offset + metrics->height > map->rows || pix_bits != 32 || map->pixel_mode != FT_PIXEL_MODE_BGRA ) ) { error = FT_THROW( Invalid_Argument ); goto Exit; } FT_Stream_OpenMemory( &stream, data, png_len ); png = png_create_read_struct( PNG_LIBPNG_VER_STRING, &error, error_callback, warning_callback ); if ( !png ) { error = FT_THROW( Out_Of_Memory ); goto Exit; } info = png_create_info_struct( png ); if ( !info ) { error = FT_THROW( Out_Of_Memory ); png_destroy_read_struct( &png, NULL, NULL ); goto Exit; } if ( ft_setjmp( png_jmpbuf( png ) ) ) { error = FT_THROW( Invalid_File_Format ); goto DestroyExit; } png_set_read_fn( png, &stream, read_data_from_FT_Stream ); png_read_info( png, info ); png_get_IHDR( png, info, &imgWidth, &imgHeight, &bitdepth, &color_type, &interlace, NULL, NULL ); if ( error || ( !populate_map_and_metrics && ( (FT_Int)imgWidth != metrics->width || (FT_Int)imgHeight != metrics->height ) ) ) goto DestroyExit; if ( populate_map_and_metrics ) { FT_Long size; metrics->width = (FT_Int)imgWidth; metrics->height = (FT_Int)imgHeight; map->width = metrics->width; map->rows = metrics->height; map->pixel_mode = FT_PIXEL_MODE_BGRA; map->pitch = map->width * 4; map->num_grays = 256; size = map->rows * map->pitch; error = ft_glyphslot_alloc_bitmap( slot, size ); if ( error ) goto DestroyExit; } /* convert palette/gray image to rgb */ if ( color_type == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb( png ); /* expand gray bit depth if needed */ if ( color_type == PNG_COLOR_TYPE_GRAY ) { #if PNG_LIBPNG_VER >= 10209 png_set_expand_gray_1_2_4_to_8( png ); #else png_set_gray_1_2_4_to_8( png ); #endif } /* transform transparency to alpha */ if ( png_get_valid(png, info, PNG_INFO_tRNS ) ) png_set_tRNS_to_alpha( png ); if ( bitdepth == 16 ) png_set_strip_16( png ); if ( bitdepth < 8 ) png_set_packing( png ); /* convert grayscale to RGB */ if ( color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) png_set_gray_to_rgb( png ); if ( interlace != PNG_INTERLACE_NONE ) png_set_interlace_handling( png ); png_set_filler( png, 0xFF, PNG_FILLER_AFTER ); /* recheck header after setting EXPAND options */ png_read_update_info(png, info ); png_get_IHDR( png, info, &imgWidth, &imgHeight, &bitdepth, &color_type, &interlace, NULL, NULL ); if ( bitdepth != 8 || !( color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA ) ) { error = FT_THROW( Invalid_File_Format ); goto DestroyExit; } switch ( color_type ) { default: /* Shouldn't happen, but fall through. */ case PNG_COLOR_TYPE_RGB_ALPHA: png_set_read_user_transform_fn( png, premultiply_data ); break; case PNG_COLOR_TYPE_RGB: /* Humm, this smells. Carry on though. */ png_set_read_user_transform_fn( png, convert_bytes_to_data ); break; } if ( FT_NEW_ARRAY( rows, imgHeight ) ) { error = FT_THROW( Out_Of_Memory ); goto DestroyExit; } for ( i = 0; i < (FT_Int)imgHeight; i++ ) rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4; png_read_image( png, rows ); FT_FREE( rows ); png_read_end( png, info ); DestroyExit: png_destroy_read_struct( &png, &info, NULL ); FT_Stream_Close( &stream ); Exit: return error; }
MMBitmapRef newMMBitmapFromPNG(const char *path, MMPNGReadError *err) { FILE *fp; uint8_t header[8]; png_struct *png_ptr = NULL; png_info *info_ptr = NULL; png_byte bit_depth, color_type; uint8_t *row, *bitmapData; uint8_t bytesPerPixel; png_uint_32 width, height, y; uint32_t bytewidth; if ((fp = fopen(path, "rb")) == NULL) { if (err != NULL) *err = kPNGAccessError; return NULL; } /* Initialize error code to generic value. */ if (err != NULL) *err = kPNGGenericError; /* Validate the PNG. */ if (fread(header, 1, sizeof header, fp) == 0) { if (err != NULL) *err = kPNGReadError; goto bail; } else if (!png_check_sig(header, sizeof(header))) { if (err != NULL) *err = kPNGInvalidHeaderError; goto bail; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) goto bail; info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) goto bail; /* Set up error handling. */ if (setjmp(png_jmpbuf(png_ptr))) { goto bail; } png_init_io(png_ptr, fp); /* Skip past the header. */ png_set_sig_bytes(png_ptr, sizeof header); png_read_info(png_ptr, info_ptr); /* Convert different image types to common type to be read. */ bit_depth = png_get_bit_depth(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); /* Convert color palettes to RGB. */ if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); } /* Convert PNG to bit depth of 8. */ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { #ifdef PNG_LIBPNG_VER_SONUM #if PNG_LIBPNG_VER_SONUM >= 14 png_set_expand_gray_1_2_4_to_8(png_ptr); #else png_set_gray_1_2_4_to_8(png_ptr); #endif #else png_set_gray_1_2_4_to_8(png_ptr); #endif } else if (bit_depth == 16) { png_set_strip_16(png_ptr); } /* Convert transparency chunk to alpha channel. */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); } /* Convert gray images to RGB. */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); } /* Ignore alpha for now. */ if (color_type & PNG_COLOR_MASK_ALPHA) { png_set_strip_alpha(png_ptr); } /* Get image attributes. */ width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); bytesPerPixel = 3; /* All images decompress to this size. */ bytewidth = ADD_PADDING(width * bytesPerPixel); /* Align width. */ /* Decompress the PNG row by row. */ bitmapData = calloc(1, bytewidth * height); row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); if (bitmapData == NULL || row == NULL) goto bail; for (y = 0; y < height; ++y) { png_uint_32 x; const uint32_t rowOffset = y * bytewidth; uint8_t *rowptr = row; png_read_row(png_ptr, (png_byte *)row, NULL); for (x = 0; x < width; ++x) { const uint32_t colOffset = x * bytesPerPixel; MMRGBColor *color = (MMRGBColor *)(bitmapData + rowOffset + colOffset); color->red = *rowptr++; color->green = *rowptr++; color->blue = *rowptr++; } } free(row); /* Finish reading. */ png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return createMMBitmap(bitmapData, width, height, bytewidth, bytesPerPixel * 8, bytesPerPixel); bail: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return NULL; }
static struct gl_texture_t *ReadPNGFromFile (const char *filename) { struct gl_texture_t *texinfo; png_byte magic[8]; png_structp png_ptr; png_infop info_ptr; int bit_depth, color_type; FILE *fp = NULL; png_bytep *row_pointers = NULL; png_uint_32 w, h; int i; /* Open image file */ fp = fopen (filename, "rb"); if (!fp) { fprintf (stderr, "error: couldn't open \"%s\"!\n", filename); return NULL; } /* Read magic number */ fread (magic, 1, sizeof (magic), fp); /* Check for valid magic number */ if (!png_check_sig (magic, sizeof (magic))) { fprintf (stderr, "error: \"%s\" is not a valid PNG image!\n", filename); fclose (fp); return NULL; } /* Create a png read struct */ png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fclose (fp); return NULL; } /* Create a png info struct */ info_ptr = png_create_info_struct (png_ptr); if (!info_ptr) { fclose (fp); png_destroy_read_struct (&png_ptr, NULL, NULL); return NULL; } /* Create our OpenGL texture object */ texinfo = (struct gl_texture_t *) malloc (sizeof (struct gl_texture_t)); /* Initialize the setjmp for returning properly after a libpng error occured */ if (setjmp (png_jmpbuf (png_ptr))) { fclose (fp); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); if (row_pointers) free (row_pointers); if (texinfo) { if (texinfo->texels) free (texinfo->texels); free (texinfo); } return NULL; } /* Setup libpng for using standard C fread() function with our FILE pointer */ png_init_io (png_ptr, fp); /* Tell libpng that we have already read the magic number */ png_set_sig_bytes (png_ptr, sizeof (magic)); /* Read png info */ png_read_info (png_ptr, info_ptr); /* Get some usefull information from header */ bit_depth = png_get_bit_depth (png_ptr, info_ptr); color_type = png_get_color_type (png_ptr, info_ptr); /* Convert index color images to RGB images */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb (png_ptr); /* Convert 1-2-4 bits grayscale images to 8 bits grayscale. */ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8 (png_ptr); if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png_ptr); if (bit_depth == 16) png_set_strip_16 (png_ptr); else if (bit_depth < 8) png_set_packing (png_ptr); /* Update info structure to apply transformations */ png_read_update_info (png_ptr, info_ptr); /* Retrieve updated information */ png_get_IHDR (png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, NULL, NULL, NULL); texinfo->width = w; texinfo->height = h; /* Get image format and components per pixel */ GetPNGtextureInfo (color_type, texinfo); /* We can now allocate memory for storing pixel data */ texinfo->texels = (GLubyte *)malloc (sizeof (GLubyte) * texinfo->width * texinfo->height * texinfo->internalFormat); /* Setup a pointer array. Each one points at the begening of a row. */ row_pointers = (png_bytep *)malloc (sizeof (png_bytep) * texinfo->height); for (i = 0; i < texinfo->height; ++i) { row_pointers[i] = (png_bytep)(texinfo->texels + ((texinfo->height - (i + 1)) * texinfo->width * texinfo->internalFormat)); } /* Read pixel data using row pointers */ png_read_image (png_ptr, row_pointers); /* Finish decompression and release memory */ png_read_end (png_ptr, NULL); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); /* We don't need row pointers anymore */ free (row_pointers); fclose (fp); return texinfo; }
gavl_video_frame_t * read_png(const char * filename, gavl_video_format_t * format, gavl_pixelformat_t pixelformat) { int i; unsigned char ** rows; gavl_video_converter_t * cnv; gavl_video_options_t * opt; gavl_video_format_t format_1; gavl_video_frame_t * frame, * frame_1; int bit_depth; int color_type; int has_alpha = 0; png_structp png_ptr; png_infop info_ptr; png_infop end_info; FILE * file; file = fopen(filename, "rb"); if(!file) { fprintf(stderr, "Cannot open file %s\n", filename); return NULL; } png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); setjmp(png_jmpbuf(png_ptr)); info_ptr = png_create_info_struct(png_ptr); end_info = png_create_info_struct(png_ptr); png_init_io(png_ptr, file); png_read_info(png_ptr, info_ptr); format->frame_width = png_get_image_width(png_ptr, info_ptr); format->frame_height = png_get_image_height(png_ptr, info_ptr); format->image_width = format->frame_width; format->image_height = format->frame_height; format->pixel_width = 1; format->pixel_height = 1; 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: /* (bit depths 1, 2, 4, 8, 16) */ if(bit_depth < 8) #if GAVL_MAKE_BUILD(PNG_LIBPNG_VER_MAJOR, PNG_LIBPNG_VER_MINOR, PNG_LIBPNG_VER_RELEASE) < GAVL_MAKE_BUILD(1,2,9) png_set_gray_1_2_4_to_8(png_ptr); #else png_set_expand_gray_1_2_4_to_8(png_ptr); #endif if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); has_alpha = 1; } png_set_gray_to_rgb(png_ptr); break; case PNG_COLOR_TYPE_GRAY_ALPHA: /* (bit depths 8, 16) */ if(bit_depth == 16) png_set_strip_16(png_ptr); png_set_gray_to_rgb(png_ptr); break; case PNG_COLOR_TYPE_PALETTE: /* (bit depths 1, 2, 4, 8) */ png_set_palette_to_rgb(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); has_alpha = 1; } break; case PNG_COLOR_TYPE_RGB: /* (bit_depths 8, 16) */ if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); has_alpha = 1; } if(bit_depth == 16) png_set_strip_16(png_ptr); break; case PNG_COLOR_TYPE_RGB_ALPHA: /* (bit_depths 8, 16) */ if(bit_depth == 16) png_set_strip_16(png_ptr); has_alpha = 1; break; } if(has_alpha) format->pixelformat = GAVL_RGBA_32; else format->pixelformat = GAVL_RGB_24; frame = gavl_video_frame_create(format); rows = malloc(format->frame_height * sizeof(*rows)); for(i = 0; i < format->frame_height; i++) rows[i] = frame->planes[0] + i * frame->strides[0]; png_read_image(png_ptr, rows); png_read_end(png_ptr, end_info); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(file); free(rows); /* Check wether to set up the converter */ if(format->pixelformat != pixelformat) { cnv = gavl_video_converter_create(); opt = gavl_video_converter_get_options(cnv); gavl_video_options_set_alpha_mode(opt, GAVL_ALPHA_BLEND_COLOR); gavl_video_format_copy(&format_1, format); format_1.pixelformat = pixelformat; frame_1 = gavl_video_frame_create(&format_1); gavl_video_converter_init(cnv, format, &format_1); gavl_video_convert(cnv, frame, frame_1); gavl_video_converter_destroy(cnv); format->pixelformat = pixelformat; } else frame_1 = NULL; if(frame_1) { gavl_video_frame_destroy(frame); return frame_1; } else return frame; }
bool CGLImageData::LoadPNG(const char * filename) { FILE *png_file = fopen(filename, "rb"); if (png_file == NULL) { sLog(DEFAULT_LOG_NAME, LOG_WARNING_EV, "Can't Load PNG file: \"%s\" can't open or doesn't exist", filename); return false; } BYTE header[PNG_SIG_BYTES]; fread(header, 1, PNG_SIG_BYTES, png_file); if (png_sig_cmp(header, 0, PNG_SIG_BYTES)) { sLog(DEFAULT_LOG_NAME, LOG_WARNING_EV, "Can't load PNG file: \"%s\" is not a PNG file.", filename); return false; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_infop info_ptr = png_create_info_struct(png_ptr); png_infop end_info = png_create_info_struct(png_ptr); if(setjmp(png_jmpbuf(png_ptr))) { sLog(DEFAULT_LOG_NAME, LOG_WARNING_EV, "Can't load PNG file: \"%s\". Some error occured.", filename); return false; } png_init_io(png_ptr, png_file); png_set_sig_bytes(png_ptr, PNG_SIG_BYTES); 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_uint_32 bit_depth, color_type; bit_depth = png_get_bit_depth(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); if(color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); else if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); else png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); png_read_update_info(png_ptr, info_ptr); png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr); png_uint_32 numbytes = rowbytes*(height); png_byte* pixels = (png_byte *)malloc(numbytes); png_byte** row_ptrs = (png_byte **)malloc((height) * sizeof(png_byte*)); for (UINT i=0; i<(height); i++) row_ptrs[i] = pixels + ((height) - 1 - i)*rowbytes; png_read_image(png_ptr, row_ptrs); free(row_ptrs); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(png_file); data = pixels; sLog(DEFAULT_LOG_NAME, LOG_INFO_EV, "PNG image \"%s\" loaded", filename); return true; }
t_image *img_read_png(const char *filename) { FILE *file ; png_byte magic[8]; file = fopen(filename,"rb"); if (!file) { printf("couldn't read %s\n",filename); return NULL; } size_t r = fread(magic,1,sizeof(magic),file); if(r != sizeof(magic)) printf("read error\n"); if (!png_check_sig(magic,sizeof(magic))) { printf("no magic\n"); return NULL; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); if (!png_ptr) { fclose(file); return NULL; } png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { fclose(file); png_destroy_read_struct(&png_ptr,NULL,NULL); return NULL; } png_init_io(png_ptr,file); png_set_sig_bytes(png_ptr,sizeof(magic)); png_read_info(png_ptr,info_ptr); int bit_depth,color_type; bit_depth = png_get_bit_depth(png_ptr,info_ptr); 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 && bit_depth < 8) png_set_gray_1_2_4_to_8 (png_ptr); if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png_ptr); if (bit_depth == 16) png_set_strip_16 (png_ptr); else if (bit_depth < 8) png_set_packing (png_ptr); png_read_update_info(png_ptr,info_ptr); png_uint_32 w, h; png_get_IHDR (png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, NULL, NULL, NULL); char name_raw[_NAME_]; image_get_filename( filename, name_raw); t_image *image = image_new( name_raw); image->width=w; image->height=h; image->file_type = IMG_PNG; image->data_type = IMG_BYTE; switch (color_type) { case PNG_COLOR_TYPE_GRAY: image->color_type = IMG_GRAYSCALE; image->alpha = 0; image->bpp = 1; break; case PNG_COLOR_TYPE_GRAY_ALPHA: image->color_type = IMG_GRAYSCALE; image->alpha = 1; image->bpp = 2; break; case PNG_COLOR_TYPE_RGB: image->color_type = IMG_RGB; image->alpha = 0; image->bpp = 3; break; case PNG_COLOR_TYPE_RGB_ALPHA: image->color_type = IMG_RGB; image->alpha = 1; image->bpp = 4; break; default: break; } image->vlst = vlst_make( "vlst", dt_uchar, image->width * image->height, image->bpp, NULL); png_bytep *row_pointers; row_pointers = (png_bytep *)mem_malloc (sizeof (png_bytep) * image->height); int i; for (i = 0; i < image->height; ++i) { row_pointers[i] = (png_bytep)(image->vlst->data + ((image->height - (i + 1)) * image->width * image->bpp)); } png_read_image (png_ptr, row_pointers); free (row_pointers); png_read_end (png_ptr, NULL); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); fclose (file); return image; }