unsigned char * ReadPNG( FILE *fp,
                         unsigned int &sizeX,
                         unsigned int &sizeY,
                         int &img_depth,
                         int &img_color_type,
                         unsigned char ***row_pointer_ptr )
{
    png_structp png_ptr;
    png_bytepp  row_pointers;
    png_infop   info_ptr;
    int interlace_type;

    png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr) png_cexcept_error, (png_error_ptr) NULL );
    if (png_ptr == NULL) {
        exit( 1 );
        return NULL;
    }
    info_ptr = png_create_info_struct( png_ptr );
    if (info_ptr == NULL) {
        png_destroy_read_struct( &png_ptr, (png_infopp) NULL, (png_infopp) NULL );
        fprintf( stderr, "VSImage ERROR : PNG info_ptr == NULL !!!\n" );
        exit( 1 );
        return NULL;
    }
    if ( setjmp( png_jmpbuf( png_ptr ) ) ) {
        /* Free all of the memory associated with the png_ptr and info_ptr */
        png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
        /* If we get here, we had a problem reading the file */
        exit( 1 );
        return NULL;
    }
    png_init_io( png_ptr, fp );

    //png_set_sig_bytes(png_ptr, 8);
    png_read_info( png_ptr, info_ptr );     /* read all PNG info up to image data */
    png_get_IHDR( png_ptr,
                  info_ptr,
                  (png_uint_32*) &sizeX,
                  (png_uint_32*) &sizeY,
                  &img_depth,
                  &img_color_type,
                  &interlace_type,
                  NULL,
                  NULL );

# if __BYTE_ORDER != __BIG_ENDIAN
    if (img_depth == 16)
        png_set_swap( png_ptr );
#endif
    if (img_depth == 16)      //for now
        png_set_strip_16( png_ptr );
    if (img_color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb( png_ptr );
    if (img_color_type == PNG_COLOR_TYPE_GRAY && img_depth < 8)
        png_set_expand_gray_1_2_4_to_8( png_ptr );
    png_set_expand( png_ptr );
    png_read_update_info( png_ptr, info_ptr );
    png_get_IHDR( png_ptr,
                  info_ptr,
                  (png_uint_32*) &sizeX,
                  (png_uint_32*) &sizeY,
                  &img_depth,
                  &img_color_type,
                  &interlace_type,
                  NULL,
                  NULL );
    row_pointers = (unsigned char**) malloc( sizeof (unsigned char*)*sizeY );
    int numchan = 1;
    if (img_color_type&PNG_COLOR_MASK_COLOR)
        numchan = 3;
    if (img_color_type&PNG_COLOR_MASK_PALETTE)
        numchan = 1;
    if (img_color_type&PNG_COLOR_MASK_ALPHA)
        numchan++;
    unsigned long  stride = numchan*sizeof (unsigned char)*img_depth/8;
    unsigned char *image  = (unsigned char*) malloc( stride*sizeX*sizeY );
    for (unsigned int i = 0; i < sizeY; i++)
        row_pointers[i] = &image[i*stride*sizeX];
    png_read_image( png_ptr, row_pointers );
    unsigned char *result;
    result = image;
    //free (row_pointers);
    *row_pointer_ptr = row_pointers;
    png_read_end( png_ptr, info_ptr );
    png_destroy_read_struct( &png_ptr, &info_ptr, NULL );

    return result;
}
Beispiel #2
0
Error ImageLoaderPNG::_load_image(void *rf_up, png_rw_ptr p_func, Ref<Image> p_image) {

	png_structp png;
	png_infop info;

	//png = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);

	png = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, _png_error_function, _png_warn_function, (png_voidp)NULL,
			_png_malloc_fn, _png_free_fn);

	ERR_FAIL_COND_V(!png, ERR_OUT_OF_MEMORY);

	info = png_create_info_struct(png);
	if (!info) {
		png_destroy_read_struct(&png, NULL, NULL);
		ERR_PRINT("Out of Memory");
		return ERR_OUT_OF_MEMORY;
	}

	if (setjmp(png_jmpbuf(png))) {

		png_destroy_read_struct(&png, NULL, NULL);
		ERR_PRINT("PNG Corrupted");
		return ERR_FILE_CORRUPT;
	}

	png_set_read_fn(png, (void *)rf_up, p_func);

	png_uint_32 width, height;
	int depth, color;

	png_read_info(png, info);
	png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);

	//https://svn.gov.pt/projects/ccidadao/repository/middleware-offline/trunk/_src/eidmw/FreeImagePTEiD/Source/FreeImage/PluginPNG.cpp
	//png_get_text(png,info,)
	/*
	printf("Image width:%i\n", width);
	printf("Image Height:%i\n", height);
	printf("Bit depth:%i\n", depth);
	printf("Color type:%i\n", color);
	*/

	bool update_info = false;

	if (depth < 8) { //only bit dept 8 per channel is handled

		png_set_packing(png);
		update_info = true;
	};

	if (png_get_color_type(png, info) == PNG_COLOR_TYPE_PALETTE) {
		png_set_palette_to_rgb(png);
		update_info = true;
	}

	if (depth > 8) {
		png_set_strip_16(png);
		update_info = true;
	}

	if (png_get_valid(png, info, PNG_INFO_tRNS)) {
		//png_set_expand_gray_1_2_4_to_8(png);
		png_set_tRNS_to_alpha(png);
		update_info = true;
	}

	if (update_info) {
		png_read_update_info(png, info);
		png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);
	}

	int components = 0;

	Image::Format fmt;
	switch (color) {

		case PNG_COLOR_TYPE_GRAY: {

			fmt = Image::FORMAT_L8;
			components = 1;
		} break;
		case PNG_COLOR_TYPE_GRAY_ALPHA: {

			fmt = Image::FORMAT_LA8;
			components = 2;
		} break;
		case PNG_COLOR_TYPE_RGB: {

			fmt = Image::FORMAT_RGB8;
			components = 3;
		} break;
		case PNG_COLOR_TYPE_RGB_ALPHA: {

			fmt = Image::FORMAT_RGBA8;
			components = 4;
		} break;
		default: {

			ERR_PRINT("INVALID PNG TYPE");
			png_destroy_read_struct(&png, &info, NULL);
			return ERR_UNAVAILABLE;
		} break;
	}

	//int rowsize = png_get_rowbytes(png, info);
	int rowsize = components * width;

	PoolVector<uint8_t> dstbuff;

	dstbuff.resize(rowsize * height);

	PoolVector<uint8_t>::Write dstbuff_write = dstbuff.write();

	uint8_t *data = dstbuff_write.ptr();

	uint8_t **row_p = memnew_arr(uint8_t *, height);

	for (unsigned int i = 0; i < height; i++) {
		row_p[i] = &data[components * width * i];
	}

	png_read_image(png, (png_bytep *)row_p);

	memdelete_arr(row_p);

	p_image->create(width, height, 0, fmt, dstbuff);

	png_destroy_read_struct(&png, &info, NULL);

	return OK;
}
Beispiel #3
0
/*
=================
image_png_load
=================
*/
GNUC_NONNULL static erbool image_png_load (const char *name, image_t *im)
{
    fs_file_t   f;
    int         size, r, width, height, inc;
    png_byte   *image = NULL, *p = NULL;
    png_structp pngst;
    png_infop   info = NULL;
    png_byte    depth, color_type;

    if (NULL == (f = fs_open(name, FS_RDONLY, &size, false)))
        return false;

    if (NULL == (pngst = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                                NULL,
                                                &epng_error,
                                                &epng_warn)))
    {
        sys_printf("failed to create png read struct\n");
        fs_close(f);
        return false;
    }

    if (NULL == (info = png_create_info_struct(pngst)))
    {
        sys_printf("failed to create png info struct\n");
        goto error;
    }

    if (setjmp(png_jmpbuf(pngst)))
        goto error;

    png_set_user_limits(pngst, IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT);
    png_set_read_fn(pngst, f, &epng_read);
    png_read_info(pngst, info);

    width  = png_get_image_width(pngst, info);
    height = png_get_image_height(pngst, info);
    depth  = png_get_bit_depth(pngst, info);

    if (16 == depth)
    {
        /* 16 -> 8 */
        png_set_strip_16(pngst);
        depth = 8;
    }

    color_type = png_get_color_type(pngst, info);

    /* 1/2/4 gray -> 8 gray */
    if (PNG_COLOR_TYPE_GRAY == color_type && depth < 8)
        png_set_expand_gray_1_2_4_to_8(pngst);

    /* gray/palette -> rgb */
    if (PNG_COLOR_TYPE_GRAY == color_type || PNG_COLOR_TYPE_GRAY_ALPHA == color_type)
        png_set_gray_to_rgb(pngst);
    else if (PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(pngst);

    /* transparency -> alpha */
    if (png_get_valid(pngst, info, PNG_INFO_tRNS))
    {
        png_set_tRNS_to_alpha(pngst);
    }
    else
    {
        /* to rgba */
        if (PNG_COLOR_TYPE_RGB_ALPHA != color_type &&
            PNG_COLOR_TYPE_GRAY_ALPHA != color_type)
            png_set_add_alpha(pngst, 0xff, PNG_FILLER_AFTER);
    }

    /* deinterlace */
    png_set_interlace_handling(pngst);

    /* read */
    inc = width * 4;

    p = image = mem_alloc(image_mempool, height * inc);

    for (r = 0; r < height ;r++, p += inc)
        png_read_row(pngst, p, NULL);

    png_read_end(pngst, NULL);
    png_destroy_read_struct(&pngst, &info, NULL);

    fs_close(f);

    im->width  = width;
    im->height = height;
    im->data   = image;

    return true;

error:
    if (NULL != f)
        fs_close(f);

    png_destroy_read_struct(&pngst, NULL != info ? &info : NULL, NULL);

    if (NULL != image)
        mem_free(image);

    return false;
}
Beispiel #4
0
   /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
      Return nonzero (true) if they match */

   return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
}

#ifdef open_file /* prototype 1 */
void read_png(char *file_name)  /* We need to open the file */
{
   png_structp png_ptr;
   png_infop info_ptr;
   unsigned int sig_read = 0;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
   FILE *fp;

   if ((fp = fopen(file_name, "rb")) == NULL)
      return (ERROR);

#else no_open_file /* prototype 2 */
void read_png(FILE *fp, unsigned int sig_read)  /* File is already open */
{
   png_structp png_ptr;
   png_infop info_ptr;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
#endif no_open_file /* Only use one prototype! */

   /* Create and initialize the png_struct with the desired error handler
    * functions.  If you want to use the default stderr and longjump method,
    * you can supply NULL for the last three parameters.  We also supply the
    * the compiler header file version, so that we know if the application
    * was compiled with a compatible version of the library.  REQUIRED
    */
   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
      png_voidp user_error_ptr, user_error_fn, user_warning_fn);

   if (png_ptr == NULL)
   {
      fclose(fp);
      return (ERROR);
   }

   /* Allocate/initialize the memory for image information.  REQUIRED. */
   info_ptr = png_create_info_struct(png_ptr);
   if (info_ptr == NULL)
   {
      fclose(fp);
      png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
      return (ERROR);
   }

   /* Set error handling if you are using the setjmp/longjmp method (this is
    * the normal method of doing things with libpng).  REQUIRED unless you
    * set up your own error handlers in the png_create_read_struct() earlier.
    */

   if (setjmp(png_jmpbuf(png_ptr)))
   {
      /* Free all of the memory associated with the png_ptr and info_ptr */
      png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
      fclose(fp);
      /* If we get here, we had a problem reading the file */
      return (ERROR);
   }

   /* One of the following I/O initialization methods is REQUIRED */
#ifdef streams /* PNG file I/O method 1 */
   /* Set up the input control if you are using standard C streams */
   png_init_io(png_ptr, fp);

#else no_streams /* PNG file I/O method 2 */
   /* If you are using replacement read functions, instead of calling
    * png_init_io() here you would call:
    */
   png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn);
   /* where user_io_ptr is a structure you want available to the callbacks */
#endif no_streams /* Use only one I/O method! */

   /* If we have already read some of the signature */
   png_set_sig_bytes(png_ptr, sig_read);

#ifdef hilevel
   /*
    * If you have enough memory to read in the entire image at once,
    * and you need to specify only transforms that can be controlled
    * with one of the PNG_TRANSFORM_* bits (this presently excludes
    * dithering, filling, setting background, and doing gamma
    * adjustment), then you can read the entire image (including
    * pixels) into the info structure with this call:
    */
   png_read_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL);

#else
   /* OK, you're doing it the hard way, with the lower-level functions */

   /* The call to png_read_info() gives us all of the information from the
    * PNG file before the first IDAT (image data chunk).  REQUIRED
    */
   png_read_info(png_ptr, info_ptr);

   png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
       &interlace_type, int_p_NULL, int_p_NULL);

   /* Set up the data transformations you want.  Note that these are all
    * optional.  Only call them if you want/need them.  Many of the
    * transformations only work on specific types of images, and many
    * are mutually exclusive.
    */

   /* Tell libpng to strip 16 bit/color files down to 8 bits/color */
   png_set_strip_16(png_ptr);

   /* Strip alpha bytes from the input data without combining with the
    * background (not recommended).
    */
   png_set_strip_alpha(png_ptr);

   /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
    * byte into separate bytes (useful for paletted and grayscale images).
    */
   png_set_packing(png_ptr);

   /* Change the order of packed pixels to least significant bit first
    * (not useful if you are using png_set_packing). */
   png_set_packswap(png_ptr);

   /* Expand paletted colors into true RGB triplets */
   if (color_type == PNG_COLOR_TYPE_PALETTE)
      png_set_palette_to_rgb(png_ptr);

   /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
   if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
      png_set_expand_gray_1_2_4_to_8(png_ptr);

   /* Expand paletted or RGB images with transparency to full alpha channels
    * so the data will be available as RGBA quartets.
    */
   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
      png_set_tRNS_to_alpha(png_ptr);

   /* Set the background color to draw transparent and alpha images over.
    * It is possible to set the red, green, and blue components directly
    * for paletted images instead of supplying a palette index.  Note that
    * even if the PNG file supplies a background, you are not required to
    * use it - you should use the (solid) application background if it has one.
    */

   png_color_16 my_background, *image_background;

   if (png_get_bKGD(png_ptr, info_ptr, &image_background))
      png_set_background(png_ptr, image_background,
                         PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
   else
      png_set_background(png_ptr, &my_background,
                         PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);

   /* Some suggestions as to how to get a screen gamma value
    *
    * Note that screen gamma is the display_exponent, which includes
    * the CRT_exponent and any correction for viewing conditions
    */
   if (/* We have a user-defined screen gamma value */)
   {
      screen_gamma = user-defined screen_gamma;
   }
   /* This is one way that applications share the same screen gamma value */
   else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
Beispiel #5
0
Image *
readPNG(const char *filename)
{
    FILE *fp;
    png_structp png_ptr;
    png_infop info_ptr;
    png_infop end_info;
    Image *image;

    fp = fopen(filename, "rb");
    if (!fp)
        goto no_fp;

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
        goto no_png;

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        goto no_png;
    }

    end_info = png_create_info_struct(png_ptr);
    if (!end_info) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        goto no_png;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        goto no_png;
    }

    png_init_io(png_ptr, fp);

    png_read_info(png_ptr, info_ptr);

    png_uint_32 width, height;
    int bit_depth, color_type, interlace_type, compression_type, filter_method;

    png_get_IHDR(png_ptr, info_ptr,
                 &width, &height,
                 &bit_depth, &color_type, &interlace_type,
                 &compression_type, &filter_method);

    image = new Image(width, height);
    if (!image)
        goto no_image;

    /* Convert to RGBA8 */
    if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(png_ptr);
    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
        png_set_expand_gray_1_2_4_to_8(png_ptr);
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_tRNS_to_alpha(png_ptr);
    if (bit_depth == 16)
        png_set_strip_16(png_ptr);

    for (unsigned y = 0; y < height; ++y) {
        png_bytep row = (png_bytep)(image->pixels + y*width*4);
        png_read_row(png_ptr, row, NULL);
    }

    png_read_end(png_ptr, info_ptr);
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    fclose(fp);
    return image;

no_image:
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
no_png:
    fclose(fp);
no_fp:
    return NULL;
}
Beispiel #6
0
/*****************************************************************************
 * LoadPNG: loads the PNG logo into memory
 *****************************************************************************/
static picture_t *LoadPNG( vlc_object_t *p_this )
{
    picture_t *p_pic;
    char *psz_filename;
    vlc_value_t val;
    FILE *file;
    int i, j, i_trans;
    vlc_bool_t b_alpha = VLC_TRUE;

    png_uint_32 i_width, i_height;
    int i_color_type, i_interlace_type, i_compression_type, i_filter_type;
    int i_bit_depth;
    png_bytep *p_row_pointers;
    png_structp p_png;
    png_infop p_info, p_end_info;

    var_Create( p_this, "logo-file", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
    var_Get( p_this, "logo-file", &val );
    psz_filename = val.psz_string;
    if( !psz_filename || !*psz_filename )
    {
        msg_Err( p_this, "logo file not specified" );
        return 0;
    }

    if( !(file = fopen( psz_filename , "rb" )) )
    {
        msg_Err( p_this, "logo file (%s) not found", psz_filename );
        free( psz_filename );
        return 0;
    }
    free( psz_filename );

    p_png = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
    p_info = png_create_info_struct( p_png );
    p_end_info = png_create_info_struct( p_png );
    png_init_io( p_png, file );
    png_read_info( p_png, p_info );
    png_get_IHDR( p_png, p_info, &i_width, &i_height,
                  &i_bit_depth, &i_color_type, &i_interlace_type,
                  &i_compression_type, &i_filter_type);

    if( i_color_type == PNG_COLOR_TYPE_PALETTE )
        png_set_palette_to_rgb( p_png );

    if( i_color_type == PNG_COLOR_TYPE_GRAY ||
        i_color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
          png_set_gray_to_rgb( p_png );

    if( png_get_valid( p_png, p_info, PNG_INFO_tRNS ) )
    {
        png_set_tRNS_to_alpha( p_png );
    }
    else if( !(i_color_type & PNG_COLOR_MASK_ALPHA) )
    {
        b_alpha = VLC_FALSE;
    }

    p_row_pointers = malloc( sizeof(png_bytep) * i_height );
    for( i = 0; i < (int)i_height; i++ )
        p_row_pointers[i] = malloc( 4 * ( i_bit_depth + 7 ) / 8 * i_width );

    png_read_image( p_png, p_row_pointers );
    png_read_end( p_png, p_end_info );

    fclose( file );
    png_destroy_read_struct( &p_png, &p_info, &p_end_info );

    /* Convert to YUVA */
    p_pic = malloc( sizeof(picture_t) );
    if( vout_AllocatePicture( p_this, p_pic, VLC_FOURCC('Y','U','V','A'),
                              i_width, i_height, VOUT_ASPECT_FACTOR ) !=
        VLC_SUCCESS )
    {
        for( i = 0; i < (int)i_height; i++ ) free( p_row_pointers[i] );
        free( p_row_pointers );
        return 0;
    }

    var_Create(p_this, "logo-transparency", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT);
    var_Get( p_this, "logo-transparency", &val );
    i_trans = __MAX( __MIN( val.i_int, 255 ), 0 );

    for( j = 0; j < (int)i_height ; j++ )
    {
        uint8_t *p = (uint8_t *)p_row_pointers[j];

        for( i = 0; i < (int)i_width ; i++ )
        {
            int i_offset = i + j * p_pic->p[Y_PLANE].i_pitch;

            p_pic->p[Y_PLANE].p_pixels[i_offset] =
                (p[0] * 257L + p[1] * 504 + p[2] * 98)/1000 + 16;
            p_pic->p[U_PLANE].p_pixels[i_offset] =
                (p[2] * 439L - p[0] * 148 - p[1] * 291)/1000 + 128;
            p_pic->p[V_PLANE].p_pixels[i_offset] =
                (p[0] * 439L - p[1] * 368 - p[2] * 71)/1000 + 128;
            p_pic->p[A_PLANE].p_pixels[i_offset] =
                b_alpha ? (p[3] * i_trans) / 255 : i_trans;

            p += (b_alpha ? 4 : 3);
        }
    }

    for( i = 0; i < (int)i_height; i++ ) free( p_row_pointers[i] );
    free( p_row_pointers );
    return p_pic;
}
ImageReaderPNG::ImageType ImageReaderPNG::readData(const std::string& filePath, PNGInfra& infra, bool wantAlpha)
{
	if (filePath.empty())
		return eInvalid;

	infra.pFile = fopen(filePath.c_str(), "rb");
	if (!infra.pFile)
	{
		fprintf(stderr, "Error opening file: %s\n", filePath.c_str());
		return eInvalid;
	}

	unsigned char sig[8];

	// check the signature
	fread(sig, 1, 8, infra.pFile);
	if (!png_check_sig(sig, 8))
	{
		fprintf(stderr, "Cannot open file: %s - not a valid PNG file.\n", filePath.c_str());
		fclose(infra.pFile);
		return eInvalid;
	}

	infra.pPNG = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!infra.pPNG)
	{
		fclose(infra.pFile);
		return eInvalid;
	}

	infra.pInfo = png_create_info_struct(infra.pPNG);
	if (!infra.pInfo)
	{
		png_destroy_read_struct(&infra.pPNG, NULL, NULL);
		fclose(infra.pFile);
		return eInvalid;
	}

	if (setjmp(png_jmpbuf(infra.pPNG)))
	{
		png_destroy_read_struct(&infra.pPNG, &infra.pInfo, NULL);
		fclose(infra.pFile);
		return eInvalid;
	}

	png_init_io(infra.pPNG, infra.pFile);
	png_set_sig_bytes(infra.pPNG, 8);
	png_read_info(infra.pPNG, infra.pInfo);

	int colorType;
	int bitDepth, interlaceType, compressionType;

	png_get_IHDR(infra.pPNG, infra.pInfo, &infra.width, &infra.height, &bitDepth, &colorType, &interlaceType, &compressionType, NULL);

	if (colorType == PNG_COLOR_TYPE_PALETTE)
		png_set_palette_to_rgb(infra.pPNG);

	if (png_get_valid(infra.pPNG, infra.pInfo, PNG_INFO_tRNS))
	{
		png_set_tRNS_to_alpha(infra.pPNG);
	}

	if (bitDepth == 16)
		png_set_strip_16(infra.pPNG);

	ImageType type = eInvalid;

	if (!wantAlpha)
	{
		// add black Alpha
		if ((colorType & PNG_COLOR_MASK_ALPHA) == 0)
			png_set_add_alpha(infra.pPNG, 0xFF, PNG_FILLER_AFTER);

		if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
			png_set_gray_to_rgb(infra.pPNG);
		else if (colorType != PNG_COLOR_TYPE_RGB && colorType != PNG_COLOR_TYPE_RGB_ALPHA)
			return eInvalid;

		type = eRGBA;
	}
	else
	{
		if (colorType == PNG_COLOR_TYPE_RGB_ALPHA)
			type = eRGBA;
		else if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
			type = eA;
		else
			return eInvalid;
	}

	png_read_update_info(infra.pPNG, infra.pInfo);

	infra.pRows = new png_bytep[infra.height * png_sizeof(png_bytep)];

	png_set_rows(infra.pPNG, infra.pInfo, infra.pRows);

	for (unsigned int i = 0; i < infra.height; i++)
	{
		infra.pRows[i] = new png_byte[png_get_rowbytes(infra.pPNG, infra.pInfo)];
	}

	png_read_image(infra.pPNG, infra.pRows);
	png_read_end(infra.pPNG, infra.pInfo);

	return type;
}
Beispiel #8
0
plMipmap* plPNG::IRead(hsStream* inStream)
{
    plMipmap* newMipmap = NULL;
    png_structp png_ptr;
    png_infop info_ptr;
    png_infop end_info;

    try {
        //  Check PNG Signature
        png_byte sig[PNGSIGSIZE];
        inStream->Read8Bytes((char*) sig);

        if (!png_sig_cmp(sig, 0, PNGSIGSIZE)) {
            //  Allocate required structs
            png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

            if (!png_ptr) {
                throw false;
            }

            info_ptr = png_create_info_struct(png_ptr);

            if (!info_ptr) {
                png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
                throw false;
            }

            end_info = png_create_info_struct(png_ptr);

            if (!end_info) {
                png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
                throw false;
            }

            //  Assign delegate function for reading from hsStream
            png_set_read_fn(png_ptr, (png_voidp)inStream, pngReadDelegate);
            //  Get PNG Header information
            png_set_sig_bytes(png_ptr, PNGSIGSIZE);
            png_read_info(png_ptr, info_ptr);
            png_uint_32 imgWidth =  png_get_image_width(png_ptr, info_ptr);
            png_uint_32 imgHeight = png_get_image_height(png_ptr, info_ptr);
            png_uint_32 bitdepth   = png_get_bit_depth(png_ptr, info_ptr);
            png_uint_32 channels   = png_get_channels(png_ptr, info_ptr);
            png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr);

            //  Convert images to RGB color space
            switch (color_type) {
                case PNG_COLOR_TYPE_PALETTE:
                    png_set_palette_to_rgb(png_ptr);
                    channels = 3;
                    break;
                case PNG_COLOR_TYPE_GRAY:

                    if (bitdepth < 8) {
                        png_set_expand_gray_1_2_4_to_8(png_ptr);
                    }

                    bitdepth = 8;
                    break;
            }

            //  Convert transparency (if needed) to a full alpha channel
            if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
                png_set_tRNS_to_alpha(png_ptr);
                channels += 1;
            } else if (channels == 3) {
                // Add an opaque alpha channel if still none exists
                png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
                channels = 4;
            }

            // Invert color byte-order as used by plMipmap for DirectX
            png_set_bgr(png_ptr);
            /// Construct a new mipmap to hold everything
            newMipmap = new plMipmap(imgWidth, imgHeight, plMipmap::kARGB32Config, 1, plMipmap::kUncompressed);
            char* destp = (char*)newMipmap->GetImage();
            png_bytep* row_ptrs = new png_bytep[imgHeight];
            const unsigned int stride = imgWidth * bitdepth * channels / 8;

            //  Assign row pointers to the appropriate locations in the newly-created Mipmap
            for (size_t i = 0; i < imgHeight; i++) {
                row_ptrs[i] = (png_bytep)destp + (i * stride);
            }

            png_read_image(png_ptr, row_ptrs);
            png_read_end(png_ptr, end_info);
            //  Clean up allocated structs
            png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
            delete [] row_ptrs;
        }
    } catch (...) {
        delete newMipmap;
        newMipmap = nullptr;
    }

    return newMipmap;
}
Beispiel #9
0
Py::Object
_png_module::read_png(const Py::Tuple& args) {

    args.verify_length(1);
    std::string fname = Py::String(args[0]);

    png_byte header[8];	// 8 is the maximum size that can be checked

    FILE *fp = fopen(fname.c_str(), "rb");
    if (!fp)
        throw Py::RuntimeError(Printf("_image_module::readpng could not open PNG file %s for reading", fname.c_str()).str());

    if (fread(header, 1, 8, fp) != 8)
        throw Py::RuntimeError("_image_module::readpng: error reading PNG header");
    if (png_sig_cmp(header, 0, 8))
        throw Py::RuntimeError("_image_module::readpng: file not recognized as a PNG file");


    /* initialize stuff */
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

    if (!png_ptr)
        throw Py::RuntimeError("_image_module::readpng:  png_create_read_struct failed");

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
        throw Py::RuntimeError("_image_module::readpng:  png_create_info_struct failed");

    if (setjmp(png_jmpbuf(png_ptr)))
        throw Py::RuntimeError("_image_module::readpng:  error during init_io");

    png_init_io(png_ptr, fp);
    png_set_sig_bytes(png_ptr, 8);

    png_read_info(png_ptr, info_ptr);

    png_uint_32 width = info_ptr->width;
    png_uint_32 height = info_ptr->height;

    // convert misc color types to rgb for simplicity
    if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY ||
            info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);
    else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(png_ptr);


    int bit_depth = info_ptr->bit_depth;
    if (bit_depth == 16)  png_set_strip_16(png_ptr);


    png_set_interlace_handling(png_ptr);
    png_read_update_info(png_ptr, info_ptr);

    bool rgba = info_ptr->color_type == PNG_COLOR_TYPE_RGBA;
    if ( (info_ptr->color_type != PNG_COLOR_TYPE_RGB) && !rgba) {
        std::cerr << "Found color type " << (int)info_ptr->color_type  << std::endl;
        throw Py::RuntimeError("_image_module::readpng: cannot handle color_type");
    }

    /* read file */
    if (setjmp(png_jmpbuf(png_ptr)))
        throw Py::RuntimeError("_image_module::readpng: error during read_image");

    png_bytep *row_pointers = new png_bytep[height];
    png_uint_32 row;

    for (row = 0; row < height; row++)
        row_pointers[row] = new png_byte[png_get_rowbytes(png_ptr,info_ptr)];

    png_read_image(png_ptr, row_pointers);



    int dimensions[3];
    dimensions[0] = height;  //numrows
    dimensions[1] = width;   //numcols
    dimensions[2] = 4;

    PyArrayObject *A = (PyArrayObject *) PyArray_FromDims(3, dimensions, PyArray_FLOAT);


    for (png_uint_32 y = 0; y < height; y++) {
        png_byte* row = row_pointers[y];
        for (png_uint_32 x = 0; x < width; x++) {

            png_byte* ptr = (rgba) ? &(row[x*4]) : &(row[x*3]);
            size_t offset = y*A->strides[0] + x*A->strides[1];
            //if ((y<10)&&(x==10)) std::cout << "r = " << ptr[0] << " " << ptr[0]/255.0 << std::endl;
            *(float*)(A->data + offset + 0*A->strides[2]) = (float)(ptr[0]/255.0f);
            *(float*)(A->data + offset + 1*A->strides[2]) = (float)(ptr[1]/255.0f);
            *(float*)(A->data + offset + 2*A->strides[2]) = (float)(ptr[2]/255.0f);
            *(float*)(A->data + offset + 3*A->strides[2]) = rgba ? (float)(ptr[3]/255.0f) : 1.0f;
        }
    }

    //free the png memory
    png_read_end(png_ptr, info_ptr);
    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
    fclose(fp);
    for (row = 0; row < height; row++)
        delete [] row_pointers[row];
    delete [] row_pointers;
    return Py::asObject((PyObject*)A);
}
Beispiel #10
0
ImageData ReadPNG(char* fileName)
{
    ImageData meta;
    meta.valid = false;

    // Step 0: Make sure we can open the input file
    FILE* inFile = fopen(fileName, "rb");
    if (!inFile) {
        abort_("ReadPNG: Can't open %s for reading\n", fileName);
    }

    // Step 1: initialize the reader
    png_structp png = png_create_read_struct(
            PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png) {
        abort_("ReadPNG: png_create_read_struct() failed\n");
    }

    png_infop info = png_create_info_struct(png);
    if (!info) {
        abort_("ReadPNG: png_create_info_struct() failed\n");
    }

    if (setjmp(png_jmpbuf(png))) {
        abort_("ReadPNG: Error during initialization.\n");
    }
    
    png_init_io(png, inFile);
    png_read_info(png, info);

    // Step 2: Collect image statistics
    int width           = png_get_image_width(png, info);
    int height          = png_get_image_height(png, info);
    png_byte color_type = png_get_color_type(png, info);
    png_byte bit_depth  = png_get_bit_depth(png, info);

    // Make some adjustments
    if (bit_depth == 16) {
        png_set_strip_16(png);
    }
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(png);
    }
    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
        png_set_expand_gray_1_2_4_to_8(png);
    }

    if(png_get_valid(png, info, PNG_INFO_tRNS))
            png_set_tRNS_to_alpha(png);

    // These color_type don't have an alpha channel then fill it with 0xff.
    if(color_type == PNG_COLOR_TYPE_RGB ||
       color_type == PNG_COLOR_TYPE_GRAY ||
       color_type == PNG_COLOR_TYPE_PALETTE) {
        png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
    }
    
    if(color_type == PNG_COLOR_TYPE_GRAY ||
       color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
        png_set_gray_to_rgb(png);
    }

    png_read_update_info(png, info);

    // Step 3: Read the data
    if (setjmp(png_jmpbuf(png))) {
        abort_("ReadPNG: Error during image data reading.\n");
    }

    png_bytep row_pointers[height];

    // This method gives a discontiguous array of rows
    // Each row is later copied to the destination image, RGB only.
    // There should be a more streamlined method, but this method works for lena.png
    for (int y = 0; y < height; y++) {
       row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png, info));
       if (!row_pointers[y]) {
           abort_("ReadPNG: Couldn't allocate row %d\n", y);
        }
    }
    
    // Now we can read the image
    int row_bytes = png_get_rowbytes(png, info);
    png_read_image(png, row_pointers);

    // Convert the image from discontiguous rows to contiguous rows, discarding alpha
    Pixel* image = (Pixel*)malloc(height * width * 3);
    if (!image) {
        abort_("ReadPNG: Couldn't allocate image (%d, %d)\n", height, row_bytes);
    }

    // Brute force copy, skip over ALPHA channel
    for (int row = 0; row < height; row++) {
        for (int pixel = 0; pixel < width; pixel++)
        {
            image[(row * width + pixel)] = 
                *(Pixel*)(row_pointers[row] + pixel * 4);
        }
        // As we use them, delete the pointers to the image rows.
        free(row_pointers[row]);
    }

   
    meta.xDim = width;
    meta.yDim = height;
    meta.valid = true;
    meta.pixels = (Pixel*)image;

    // Step 4: Tidy up.
    fclose(inFile);

    // Done.
    return meta;

}
void FPngImageWrapper::UncompressPNGData( const ERGBFormat::Type InFormat, const int32 InBitDepth )
{
	// thread safety
	FScopeLock PNGLock(&GPNGSection);

	check( CompressedData.Num() );
	check( Width > 0 );
	check( Height > 0 );

	// Note that PNGs on PC tend to be BGR
	check( InFormat == ERGBFormat::BGRA || InFormat == ERGBFormat::RGBA || InFormat == ERGBFormat::Gray )	// Other formats unsupported at present
	check( InBitDepth == 8 || InBitDepth == 16 )	// Other formats unsupported at present

	// Reset to the beginning of file so we can use png_read_png(), which expects to start at the beginning.
	ReadOffset = 0;
		
	png_structp png_ptr	= png_create_read_struct_2( PNG_LIBPNG_VER_STRING, this, FPngImageWrapper::user_error_fn, FPngImageWrapper::user_warning_fn, NULL, FPngImageWrapper::user_malloc, FPngImageWrapper::user_free);
	check( png_ptr );

	png_infop info_ptr	= png_create_info_struct( png_ptr );
	check( info_ptr );
	PNGReadGuard PNGGuard( &png_ptr, &info_ptr );
	{
		if (ColorType == PNG_COLOR_TYPE_PALETTE)
		{
			png_set_palette_to_rgb(png_ptr);
		}

		if ((ColorType & PNG_COLOR_MASK_COLOR) == 0 && BitDepth < 8)
		{
			png_set_expand_gray_1_2_4_to_8(png_ptr);
		}

		// Insert alpha channel with full opacity for RGB images without alpha
		if ((ColorType & PNG_COLOR_MASK_ALPHA) == 0 && (InFormat == ERGBFormat::BGRA || InFormat == ERGBFormat::RGBA))
		{
			// png images don't set PNG_COLOR_MASK_ALPHA if they have alpha from a tRNS chunk, but png_set_add_alpha seems to be safe regardless
			if ((ColorType & PNG_COLOR_MASK_COLOR) == 0)
			{
				png_set_tRNS_to_alpha(png_ptr);
			}
			else if (ColorType == PNG_COLOR_TYPE_PALETTE)
			{
				png_set_tRNS_to_alpha(png_ptr);
			}
			if (InBitDepth == 8)
			{
				png_set_add_alpha(png_ptr, 0xff , PNG_FILLER_AFTER);
			}
			else if (InBitDepth == 16)
			{
				png_set_add_alpha(png_ptr, 0xffff , PNG_FILLER_AFTER);
			}
		}

		// Calculate Pixel Depth
		const uint32 PixelChannels = (InFormat == ERGBFormat::Gray) ? 1 : 4;
		const uint32 BytesPerPixel = (InBitDepth * PixelChannels) / 8;
		const uint32 BytesPerRow = BytesPerPixel * Width;
		RawData.Empty(Height * BytesPerRow);
		RawData.AddUninitialized(Height * BytesPerRow);

		png_set_read_fn( png_ptr, this, FPngImageWrapper::user_read_compressed );

		png_bytep* row_pointers = (png_bytep*) png_malloc( png_ptr, Height*sizeof(png_bytep) );
		PNGGuard.SetRowPointers(&row_pointers);
		for (int32 i = 0; i < Height; i++)
		{
			row_pointers[i]= &RawData[i * BytesPerRow];
		}
		png_set_rows(png_ptr, info_ptr, row_pointers);

		uint32 Transform = (InFormat == ERGBFormat::BGRA) ? PNG_TRANSFORM_BGR : PNG_TRANSFORM_IDENTITY;
			
		// PNG files store 16-bit pixels in network byte order (big-endian, ie. most significant bits first).
#if PLATFORM_LITTLE_ENDIAN
		// We're little endian so we need to swap
		if (BitDepth == 16)
		{
			Transform |= PNG_TRANSFORM_SWAP_ENDIAN;
		}
#endif

		// Convert grayscale png to RGB if requested
		if ((ColorType & PNG_COLOR_MASK_COLOR) == 0 &&
			(InFormat == ERGBFormat::RGBA || InFormat == ERGBFormat::BGRA))
		{
			Transform |= PNG_TRANSFORM_GRAY_TO_RGB;
		}

		// Convert RGB png to grayscale if requested
		if ((ColorType & PNG_COLOR_MASK_COLOR) != 0 && InFormat == ERGBFormat::Gray)
		{
			png_set_rgb_to_gray_fixed(png_ptr, 2 /* warn if image is in color */, -1, -1);
		}

		// Strip alpha channel if requested output is grayscale
		if (InFormat == ERGBFormat::Gray)
		{
			// this is not necessarily the best option, instead perhaps:
			// png_color background = {0,0,0};
			// png_set_background(png_ptr, &background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
			Transform |= PNG_TRANSFORM_STRIP_ALPHA;
		}

		// Reduce 16-bit to 8-bit if requested
		if (BitDepth == 16 && InBitDepth == 8)
		{
#if PNG_LIBPNG_VER >= 10504
			check(0); // Needs testing
			Transform |= PNG_TRANSFORM_SCALE_16;
#else
			Transform |= PNG_TRANSFORM_STRIP_16;
#endif
		}

		// Increase 8-bit to 16-bit if requested
		if (BitDepth <= 8 && InBitDepth == 16)
		{
#if PNG_LIBPNG_VER >= 10504
			check(0); // Needs testing
			Transform |= PNG_TRANSFORM_EXPAND_16
#else
			// Expanding 8-bit images to 16-bit via transform needs a libpng update
			check(0);
#endif
		}

		png_read_png(png_ptr, info_ptr, Transform, NULL);
	}

	RawFormat = InFormat;
	RawBitDepth = InBitDepth;
}
Beispiel #12
0
bool  PngDecoder::readData( Mat& img )
{
    bool result = false;
    AutoBuffer<uchar*> _buffer(m_height);
    uchar** buffer = _buffer;
    int color = img.channels() > 1;
    uchar* data = img.data;
    int step = (int)img.step;

    if( m_png_ptr && m_info_ptr && m_end_info && m_width && m_height )
    {
        png_structp png_ptr = (png_structp)m_png_ptr;
        png_infop info_ptr = (png_infop)m_info_ptr;
        png_infop end_info = (png_infop)m_end_info;

        if( setjmp( png_jmpbuf ( png_ptr ) ) == 0 )
        {
            int y;

            if( img.depth() == CV_8U && m_bit_depth == 16 )
                png_set_strip_16( png_ptr );
            else if( !isBigEndian() )
                png_set_swap( png_ptr );

            if(img.channels() < 4)
            {
                /* observation: png_read_image() writes 400 bytes beyond
                 * end of data when reading a 400x118 color png
                 * "mpplus_sand.png".  OpenCV crashes even with demo
                 * programs.  Looking at the loaded image I'd say we get 4
                 * bytes per pixel instead of 3 bytes per pixel.  Test
                 * indicate that it is a good idea to always ask for
                 * stripping alpha..  18.11.2004 Axel Walthelm
                 */
                 png_set_strip_alpha( png_ptr );
            }

            if( m_color_type == PNG_COLOR_TYPE_PALETTE )
                png_set_palette_to_rgb( png_ptr );

            if( m_color_type == PNG_COLOR_TYPE_GRAY && m_bit_depth < 8 )
#if (PNG_LIBPNG_VER_MAJOR*10000 + PNG_LIBPNG_VER_MINOR*100 + PNG_LIBPNG_VER_RELEASE >= 10209) || \
    (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR == 0 && PNG_LIBPNG_VER_RELEASE >= 18)
                png_set_expand_gray_1_2_4_to_8( png_ptr );
#else
                png_set_gray_1_2_4_to_8( png_ptr );
#endif

            if( CV_MAT_CN(m_type) > 1 && color )
                png_set_bgr( png_ptr ); // convert RGB to BGR
            else if( color )
                png_set_gray_to_rgb( png_ptr ); // Gray->RGB
            else
                png_set_rgb_to_gray( png_ptr, 1, 0.299, 0.587 ); // RGB->Gray

            png_read_update_info( png_ptr, info_ptr );

            for( y = 0; y < m_height; y++ )
                buffer[y] = data + y*step;

            png_read_image( png_ptr, buffer );
            png_read_end( png_ptr, end_info );

            result = true;
        }
    }

    close();
    return result;
}
int load_png( char *file_name, int stype )
{
	char buf[PNG_BYTES_TO_CHECK], *mess;
	unsigned char *rgb, *rgb2, *rgb3;
	int i, row, do_prog, bit_depth, color_type, interlace_type, width, height;
	unsigned int sig_read = 0;
	FILE *fp;
	png_bytep *row_pointers, trans;
	png_color_16p trans_rgb;

	png_structp png_ptr;
	png_infop info_ptr;
	png_uint_32 pwidth, pheight;
	png_colorp png_palette;

	if ((fp = fopen(file_name, "rb")) == NULL) return -1;
	i = fread(buf, 1, PNG_BYTES_TO_CHECK, fp);
	if ( i != PNG_BYTES_TO_CHECK ) goto fail;
	i = !png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK);
	if ( i<=0 ) goto fail;
	rewind( fp );

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

	if (png_ptr == NULL) goto fail;

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL)
	{
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		goto fail;
	}

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		fclose(fp);
		return -1;
	}

	png_init_io(png_ptr, fp);
	png_set_sig_bytes(png_ptr, sig_read);

	png_read_info(png_ptr, info_ptr);

	png_get_IHDR(png_ptr, info_ptr, &pwidth, &pheight, &bit_depth, &color_type,
		&interlace_type, NULL, NULL);

	width = (int) pwidth;
	height = (int) pheight;

	if ( width > MAX_WIDTH || height > MAX_HEIGHT )
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		fclose(fp);
		return TOO_BIG;
	}

	row_pointers = malloc( sizeof(png_bytep) * height );

	if (setjmp(png_jmpbuf(png_ptr)))	// If libpng generates an error now, clean up
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		fclose(fp);
		free(row_pointers);
		return FILE_LIB_ERROR;
	}

	rgb = NULL;
	mess = NULL;
	if ( width*height > FILE_PROGRESS ) do_prog = 1;
	else do_prog = 0;

	if ( stype == 0 )
	{
		mess = _("Loading PNG image");
		rgb = mem_image;
	}
	if ( stype == 1 )
	{
		mess = _("Loading clipboard image");
		rgb = mem_clipboard;
		if ( rgb != NULL ) free( rgb );		// Lose old clipboard
		mem_clip_mask_clear();			// Lose old clipboard mask
	}

	if ( color_type != PNG_COLOR_TYPE_PALETTE || bit_depth>8 )	// RGB PNG file
	{
		png_set_strip_16(png_ptr);
		png_set_gray_1_2_4_to_8(png_ptr);
		png_set_palette_to_rgb(png_ptr);
		png_set_gray_to_rgb(png_ptr);

		if ( stype == 0 )
		{
			mem_pal_copy( mem_pal, mem_pal_def );
			mem_cols = 256;
			if ( mem_new( width, height, 3 ) != 0 ) goto file_too_huge;
			rgb = mem_image;
			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
			{
				// Image has a transparent index
				png_get_tRNS(png_ptr, info_ptr, 0, 0, &trans_rgb);
				mem_pal[255].red = trans_rgb->red;
				mem_pal[255].green = trans_rgb->green;
				mem_pal[255].blue = trans_rgb->blue;
				if (color_type == PNG_COLOR_TYPE_GRAY)
				{
					if ( bit_depth==4 ) i = trans_rgb->gray * 17;
					if ( bit_depth==8 ) i = trans_rgb->gray;
					if ( bit_depth==16 ) i = trans_rgb->gray >> (bit_depth-8);
					mem_pal[255].red = i;
					mem_pal[255].green = i;
					mem_pal[255].blue = i;
				}
				mem_xpm_trans = 255;
			}
		}
Beispiel #14
0
GLuint loadPNG(const char * file_name, GLuint tex)
{
    png_byte header[8];

    FILE *fp = fopen(file_name, "rb");
    if (fp == 0)
    {
        perror(file_name);
        return 0;
    }

    // read the header
    fread(header, 1, 8, fp);

    if (png_sig_cmp(header, 0, 8))
    {
        fprintf(stderr, "error: %s is not a PNG.\n", file_name);
        fclose(fp);
        return 0;
    }

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
    {
        fprintf(stderr, "error: png_create_read_struct returned 0.\n");
        fclose(fp);
        return 0;
    }

    // create png info struct
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        fprintf(stderr, "error: png_create_info_struct returned 0.\n");
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        fclose(fp);
        return 0;
    }

    // create png info struct
    png_infop end_info = png_create_info_struct(png_ptr);
    if (!end_info)
    {
        fprintf(stderr, "error: png_create_info_struct returned 0.\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
        fclose(fp);
        return 0;
    }

    // the code in this if statement gets called if libpng encounters an error
    if (setjmp(png_jmpbuf(png_ptr))) {
        fprintf(stderr, "error from libpng\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        fclose(fp);
        return 0;
    }

    // init png reading
    png_init_io(png_ptr, fp);

    // let libpng know you already read the first 8 bytes
    png_set_sig_bytes(png_ptr, 8);

    // read all the info up to the image data
    png_read_info(png_ptr, info_ptr);

    // variables to pass to get info
    int bit_depth, color_type;
    png_uint_32 temp_width, temp_height;

    // get info about png
    png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type,
        NULL, NULL, NULL);

    GLint format;
    switch(color_type)
    {
    case PNG_COLOR_TYPE_RGB:
        format = GL_RGB;
        break;
    case PNG_COLOR_TYPE_RGB_ALPHA:
        format = GL_RGBA;
        break;
    case PNG_COLOR_TYPE_GRAY:
        //cout<<"color Type Grey"<<endl;
        format = GL_RGBA;
        png_set_gray_to_rgb(png_ptr);
        png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);

        break;
    case PNG_COLOR_TYPE_GRAY_ALPHA:
        //cout<<"color Type Grey Alpha"<<endl;
        format = GL_RGBA;
        png_set_gray_to_rgb(png_ptr);

        break;
    case PNG_COLOR_TYPE_PALETTE:
        //cout<<"color Type Palette"<<endl;
        format = GL_RGBA;
        png_set_palette_to_rgb(png_ptr);
        png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
        //return 0;
        break;
    default:
        fprintf(stderr, "%s: Unknown libpng color type %d.\n", file_name, color_type);
        return 0;
    }

    // Update the png info struct.
    png_read_update_info(png_ptr, info_ptr);

    // Row size in bytes.
    int rowbytes = png_get_rowbytes(png_ptr, info_ptr);

    // glTexImage2d requires rows to be 4-byte aligned
    rowbytes += 3 - ((rowbytes-1) % 4);

    // Allocate the image_data as a big block, to be given to opengl
    png_byte * image_data;
    //image_data = (png_byte*) malloc(rowbytes * temp_height * sizeof(png_byte)+15);
    image_data = new png_byte[rowbytes * temp_height];
    if (image_data == NULL)
    {
        fprintf(stderr, "error: could not allocate memory for PNG image data\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        fclose(fp);
        return 0;
    }

    // row_pointers is for pointing to image_data for reading the png with libpng
    //png_bytep * row_pointers = (png_bytep*) malloc(temp_height * sizeof(png_bytep));
    png_bytep * row_pointers = new png_bytep[temp_height];
    if (row_pointers == NULL)
    {
        fprintf(stderr, "error: could not allocate memory for PNG row pointers\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        free(image_data);
        fclose(fp);
        return 0;
    }

    // set the individual row_pointers to point at the correct offsets of image_data
    int i;
    for (i = 0; i < temp_height; i++)
    {
        row_pointers[/*temp_height - 1 - */i] = image_data + i * rowbytes;
    }

    // read the png into image_data through row_pointers
    png_read_image(png_ptr, row_pointers);

    glBindTexture(GL_TEXTURE_2D, tex);

    glTexImage2D(GL_TEXTURE_2D, 0, format, temp_width, temp_height, 0, format, GL_UNSIGNED_BYTE, image_data);

    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    // clean up
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    delete[] image_data;
    delete[] row_pointers;
    fclose(fp);
    return tex;
}
Beispiel #15
0
static const char * VS_CC
check_png(img_hnd_t *ih, int n, FILE *fp, vs_args_t *va)
{
    uint8_t signature[PNG_SIG_LENGTH];
    if (fread(signature, 1, PNG_SIG_LENGTH, fp) != PNG_SIG_LENGTH ||
        png_sig_cmp(signature, 0, PNG_SIG_LENGTH)) {
        return "unsupported format";
    }

    png_structp p_str = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
                                               NULL, NULL);
    if (!p_str) {
        return "failed to create png_read_struct";
    }

    png_infop p_info = png_create_info_struct(p_str);
    if (!p_info) {
        png_destroy_read_struct(&p_str, NULL, NULL);
        return "failed to create png_info_struct";
    }

    png_init_io(p_str, fp);
    png_set_sig_bytes(p_str, PNG_SIG_LENGTH);
    png_read_info(p_str, p_info);

    png_uint_32 width, height;
    int color_type, bit_depth;
    png_get_IHDR(p_str, p_info, &width, &height, &bit_depth, &color_type,
                 NULL, NULL, NULL);
    if (color_type & PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(p_str);
    }
    if (bit_depth < 8) {
        png_set_packing(p_str);
    }
    if (ih->enable_alpha == 0) {
        if (color_type & PNG_COLOR_MASK_ALPHA) {
            png_set_strip_alpha(p_str);
        }
    } else if ((color_type & PNG_COLOR_MASK_ALPHA) == 0) {
        png_set_add_alpha(p_str, 0x00, PNG_FILLER_AFTER);
    }

    png_read_update_info(p_str, p_info);
    png_get_IHDR(p_str, p_info, &width, &height, &bit_depth, &color_type,
                 NULL, NULL, NULL);
    uint32_t row_size = png_get_rowbytes(p_str, p_info);

    png_destroy_read_struct(&p_str, &p_info, NULL);

    ih->src[n].width = width;

    ih->src[n].height = height;

    VSPresetFormat pf = get_dst_format(color_type, bit_depth);
    if (pf == pfNone) {
        return "unsupported png color type";
    }
    ih->src[n].format = va->vsapi->getFormatPreset(pf, va->core);

    ih->src[n].read = read_png;

    ih->src[n].flip = 0;

    if (row_size > va->max_row_size) {
        va->max_row_size = row_size;
    }

    return NULL;
}
Beispiel #16
0
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;    
}
Beispiel #17
0
static int VS_CC read_png(img_hnd_t *ih, int n)
{
    FILE *fp = imgr_fopen(ih->src[n].name);
    if (!fp) {
        return -1;
    }

    png_structp p_str =
        png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!p_str) {
        fclose(fp);
        return -1;
    }

    png_infop p_info = png_create_info_struct(p_str);
    if (!p_info) {
        fclose(fp);
        png_destroy_read_struct(&p_str, NULL, NULL);
        return -1;
    }

    png_init_io(p_str, fp);
    png_read_info(p_str, p_info);

    png_uint_32 width, height;
    int color_type, bit_depth;
    png_get_IHDR(p_str, p_info, &width, &height, &bit_depth, &color_type,
                 NULL, NULL, NULL);
    if (color_type & PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(p_str);
    }
    if (bit_depth < 8) {
        png_set_packing(p_str);
    }
    if (bit_depth > 8) {
        png_set_swap(p_str);
    }
    if (ih->enable_alpha == 0) {
        if (color_type & PNG_COLOR_MASK_ALPHA) {
            png_set_strip_alpha(p_str);
        }
    } else if ((color_type & PNG_COLOR_MASK_ALPHA) == 0) {
        png_set_add_alpha(p_str, 0x00, PNG_FILLER_AFTER);
    }
    png_read_update_info(p_str, p_info);
    png_read_image(p_str, ih->png_row_index);

    fclose(fp);
    png_destroy_read_struct(&p_str, &p_info, NULL);

    ih->misc = IMG_ORDER_RGB;
    ih->row_adjust = 1;

    switch ((ih->src[n].format->id << 1) | ih->enable_alpha) {
    case (pfRGB24 << 1 | 0):
        ih->write_frame = func_write_rgb24;
        break;
    case (pfRGB24 << 1 | 1):
        ih->write_frame = func_write_rgb32;
        break;
    case (pfRGB48 << 1 | 0):
        ih->write_frame = func_write_rgb48;
        break;
    case (pfRGB48 << 1 | 1):
        ih->write_frame = func_write_rgb64;
        break;
    case (pfGray8 << 1 | 0):
    case (pfGray16 << 1 | 0):
        ih->write_frame = func_write_planar;
        break;
    case (pfGray8 << 1 | 1):
        ih->write_frame = func_write_gray8_a;
        break;
    case (pfGray16 << 1 | 1):
        ih->write_frame = func_write_gray16_a;
        break;
    default:
        break;
    }

    return 0;
}
Beispiel #18
0
gboolean read_png(curlMemoryStructGCS *chunk, unsigned char **raw_image, picSrcImageInfoGCS *info, char *errBuf) 
{
		
  png_structp png_ptr;
  png_infop info_ptr;
  /* initialize stuff */
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

  if (!png_ptr) {
    GST_DEBUG("png_create_read_struct failed");
    strcpy(errBuf, "read_png - Error : png_create_read_struct failed");
    return FALSE;
  }
  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    GST_DEBUG("png_create_info_struct failed"); 
    strcpy(errBuf, "read_png - Error : png_create_info_struct failed");
    return FALSE; 
  }
  FILE* memstream = fmemopen((void *)chunk->memory, chunk->size, "rb");
  if (!memstream) {
    GST_DEBUG("fmemopen failed"); 
    strcpy(errBuf, "read_imgheader - Error : fmemopen failed");
    return FALSE; 
  }		  
  png_init_io(png_ptr, memstream);
		  
  png_set_error_fn(png_ptr, (png_voidp)NULL,  png_error_fn, png_warning_fn);

		 
  /* read file */
  if (setjmp(png_jmpbuf(png_ptr))) {
    sprintf(errBuf, "read_png - Error : %s", "undetermined"); 
    fclose(memstream);
    return FALSE;
  }
		  
       
  png_uint_32 imgWidth, imgHeight;
  int bitdepth, color_type;
		 
  png_read_info(png_ptr, info_ptr);
  png_get_IHDR( png_ptr, info_ptr, &imgWidth, &imgHeight,
                &bitdepth, &color_type, 0, 0, 0 );		  
  //Number of channels
  int channels   = png_get_channels(png_ptr, info_ptr);
		 
  switch (color_type) {
  case PNG_COLOR_TYPE_PALETTE:
    png_set_palette_to_rgb(png_ptr);
    channels = 3;
    info->colorspace =  COLOR_TYPE_GCS_RGB;          
    break;
  case PNG_COLOR_TYPE_GRAY:
    if (bitdepth < 8)
      png_set_gray_1_2_4_to_8(png_ptr);
    //And the bitdepth info
    bitdepth = 8;
    png_set_gray_to_rgb(png_ptr);
    info->colorspace =  COLOR_TYPE_GCS_RGB;       
    break;
  }
  /*if the image has a transperancy set.. convert it to a full Alpha channel..*/
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
    png_set_tRNS_to_alpha(png_ptr);
    channels+=1;
    info->colorspace =  COLOR_TYPE_GCS_RGB_ALPHA;   
  }
  //We don't support 16 bit precision.. so if the image Has 16 bits per channel
  //precision... round it down to 8.
  if (bitdepth == 16)
    png_set_strip_16(png_ptr);
		  
  info->width	 = imgWidth;
  info->height   = imgHeight;
  info->channels = channels;
		   	
		  
  /* read file */
  if (setjmp(png_jmpbuf(png_ptr))) {
    sprintf(errBuf, "read_png - Error : %s", "undetermined");
    fclose(memstream);
    return FALSE;
  }
		  
		   
  png_bytep* rowPtrs[imgHeight];
         
			
         
			
  *raw_image = (unsigned char*)malloc(imgWidth * imgHeight * bitdepth * channels / 8);
  const unsigned int stride = imgWidth * bitdepth * channels / 8;
  GST_DEBUG("imgWidth:%d, imgHeight:%d, bitdepth:%d, channels:%d, stride:%d", imgWidth,imgHeight,bitdepth,channels, stride  );
  size_t i;
  for (i = 0; i < imgHeight; i++) {         	
    rowPtrs[i] = (png_bytep*)((png_bytep)(*raw_image) + ( i  * stride));

  }
  png_read_image(png_ptr, (png_bytepp)rowPtrs);
  fclose(memstream);
  return TRUE;
}
Beispiel #19
0
/****************************************************************************
 * DecodeBlock: the whole thing
 ****************************************************************************
 * This function must be fed with a complete compressed frame.
 ****************************************************************************/
static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_block;
    picture_t *p_pic = 0;

    png_uint_32 i_width, i_height;
    int i_color_type, i_interlace_type, i_compression_type, i_filter_type;
    int i_bit_depth, i;

    png_structp p_png;
    png_infop p_info, p_end_info;
    png_bytep *p_row_pointers = NULL;

    if( !pp_block || !*pp_block ) return NULL;

    p_block = *pp_block;
    p_sys->b_error = false;

    if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
    {
        block_Release( p_block ); *pp_block = NULL;
        return NULL;
    }

    p_png = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
    if( p_png == NULL )
    {
        block_Release( p_block ); *pp_block = NULL;
        return NULL;
    }

    p_info = png_create_info_struct( p_png );
    if( p_info == NULL )
    {
        png_destroy_read_struct( &p_png, NULL, NULL );
        block_Release( p_block ); *pp_block = NULL;
        return NULL;
    }

    p_end_info = png_create_info_struct( p_png );
    if( p_end_info == NULL )
    {
        png_destroy_read_struct( &p_png, &p_info, NULL );
        block_Release( p_block ); *pp_block = NULL;
        return NULL;
    }

    /* libpng longjmp's there in case of error */
    if( setjmp( png_jmpbuf( p_png ) ) )
        goto error;

    png_set_read_fn( p_png, (void *)p_block, user_read );
    png_set_error_fn( p_png, (void *)p_dec, user_error, user_warning );

    png_read_info( p_png, p_info );
    if( p_sys->b_error ) goto error;

    png_get_IHDR( p_png, p_info, &i_width, &i_height,
                  &i_bit_depth, &i_color_type, &i_interlace_type,
                  &i_compression_type, &i_filter_type);
    if( p_sys->b_error ) goto error;

    /* Set output properties */
    p_dec->fmt_out.i_codec = VLC_CODEC_RGBA;
    p_dec->fmt_out.video.i_visible_width = p_dec->fmt_out.video.i_width = i_width;
    p_dec->fmt_out.video.i_visible_height = p_dec->fmt_out.video.i_height = i_height;
    p_dec->fmt_out.video.i_sar_num = 1;
    p_dec->fmt_out.video.i_sar_den = 1;
    p_dec->fmt_out.video.i_rmask = 0x000000ff;
    p_dec->fmt_out.video.i_gmask = 0x0000ff00;
    p_dec->fmt_out.video.i_bmask = 0x00ff0000;

    if( i_color_type == PNG_COLOR_TYPE_PALETTE )
        png_set_palette_to_rgb( p_png );

    if( i_color_type == PNG_COLOR_TYPE_GRAY ||
        i_color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
          png_set_gray_to_rgb( p_png );

    /* Strip to 8 bits per channel */
    if( i_bit_depth == 16 ) png_set_strip_16( p_png );

    if( png_get_valid( p_png, p_info, PNG_INFO_tRNS ) )
    {
        png_set_tRNS_to_alpha( p_png );
    }
    else if( !(i_color_type & PNG_COLOR_MASK_ALPHA) )
    {
        p_dec->fmt_out.i_codec = VLC_CODEC_RGB24;
    }

    /* Get a new picture */
    p_pic = decoder_NewPicture( p_dec );
    if( !p_pic ) goto error;

    /* Decode picture */
    p_row_pointers = malloc( sizeof(png_bytep) * i_height );
    if( !p_row_pointers )
        goto error;
    for( i = 0; i < (int)i_height; i++ )
        p_row_pointers[i] = p_pic->p->p_pixels + p_pic->p->i_pitch * i;

    png_read_image( p_png, p_row_pointers );
    if( p_sys->b_error ) goto error;
    png_read_end( p_png, p_end_info );
    if( p_sys->b_error ) goto error;

    png_destroy_read_struct( &p_png, &p_info, &p_end_info );
    free( p_row_pointers );

    p_pic->date = p_block->i_pts > VLC_TS_INVALID ? p_block->i_pts : p_block->i_dts;

    block_Release( p_block ); *pp_block = NULL;
    return p_pic;

 error:

    free( p_row_pointers );
    png_destroy_read_struct( &p_png, &p_info, &p_end_info );
    block_Release( p_block ); *pp_block = NULL;
    return NULL;
}
Beispiel #20
0
static bool loadPng(const uint8_t *inputData, size_t size,
		Bytes &outputData, Color &color, Alpha &alpha, uint32_t &width, uint32_t &height,
		uint32_t &stride, const Bitmap::StrideFn &strideFn) {
	auto png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {
    	log::text("libpng", "fail to create read struct");
        return false;
    }

    auto info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
    	log::text("libpng", "fail to create info struct");
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return false;
    }

	if (setjmp(png_jmpbuf(png_ptr))) {
		log::text("libpng", "error in processing (setjmp return)");
	    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	    return false;
	}

	Bitmap_readState state;
	state.data = inputData;
	state.offset = 0;

	png_set_read_fn(png_ptr,(png_voidp)&state, Bitmap_readDynamicData);
    png_read_info(png_ptr, info_ptr);

    width = png_get_image_width(png_ptr, info_ptr);
    height = png_get_image_height(png_ptr, info_ptr);
    png_byte bitdepth = png_get_bit_depth(png_ptr, info_ptr);
    png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr);

    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(png_ptr);
    }
    if (color_type == PNG_COLOR_TYPE_GRAY && bitdepth < 8) {
    	bitdepth = 8;
        png_set_expand_gray_1_2_4_to_8(png_ptr);
    }
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
        png_set_tRNS_to_alpha(png_ptr);
    }
    if (bitdepth == 16) {
        png_set_strip_16(png_ptr);
    }
    if (bitdepth < 8) {
        png_set_packing(png_ptr);
    }

    png_read_update_info(png_ptr, info_ptr);
    bitdepth = png_get_bit_depth(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
	auto rowbytes = png_get_rowbytes(png_ptr, info_ptr);

	if (color_type == PNG_COLOR_TYPE_GRAY) {
		color = (color == Color::A8?Color::A8:Color::I8);
	} else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
		color = Color::IA88;
	} else if (color_type == PNG_COLOR_TYPE_RGB) {
		color = Color::RGB888;
	} else if (color_type == PNG_COLOR_TYPE_RGBA) {
		color = Color::RGBA8888;
	} else {
		width = 0;
		height = 0;
		stride = 0;
		outputData.clear();
        log::format("Bitmap", "unsupported color type: %u", (unsigned int)color_type);
	    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	    return false;
	}

	if (strideFn) {
		stride = max((uint32_t)strideFn(color, width), (uint32_t)rowbytes);
	} else {
		stride = (uint32_t)rowbytes;
	}

	if (color == Color::I8 || color == Color::RGB888) {
		alpha = Alpha::Opaque;
	} else {
		alpha = Alpha::Unpremultiplied;
	}

    // read png data
    png_bytep* row_pointers = new png_bytep[height];

    auto dataLen = stride * height;
    outputData.resize(dataLen);

    for (unsigned short i = 0; i < height; ++i) {
        row_pointers[i] = outputData.data() + i*stride;
    }

    png_read_image(png_ptr, row_pointers);
    png_read_end(png_ptr, nullptr);

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    delete [] row_pointers;

	if (!outputData.empty()) {
		return true;
	}

	return false;
}
Beispiel #21
0
bool Image::initWithPngData(const unsigned char * data, ssize_t dataLen)
{
#if CC_USE_WIC
	return decodeWithWIC(data, dataLen);
#else
	// length of bytes to check if it is a valid png file
#define PNGSIGSIZE  8
	bool ret = false;
	png_byte        header[PNGSIGSIZE] = { 0 };
	png_structp     png_ptr = 0;
	png_infop       info_ptr = 0;

	do
	{
		// png header len is 8 bytes
		CC_BREAK_IF(dataLen < PNGSIGSIZE);

		// check the data is png or not
		memcpy(header, data, PNGSIGSIZE);
		CC_BREAK_IF(png_sig_cmp(header, 0, PNGSIGSIZE));

		// init png_struct
		png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
		CC_BREAK_IF(!png_ptr);

		// init png_info
		info_ptr = png_create_info_struct(png_ptr);
		CC_BREAK_IF(!info_ptr);

#if (PARA_TARGET_PLATFORM != PARA_PLATFORM_BADA && PARA_TARGET_PLATFORM != PARA_PLATFORM_NACL && PARA_TARGET_PLATFORM != PARA_PLATFORM_TIZEN)
		CC_BREAK_IF(setjmp(png_jmpbuf(png_ptr)));
#endif

		// set the read call back function
		tImageSource imageSource;
		imageSource.data = (unsigned char*)data;
		imageSource.size = dataLen;
		imageSource.offset = 0;
		png_set_read_fn(png_ptr, &imageSource, pngReadCallback);

		// read png header info

		// read png file info
		png_read_info(png_ptr, info_ptr);

		_width = png_get_image_width(png_ptr, info_ptr);
		_height = png_get_image_height(png_ptr, info_ptr);
		png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
		png_uint_32 color_type = png_get_color_type(png_ptr, info_ptr);

		//OUTPUT_LOG("color type %u", color_type);

		// force palette images to be expanded to 24-bit RGB
		// it may include alpha channel
		if (color_type == PNG_COLOR_TYPE_PALETTE)
		{
			png_set_palette_to_rgb(png_ptr);
		}
		// low-bit-depth grayscale images are to be expanded to 8 bits
		if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
		{
			bit_depth = 8;
			png_set_expand_gray_1_2_4_to_8(png_ptr);
		}
		// expand any tRNS chunk data into a full alpha channel
		if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		{
			png_set_tRNS_to_alpha(png_ptr);
		}
		// reduce images with 16-bit samples to 8 bits
		if (bit_depth == 16)
		{
			png_set_strip_16(png_ptr);
		}

		// Expanded earlier for grayscale, now take care of palette and rgb
		if (bit_depth < 8)
		{
			png_set_packing(png_ptr);
		}
		// update info
		png_read_update_info(png_ptr, info_ptr);
		bit_depth = png_get_bit_depth(png_ptr, info_ptr);
		color_type = png_get_color_type(png_ptr, info_ptr);

		switch (color_type)
		{
		case PNG_COLOR_TYPE_GRAY:
			_renderFormat = Texture2D::PixelFormat::I8;
			break;
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			_renderFormat = Texture2D::PixelFormat::AI88;
			break;
		case PNG_COLOR_TYPE_RGB:
			_renderFormat = Texture2D::PixelFormat::RGB888;
			break;
		case PNG_COLOR_TYPE_RGB_ALPHA:
			_renderFormat = Texture2D::PixelFormat::RGBA8888;
			break;
		default:
			break;
		}

		// read png data
		png_size_t rowbytes;
		png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * _height);

		rowbytes = png_get_rowbytes(png_ptr, info_ptr);

		_dataLen = rowbytes * _height;
		_data = static_cast<unsigned char*>(malloc(_dataLen * sizeof(unsigned char)));
		if (!_data)
		{
			if (row_pointers != nullptr)
			{
				free(row_pointers);
			}
			break;
		}

		for (unsigned short i = 0; i < _height; ++i)
		{
			row_pointers[i] = _data + i*rowbytes;
		}
		png_read_image(png_ptr, row_pointers);

		png_read_end(png_ptr, nullptr);

		// premultiplied alpha for RGBA8888
		if (PNG_PREMULTIPLIED_ALPHA_ENABLED && color_type == PNG_COLOR_TYPE_RGB_ALPHA)
		{
			premultipliedAlpha();
		}

		if (row_pointers != nullptr)
		{
			free(row_pointers);
		}

		ret = true;
	} while (0);

	if (png_ptr)
	{
		png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0);
	}
	return ret;
#endif
}
int ReadPNG(FILE* in_file, WebPPicture* const pic, int keep_alpha,
            Metadata* const metadata) {
  png_structp png;
  png_infop info = NULL;
  png_infop end_info = NULL;
  int color_type, bit_depth, interlaced;
  int has_alpha;
  int num_passes;
  int p;
  int ok = 0;
  png_uint_32 width, height, y;
  int stride;
  uint8_t* rgb = NULL;

  png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
  if (png == NULL) {
    goto End;
  }

  png_set_error_fn(png, 0, error_function, NULL);
  if (setjmp(png_jmpbuf(png))) {
 Error:
    MetadataFree(metadata);
    png_destroy_read_struct(&png, &info, &end_info);
    goto End;
  }

  info = png_create_info_struct(png);
  if (info == NULL) goto Error;
  end_info = png_create_info_struct(png);
  if (end_info == NULL) goto Error;

  png_init_io(png, in_file);
  png_read_info(png, info);
  if (!png_get_IHDR(png, info,
                    &width, &height, &bit_depth, &color_type, &interlaced,
                    NULL, NULL)) goto Error;

  png_set_strip_16(png);
  png_set_packing(png);
  if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png);
  if (color_type == PNG_COLOR_TYPE_GRAY ||
      color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
    if (bit_depth < 8) {
      png_set_expand_gray_1_2_4_to_8(png);
    }
    png_set_gray_to_rgb(png);
  }
  if (png_get_valid(png, info, PNG_INFO_tRNS)) {
    png_set_tRNS_to_alpha(png);
    has_alpha = 1;
  } else {
    has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
  }

  if (!keep_alpha) {
    png_set_strip_alpha(png);
    has_alpha = 0;
  }

  num_passes = png_set_interlace_handling(png);
  png_read_update_info(png, info);
  stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb);
  rgb = (uint8_t*)malloc(stride * height);
  if (rgb == NULL) goto Error;
  for (p = 0; p < num_passes; ++p) {
    for (y = 0; y < height; ++y) {
      png_bytep row = rgb + y * stride;
      png_read_rows(png, &row, NULL, 1);
    }
  }
  png_read_end(png, end_info);

  if (metadata != NULL &&
      !ExtractMetadataFromPNG(png, info, end_info, metadata)) {
    fprintf(stderr, "Error extracting PNG metadata!\n");
    goto Error;
  }

  png_destroy_read_struct(&png, &info, &end_info);

  pic->width = width;
  pic->height = height;
  ok = has_alpha ? WebPPictureImportRGBA(pic, rgb, stride)
                 : WebPPictureImportRGB(pic, rgb, stride);

  if (!ok) {
    goto Error;
  }

 End:
  free(rgb);
  return ok;
}
Beispiel #23
0
/* 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;
}
Beispiel #24
0
PyObject*
_png_module::_read_png(const Py::Object& py_fileobj, const bool float_result,
                       int result_bit_depth)
{
    png_byte header[8];   // 8 is the maximum size that can be checked
    FILE* fp = NULL;
    bool close_file = false;
    bool close_dup_file = false;
    PyObject *py_file = NULL;

    if (py_fileobj.isString())
    {
        if ((py_file = npy_PyFile_OpenFile(py_fileobj.ptr(), (char *)"rb")) == NULL) {
            throw Py::Exception();
        }
        close_file = true;
    } else {
        py_file = py_fileobj.ptr();
    }

    if ((fp = npy_PyFile_Dup(py_file, "rb")))
    {
        close_dup_file = true;
    }
    else
    {
        PyErr_Clear();
        PyObject* read_method = PyObject_GetAttrString(py_file, "read");
        if (!(read_method && PyCallable_Check(read_method)))
        {
            Py_XDECREF(read_method);
            throw Py::TypeError(
                "Object does not appear to be a 8-bit string path or a Python "
                "file-like object");
        }
        Py_XDECREF(read_method);
    }

    if (fp)
    {
        if (fread(header, 1, 8, fp) != 8)
        {
            throw Py::RuntimeError(
                "_image_module::readpng: error reading PNG header");
        }
    }
    else
    {
        _read_png_data(py_file, header, 8);
    }
    if (png_sig_cmp(header, 0, 8))
    {
        throw Py::RuntimeError(
            "_image_module::readpng: file not recognized as a PNG file");
    }

    /* initialize stuff */
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

    if (!png_ptr)
    {
        throw Py::RuntimeError(
            "_image_module::readpng:  png_create_read_struct failed");
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        throw Py::RuntimeError(
            "_image_module::readpng:  png_create_info_struct failed");
    }

    if (setjmp(png_jmpbuf(png_ptr)))
    {
        throw Py::RuntimeError(
            "_image_module::readpng:  error during init_io");
    }

    if (fp)
    {
        png_init_io(png_ptr, fp);
    }
    else
    {
        png_set_read_fn(png_ptr, (void*)py_file, &read_png_data);
    }
    png_set_sig_bytes(png_ptr, 8);
    png_read_info(png_ptr, info_ptr);

    png_uint_32 width = png_get_image_width(png_ptr, info_ptr);
    png_uint_32 height = png_get_image_height(png_ptr, info_ptr);

    int bit_depth = png_get_bit_depth(png_ptr, info_ptr);

    // Unpack 1, 2, and 4-bit images
    if (bit_depth < 8)
        png_set_packing(png_ptr);

    // If sig bits are set, shift data
    png_color_8p sig_bit;
    if ((png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_PALETTE) &&
        png_get_sBIT(png_ptr, info_ptr, &sig_bit))
    {
        png_set_shift(png_ptr, sig_bit);
    }

    // Convert big endian to little
    if (bit_depth == 16)
    {
        png_set_swap(png_ptr);
    }

    // Convert palletes to full RGB
    if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE)
    {
        png_set_palette_to_rgb(png_ptr);
        bit_depth = 8;
    }

    // If there's an alpha channel convert gray to RGB
    if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY_ALPHA)
    {
        png_set_gray_to_rgb(png_ptr);
    }

    png_set_interlace_handling(png_ptr);
    png_read_update_info(png_ptr, info_ptr);

    /* read file */
    if (setjmp(png_jmpbuf(png_ptr)))
    {
        throw Py::RuntimeError(
            "_image_module::readpng: error during read_image");
    }

    png_bytep *row_pointers = new png_bytep[height];
    png_uint_32 row;

    for (row = 0; row < height; row++)
    {
        row_pointers[row] = new png_byte[png_get_rowbytes(png_ptr,info_ptr)];
    }

    png_read_image(png_ptr, row_pointers);

    npy_intp dimensions[3];
    dimensions[0] = height;  //numrows
    dimensions[1] = width;   //numcols
    if (png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_ALPHA)
    {
        dimensions[2] = 4;     //RGBA images
    }
    else if (png_get_color_type(png_ptr, info_ptr) & PNG_COLOR_MASK_COLOR)
    {
        dimensions[2] = 3;     //RGB images
    }
    else
    {
        dimensions[2] = 1;     //Greyscale images
    }
    //For gray, return an x by y array, not an x by y by 1
    int num_dims  = (png_get_color_type(png_ptr, info_ptr)
                                & PNG_COLOR_MASK_COLOR) ? 3 : 2;

    PyArrayObject *A = NULL;
    if (float_result) {
        double max_value = (1 << bit_depth) - 1;

        A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, NPY_FLOAT);

        if (A == NULL)
        {
            throw Py::MemoryError("Could not allocate image array");
        }

        for (png_uint_32 y = 0; y < height; y++)
        {
            png_byte* row = row_pointers[y];
            for (png_uint_32 x = 0; x < width; x++)
            {
                size_t offset = y * A->strides[0] + x * A->strides[1];
                if (bit_depth == 16)
                {
                    png_uint_16* ptr = &reinterpret_cast<png_uint_16*>(row)[x * dimensions[2]];
                    for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                    {
                        *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value;
                    }
                }
                else
                {
                    png_byte* ptr = &(row[x * dimensions[2]]);
                    for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                    {
                        *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value;
                    }
                }
            }
        }
    } else {
        if (result_bit_depth < 0) {
            result_bit_depth = bit_depth;
        }

        if (result_bit_depth == 8) {
            A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, NPY_UBYTE);
        } else if (result_bit_depth == 16) {
            A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, NPY_UINT16);
        } else {
            throw Py::RuntimeError(
                "_image_module::readpng: image has unknown bit depth");
        }

        if (A == NULL)
        {
            throw Py::MemoryError("Could not allocate image array");
        }

        for (png_uint_32 y = 0; y < height; y++)
        {
            png_byte* row = row_pointers[y];
            for (png_uint_32 x = 0; x < width; x++)
            {
                size_t offset = y * A->strides[0] + x * A->strides[1];
                if (bit_depth == 16)
                {
                    png_uint_16* ptr = &reinterpret_cast<png_uint_16*>(row)[x * dimensions[2]];

                    if (result_bit_depth == 16) {
                        for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                        {
                            *(png_uint_16*)(A->data + offset + p*A->strides[2]) = ptr[p];
                        }
                    } else {
                        for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                        {
                            *(png_byte*)(A->data + offset + p*A->strides[2]) = ptr[p] >> 8;
                        }
                    }
                }
                else
                {
                    png_byte* ptr = &(row[x * dimensions[2]]);
                    if (result_bit_depth == 16) {
                        for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                        {
                            *(png_uint_16*)(A->data + offset + p*A->strides[2]) = ptr[p];
                        }
                    } else {
                        for (png_uint_32 p = 0; p < (png_uint_32)dimensions[2]; p++)
                        {
                            *(png_byte*)(A->data + offset + p*A->strides[2]) = ptr[p];
                        }
                    }
                }
            }
        }
Beispiel #25
0
PNGImage LoadImagePNG(const char *path)
{
	PNGImage loadedImage;
	loadedImage.loadedSuccessfully = GL_FALSE;
	
	FILE *PNG_file = fopen(path, "rb");
    if (PNG_file == NULL)
    {
        printf("Can't open PNG file %s\n", path);
        return loadedImage;
    }
    
    GLubyte PNG_header[PNG_HEADER_SIZE];
    
    fread(PNG_header, 1, PNG_HEADER_SIZE, PNG_file);
    if (png_sig_cmp(PNG_header, 0, PNG_HEADER_SIZE) != 0)
    {
        printf("%s is not a PNG file\n", path);
        return loadedImage;
    }
    
    png_structp PNG_reader
	= png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (PNG_reader == NULL)
    {
        printf("Can't start reading PNG file %s\n", path);
        fclose(PNG_file);
        return loadedImage;
    }
	
    png_infop PNG_info = png_create_info_struct(PNG_reader);
    if (PNG_info == NULL)
    {
        printf("Can't get info for PNG file %s\n", path);
		
        png_destroy_read_struct(&PNG_reader, NULL, NULL);
        fclose(PNG_file);
        return loadedImage;
    }
	
    png_infop PNG_end_info = png_create_info_struct(PNG_reader);
    if (PNG_end_info == NULL)
    {
        printf("Can't get end info for PNG file %s\n", path);
		
        png_destroy_read_struct(&PNG_reader, &PNG_info, NULL);
        fclose(PNG_file);
        return loadedImage;
    }
    
    if (setjmp(png_jmpbuf(PNG_reader)))
    {
        printf("Can't load PNG file %s\n", path);
		
        png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
        fclose(PNG_file);
        return loadedImage;
    }
    
    png_init_io(PNG_reader, PNG_file);
    png_set_sig_bytes(PNG_reader, PNG_HEADER_SIZE);
    
    png_read_info(PNG_reader, PNG_info);
	
	// we have to do a custom transformation to premultiply the alpha of the image
    png_set_read_user_transform_fn(PNG_reader, png_read_premultiply_alpha);
    
	png_uint_32 width, height;
    int bit_depth, color_type;
    
	png_get_IHDR(PNG_reader, PNG_info, &width, &height, &bit_depth, &color_type,NULL, NULL, NULL);
	
    if (color_type == PNG_COLOR_TYPE_PALETTE)
    {
        png_set_palette_to_rgb(PNG_reader);
    }
	
    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) 
    {
        png_set_expand_gray_1_2_4_to_8(PNG_reader);
    }
    
    if (color_type == PNG_COLOR_TYPE_GRAY ||
        color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    {
        png_set_gray_to_rgb(PNG_reader);
    }
	
    if (png_get_valid(PNG_reader, PNG_info, PNG_INFO_tRNS))
    {
        png_set_tRNS_to_alpha(PNG_reader);
    }
    else
    {
        png_set_filler(PNG_reader, 0xff, PNG_FILLER_AFTER);
    }
    

    if (bit_depth == 16)
    {
        png_set_strip_16(PNG_reader);
    }
	
    png_read_update_info(PNG_reader, PNG_info);
    
	png_uint_32 widthPow2, heightPow2;
	widthPow2 = pow2(width);
	heightPow2 = pow2(height);
	
    png_byte* PNG_image_buffer = (png_byte*)malloc(4 * widthPow2 * heightPow2);
	memset(PNG_image_buffer,0,4*widthPow2*heightPow2); // clear image buffer
    png_byte** PNG_rows = (png_byte**)malloc(height * sizeof(png_byte*));


	png_uint_32 rowBytes = widthPow2*4;

	// load the image from the bottom up
	/*
	 image texture in mem looks like:
	 --------
	 |       |
	 |xxxx	 |
	 |xxxx	 |
	 --------
	 where 'x's represent actual image data and the lines are the image buffer.
	 so the image is aligned at the (0,0) texel coordinate of the image buffer.
	 */
	unsigned int row;
    for (row = 0; row < height; ++row)
    {
        PNG_rows[height-1-row] = PNG_image_buffer + (row * rowBytes);
    }
    png_read_image(PNG_reader, PNG_rows);
	
    free(PNG_rows);
   
    png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
    fclose(PNG_file);
    
	
	GLuint textureID = 0;
	glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	
	glTexImage2D(
				 GL_TEXTURE_2D,
				 0,
				 GL_RGBA,
				 widthPow2,
				 heightPow2,
				 0,
				 GL_RGBA,
				 GL_UNSIGNED_BYTE,
				 PNG_image_buffer);
    
     free(PNG_image_buffer);
	
	loadedImage.width = width;
	loadedImage.height = height;
	loadedImage.widthPow2 = widthPow2;
	loadedImage.heightPow2 = heightPow2;
	loadedImage.textureId = textureID;
	loadedImage.loadedSuccessfully = GL_TRUE;
	
    return loadedImage;
}
Beispiel #26
0
unsigned char* load_png_data(char *filename, int *w, int *h) {
    FILE *fp = fopen(filename, "rb");
    if(!fp) {
        return NULL;
    }
    png_byte header[8];
    fread(header, 1, 8, fp);
    if(png_sig_cmp(header, 0, 8)) {
        return NULL;
    }

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if(!png_ptr) {
        return NULL;
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if(!info_ptr) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        fclose(fp);
        return NULL;
    }

    png_infop end_ptr = png_create_info_struct(png_ptr);
    if(!end_ptr) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        fclose(fp);
        return NULL;
    }

    if(setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_ptr);
        fclose(fp);
        return NULL;
    }

    png_init_io(png_ptr, fp);
    png_set_sig_bytes(png_ptr, 8);

    png_read_info(png_ptr, info_ptr);

    int bit_depth = png_get_bit_depth(png_ptr, info_ptr);

    switch(png_get_color_type(png_ptr, info_ptr)) {
    case PNG_COLOR_TYPE_PALETTE:
        png_set_palette_to_rgb(png_ptr);
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
        break;
    case PNG_COLOR_TYPE_GRAY:
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
    case PNG_COLOR_TYPE_GRAY_ALPHA:
        if(bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr);
        if(bit_depth==16) png_set_strip_16(png_ptr);
        png_set_gray_to_rgb(png_ptr);
        break;
    case PNG_COLOR_TYPE_RGB:
        if(bit_depth <  8 ) png_set_packing(png_ptr);
        if(bit_depth == 16) png_set_strip_16(png_ptr);
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
        break;
    default:
        break;
    }

    png_read_update_info(png_ptr, info_ptr);

    *w = png_get_image_width(png_ptr, info_ptr);
    *h = png_get_image_height(png_ptr, info_ptr);
    int rowbytes = (int)png_get_rowbytes(png_ptr, info_ptr);

    png_bytep data = malloc((*h)*rowbytes*sizeof(*data));

    png_bytep row_pointers[*h];

    int i;
    for(i=0; i<(*h); ++i) {
        row_pointers[i] = &data[i*rowbytes];
    }

    png_read_image(png_ptr, row_pointers);

    png_destroy_read_struct(&png_ptr, &info_ptr, &end_ptr);

    fclose(fp);

    return data;
}
Beispiel #27
0
static png_bytepp 
eiio_png_read_rgb(const void *blob, size_t blob_size, int *width, int *height, int *channels)
{
	png_structp png = NULL;
	png_infop info = NULL;
	blob_input_t blob_input;
	int bit_depth, color_type;
	png_bytepp rows = NULL;
	png_uint_32 uwidth, uheight;
	int i;

	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png == NULL){
		return NULL;
	}

	info = png_create_info_struct(png);
	if(info == NULL){
		png_destroy_read_struct(&png, NULL, NULL);
		return NULL;
	}

	if (setjmp(png_jmpbuf(png))) {
		png_destroy_read_struct(&png, &info, NULL);
		eiio_png_rows_free(&rows);

		return NULL;
	}

	blob_input.blob = blob;
	blob_input.offset = 0;
	blob_input.blob_size = blob_size;
	png_set_read_fn(png, &blob_input, read_blob);

	*width = *height = 0;
	png_read_info(png, info);
	png_get_IHDR(png, info, &uwidth, &uheight, &bit_depth, &color_type, NULL, NULL, NULL);

	if (uwidth > 0x7fffffff || uheight > 0x7fffffff) {
		png_destroy_read_struct(&png, &info, NULL);
		eiio_png_rows_free(&rows);

		return NULL;
	}
	*width = (int)uwidth;
	*height = (int)uheight;	

	if (bit_depth == 16) {
		png_set_strip_16(png);
	}
	if ((color_type == PNG_COLOR_TYPE_GRAY 
		|| color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
		&& bit_depth < 8) 
	{
		png_set_expand_gray_1_2_4_to_8(png);
		//png_set_gray_1_2_4_to_8(png);
	}

	if (bit_depth < 8) {
		png_set_packing(png);
	}

	if (color_type & PNG_COLOR_MASK_ALPHA) {
		*channels = 4;
	} else {
		*channels = 3;
	}

	if (color_type & PNG_COLOR_MASK_PALETTE) {
		png_set_palette_to_rgb(png);
	}

	if (color_type == PNG_COLOR_TYPE_GRAY
		|| color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 
	{
		png_set_gray_to_rgb(png);
	}
	png_read_update_info(png, info);

	rows = (png_bytepp)eiio_malloc(sizeof(png_bytep) * (*height + 1));
	if (rows == NULL) {
		png_destroy_read_struct(&png, &info, NULL);
		return NULL;
	}
	for (i = 0; i < *height; ++i) {
		rows[i] = (png_bytep)eiio_malloc(sizeof(png_byte) * *width * *channels);
		if (rows[i] == NULL) {
			png_destroy_read_struct(&png, &info, NULL);
			eiio_png_rows_free(&rows);
			return NULL;
		}
	}
	rows[*height] = NULL; /* null terminater */

	png_read_image(png, rows);
	png_read_end(png, info);

	png_destroy_read_struct(&png, &info, NULL);

	return rows;
}
Beispiel #28
0
 int read_png(const std::string & file_name, image_t & image) {
  png_structp png;
  png_infop info;
  int color_type, bit_depth, interlaced;
  int has_alpha;
  int num_passes;
  int p;
  int ok = 0;
  png_uint_32 width, height, y;
  int stride;
  uint8_t* rgb = NULL;

  FILE * fp;

	#ifdef LINUX
	  fp = fopen(file_name.c_str(), "rb");
	#endif
	#ifdef WINDOWS
	  fopen_s(&fp, file_name.c_str(), "rb");
	#endif
	if (fp == NULL)
		throw  webp::exception::FileOperationException();

  png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
  if (png == NULL) {
    goto End;
  }

  png_set_error_fn(png, 0, error_function, NULL);
  if (setjmp(png_jmpbuf(png))) {
 Error:
    png_destroy_read_struct(&png, NULL, NULL);
    free(rgb);
    goto End;
  }

  info = png_create_info_struct(png);
  if (info == NULL) goto Error;

  png_init_io(png, fp);
  png_read_info(png, info);
  if (!png_get_IHDR(png, info,
                    &width, &height, &bit_depth, &color_type, &interlaced,
                    NULL, NULL)) goto Error;

  png_set_strip_16(png);
  png_set_packing(png);
  if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png);
  if (color_type == PNG_COLOR_TYPE_GRAY ||
      color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
    if (bit_depth < 8) {
      png_set_expand_gray_1_2_4_to_8(png);
    }
    png_set_gray_to_rgb(png);
  }
  if (png_get_valid(png, info, PNG_INFO_tRNS)) {
    png_set_tRNS_to_alpha(png);
    has_alpha = 1;
  } else {
    has_alpha = !!(color_type & PNG_COLOR_MASK_ALPHA);
  }


  num_passes = png_set_interlace_handling(png);
  png_read_update_info(png, info);
  stride = (has_alpha ? 4 : 3) * width * sizeof(*rgb);
  rgb = (uint8_t*)malloc(stride * height);
  if (rgb == NULL) goto Error;
  for (p = 0; p < num_passes; ++p) {
    for (y = 0; y < height; ++y) {
      png_bytep row = rgb + y * stride;
      png_read_rows(png, &row, NULL, 1);
    }
  }
  png_read_end(png, info);
  png_destroy_read_struct(&png, &info, NULL);

  image.width = width;
  image.height = height;
  image.image.realloc(height * width);
  for(size_t y = 0; y < height; y++)
	  for(size_t x = 0; x < width; x++){
		  size_t i = y * width + x;
		  if (has_alpha) {
			  *webp::utils::ALPHA(image.image[i]) = rgb[stride * y + x * 4];
			  *webp::utils::RED(image.image[i])   = rgb[stride * y + x * 4 + 1];
			  *webp::utils::GREEN(image.image[i]) = rgb[stride * y + x * 4 + 2];
			  *webp::utils::BLUE(image.image[i])  = rgb[stride * y + x * 4 + 3];
		  }
		  else{
			  *webp::utils::ALPHA(image.image[i]) = 0xFF;
			  *webp::utils::RED(image.image[i])   = rgb[stride * y + x * 3];
			  *webp::utils::GREEN(image.image[i]) = rgb[stride * y + x * 3 + 1];
			  *webp::utils::BLUE(image.image[i])  = rgb[stride * y + x * 3 + 2];
		  }
	  }
  free(rgb);
  
 End:
  fclose(fp);
  return ok;
}
Beispiel #29
0
Datei: png.c Projekt: jinjoh/NOOR
struct ImBuf *imb_loadpng(unsigned char *mem, int size, int flags)
{
    struct ImBuf *ibuf = 0;
    png_structp png_ptr;
    png_infop info_ptr;
    unsigned char *pixels = 0;
    png_bytepp row_pointers = 0;
    png_uint_32 width, height;
    int bit_depth, color_type;
    PNGReadStruct ps;

    unsigned char *from, *to;
    int i, bytesperpixel;

    if (imb_is_a_png(mem) == 0) return(0);

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                     NULL, NULL, NULL);
    if (png_ptr == NULL) {
        printf("Cannot png_create_read_struct\n");
        return 0;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL,
                                (png_infopp)NULL);
        printf("Cannot png_create_info_struct\n");
        return 0;
    }

    ps.size = size;
    ps.data = mem;
    ps.seek = 0;

    png_set_read_fn(png_ptr, (void *) &ps, ReadData);

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
        if (pixels) MEM_freeN(pixels);
        if (row_pointers) MEM_freeN(row_pointers);
        if (ibuf) IMB_freeImBuf(ibuf);
        return 0;
    }

    // png_set_sig_bytes(png_ptr, 8);

    png_read_info(png_ptr, info_ptr);
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
                 &color_type, NULL, NULL, NULL);

    if (bit_depth == 16) {
        png_set_strip_16(png_ptr);
        bit_depth = 8;
    }

    bytesperpixel = png_get_channels(png_ptr, info_ptr);

    switch(color_type) {
    case PNG_COLOR_TYPE_RGB:
    case PNG_COLOR_TYPE_RGB_ALPHA:
        break;
    case PNG_COLOR_TYPE_PALETTE:
        png_set_palette_to_rgb(png_ptr);
        if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
            bytesperpixel = 4;
        } else {
            bytesperpixel = 3;
        }
        break;
    case PNG_COLOR_TYPE_GRAY:
    case PNG_COLOR_TYPE_GRAY_ALPHA:
        if (bit_depth < 8) {
            png_set_expand(png_ptr);
            bit_depth = 8;
        }
        break;
    default:
        printf("PNG format not supported\n");
        longjmp(png_jmpbuf(png_ptr), 1);
    }

    ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0, 0);

    if (ibuf) {
        ibuf->ftype = PNG;
    } else {
        printf("Couldn't allocate memory for PNG image\n");
    }

    if (ibuf && ((flags & IB_test) == 0)) {
        imb_addrectImBuf(ibuf);

        pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
        if (pixels == NULL) {
            printf("Cannot allocate pixels array\n");
            longjmp(png_jmpbuf(png_ptr), 1);
        }

        // allocate memory for an array of row-pointers
        row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
        if (row_pointers == NULL) {
            printf("Cannot allocate row-pointers array\n");
            longjmp(png_jmpbuf(png_ptr), 1);
        }

        // set the individual row-pointers to point at the correct offsets
        for (i = 0; i < ibuf->y; i++) {
            row_pointers[ibuf->y-1-i] = (png_bytep)
                                        ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char));
        }

        png_read_image(png_ptr, row_pointers);

        // copy image data

        to = (unsigned char *) ibuf->rect;
        from = pixels;

        switch (bytesperpixel) {
        case 4:
            for (i = ibuf->x * ibuf->y; i > 0; i--) {
                to[0] = from[0];
                to[1] = from[1];
                to[2] = from[2];
                to[3] = from[3];
                to += 4;
                from += 4;
            }
            break;
        case 3:
            for (i = ibuf->x * ibuf->y; i > 0; i--) {
                to[0] = from[0];
                to[1] = from[1];
                to[2] = from[2];
                to[3] = 0xff;
                to += 4;
                from += 3;
            }
            break;
        case 2:
            for (i = ibuf->x * ibuf->y; i > 0; i--) {
                to[0] = to[1] = to[2] = from[0];
                to[3] = from[1];
                to += 4;
                from += 2;
            }
            break;
        case 1:
            for (i = ibuf->x * ibuf->y; i > 0; i--) {
                to[0] = to[1] = to[2] = from[0];
                to[3] = 0xff;
                to += 4;
                from++;
            }
            break;
        }

        if (flags & IB_imginfo) {
            png_text* text_chunks;
            int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL);
            for(i = 0; i < count; i++) {
                IMB_imginfo_add_field(ibuf, text_chunks[i].key, text_chunks[i].text);
                ibuf->flags |= IB_imginfo;
            }
        }

        png_read_end(png_ptr, info_ptr);
    }

    // clean up
    MEM_freeN(pixels);
    MEM_freeN(row_pointers);
    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);

    return(ibuf);
}
Beispiel #30
0
ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
	struct ImBuf *ibuf = NULL;
	png_structp png_ptr;
	png_infop info_ptr;
	unsigned char *pixels = NULL;
	unsigned short *pixels16 = NULL;
	png_bytepp row_pointers = NULL;
	png_uint_32 width, height;
	int bit_depth, color_type;
	PNGReadStruct ps;

	unsigned char *from, *to;
	unsigned short *from16;
	float *to_float;
	int i, bytesperpixel;

	if (imb_is_a_png(mem) == 0) return(NULL);

	/* both 8 and 16 bit PNGs are default to standard byte colorspace */
	colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
	                                 NULL, NULL, NULL);
	if (png_ptr == NULL) {
		printf("Cannot png_create_read_struct\n");
		return NULL;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, 
		                        (png_infopp)NULL);
		printf("Cannot png_create_info_struct\n");
		return NULL;
	}

	ps.size = size; /* XXX, 4gig limit! */
	ps.data = mem;
	ps.seek = 0;

	png_set_read_fn(png_ptr, (void *) &ps, ReadData);

	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		if (pixels) MEM_freeN(pixels);
		if (pixels16) MEM_freeN(pixels16);
		if (row_pointers) MEM_freeN(row_pointers);
		if (ibuf) IMB_freeImBuf(ibuf);
		return NULL;
	}

	// png_set_sig_bytes(png_ptr, 8);

	png_read_info(png_ptr, info_ptr);
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, 
	             &color_type, NULL, NULL, NULL);

	bytesperpixel = png_get_channels(png_ptr, info_ptr);

	switch (color_type) {
		case PNG_COLOR_TYPE_RGB:
		case PNG_COLOR_TYPE_RGB_ALPHA:
			break;
		case PNG_COLOR_TYPE_PALETTE:
			png_set_palette_to_rgb(png_ptr);
			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
				bytesperpixel = 4;
			}
			else {
				bytesperpixel = 3;
			}
			break;
		case PNG_COLOR_TYPE_GRAY:
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			if (bit_depth < 8) {
				png_set_expand(png_ptr);
				bit_depth = 8;
			}
			break;
		default:
			printf("PNG format not supported\n");
			longjmp(png_jmpbuf(png_ptr), 1);
			break;
	}
	
	ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0);

	if (ibuf) {
		ibuf->ftype = PNG;
		if (bit_depth == 16)
			ibuf->ftype |= PNG_16BIT;

		if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
			int unit_type;
			png_uint_32 xres, yres;

			if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type))
				if (unit_type == PNG_RESOLUTION_METER) {
					ibuf->ppm[0] = xres;
					ibuf->ppm[1] = yres;
				}
		}
	}
	else {
		printf("Couldn't allocate memory for PNG image\n");
	}

	if (ibuf && ((flags & IB_test) == 0)) {
		if (bit_depth == 16) {
			imb_addrectfloatImBuf(ibuf);
			png_set_swap(png_ptr);

			pixels16 = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(png_uint_16), "pixels");
			if (pixels16 == NULL) {
				printf("Cannot allocate pixels array\n");
				longjmp(png_jmpbuf(png_ptr), 1);
			}

			/* allocate memory for an array of row-pointers */
			row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_uint_16p), "row_pointers");
			if (row_pointers == NULL) {
				printf("Cannot allocate row-pointers array\n");
				longjmp(png_jmpbuf(png_ptr), 1);
			}

			/* set the individual row-pointers to point at the correct offsets */
			for (i = 0; i < ibuf->y; i++) {
				row_pointers[ibuf->y - 1 - i] = (png_bytep)
				                                ((png_uint_16 *)pixels16 + (i * ibuf->x) * bytesperpixel);
			}

			png_read_image(png_ptr, row_pointers);

			/* copy image data */

			to_float = ibuf->rect_float;
			from16 = pixels16;

			switch (bytesperpixel) {
				case 4:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to_float[0] = from16[0] / 65535.0;
						to_float[1] = from16[1] / 65535.0;
						to_float[2] = from16[2] / 65535.0;
						to_float[3] = from16[3] / 65535.0;
						to_float += 4; from16 += 4;
					}
					break;
				case 3:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to_float[0] = from16[0] / 65535.0;
						to_float[1] = from16[1] / 65535.0;
						to_float[2] = from16[2] / 65535.0;
						to_float[3] = 1.0;
						to_float += 4; from16 += 3;
					}
					break;
				case 2:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0;
						to_float[3] = from16[1] / 65535.0;
						to_float += 4; from16 += 2;
					}
					break;
				case 1:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0;
						to_float[3] = 1.0;
						to_float += 4; from16++;
					}
					break;
			}
		}
		else {
			imb_addrectImBuf(ibuf);

			pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels");
			if (pixels == NULL) {
				printf("Cannot allocate pixels array\n");
				longjmp(png_jmpbuf(png_ptr), 1);
			}

			/* allocate memory for an array of row-pointers */
			row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
			if (row_pointers == NULL) {
				printf("Cannot allocate row-pointers array\n");
				longjmp(png_jmpbuf(png_ptr), 1);
			}

			/* set the individual row-pointers to point at the correct offsets */
			for (i = 0; i < ibuf->y; i++) {
				row_pointers[ibuf->y - 1 - i] = (png_bytep)
				                                ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char));
			}

			png_read_image(png_ptr, row_pointers);

			/* copy image data */

			to = (unsigned char *) ibuf->rect;
			from = pixels;

			switch (bytesperpixel) {
				case 4:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to[0] = from[0];
						to[1] = from[1];
						to[2] = from[2];
						to[3] = from[3];
						to += 4; from += 4;
					}
					break;
				case 3:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to[0] = from[0];
						to[1] = from[1];
						to[2] = from[2];
						to[3] = 0xff;
						to += 4; from += 3;
					}
					break;
				case 2:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to[0] = to[1] = to[2] = from[0];
						to[3] = from[1];
						to += 4; from += 2;
					}
					break;
				case 1:
					for (i = ibuf->x * ibuf->y; i > 0; i--) {
						to[0] = to[1] = to[2] = from[0];
						to[3] = 0xff;
						to += 4; from++;
					}
					break;
			}
		}

		if (flags & IB_metadata) {
			png_text *text_chunks;
			int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL);
			for (i = 0; i < count; i++) {
				IMB_metadata_add_field(ibuf, text_chunks[i].key, text_chunks[i].text);
				ibuf->flags |= IB_metadata;
			}
		}

		png_read_end(png_ptr, info_ptr);
	}

	/* clean up */
	if (pixels)
		MEM_freeN(pixels);
	if (pixels16)
		MEM_freeN(pixels16);
	if (row_pointers)
		MEM_freeN(row_pointers);
	png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);

	return(ibuf);
}