Esempio n. 1
0
static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr) {
    mainprog_info *mainprog_ptr;
    int color_type, bit_depth;
    png_uint_32 width, height;
#ifdef PNG_FLOATING_POINT_SUPPORTED
    double  gamma;
#else
    png_fixed_point gamma;
#endif


    /* setjmp() doesn't make sense here, because we'd either have to exit(),
     * longjmp() ourselves, or return control to libpng, which doesn't want
     * to see us again.  By not doing anything here, libpng will instead jump
     * to readpng2_decode_data(), which can return an error value to the main
     * program. */


    /* retrieve the pointer to our special-purpose struct, using the png_ptr
     * that libpng passed back to us (i.e., not a global this time--there's
     * no real difference for a single image, but for a multithreaded browser
     * decoding several PNG images at the same time, one needs to avoid mixing
     * up different images' structs) */

    mainprog_ptr = png_get_progressive_ptr(png_ptr);

    if (mainprog_ptr == NULL) {         /* we be hosed */
        fprintf(stderr,
                "readpng2 error:  main struct not recoverable in info_callback.\n");
        fflush(stderr);
        return;
        /*
         * Alternatively, we could call our error-handler just like libpng
         * does, which would effectively terminate the program.  Since this
         * can only happen if png_ptr gets redirected somewhere odd or the
         * main PNG struct gets wiped, we're probably toast anyway.  (If
         * png_ptr itself is NULL, we would not have been called.)
         */
    }


    /* this is just like in the non-progressive case */

    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
                 NULL, NULL, NULL);
    mainprog_ptr->width = (ulg) width;
    mainprog_ptr->height = (ulg) height;


    /* since we know we've read all of the PNG file's "header" (i.e., up
     * to IDAT), we can check for a background color here */

    if (mainprog_ptr->need_bgcolor &&
        png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) {
        png_color_16p pBackground;

        /* it is not obvious from the libpng documentation, but this function
         * takes a pointer to a pointer, and it always returns valid red,
         * green and blue values, regardless of color_type: */
        png_get_bKGD(png_ptr, info_ptr, &pBackground);

        /* however, it always returns the raw bKGD data, regardless of any
         * bit-depth transformations, so check depth and adjust if necessary */
        if (bit_depth == 16) {
            mainprog_ptr->bg_red = pBackground->red >> 8;
            mainprog_ptr->bg_green = pBackground->green >> 8;
            mainprog_ptr->bg_blue = pBackground->blue >> 8;
        } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
Esempio n. 2
0
GLuint XL::Texture2D::loadPNG(const std::string& filePNG)
{
	//std::string fileName; //just in case
	//fileName = filePNG;

	//FILE* file = fopen(fileName.c_str(), "rb");
	//assert(file);

	file.open(filePNG, std::ios::binary);

	unsigned char header[8];
	file.read((char*)header, PNG_SIG_SIZE);
	//fread(header, 1, PNG_SIG_SIZE, file);

	if (!file.good())
	{
		std::cout << "FILE NOT GOOD!" << std::endl;
	}

	if(png_sig_cmp(header, 0, 8))
	{
		std::cout << filePNG.c_str() << " is not a PNG file" << std::endl;
	}

	png_structp pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	assert(pngPtr);

	png_infop infoPtr = png_create_info_struct(pngPtr);
	assert(infoPtr);

	png_bytep* rowPtrs = NULL;
	char* data = NULL;

	if (setjmp(png_jmpbuf(pngPtr)))
	{
		//this block executes when a libPNG error has occured
		png_destroy_read_struct(&pngPtr, (png_infopp)0, (png_infopp)0);

		delete[] rowPtrs;
		delete[] data;

		std::cout << "An error occured reading the PNG file." << std::endl;

		return 0;
	}

	png_set_read_fn(pngPtr, &file, XL::readData);
	/*png_init_io(pngPtr, &file);*/

	//read the PNG file
	png_set_sig_bytes(pngPtr, PNG_SIG_SIZE);
	png_read_info(pngPtr, infoPtr);

	width = png_get_image_width(pngPtr, infoPtr);
	height = png_get_image_height(pngPtr, infoPtr);

	//bit depth per channel
	png_uint_32 bitDepth = png_get_bit_depth(pngPtr, infoPtr);

	//number of channels
	png_uint_32 channels = png_get_channels(pngPtr, infoPtr);

	//color type (RGB, RGBA)
	png_uint_32 colorType = png_get_color_type(pngPtr, infoPtr);

	switch (colorType)
	{
	case PNG_COLOR_TYPE_PALETTE:
		png_set_palette_to_rgb(pngPtr);
		channels = 3;
		break;

	case PNG_COLOR_TYPE_GRAY:
		if (bitDepth < 8)
		{
			png_set_expand_gray_1_2_4_to_8(pngPtr);
			bitDepth = 8;
		}
		break;
	}

	if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS))
	{
		png_set_tRNS_to_alpha(pngPtr);
		channels++;
	}

	//strip the bit depth down to 8 if it is 16 //WHY?!  CHECK THIS!
	if (bitDepth == 16)
	{
		png_set_strip_16(pngPtr);
	}

	//create an array of row pointers, one for every row, on the heap
	rowPtrs = new png_bytep[height];

	//allocate a buffer with enough space (in bytes)
	int dataSize = width * height * bitDepth * channels / 8;
	data = new char[dataSize];
	int dataWidth = dataSize / height; //length of a row in the data array

	//length in bytes of one row //MIGHT BE CULPRIT OF NON-WORKING 32-BIT PNG LOADING
	const unsigned int stride = width * bitDepth * channels / 8;

	for (size_t i = 0; i < height; i++)
	{
		png_uint_32 q = (height - i - 1) * stride;
		rowPtrs[i] = (png_bytep)data + q;
	}

	png_read_image(pngPtr, rowPtrs); //application crashes here
	
	//fclose(file);

	//flip the image
	char* newData = new char[dataSize];

	for (int i = dataSize - dataWidth; i + 1 > 0; i -= dataWidth)
	{
		for (int k = 0; k < dataWidth; k++)
		{
			newData[dataSize - i - dataWidth + k] = data[i + k];
		}
	}

	//Load OpenGL textures
	//add support for GL_RGB?
	glGenTextures(1, &id);
	glBindTexture(GL_TEXTURE_2D, id);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)newData);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	glBindTexture(GL_TEXTURE_2D, NULL);

	png_destroy_read_struct(&pngPtr, &infoPtr, (png_infopp)0);

	delete[] rowPtrs;
	delete[] data;
	delete[] newData;

	return id;
}
Esempio n. 3
0
bool
wxPNGHandler::LoadFile(wxImage *image,
                       wxInputStream& stream,
                       bool verbose,
                       int WXUNUSED(index))
{
    // VZ: as this function uses setjmp() the only fool proof error handling
    //     method is to use goto (setjmp is not really C++ dtors friendly...)

    unsigned char **lines = NULL;
    png_infop info_ptr = (png_infop) NULL;
    wxPNGInfoStruct wxinfo;

    wxinfo.verbose = verbose;
    wxinfo.stream.in = &stream;

    image->Destroy();

    png_structp png_ptr = png_create_read_struct
                          (
                              PNG_LIBPNG_VER_STRING,
                              (voidp) NULL,
                              wx_png_error,
                              wx_png_warning
                          );
    if (!png_ptr)
        goto error;

    // NB: please see the comment near wxPNGInfoStruct declaration for
    //     explanation why this line is mandatory
    png_set_read_fn( png_ptr, &wxinfo, wx_PNG_stream_reader);

    info_ptr = png_create_info_struct( png_ptr );
    if (!info_ptr)
        goto error;

    if (setjmp(wxinfo.jmpbuf))
        goto error;

    png_uint_32 i, width, height;
    int bit_depth, color_type, interlace_type;

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

    if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_expand( png_ptr );

    // Fix for Bug [ 439207 ] Monochrome PNG images come up black
    if (bit_depth < 8)
        png_set_expand( png_ptr );

    png_set_strip_16( png_ptr );
    png_set_packing( png_ptr );
    if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_expand( png_ptr );
    png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER );

    image->Create((int)width, (int)height, (bool) false /* no need to init pixels */);

    if (!image->Ok())
        goto error;

    lines = (unsigned char **)malloc( (size_t)(height * sizeof(unsigned char *)) );
    if ( !lines )
        goto error;

    for (i = 0; i < height; i++)
    {
        if ((lines[i] = (unsigned char *)malloc( (size_t)(width * (sizeof(unsigned char) * 4)))) == NULL)
        {
            for ( unsigned int n = 0; n < i; n++ )
                free( lines[n] );
            goto error;
        }
    }

    png_read_image( png_ptr, lines );
    png_read_end( png_ptr, info_ptr );
    png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );

    // loaded successfully, now init wxImage with this data
    CopyDataFromPNG(image, lines, width, height, color_type);

    for ( i = 0; i < height; i++ )
        free( lines[i] );
    free( lines );

    return true;

error:
    if (verbose)
        wxLogError(_("Couldn't load a PNG image - file is corrupted or not enough memory."));

    if ( image->Ok() )
    {
        image->Destroy();
    }

    if ( lines )
    {
        free( lines );
    }

    if ( png_ptr )
    {
        if ( info_ptr )
        {
            png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
            free(info_ptr);
        }
        else
            png_destroy_read_struct( &png_ptr, (png_infopp) NULL, (png_infopp) NULL );
    }
    return false;
}
Esempio n. 4
0
BOOL png2pnm (FILE *png_file, FILE *pnm_file, FILE *alpha_file,
    volatile BOOL raw, BOOL alpha)
{
  png_struct    *png_ptr = NULL;
  png_info        *info_ptr = NULL;
  png_byte      buf[8];
  png_byte      *png_pixels = NULL;
  png_byte      **row_pointers = NULL;
  png_byte      *pix_ptr = NULL;
  png_uint_32   row_bytes;

  png_uint_32   width;
  png_uint_32   height;
  int           bit_depth;
  int           channels;
  int           color_type;
  int           alpha_present;
  int           row, col;
  int           ret;
  int           i;
  long          dep_16;

  /* read and check signature in PNG file */
  ret = fread (buf, 1, 8, png_file);
  if (ret != 8)
    return FALSE;

  ret = png_sig_cmp (buf, 0, 8);
  if (ret)
    return FALSE;

  /* create png and info structures */

  png_ptr = png_create_read_struct (png_get_libpng_ver(NULL),
    NULL, NULL, NULL);
  if (!png_ptr)
    return FALSE;   /* out of memory */

  info_ptr = png_create_info_struct (png_ptr);
  if (!info_ptr)
  {
    png_destroy_read_struct (&png_ptr, NULL, NULL);
    return FALSE;   /* out of memory */
  }

  if (setjmp (png_jmpbuf(png_ptr)))
  {
    png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
    return FALSE;
  }

  /* set up the input control for C streams */
  png_init_io (png_ptr, png_file);
  png_set_sig_bytes (png_ptr, 8);  /* we already read the 8 signature bytes */

  /* read the file information */
  png_read_info (png_ptr, info_ptr);

  /* get size and bit-depth of the PNG-image */
  png_get_IHDR (png_ptr, info_ptr,
    &width, &height, &bit_depth, &color_type,
    NULL, NULL, NULL);

  /* set-up the transformations */

  /* transform paletted images into full-color rgb */
  if (color_type == PNG_COLOR_TYPE_PALETTE)
    png_set_expand (png_ptr);
  /* expand images to bit-depth 8 (only applicable for grayscale images) */
  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
    png_set_expand (png_ptr);
  /* transform transparency maps into full alpha-channel */
  if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
    png_set_expand (png_ptr);

#ifdef NJET
  /* downgrade 16-bit images to 8-bit */
  if (bit_depth == 16)
    png_set_strip_16 (png_ptr);
  /* transform grayscale images into full-color */
  if (color_type == PNG_COLOR_TYPE_GRAY ||
    color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    png_set_gray_to_rgb (png_ptr);
  /* only if file has a file gamma, we do a correction */
  if (png_get_gAMA (png_ptr, info_ptr, &file_gamma))
    png_set_gamma (png_ptr, (double) 2.2, file_gamma);
#endif

  /* all transformations have been registered; now update info_ptr data,
   * get rowbytes and channels, and allocate image memory */

  png_read_update_info (png_ptr, info_ptr);

  /* get the new color-type and bit-depth (after expansion/stripping) */
  png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
    NULL, NULL, NULL);

  /* check for 16-bit files */
  if (bit_depth == 16)
  {
    raw = FALSE;
#ifdef __TURBOC__
    pnm_file->flags &= ~((unsigned) _F_BIN);
#endif
  }

  /* calculate new number of channels and store alpha-presence */
  if (color_type == PNG_COLOR_TYPE_GRAY)
    channels = 1;
  else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    channels = 2;
  else if (color_type == PNG_COLOR_TYPE_RGB)
    channels = 3;
  else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
    channels = 4;
  else
    channels = 0; /* should never happen */
  alpha_present = (channels - 1) % 2;

  /* check if alpha is expected to be present in file */
  if (alpha && !alpha_present)
  {
    fprintf (stderr, "PNG2PNM\n");
    fprintf (stderr, "Error:  PNG-file doesn't contain alpha channel\n");
    exit (1);
  }

  /* row_bytes is the width x number of channels x (bit-depth / 8) */
  row_bytes = png_get_rowbytes (png_ptr, info_ptr);

  if ((png_pixels = (png_byte *)
     malloc (row_bytes * height * sizeof (png_byte))) == NULL) {
    png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
    return FALSE;
  }

  if ((row_pointers = (png_byte **)
     malloc (height * sizeof (png_bytep))) == NULL)
  {
    png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
    free (png_pixels);
    png_pixels = NULL;
    return FALSE;
  }

  /* set the individual row_pointers to point at the correct offsets */
  for (i = 0; i < ((int) height); i++)
    row_pointers[i] = png_pixels + i * row_bytes;

  /* now we can go ahead and just read the whole image */
  png_read_image (png_ptr, row_pointers);

  /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
  png_read_end (png_ptr, info_ptr);

  /* clean up after the read, and free any memory allocated - REQUIRED */
  png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL);

  /* write header of PNM file */

  if ((color_type == PNG_COLOR_TYPE_GRAY) ||
      (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
  {
    fprintf (pnm_file, "%s\n", (raw) ? "P5" : "P2");
    fprintf (pnm_file, "%d %d\n", (int) width, (int) height);
    fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
  }
  else if ((color_type == PNG_COLOR_TYPE_RGB) ||
           (color_type == PNG_COLOR_TYPE_RGB_ALPHA))
  {
    fprintf (pnm_file, "%s\n", (raw) ? "P6" : "P3");
    fprintf (pnm_file, "%d %d\n", (int) width, (int) height);
    fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
  }

  /* write header of PGM file with alpha channel */

  if ((alpha) &&
      ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
       (color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
  {
    fprintf (alpha_file, "%s\n", (raw) ? "P5" : "P2");
    fprintf (alpha_file, "%d %d\n", (int) width, (int) height);
    fprintf (alpha_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
  }

  /* write data to PNM file */
  pix_ptr = png_pixels;

  for (row = 0; row < (int) height; row++)
  {
    for (col = 0; col < (int) width; col++)
    {
      for (i = 0; i < (channels - alpha_present); i++)
      {
        if (raw)
          fputc ((int) *pix_ptr++ , pnm_file);
        else
          if (bit_depth == 16){
            dep_16 = (long) *pix_ptr++;
            fprintf (pnm_file, "%ld ", (dep_16 << 8) + ((long) *pix_ptr++));
          }
          else
            fprintf (pnm_file, "%ld ", (long) *pix_ptr++);
      }
      if (alpha_present)
      {
        if (!alpha)
        {
          pix_ptr++; /* alpha */
          if (bit_depth == 16)
            pix_ptr++;
        }
        else /* output alpha-channel as pgm file */
        {
          if (raw)
            fputc ((int) *pix_ptr++ , alpha_file);
          else
            if (bit_depth == 16){
              dep_16 = (long) *pix_ptr++;
              fprintf (alpha_file, "%ld ", (dep_16 << 8) + (long) *pix_ptr++);
            }
            else
              fprintf (alpha_file, "%ld ", (long) *pix_ptr++);
        }
      } /* if alpha_present */

      if (!raw)
        if (col % 4 == 3)
          fprintf (pnm_file, "\n");
    } /* end for col */

    if (!raw)
      if (col % 4 != 0)
        fprintf (pnm_file, "\n");
  } /* end for row */

  if (row_pointers != (unsigned char**) NULL)
    free (row_pointers);
  if (png_pixels != (unsigned char*) NULL)
    free (png_pixels);

  return TRUE;

} /* end of source */
Esempio n. 5
0
void PNGAPI
png_read_png(png_structp png_ptr, png_infop info_ptr,
                           int transforms,
                           voidp params)
{
   int row;

#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
   /* invert the alpha channel from opacity to transparency */
   if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
       png_set_invert_alpha(png_ptr);
#endif

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

   /* -------------- image transformations start here ------------------- */

#if defined(PNG_READ_16_TO_8_SUPPORTED)
   /* tell libpng to strip 16 bit/color files down to 8 bits/color */
   if (transforms & PNG_TRANSFORM_STRIP_16)
       png_set_strip_16(png_ptr);
#endif

#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
   /* Strip alpha bytes from the input data without combining with the
    * background (not recommended).
    */
   if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
       png_set_strip_alpha(png_ptr);
#endif

#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
   /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
    * byte into separate bytes (useful for paletted and grayscale images).
    */
   if (transforms & PNG_TRANSFORM_PACKING)
       png_set_packing(png_ptr);
#endif

#if defined(PNG_READ_PACKSWAP_SUPPORTED)
   /* Change the order of packed pixels to least significant bit first
    * (not useful if you are using png_set_packing). */
   if (transforms & PNG_TRANSFORM_PACKSWAP)
       png_set_packswap(png_ptr);
#endif

#if defined(PNG_READ_EXPAND_SUPPORTED)
   /* Expand paletted colors into true RGB triplets
    * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
    * Expand paletted or RGB images with transparency to full alpha
    * channels so the data will be available as RGBA quartets.
    */
   if (transforms & PNG_TRANSFORM_EXPAND)
       if ((png_ptr->bit_depth < 8) ||
           (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
           (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
         png_set_expand(png_ptr);
#endif

   /* We don't handle background color or gamma transformation or dithering. */

#if defined(PNG_READ_INVERT_SUPPORTED)
   /* invert monochrome files to have 0 as white and 1 as black */
   if (transforms & PNG_TRANSFORM_INVERT_MONO)
       png_set_invert_mono(png_ptr);
#endif

#if defined(PNG_READ_SHIFT_SUPPORTED)
   /* If you want to shift the pixel values from the range [0,255] or
    * [0,65535] to the original [0,7] or [0,31], or whatever range the
    * colors were originally in:
    */
   if ((transforms & PNG_TRANSFORM_SHIFT)
       && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
   {
      png_color_8p sig_bit;

      png_get_sBIT(png_ptr, info_ptr, &sig_bit);
      png_set_shift(png_ptr, sig_bit);
   }
#endif

#if defined(PNG_READ_BGR_SUPPORTED)
   /* flip the RGB pixels to BGR (or RGBA to BGRA) */
   if (transforms & PNG_TRANSFORM_BGR)
       png_set_bgr(png_ptr);
#endif

#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
   /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
   if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
       png_set_swap_alpha(png_ptr);
#endif

#if defined(PNG_READ_SWAP_SUPPORTED)
   /* swap bytes of 16 bit files to least significant byte first */
   if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
       png_set_swap(png_ptr);
#endif

   /* We don't handle adding filler bytes */

   /* Optional call to gamma correct and add the background to the palette
    * and update info structure.  REQUIRED if you are expecting libpng to
    * update the palette for you (i.e., you selected such a transform above).
    */
   png_read_update_info(png_ptr, info_ptr);

   /* -------------- image transformations end here ------------------- */

#ifdef PNG_FREE_ME_SUPPORTED
   png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
#endif
   if(info_ptr->row_pointers == NULL)
   {
      info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
         info_ptr->height * sizeof(png_bytep));
#ifdef PNG_FREE_ME_SUPPORTED
      info_ptr->free_me |= PNG_FREE_ROWS;
#endif
      for (row = 0; row < (int)info_ptr->height; row++)
      {
         info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,
            png_get_rowbytes(png_ptr, info_ptr));
      }
   }

   png_read_image(png_ptr, info_ptr->row_pointers);
   info_ptr->valid |= PNG_INFO_IDAT;

   /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
   png_read_end(png_ptr, info_ptr);

   if(transforms == 0 || params == NULL)
      /* quiet compiler warnings */ return;

}
Esempio n. 6
0
int readpng_get_image(png_containerp ctx, uint32_t *pChannels, uint32_t *pRowBytes) {
  double display_exponent = 2.2; // sane default
  double  gamma;
  png_uint_32  i, rowbytes;
  png_bytepp  row_pointers = NULL;


  /* setjmp() must be called in every function that calls a PNG-reading
    * libpng function */

  if (setjmp(png_jmpbuf(ctx->png))) {
    png_destroy_read_struct(&ctx->png, &ctx->info, NULL);
    return -1;
  }


  /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
    * transparency chunks to full alpha channel; strip 16-bit-per-sample
    * images to 8 bits per sample; and convert grayscale to RGB[A] */

  if (ctx->color_type == PNG_COLOR_TYPE_PALETTE)
    png_set_expand(ctx->png);
  if (ctx->color_type == PNG_COLOR_TYPE_GRAY && ctx->bit_depth < 8)
    png_set_expand(ctx->png);
  if (png_get_valid(ctx->png, ctx->info, PNG_INFO_tRNS))
    png_set_expand(ctx->png);
  if (ctx->bit_depth == 16)
    png_set_strip_16(ctx->png);
  if (ctx->color_type == PNG_COLOR_TYPE_GRAY ||
    ctx->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    png_set_gray_to_rgb(ctx->png);


  /* unlike the example in the libpng documentation, we have *no* idea where
    * this file may have come from--so if it doesn't have a file gamma, don't
    * do any correction ("do no harm") */

  if (png_get_gAMA(ctx->png, ctx->info, &gamma))
    png_set_gamma(ctx->png, display_exponent, gamma);


  /* all transformations have been registered; now update ctx->info data,
    * get rowbytes and channels, and allocate image memory */

  png_read_update_info(ctx->png, ctx->info);

  *pRowBytes = rowbytes = png_get_rowbytes(ctx->png, ctx->info);
  *pChannels = png_get_channels(ctx->png, ctx->info);

  if ((ctx->bytes = (uint8_t*) malloc(rowbytes*ctx->height)) == NULL) {
    png_destroy_read_struct(&ctx->png, &ctx->info, NULL);
    return -1;
  }
  if ((row_pointers = (png_bytepp)malloc(ctx->height*sizeof(png_bytep))) == NULL) {
    png_destroy_read_struct(&ctx->png, &ctx->info, NULL);
    free(ctx->bytes);
    ctx->bytes = NULL;
    return -1;
  }

  /* set the individual row_pointers to point at the correct offsets */

  for (i = 0;  i < ctx->height;  ++i)
    row_pointers[i] = ctx->bytes + i*rowbytes;


  /* now we can go ahead and just read the whole image */

  png_read_image(ctx->png, row_pointers);


  /* and we're done!  (png_read_end() can be omitted if no processing of
    * post-IDAT text/time/etc. is desired) */

  free(row_pointers);
  row_pointers = NULL;

  png_read_end(ctx->png, NULL);

  return 0;
}
Esempio n. 7
0
int DisplayMakePNG(uint8_t *pu8Data, uint32_t cx, uint32_t cy,
                   uint8_t **ppu8PNG, uint32_t *pcbPNG, uint32_t *pcxPNG, uint32_t *pcyPNG,
                   uint8_t fLimitSize)
{
    int rc = VINF_SUCCESS;

    uint8_t * volatile pu8Bitmap = NULL; /* gcc setjmp  warning */
    uint32_t volatile cbBitmap = 0; /* gcc setjmp warning */
    uint32_t volatile cxBitmap = 0; /* gcc setjmp warning */
    uint32_t volatile cyBitmap = 0; /* gcc setjmp warning */

    if (!fLimitSize || (cx < kMaxSizePNG && cy < kMaxSizePNG))
    {
        /* Save unscaled screenshot. */
        pu8Bitmap = pu8Data;
        cbBitmap = cx * 4 * cy;
        cxBitmap = cx;
        cyBitmap = cy;
    }
    else
    {
        /* Large screenshot, scale. */
        if (cx > cy)
        {
            cxBitmap = kMaxSizePNG;
            cyBitmap = (kMaxSizePNG * cy) / cx;
        }
        else
        {
            cyBitmap = kMaxSizePNG;
            cxBitmap = (kMaxSizePNG * cx) / cy;
        }

        cbBitmap = cxBitmap * 4 * cyBitmap;

        pu8Bitmap = (uint8_t *)RTMemAlloc(cbBitmap);

        if (pu8Bitmap)
        {
            uint8_t *dst = pu8Bitmap;
            uint8_t *src = pu8Data;
            int dstW = cxBitmap;
            int dstH = cyBitmap;
            int srcW = cx;
            int srcH = cy;
            int iDeltaLine = cx * 4;

            BitmapScale32 (dst,
                           dstW, dstH,
                           src,
                           iDeltaLine,
                           srcW, srcH);
        }
        else
        {
            rc = VERR_NO_MEMORY;
        }
    }

    LogFlowFunc(("%dx%d -> %dx%d\n", cx, cy, cxBitmap, cyBitmap));

    if (RT_SUCCESS(rc))
    {
        png_bytep *row_pointers = (png_bytep *)RTMemAlloc(cyBitmap * sizeof(png_bytep));
        if (row_pointers)
        {
            png_infop info_ptr = NULL;
            png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                                          (png_voidp)NULL, /* error/warning context pointer */
                                                          (png_error_ptr)NULL, /* error function */
                                                          (png_error_ptr)NULL /* warning function */);
            if (png_ptr)
            {
                info_ptr = png_create_info_struct(png_ptr);
                if (info_ptr)
                {
                    if (!setjmp(png_jmpbuf(png_ptr)))
                    {
                        PNGWriteCtx ctx;
                        ctx.pu8PNG = NULL;
                        ctx.cbPNG = 0;
                        ctx.cbAllocated = 0;
                        ctx.rc = VINF_SUCCESS;

                        png_set_write_fn(png_ptr,
                                         (png_voidp)&ctx,
                                         png_write_data_fn,
                                         png_output_flush_fn);

                        png_set_IHDR(png_ptr, info_ptr,
                                     cxBitmap, cyBitmap,
                                     8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
                                     PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

                        png_bytep row_pointer = (png_bytep)pu8Bitmap;
                        unsigned i = 0;
                        for (; i < cyBitmap; i++, row_pointer += cxBitmap * 4)
                        {
                            row_pointers[i] = row_pointer;
                        }
                        png_set_rows(png_ptr, info_ptr, &row_pointers[0]);

                        png_write_info(png_ptr, info_ptr);
                        png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
                        png_set_bgr(png_ptr);

                        if (png_get_valid(png_ptr, info_ptr, PNG_INFO_IDAT))
                            png_write_image(png_ptr, png_get_rows(png_ptr, info_ptr));

                        png_write_end(png_ptr, info_ptr);

                        rc = ctx.rc;

                        if (RT_SUCCESS(rc))
                        {
                            *ppu8PNG = ctx.pu8PNG;
                            *pcbPNG = ctx.cbPNG;
                            *pcxPNG = cxBitmap;
                            *pcyPNG = cyBitmap;
                            LogFlowFunc(("PNG %d bytes, bitmap %d bytes\n", ctx.cbPNG, cbBitmap));
                        }
                    }
                    else
                    {
                        rc = VERR_GENERAL_FAILURE; /* Something within libpng. */
                    }
                }
                else
                {
                    rc = VERR_NO_MEMORY;
                }

                png_destroy_write_struct(&png_ptr, info_ptr ? &info_ptr
                                                            : (png_infopp)NULL);
            }
            else
            {
                rc = VERR_NO_MEMORY;
            }

            RTMemFree(row_pointers);
        }
        else
        {
            rc = VERR_NO_MEMORY;
        }
    }

    if (pu8Bitmap && pu8Bitmap != pu8Data)
    {
        RTMemFree(pu8Bitmap);
    }

    return rc;

}
Esempio n. 8
0
unsigned char *
readpng_get_image(unsigned char *png_data, unsigned int png_size, png_uint_32 *width, png_uint_32 *height)
{
	unsigned char *rgba = NULL;
	png_structp png_ptr;
	png_infop info_ptr;
	int bit_depth;
	int colour_type;
	png_uint_32 i, rowbytes;
	png_bytepp row_pointers = NULL;

	/* check the signature */
	if(!png_check_sig(png_data, 8))
		return NULL;

	/* init libpng data structures */
	if((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL)
		return NULL;

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

	/* setjmp() must be called in every function that calls a PNG-reading libpng function */
	if(setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		if(row_pointers != NULL)
			free(row_pointers);
		if(rgba != NULL)
			free(rgba);
		return NULL;
	}

	/* read from memory rather than a file */
	read_mem_state.data = png_data;
	read_mem_state.size = png_size;
	/* unlike file IO we don't need to seek passed the signature */
	read_mem_state.used = 0;
	png_set_read_fn(png_ptr, &read_mem_state, read_mem);

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

	/* don't care about compression_type and filter_type => NULL */
	png_get_IHDR(png_ptr, info_ptr, width, height, &bit_depth, &colour_type, NULL, NULL, NULL);

	/* expand palette images to RGB */
	if((colour_type & PNG_COLOR_MASK_PALETTE) != 0)
		png_set_expand(png_ptr);
	/* expand low-bit-depth images to 8 bits */
	if(bit_depth < 8)
		png_set_expand(png_ptr);
	/* expand transparency chunks to full alpha channel */
	if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_expand(png_ptr);
	/* strip 16-bit-per-sample images to 8-bits-per-sample */
	if(bit_depth == 16)
		png_set_strip_16(png_ptr);
	/* convert grayscale to RGB */
	if((colour_type & PNG_COLOR_MASK_COLOR) == 0)
		png_set_gray_to_rgb(png_ptr);
	/* add an opaque alpha channel if none exists in the PNG file */
	if((colour_type & PNG_COLOR_MASK_ALPHA) == 0)
		png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);

	/* recalc rowbytes etc */
	png_read_update_info(png_ptr, info_ptr);

	/* assert */
	if(png_get_channels(png_ptr, info_ptr) != 4)
		fatal("readpng: didn't get 4 channels");

	/* alloc our RGBA array */
	rowbytes = png_get_rowbytes(png_ptr, info_ptr);

	if((rgba = (unsigned char *) malloc(rowbytes * (*height))) == NULL)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return NULL;
	}

	if((row_pointers = (png_bytepp) malloc((*height) * sizeof(png_bytep))) == NULL)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		free(rgba);
		return NULL;
	}

	/* set the individual row_pointers to point at the correct offsets */
	for(i=0; i<(*height); i++)
		row_pointers[i] = rgba + (i * rowbytes);

	/* now we can go ahead and just read the whole image */
	png_read_image(png_ptr, row_pointers);

	/* clean up */
	free(row_pointers);
	row_pointers = NULL;
	png_read_end(png_ptr, NULL);
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

	return rgba;
}
Esempio n. 9
0
static uint8_t png_read( png_structp readPtr, png_image * image, uint32_t flags )
{
//	png_set_error_fn( readPtr, NULL, png_user_error, NULL );

	png_infop infoPtr = png_create_info_struct( readPtr );
	if (!infoPtr) 
	{
		pngio_error( "Couldn't initialize PNG info struct." );
		png_destroy_read_struct( & readPtr, NULL, NULL );
		return 0;
	}
	
	if (setjmp( png_jmpbuf( readPtr ) ))
	{
		pngio_error( "An error occured while reading the PNG file." );
		png_destroy_read_struct( & readPtr, & infoPtr, NULL );
		png_image_free( image );
		return 0;
	}

	png_set_sig_bytes( readPtr, 8 );
	
	#ifdef PNG_APPLE_MODE_SUPPORTED 
	if (png_get_apple_mode())
	{
		png_set_keep_unknown_chunks( readPtr, PNG_HANDLE_CHUNK_ALWAYS, NULL, 0 );
		png_set_read_user_chunk_fn( readPtr, NULL, png_read_user_chunk );
	}
	#endif
	
	png_read_info( readPtr, infoPtr );
	
	png_uint_32 w = png_get_image_width( readPtr, infoPtr );
	png_uint_32 h = png_get_image_height( readPtr, infoPtr );
	png_uint_32 bitDepth = png_get_bit_depth( readPtr, infoPtr );
	png_uint_32 channels = png_get_channels( readPtr, infoPtr );
	png_uint_32 interlaceType = png_get_interlace_type( readPtr, infoPtr );
	png_uint_32 colorType = png_get_color_type( readPtr, infoPtr );
	
	switch (colorType) 
	{
		case PNG_COLOR_TYPE_PALETTE:
			png_set_palette_to_rgb( readPtr );
			channels = 3;           
			break;
		case PNG_COLOR_TYPE_GRAY:
			if (bitDepth < 8)
			{
				png_set_expand_gray_1_2_4_to_8( readPtr );
				bitDepth = 8;
			}
			png_set_gray_to_rgb( readPtr );
			break;
	}
	
	if (png_get_valid( readPtr, infoPtr, PNG_INFO_tRNS )) 
	{
		png_set_tRNS_to_alpha( readPtr );
		channels += 1;
	}
	else if (!(colorType & PNG_COLOR_MASK_ALPHA)) 
	{
		png_set_add_alpha( readPtr, 0xff, PNG_FILLER_AFTER );
	}
	
	if (bitDepth == 16)
	{
		png_set_strip_16( readPtr );
	}

	#ifdef PNG_APPLE_MODE_SUPPORTED
	if (png_get_apple_mode())
	{
		if (flags & PNG_IMAGE_PREMULTIPLY_ALPHA)
		{
			png_set_read_user_transform_fn( readPtr, png_read_swap_transform );
		}
		else
		{
			png_set_read_user_transform_fn( readPtr, png_read_swap_and_unpremultiply_transform );
		}
		png_set_user_transform_info( readPtr, NULL, bitDepth, channels );
		png_read_update_info( readPtr, infoPtr );
	}
	else
	#endif
	{
		if (flags & PNG_IMAGE_PREMULTIPLY_ALPHA)
		{
			png_set_read_user_transform_fn( readPtr, png_read_premultiply_transform );
		}
	}

	png_image_alloc( image, w, h );
	png_bytep p = image->data;
	
	const size_t passCount = interlaceType == PNG_INTERLACE_NONE ? 1 : png_set_interlace_handling( readPtr );
	const size_t bytesPerRow = w * 4;
	if (flags & PNG_IMAGE_FLIP_VERTICAL)
	{
		for (size_t pass = 0; pass < passCount; pass++)
		{
			for (size_t i = 0; i < h; i++) 
			{
				png_read_row( readPtr, p + (bytesPerRow * (h - i - 1)), NULL );
			}
		}
	}
	else
	{
//		png_bytep rp[h];
//		for (size_t i = 0; i < h; i++) 
//		{
//			rp[i] = p + (bytesPerRow * i);
//		}
//		png_read_image( readPtr, rp );
		for (size_t pass = 0; pass < passCount; pass++)
		{
			for (size_t i = 0; i < h; i++) 
			{
				png_read_row( readPtr, p + (bytesPerRow * i), NULL );
			}
		}
	}
	
	png_destroy_read_struct( & readPtr, & infoPtr, NULL );
	
	return 1;
}
Esempio n. 10
0
void ReadFilePNG(CByteImage& img, const char* filename)
{
    // open the PNG input file
    FILE *stream = fopen(filename, "rb");
    if (stream == 0)
        throw CError("ReadFilePNG: could not open %s", filename);

    // first check the eight byte PNG signature
    png_byte pbSig[8];
    fread(pbSig, 1, 8, stream);
	if (!png_check_sig(pbSig, 8)) {
        fclose(stream);
        throw CError("ReadFilePNG: invalid PNG signature");
	}

    // create the two png(-info) structures
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
      (png_error_ptr)pngfile_error, (png_error_ptr)NULL);

	if (!png_ptr) {
        fclose(stream);
		throw CError("ReadFilePNG: error creating png structure");
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		png_destroy_read_struct(&png_ptr, NULL, NULL);
        fclose(stream);
		throw CError("ReadFilePNG: error creating png structure");
	}

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

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

	// get width, height, bit-depth and color-type
	int width, height, bits, colorType, nBands;

	png_get_IHDR(png_ptr, info_ptr, 
		(png_uint_32 *)&width, (png_uint_32 *)&height,
		&bits, &colorType, NULL, NULL, NULL);
	nBands = (int)png_get_channels(png_ptr, info_ptr);

	if (DEBUG_ImageIOpng)
	fprintf(stderr, " w=%d, h=%d, %2d bits, %s, nB=%d",
		width, height, bits,
		colorType == PNG_COLOR_TYPE_GRAY ? "gray" :
		colorType == PNG_COLOR_TYPE_PALETTE ? "plt " :
		colorType == PNG_COLOR_TYPE_RGB ? "rgb " :
		colorType == PNG_COLOR_TYPE_RGB_ALPHA ? "rgba" :
		colorType == PNG_COLOR_TYPE_GRAY_ALPHA ? "gr-a" : "??? ",
		nBands);


	// get rid of lower-order byte in 16-bit images
	// TODO: could allow this and read in IntImage in this case...
	if (bits == 16)
		png_set_strip_16(png_ptr);

	// change palette color into RGB
	if (colorType == PNG_COLOR_TYPE_PALETTE)
		png_set_expand(png_ptr);

	// want at least 8 bits
	if (bits < 8)
		png_set_expand(png_ptr);

	// if there is a transparent palette entry, create alpha channel
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_expand(png_ptr);

	// make gray images with alpha channel into RGBA -- TODO: or just ignore alpha?
	if (colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
		// colorType == PNG_COLOR_TYPE_GRAY       // but leave gray images alone
		png_set_gray_to_rgb(png_ptr);

	// set the background color to draw transparent and alpha images over.
	// only needed for gray images with alpha 
	if (colorType == PNG_COLOR_TYPE_GRAY_ALPHA ||
		colorType == PNG_COLOR_TYPE_GRAY) {
		png_color_16 *pBackground;
		if (png_get_bKGD(png_ptr, info_ptr, &pBackground))
			png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
		}

	// if required set gamma conversion
	// this seems to cause problems, so let's just leave gamma alone.
	//double gamma;
	//if (png_get_gAMA(png_ptr, info_ptr, &gamma)) {
	// //fprintf(stderr, "\n reading gamma %lf\n", gamma);
	//png_set_gamma(png_ptr, 1.0, gamma);
	//}

	// we need colors in BGR order, not RGB
	png_set_bgr(png_ptr);

	// always convert 3-band to 4-band images (add alpha):
	if (colorType == PNG_COLOR_TYPE_RGB)
		png_set_add_alpha(png_ptr, 255, PNG_FILLER_AFTER);

	// after the transformations have been registered update info_ptr data
	png_read_update_info(png_ptr, info_ptr);

	// get again width, height and the new bit-depth and color-type
	png_get_IHDR(png_ptr, info_ptr, 
		(png_uint_32 *)&width, (png_uint_32 *)&height,
		&bits, &colorType, NULL, NULL, NULL);
	nBands = (int)png_get_channels(png_ptr, info_ptr);

	if (DEBUG_ImageIOpng)
	fprintf(stderr, "  -> w=%d, h=%d, %2d bits, %s, nB=%d\n",
		width, height, bits,
		colorType == PNG_COLOR_TYPE_GRAY ? "gray" :
		colorType == PNG_COLOR_TYPE_PALETTE ? "plt " :
		colorType == PNG_COLOR_TYPE_RGB ? "rgb " :
		colorType == PNG_COLOR_TYPE_RGB_ALPHA ? "rgba" :
		colorType == PNG_COLOR_TYPE_GRAY_ALPHA ? "gr-a" : "??? ",
		nBands);
	

	if (! (nBands==1 || nBands==3 || nBands==4)) {
        fclose(stream);
		throw CError("ReadFilePNG: Can't handle nBands=%d", nBands);
	}

	// Set the image shape
	CShape sh(width, height, nBands);

	// Allocate the image if necessary
	img.ReAllocate(sh);

	//  allocate a vector of row pointers
	std::vector<uchar *> rowPtrs;
	rowPtrs.resize(height);
	for (int y = 0; y<height; y++)
		rowPtrs[y] = &img.Pixel(0, y, 0);

	// read the whole image
	png_read_image(png_ptr, &rowPtrs[0]);

 	// read the additional chunks in the PNG file (not really needed)
	png_read_end(png_ptr, NULL);

	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

	fclose(stream);
}
void ZLEwlImageManager::convertImageDirectPng(const std::string &stringData, ZLImageData &data) const {
	struct s_my_png my_png;
	my_png.p = (char*)stringData.data();
	my_png.size = stringData.length();

	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	unsigned int *row = NULL;

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
			(png_voidp)&my_png, mypng_error_func, mypng_warning_func);
	if ( !png_ptr )
		return;

	if (setjmp( png_ptr->jmpbuf )) {
		data.init(0, 0);
		if (png_ptr)
		{
			png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
		}
		if ( row )
			delete row;
		return;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
		mypng_error_func(png_ptr, "cannot create png info struct");
	png_set_read_fn(png_ptr,
			(voidp)&my_png, mypng_read_func);
	png_read_info( png_ptr, info_ptr );


	png_uint_32 width, height;
	int bit_depth, color_type, interlace_type;
	png_get_IHDR(png_ptr, info_ptr, &width, &height,
			&bit_depth, &color_type, &interlace_type,
			NULL, NULL);

	data.init(width, height);

	row = new unsigned int[ width ];

	// SET TRANSFORMS
	if (color_type & PNG_COLOR_MASK_PALETTE)
		png_set_palette_to_rgb(png_ptr);

	if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
		png_set_gray_1_2_4_to_8(png_ptr);

	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_tRNS_to_alpha(png_ptr);

	if (bit_depth == 16) png_set_strip_16(png_ptr);


	if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
		png_set_invert_alpha(png_ptr);
	} else {
		png_color_16 bg = {0, 0xffff, 0xffff, 0xffff, 0xffff};
		png_set_background(png_ptr, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 0.0);

		png_set_strip_alpha(png_ptr);
	}

	if (bit_depth < 8)
		png_set_packing(png_ptr);

	//if (color_type == PNG_COLOR_TYPE_RGB)
	//png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);

	//if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
	//    png_set_swap_alpha(png_ptr);

	if (! (color_type == PNG_COLOR_TYPE_GRAY ||
			color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
		png_set_rgb_to_gray(png_ptr, 1, -1, -1);

	int number_passes = png_set_interlace_handling(png_ptr);
	//if (color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
	//    color_type == PNG_COLOR_TYPE_GRAY_ALPHA)

	//if (color_type == PNG_COLOR_TYPE_RGB ||
	//    color_type == PNG_COLOR_TYPE_RGB_ALPHA)
	png_set_bgr(png_ptr);


	ZLIntegerOption myDitherAlgo(ZLCategoryKey::LOOK_AND_FEEL, "Options", "DitherAlgo", 0);
	register int dalgo = myDitherAlgo.value();
	char *c;	
	for(int pass = 0; pass < number_passes; pass++) {
		for(unsigned int y = 0; y < height; y++) {

			png_read_rows(png_ptr, (unsigned char **)&row, png_bytepp_NULL, 1);

			c = ((ZLEwlImageData&)data).getImageData() + width * y;


			if ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) {
				unsigned char *s = (unsigned char*)row;
				if(dalgo == 1)
					for(unsigned int i = 0; i < width; i++)
						*c++ = Dither2BitColor(*(++s)++, i, y);
				else
					for(unsigned int i = 0; i < width; i++)
						*c++ = *(++s)++;
			} else if(dalgo == 1) {
				unsigned char *s = (unsigned char*)row;
				for(unsigned int i = 0; i < width; i++)
					*c++ = Dither2BitColor(*s++, i, y);
			} else 
				memcpy(c, (char*)row, width);
		}
	}

	png_read_end(png_ptr, info_ptr);

	png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
}
Esempio n. 12
0
/*---------------------------------------------------------------------------
   Loads a PNG file.

   Image  : Image will be returned there.
   Path   : Path to image file, relative to the current working directory.
   Gamma  : Display gamma to apply on textures, 2.2 is typical.
  ---------------------------------------------------------------------------*/
void PNG::Load(Texture &Image, const std::string &Path, float Gamma)
   {
   Destroy();

   //Important - set class to reading mode
   Mode = PNG::ModeRead;

   #if defined (WINDOWS)
      if (fopen_s(&File, Path.c_str(), "rb") != 0)
         {throw dexception("Failed to open file: %s.", Path.c_str());}
   #else
      File = fopen(Path.c_str(), "rb");
      if (File == nullptr) {throw dexception("Failed to open file: %s.", Path.c_str());}
   #endif

   uint8 Header[PNG::HeaderSize];
   if (fread((png_bytep)Header, 1, PNG::HeaderSize, File) == 0)
      {throw dexception("fread( ) failed.");}

   if (!png_check_sig(Header, PNG::HeaderSize))
      {throw dexception("Not a valid PNG file.");}

   PngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
   if (PngPtr == nullptr) {throw dexception("png_create_read_struct( ) failed.");}

   InfoPtr = png_create_info_struct(PngPtr);
   if (InfoPtr == nullptr) {throw dexception("png_create_info_struct( ) failed.");}

   if (setjmp(png_jmpbuf(PngPtr)))
      {throw dexception("setjmp( ) failed.");}

   //Read into structures
   png_init_io(PngPtr, File);
   png_set_sig_bytes(PngPtr, PNG::HeaderSize);
   png_read_info(PngPtr, InfoPtr);

   //Determine image attributes
   vector2<png_uint_32> Res;
   int BitDepth, ColourType;
   png_get_IHDR(PngPtr, InfoPtr, &Res.U, &Res.V, &BitDepth, &ColourType, nullptr, nullptr, nullptr);

   Texture::TexType Type = Texture::TypeRGB;
   switch (ColourType)
      {
      case PNG_COLOR_TYPE_GRAY :
         if (BitDepth < 8)
            {
            Type = Texture::TypeLum;
            png_set_expand_gray_1_2_4_to_8(PngPtr);
            }
         else if (BitDepth == 16)
            {
            Type = Texture::TypeDepth;
            }
         break;

      case PNG_COLOR_TYPE_GRAY_ALPHA :
         Type = Texture::TypeRGBA;
         png_set_gray_to_rgb(PngPtr);
         break;

      case PNG_COLOR_TYPE_PALETTE :
         Type = Texture::TypeRGB;
         png_set_palette_to_rgb(PngPtr);
         break;

      case PNG_COLOR_TYPE_RGB :
         Type = Texture::TypeRGB;
         png_set_strip_alpha(PngPtr); //If libpng reports RGB, make sure we completely strip alpha
         break;

      case PNG_COLOR_TYPE_RGB_ALPHA :
         Type = Texture::TypeRGBA;
         break;

      default : throw dexception("Unknown colour type.");
      }

   //Convert palette alpha into a separate alpha channel
   if (png_get_valid(PngPtr, InfoPtr, PNG_INFO_tRNS))
      {
      png_set_tRNS_to_alpha(PngPtr);
      if (ColourType == PNG_COLOR_TYPE_PALETTE) {Type = Texture::TypeRGBA;}
      }

   //Force 8 bit per channel
   if (BitDepth >= 16)
      {
      if (Type != Texture::TypeDepth) {png_set_strip_16(PngPtr);}
      }
   else if (BitDepth < 8)
      {
      png_set_packing(PngPtr);
      }

   //Specify display and file gamma (assume 0.45455 for missing file gamma)
   double FileGamma;
   if (!png_get_gAMA(PngPtr, InfoPtr, &FileGamma)) {FileGamma = 0.45455;}
   png_set_gamma(PngPtr, Gamma, FileGamma);

   //Swap byte order for int16 values on big endian machines
   if ((BitDepth >= 16) && !Math::MachineLittleEndian())
      {png_set_swap(PngPtr);}

   //Apply the above transformation settings
   png_read_update_info(PngPtr, InfoPtr);

   //Allocate image
   Image.Create(cast_vector2(uint, Res), Type);

   if (Image.GetBytesPerLine() < (usize)png_get_rowbytes(PngPtr, InfoPtr))
      {throw dexception("Incorrect scan line size for allocated image.");}

   //Populate row pointer array
   Rows.Create((usize)Res.V);
   for (uiter I = 0; I < (usize)Res.V; I++)
      {
      Rows[I] = Image.Address(0, I);
      }

   //Decode
   png_read_image(PngPtr, Rows.Pointer());
   png_read_end(PngPtr, InfoPtr);

   //Clean up
   Destroy();
   }
Esempio n. 13
0
// TODO: clean up error handling, too much dupe code right now
bool PNG::_read_file(string const & file_name)
{
	// unfortunately, we need to break down to the C-code level here, since
	// libpng is written in C itself

	// we need to open the file in binary mode
	FILE * fp = fopen(file_name.c_str(), "rb");
	if (!fp)
	{
		epng_err("Failed to open " + file_name);
		return false;
	}

	// read in the header (max size of 8), use it to validate this as a PNG file
	png_byte header[8];
	fread(header, 1, 8, fp);
	if (png_sig_cmp(header, 0, 8))
	{
		epng_err("File is not a valid PNG file");
		fclose(fp);
		_init();
		return false;
	}

	// set up libpng structs for reading info
	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr)
	{
		epng_err("Failed to create read struct");
		fclose(fp);
		_init();
		return false;
	}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		epng_err("Failed to create info struct");
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		fclose(fp);
		_init();
		return false;
	}

	// set error handling to not abort the entire program
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		epng_err("Error initializing libpng io");
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		fclose(fp);
		_init();
		return false;
	}

	// initialize png reading
	png_init_io(png_ptr, fp);
	// let it know we've already read the first 8 bytes
	png_set_sig_bytes(png_ptr, 8);

	// read in the basic image info
	png_read_info(png_ptr, info_ptr);

	// convert to 8 bits
	png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
	if (bit_depth == 16)
		png_set_strip_16(png_ptr);

	// verify this is in RGBA format, and if not, convert it to RGBA
	png_byte color_type = png_get_color_type(png_ptr, info_ptr);
	if (color_type != PNG_COLOR_TYPE_RGBA && color_type != PNG_COLOR_TYPE_RGB)
	{
		if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
			if (bit_depth < 8)
				png_set_expand(png_ptr);
			png_set_gray_to_rgb(png_ptr);
		}
		if (color_type == PNG_COLOR_TYPE_PALETTE)
			png_set_palette_to_rgb(png_ptr);
	}
	// convert tRNS to alpha channel
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_tRNS_to_alpha(png_ptr);

	_width = png_get_image_width(png_ptr, info_ptr);
	_height = png_get_image_height(png_ptr, info_ptr);

	png_read_update_info(png_ptr, info_ptr);

	// begin reading in the image
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		epng_err("Error reading image with libpng");
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		fclose(fp);
		_init();
		return false;
	}


	int bpr = png_get_rowbytes(png_ptr, info_ptr); // number of bytes in a row
	int numchannels = png_get_channels(png_ptr, info_ptr);

	// initialie our image storage
	_pixels = new RGBAPixel[_height * _width];
	png_byte * row = new png_byte[bpr];
	for (int y = 0; y < _height; y++)
	{
		png_read_row(png_ptr, row, NULL);
		png_byte * pix = row;
		for (int x = 0; x < _width; x++)
		{
			RGBAPixel & pixel = _pixel(x,y);
			if (numchannels == 1 || numchannels == 2)
			{
				// monochrome
				unsigned char color = (unsigned char) *pix++;
				pixel.red = color;
				pixel.green = color;
				pixel.blue = color;
				if (numchannels == 2)
					pixel.alpha = (unsigned char) *pix++;
				else
					pixel.alpha = 255;
			} 
			else if (numchannels == 3 || numchannels == 4) 
			{
				pixel.red = (unsigned char) *pix++;
				pixel.green = (unsigned char) *pix++;
				pixel.blue = (unsigned char) *pix++;
				if (numchannels == 4)
					pixel.alpha = (unsigned char) *pix++;
				else
					pixel.alpha = 255;
			}
		}
	}
	// cleanup
	delete [] row;
	png_read_end(png_ptr, NULL);
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	fclose(fp);
	return true;
}
Esempio n. 14
0
static DFBResult
load_image (const char            *filename,
            DFBSurfaceDescription *desc)
{
     DFBSurfacePixelFormat dest_format;
     DFBSurfacePixelFormat src_format;
     FILE          *fp;
     png_structp    png_ptr  = NULL;
     png_infop      info_ptr = NULL;
     png_uint_32    width, height;
     unsigned char *data     = NULL;
     int            type;
     char           header[8];
     int            bytes, pitch;

     dest_format = (desc->flags & DSDESC_PIXELFORMAT) ? desc->pixelformat : DSPF_UNKNOWN;

     desc->flags                = DSDESC_NONE;
     desc->preallocated[0].data = NULL;

     if (!(fp = fopen (filename, "rb"))) {
          fprintf (stderr, "Failed to open file '%s': %s.\n",
                   filename, strerror (errno));
          goto cleanup;
     }

     bytes = fread (header, 1, sizeof(header), fp);
     if (png_sig_cmp ((unsigned char*) header, 0, bytes)) {
          fprintf (stderr, "File '%s' doesn't seem to be a PNG image file.\n",
                   filename);
          goto cleanup;
     }

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

     if (setjmp (png_jmpbuf(png_ptr))) {
          if (desc->preallocated[0].data) {
               free (desc->preallocated[0].data);
               desc->preallocated[0].data = NULL;
          }

          /* data might have been clobbered,
             set it to NULL and leak instead of crashing */
          data = NULL;

          goto cleanup;
     }

     info_ptr = png_create_info_struct (png_ptr);
     if (!info_ptr)
          goto cleanup;

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

     png_read_info (png_ptr, info_ptr);

     png_get_IHDR (png_ptr, info_ptr,
                   &width, &height, &bytes, &type, NULL, NULL, NULL);

     if (bytes == 16)
          png_set_strip_16 (png_ptr);

#ifdef WORDS_BIGENDIAN
     png_set_swap_alpha (png_ptr);
#else
     png_set_bgr (png_ptr);
#endif

     src_format = (type & PNG_COLOR_MASK_ALPHA) ? DSPF_ARGB : DSPF_RGB32;
     switch (type) {
          case PNG_COLOR_TYPE_GRAY:
               if (dest_format == DSPF_A8) {
                    src_format = DSPF_A8;
                    break;
               }
               /* fallthru */
          case PNG_COLOR_TYPE_GRAY_ALPHA:
               png_set_gray_to_rgb (png_ptr);
//               if (rgbformat)
//                    dest_format = rgbformat;
               break;

          case PNG_COLOR_TYPE_PALETTE:
               png_set_palette_to_rgb (png_ptr);
               /* fallthru */
          case PNG_COLOR_TYPE_RGB:
//               if (rgbformat)
//                    dest_format = rgbformat;
          case PNG_COLOR_TYPE_RGB_ALPHA:
               if (dest_format == DSPF_RGB24) {
                    png_set_strip_alpha (png_ptr);
                    src_format = DSPF_RGB24;
               }
               break;
       }

     switch (src_format) {
          case DSPF_RGB32:
                png_set_filler (png_ptr, 0xFF,
#ifdef WORDS_BIGENDIAN
                                PNG_FILLER_BEFORE
#else
                                PNG_FILLER_AFTER
#endif
                                );
                break;
          case DSPF_ARGB:
          case DSPF_A8:
               if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
                    png_set_tRNS_to_alpha (png_ptr);
               break;
          default:
               break;
     }

     pitch = (DFB_BYTES_PER_LINE( src_format, width ) + 7) & ~7;

     data  = (unsigned char*) malloc (height * pitch);
     if (!data) {
          fprintf (stderr, "Failed to allocate %lu bytes.\n", (unsigned long)(height * pitch));
          goto cleanup;
     }

     {
          unsigned int i;
          png_bytep bptrs[height];

          for (i = 0; i < height; i++)
               bptrs[i] = data + i * pitch;

          png_read_image (png_ptr, bptrs);
     }

     if (!dest_format)
          dest_format = src_format;

     if (DFB_BYTES_PER_PIXEL(src_format) != DFB_BYTES_PER_PIXEL(dest_format)) {
          unsigned char *s, *d, *dest;
          int            d_pitch, h;

          D_ASSERT( DFB_BYTES_PER_PIXEL(src_format) == 4 );

          d_pitch = (DFB_BYTES_PER_LINE(dest_format, width) + 7) & ~7;

          dest = (unsigned char*) malloc (height * d_pitch);
          if (!dest) {
               fprintf (stderr, "Failed to allocate %lu bytes.\n", (unsigned long)(height * d_pitch));
               goto cleanup;
          }

          h = height;
          switch (dest_format) {
               case DSPF_RGB16:
                    for (s = data, d = dest; h; h--, s += pitch, d += d_pitch)
                         dfb_argb_to_rgb16 ((u32 *) s, (u16 *) d, width);
                    break;
               case DSPF_ARGB8565:
                    for (s = data, d = dest; h; h--, s += pitch, d += d_pitch)
                         dfb_argb_to_argb8565 ((u32 *) s, (u8 *) d, width);
                    break;
               case DSPF_ARGB1555:
                    for (s = data, d = dest; h; h--, s += pitch, d += d_pitch)
                         dfb_argb_to_argb1555 ((u32 *) s, (u16 *) d, width);
                    break;
               case DSPF_RGBA5551:
                    for (s = data, d = dest; h; h--, s += pitch, d += d_pitch)
                         dfb_argb_to_rgba5551 ((u32 *) s, (u16 *) d, width);
                    break;
               case DSPF_ARGB2554:
                    for (s = data, d = dest; h; h--, s += pitch, d += d_pitch)
                         dfb_argb_to_argb2554 ((u32 *) s, (u16 *) d, width);
                    break;
               case DSPF_ARGB4444:
                    for (s = data, d = dest; h; h--, s += pitch, d += d_pitch)
                         dfb_argb_to_argb4444 ((u32 *) s, (u16 *) d, width);
                    break;
               case DSPF_RGB332:
                    for (s = data, d = dest; h; h--, s += pitch, d += d_pitch)
                         dfb_argb_to_rgb332 ((u32 *) s, (u8 *) d, width);
                    break;
               case DSPF_A8:
                    for (s = data, d = dest; h; h--, s += pitch, d += d_pitch)
                         dfb_argb_to_a8 ((u32 *) s, (u8 *) d, width);
                    break;
               default:
                    fprintf (stderr,
                             "Sorry, unsupported format conversion.\n");
                    goto cleanup;
          }

          free (data);
          data = dest;
          pitch = d_pitch;
     }

     desc->flags = (DFBSurfaceDescriptionFlags)(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT |
                                                DSDESC_PREALLOCATED);
     desc->width       = width;
     desc->height      = height;
     desc->pixelformat = dest_format;
     desc->preallocated[0].pitch = pitch;
     desc->preallocated[0].data  = data;

     data = NULL;

 cleanup:
     if (fp)
          fclose (fp);

     if (png_ptr)
          png_destroy_read_struct (&png_ptr, &info_ptr, NULL);

     if (data)
          free (data);

     return ((desc->flags) ? DFB_OK : DFB_FAILURE);
}
Esempio n. 15
0
static void LoadPNGBuffer( byte *buffer, int size, byte **pixels, int *width, int *height ){
	png_struct  *png;
	png_info    *info, *end;
	pngBuffer_t pb;
	//pngBuffer_t     *pb = (pngBuffer_t*) png_get_io_ptr( png );
	int bitDepth, colorType;
	png_uint_32 w, h, i;
	byte        **rowPointers;

	/* dummy check */
	if ( buffer == NULL || size <= 0 || pixels == NULL || width == NULL || height == NULL ) {
		return;
	}

	/* null out */
	*pixels = 0;
	*width = 0;
	*height = 0;

	/* determine if this is a png file */
	if ( png_sig_cmp( buffer, 0, 8 ) != 0 ) {
		Sys_Printf( "WARNING: Invalid PNG file\n" );
		return;
	}

	/* create png structs */
	png = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
	if ( png == NULL ) {
		Sys_Printf( "WARNING: Unable to create PNG read struct\n" );
		return;
	}

	info = png_create_info_struct( png );
	if ( info == NULL ) {
		Sys_Printf( "WARNING: Unable to create PNG info struct\n" );
		png_destroy_read_struct( &png, NULL, NULL );
		return;
	}

	end = png_create_info_struct( png );
	if ( end == NULL ) {
		Sys_Printf( "WARNING: Unable to create PNG end info struct\n" );
		png_destroy_read_struct( &png, &info, NULL );
		return;
	}

	/* set read callback */
	pb.buffer = buffer;
	pb.size = size;
	pb.offset = 0;
	png_set_read_fn( png, &pb, PNGReadData );
	//png->io_ptr = &pb; /* hack! */

	/* set error longjmp */
	if ( setjmp( png_jmpbuf(png) ) ) {
		Sys_Printf( "WARNING: An error occurred reading PNG image\n" );
		png_destroy_read_struct( &png, &info, &end );
		return;
	}

	/* fixme: add proper i/o stuff here */

	/* read png info */
	png_read_info( png, info );

	/* read image header chunk */
	png_get_IHDR( png, info,
				  &w, &h, &bitDepth, &colorType, NULL, NULL, NULL );

	/* the following will probably bork on certain types of png images, but hey... */

	/* force indexed/gray/trans chunk to rgb */
	if ( ( colorType == PNG_COLOR_TYPE_PALETTE && bitDepth <= 8 ) ||
		 ( colorType == PNG_COLOR_TYPE_GRAY && bitDepth <= 8 ) ||
		 png_get_valid( png, info, PNG_INFO_tRNS ) ) {
		png_set_expand( png );
	}

	/* strip 16bpc -> 8bpc */
	if ( bitDepth == 16 ) {
		png_set_strip_16( png );
	}

	/* pad rgb to rgba */
	if ( bitDepth == 8 && colorType == PNG_COLOR_TYPE_RGB ) {
		png_set_filler( png, 255, PNG_FILLER_AFTER );
	}

	/* create image pixel buffer */
	*width = w;
	*height = h;
	*pixels = safe_malloc( w * h * 4 );

	/* create row pointers */
	rowPointers = safe_malloc( h * sizeof( byte* ) );
	for ( i = 0; i < h; i++ )
		rowPointers[ i ] = *pixels + ( i * w * 4 );

	/* read the png */
	png_read_image( png, rowPointers );

	/* clean up */
	free( rowPointers );
	png_destroy_read_struct( &png, &info, &end );

}
Esempio n. 16
0
//---------------------------------------------------------------------------
void __fastcall TDeePNG::LoadFromStream(Classes::TStream * Stream)
{
    // LoadFromStream

    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    png_infop end_info = NULL;

    png_bytep *row_pointers = NULL;
    BYTE *image = NULL;

    png_uint_32 i;

    try
    {
        // create png_struct
        png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,
                                           (png_voidp)this, DeePNG_error, DeePNG_warning,
                                           (png_voidp)this, DeePNG_malloc, DeePNG_free);

        // set read_chunk_callback
        png_set_read_user_chunk_fn(png_ptr,
                                   reinterpret_cast<void*>(this),
                                   PNG_read_chunk_callback);
        png_set_keep_unknown_chunks(png_ptr, 2, NULL, 0);
        // keep only if safe-to-copy chunks, for all unknown chunks

        // create png_info
        info_ptr = png_create_info_struct(png_ptr);

        // create end_info
        end_info = png_create_info_struct(png_ptr);

        // set stream input functions
        png_set_read_fn(png_ptr, (voidp)Stream, DeePNG_read_data);

        // set read_row_callback
        png_set_read_status_fn(png_ptr, DeePNG_read_row_callback);

        // call png_read_info
        png_read_info(png_ptr, info_ptr);

        // retrieve IHDR
        png_uint_32 width, height;
        int bit_depth, color_type, interlace_type, compression_type, filter_type;
        png_get_IHDR(png_ptr,info_ptr, &width, &height, &bit_depth, &color_type,
                     &interlace_type, &compression_type, &filter_type);

        // expand palletted image which has transparent color, to 32bpp
        if (png_get_valid(png_ptr, info_ptr,PNG_INFO_tRNS))
        {
            png_set_expand(png_ptr);
            color_type=PNG_COLOR_TYPE_RGB_ALPHA;
        }

        // analyse IHDR ( color_type )
        switch(color_type)
        {
        case PNG_COLOR_TYPE_GRAY_ALPHA:
            PixelFormat=pf32bit;
            break;
        case PNG_COLOR_TYPE_GRAY:
            // w/b
            SetGrayscalePalette(this,bit_depth);
            break;
        case PNG_COLOR_TYPE_PALETTE:
            SetColorDepth(this,bit_depth);
            break;
        case PNG_COLOR_TYPE_RGB_ALPHA:
            PixelFormat=pf32bit;
            break;
        case PNG_COLOR_TYPE_RGB:
            PixelFormat=pf24bit;
            break;
        default:
            throw EDeePNG("EDeePNG : Non-supported color type.");
        }

        // retrieve offset information
        png_int_32 offset_x, offset_y;
        int offset_unit_type;
        if(png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &offset_unit_type))
        {
            ofs_x = offset_x;
            ofs_y = offset_y;
            ofs_unit = offset_unit_type;
            ofs_set = true;
        }
        else
        {
            ofs_set = false;
        }

        // check size
        if(width>=65536 || height>=65536)
        {
            throw EDeePNG("EDeePNG : Too large image size.");
        }


        // retrieve palette
        if(color_type == PNG_COLOR_TYPE_PALETTE)
        {
            int num_palette;
            png_color *palette = NULL;
            png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);

            int i;
#pragma pack(push, 1)
            struct
            {
                WORD	palVersion;
                WORD	palNumEntries;
                PALETTEENTRY entry[256];
            } pal;
#pragma pack(pop)
            pal.palVersion = 0x300;
            pal.palNumEntries = num_palette;
            for(i = 0; i < num_palette; i++)
            {
                pal.entry[i].peRed = palette[i].red;
                pal.entry[i].peGreen = palette[i].green;
                pal.entry[i].peBlue = palette[i].blue;
                pal.entry[i].peFlags = 0;
            }
            Palette = CreatePalette((const LOGPALETTE*)&pal);
        }

        // collapse 16bit precision data to 8bit
        if(bit_depth == 16) png_set_strip_16(png_ptr);

        // change color component order
        if (color_type == PNG_COLOR_TYPE_RGB ||
                color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            png_set_bgr(png_ptr);

        // call png_read_update_info ...
        png_read_update_info(png_ptr, info_ptr);

        // set size
        Width=width, Height=height;

        // allocate memory for row_pointers
        row_pointers = new png_bytep[height];
        png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
        image = new BYTE[rowbytes*height];
        for(i = 0; i < height; i++)
        {
            row_pointers[i] = image + i*rowbytes;
        }

        // load image
        png_read_image(png_ptr, row_pointers);

        // finish loading image
        png_read_end(png_ptr, info_ptr);

        // set image to ScanLines

        BYTE *imageptr = image;
        if(color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        {
            // IA IA IA ....

            for(i = 0; i < height; i++)
            {
                BYTE *scanptr = (BYTE*)ScanLine[i];
                png_uint_32 j;
                for(j = 0; j < width; j++)
                {
                    BYTE i = *(imageptr++);
                    scanptr[0] = i;
                    scanptr[1] = i;
                    scanptr[2] = i;
                    scanptr[3] = *(imageptr++);
                    scanptr += 4;
                }
            }
        }
        else
        {
            // intact copy

            for(i = 0; i < height; i++)
            {
                BYTE *scanptr = (BYTE*)ScanLine[i];
                memcpy(scanptr, imageptr, rowbytes);
                imageptr += rowbytes;
            }


        }
    }
    catch(...)
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        if(row_pointers) delete [] row_pointers;
        if(image) delete [] image;
        throw;
    }

    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    if(row_pointers) delete [] row_pointers;
    if(image) delete [] image;
}
twin_pixmap_t *twin_png_to_pixmap(const char *filepath, twin_format_t fmt)
{
	uint8_t		signature[8];
	int		fd, i, rb = 0;
	size_t		n;
	png_structp	png = NULL;
	png_infop	info = NULL;
	twin_pixmap_t	*pix = NULL;
	twin_png_priv_t priv;
	png_uint_32	width, height;
	int		depth, ctype, interlace;
	png_bytep	*rowp = NULL;

	DEBUG("png read for %s, format=%d\n", filepath, fmt);

	fd = open(filepath, O_RDONLY);
	if (fd < 0)
		goto fail;

	DEBUG("checking signature...\n");

	n = read(fd, signature, 8);
	if (png_sig_cmp(signature, 0, n) != 0)
		goto fail_close;

	DEBUG("creating libpng structures...\n");

	png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
				     NULL, NULL, NULL);
	if (png == NULL)
		goto fail_close;

	info = png_create_info_struct(png);
	if (info == NULL)
		goto fail_free;
	    
	if (setjmp(png_jmpbuf(png))) {
		DEBUG("* error callback *\n");
		if (pix)
			twin_pixmap_destroy(pix);
		pix = NULL;
		goto fail_free;
	}
	priv.fd = fd;
	png_set_read_fn(png, &priv, twin_png_read_fn);

	png_set_sig_bytes(png, n);

	DEBUG("reading picture infos ...\n");
	png_read_info(png, info);
	png_get_IHDR(png, info, &width, &height, &depth, &ctype, &interlace,
		     int_p_NULL, int_p_NULL);
	
	DEBUG(" 1- size/depth/ctype/int = %ldx%ld/%d/%d/%d\n",
	      width, height, depth, ctype, interlace);

	if (depth == 16)
		png_set_strip_16(png);
	if (ctype == PNG_COLOR_TYPE_PALETTE)
		png_set_palette_to_rgb(png);
	if (ctype == PNG_COLOR_TYPE_GRAY && depth < 8)
		png_set_gray_1_2_4_to_8(png);
	if (png_get_valid(png, info, PNG_INFO_tRNS))
		png_set_tRNS_to_alpha(png);

	png_get_IHDR(png, info, &width, &height, &depth, &ctype, &interlace,
		     int_p_NULL, int_p_NULL);

	DEBUG(" 2- size/depth/ctype/int = %ldx%ld/%d/%d/%d\n",
	      width, height, depth, ctype, interlace);

	switch(fmt) {
	case TWIN_A8:
		if (ctype != PNG_COLOR_TYPE_GRAY ||
		    depth != 8)
			goto fail_free;
		rb = width;
		break;
	case TWIN_RGB16:
		/* unsupported for now */
		goto fail_free;
	case TWIN_ARGB32:
		if (ctype == PNG_COLOR_TYPE_RGB)
			png_set_filler(png, 0xff, PNG_FILLER_BEFORE);
		if (ctype == PNG_COLOR_TYPE_RGB_ALPHA)
			png_set_swap_alpha(png);
		if (ctype == PNG_COLOR_TYPE_GRAY ||
		    ctype == PNG_COLOR_TYPE_GRAY_ALPHA)
			png_set_gray_to_rgb(png);

		png_get_IHDR(png, info, &width, &height, &depth, &ctype,
			     &interlace, int_p_NULL, int_p_NULL);

		DEBUG(" 3- size/depth/ctype/int = %ldx%ld/%d/%d/%d\n",
		      width, height, depth, ctype, interlace);

		if (depth != 8)
			goto fail_free;
		rb = width * 4;
		break;
	}
	DEBUG(" rowbytes = %d\n", rb);

	DEBUG("preparing pixmap & row pointer array...\n");

	rowp = malloc(height * sizeof(png_bytep));
	if (rowp == NULL)
		goto fail_free;
	pix = twin_pixmap_create(fmt, width, height);
	if (pix == NULL)
		goto fail_free;
	for (i = 0; i < height; i++)
		rowp[i] = pix->p.b + rb * i;

	DEBUG("reading image...\n");

	png_read_image(png, rowp);

	png_read_end(png, NULL);

	if (fmt == TWIN_ARGB32)
		twin_premultiply_alpha(pix);

 fail_free:
	if (rowp)
		free(rowp);
	png_destroy_read_struct(&png, &info, png_infopp_NULL);
 fail_close:
	close(fd);
 fail:
	return pix;
}
Esempio n. 18
0
    //-------------------------------------------------------------------------------
    Status Image::loadAsPNG(BYTE* data) {
        png_byte header[8];
        png_structp pngPtr = NULL;
        png_infop infoPtr = NULL;
        png_bytep* rowPtrs = NULL;
        png_int_32 rowSize;
        bool transparency;

        ///////////////////////////////////////////////:
        // Check the header signature
        memcpy(header, data, sizeof(header));
        if (png_sig_cmp(header, 0, 8) != 0) goto ERROR;

        pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                        NULL,
                                        png_error_fn,           // error callback
                                        png_warning_fn);        // warning callback
        if (!pngPtr) goto ERROR;

        infoPtr = png_create_info_struct(pngPtr);
        if (!infoPtr) goto ERROR;

        if (setjmp(png_jmpbuf(pngPtr))) goto ERROR;

        ////////////////////////////////////////////////////////////////////////
        // Create the read structure and set the read function from a memory pointer
        ByteBuffer bb;
        bb.offset = 8; //sig
        bb.data = data;
        png_set_read_fn(pngPtr, &bb, memoryReadCallback);

        //tell libpng we already read the signature
        png_set_sig_bytes(pngPtr, 8);

        png_read_info(pngPtr, infoPtr);

        png_int_32 depth, colorType;
        png_uint_32 width, height;
        png_get_IHDR(pngPtr, infoPtr, &width, &height,
                     &depth, &colorType, NULL, NULL, NULL);
        mWidth = width;
        mHeight = height;

        // Creates a full alpha channel if transparency is encoded as
        // an array of palette entries or a single transparent color.
        transparency = false;
        if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS)) {
            png_set_tRNS_to_alpha(pngPtr);
            transparency = true;
        }
        // Expands PNG with less than 8bits per channel to 8bits.
        if (depth < 8) {
            png_set_packing(pngPtr);
        }
            // Shrinks PNG with 16bits per color channel down to 8bits.
        else if (depth == 16){
            png_set_strip_16(pngPtr);
        }
        // Indicates that image needs conversion to RGBA if needed.
        switch (colorType){
            case PNG_COLOR_TYPE_PALETTE:
                png_set_palette_to_rgb(pngPtr);
                if (transparency) {
                    mFormat = GL_RGBA;
                    mBytesPerPixel = 4;
                } else {
                    mFormat = GL_RGB;
                    mBytesPerPixel = 3;
                }
                break;
            case PNG_COLOR_TYPE_RGB:
                if (transparency) {
                    mFormat = GL_RGBA;
                    mBytesPerPixel = 4;
                } else {
                    mFormat = GL_RGB;
                    mBytesPerPixel = 3;
                }
                break;
            case PNG_COLOR_TYPE_RGBA:
                if (transparency) {
                    mFormat = GL_RGBA;
                    mBytesPerPixel = 4;
                } else {
                    mFormat = GL_RGB;
                    mBytesPerPixel = 3;
                }
                break;
            case PNG_COLOR_TYPE_GRAY:
                png_set_expand_gray_1_2_4_to_8(pngPtr);
                mFormat = transparency  ? GL_LUMINANCE_ALPHA : GL_LUMINANCE;
                if (transparency) {
                    mFormat = GL_LUMINANCE_ALPHA;
                    mBytesPerPixel = 2;
                } else {
                    mFormat = GL_LUMINANCE;
                    mBytesPerPixel = 1;
                }
                break;
            case PNG_COLOR_TYPE_GA:
                png_set_expand_gray_1_2_4_to_8(pngPtr);
                if (transparency) {
                    mFormat = GL_LUMINANCE_ALPHA;
                    mBytesPerPixel = 2;
                } else {
                    mFormat = GL_LUMINANCE;
                    mBytesPerPixel = 1;
                }
                break;
            default:
                assert(false);
                break;
        }
        png_read_update_info(pngPtr, infoPtr);

        rowSize = png_get_rowbytes(pngPtr, infoPtr);
        if(rowSize <= 0) goto ERROR;
        mPixels = new BYTE[rowSize * height];
        if(!mPixels) goto ERROR;
        rowPtrs = new png_bytep[height];
        if(!rowPtrs) goto ERROR;

        for(U32 i = 0; i < height; ++i){
            rowPtrs[height - (i + 1)] = mPixels + i * rowSize;
        }
        png_read_image(pngPtr, rowPtrs);

        png_destroy_read_struct(&pngPtr, &infoPtr, NULL);
        delete[] rowPtrs;
        return STATUS_OK;

        ERROR:
        Log::error(TAG, "Error while reading PNG data");
        delete[] rowPtrs; delete[] mPixels;
        if(pngPtr != NULL){
            png_infop* infoPtrP = infoPtr != NULL ? &infoPtr : NULL;
            png_destroy_read_struct(&pngPtr, infoPtrP, NULL);
        }
        return throwException(TAG, ExceptionType::INVALID_FILE, "unknown error while reading PNG data");
    }
// load in the image data
IImage* CImageLoaderPng::loadImage(io::IReadFile* file) const
{
#ifdef _IRR_COMPILE_WITH_LIBPNG_
	if (!file)
		return 0;

	video::IImage* image = 0;
	//Used to point to image rows
	u8** RowPointers = 0;

	png_byte buffer[8];
	// Read the first few bytes of the PNG file
	if( file->read(buffer, 8) != 8 )
	{
		os::Printer::log("LOAD PNG: can't read file\n", file->getFileName(), ELL_ERROR);
		return 0;
	}

	// Check if it really is a PNG file
	if( png_sig_cmp(buffer, 0, 8) )
	{
		os::Printer::log("LOAD PNG: not really a png\n", file->getFileName(), ELL_ERROR);
		return 0;
	}

	// Allocate the png read struct
	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
		NULL, (png_error_ptr)png_cpexcept_error, (png_error_ptr)png_cpexcept_warn);
	if (!png_ptr)
	{
		os::Printer::log("LOAD PNG: Internal PNG create read struct failure\n", file->getFileName(), ELL_ERROR);
		return 0;
	}

	// Allocate the png info struct
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		os::Printer::log("LOAD PNG: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR);
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		return 0;
	}

	// for proper error handling
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		delete [] RowPointers;
		return 0;
	}

	// changed by zola so we don't need to have public FILE pointers
	png_set_read_fn(png_ptr, file, user_read_data_fcn);

	png_set_sig_bytes(png_ptr, 8); // Tell png that we read the signature

	png_read_info(png_ptr, info_ptr); // Read the info section of the png file

	u32 Width;
	u32 Height;
	s32 BitDepth;
	s32 ColorType;
	{
		// Use temporary variables to avoid passing casted pointers
		png_uint_32 w,h;
		// Extract info
		png_get_IHDR(png_ptr, info_ptr,
			&w, &h,
			&BitDepth, &ColorType, NULL, NULL, NULL);
		Width=w;
		Height=h;
	}

	// Convert palette color to true color
	if (ColorType==PNG_COLOR_TYPE_PALETTE)
		png_set_palette_to_rgb(png_ptr);

	// Convert low bit colors to 8 bit colors
	if (BitDepth < 8)
	{
		if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA)
			png_set_expand_gray_1_2_4_to_8(png_ptr);
		else
			png_set_packing(png_ptr);
	}

	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_tRNS_to_alpha(png_ptr);

	// Convert high bit colors to 8 bit colors
	if (BitDepth == 16)
		png_set_strip_16(png_ptr);

	// Convert gray color to true color
	if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png_ptr);

	int intent;
	const double screen_gamma = 2.2;

	if (png_get_sRGB(png_ptr, info_ptr, &intent))
		png_set_gamma(png_ptr, screen_gamma, 0.45455);
	else
	{
		double image_gamma;
		if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
			png_set_gamma(png_ptr, screen_gamma, image_gamma);
		else
			png_set_gamma(png_ptr, screen_gamma, 0.45455);
	}

	// Update the changes in between, as we need to get the new color type
	// for proper processing of the RGBA type
	png_read_update_info(png_ptr, info_ptr);
	{
		// Use temporary variables to avoid passing casted pointers
		png_uint_32 w,h;
		// Extract info
		png_get_IHDR(png_ptr, info_ptr,
			&w, &h,
			&BitDepth, &ColorType, NULL, NULL, NULL);
		Width=w;
		Height=h;
	}

	// Convert RGBA to BGRA
	if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA)
	{
#ifdef __BIG_ENDIAN__
		png_set_swap_alpha(png_ptr);
#else
		png_set_bgr(png_ptr);
#endif
	}

	// Create the image structure to be filled by png data
	if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA)
		image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(Width, Height));
	else
		image = new CImage(ECF_R8G8B8, core::dimension2d<u32>(Width, Height));
	if (!image)
	{
		os::Printer::log("LOAD PNG: Internal PNG create image struct failure\n", file->getFileName(), ELL_ERROR);
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		return 0;
	}

	// Create array of pointers to rows in image data
	RowPointers = new png_bytep[Height];
	if (!RowPointers)
	{
		os::Printer::log("LOAD PNG: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR);
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		delete image;
		return 0;
	}

	// Fill array of pointers to rows in image data
	unsigned char* data = (unsigned char*)image->getData();
	for (u32 i=0; i<Height; ++i)
	{
		RowPointers[i]=data;
		data += image->getPitch();
	}

	// for proper error handling
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		delete [] RowPointers;
		delete image;
		return 0;
	}

	// Read data using the library function that handles all transformations including interlacing
	png_read_image(png_ptr, RowPointers);

	png_read_end(png_ptr, NULL);
	delete [] RowPointers;
	png_destroy_read_struct(&png_ptr,&info_ptr, 0); // Clean up memory

	return image;
#else
	return 0;
#endif // _IRR_COMPILE_WITH_LIBPNG_
}
static void png_info_callback(png_structp png_ptr, png_infop info_ptr)
{
	int bit_depth, color_type, intent;
	double gamma;
	int bytes_per_pixel=3;
	struct cached_image *cimg;

	cimg=global_cimg;

	bit_depth=png_get_bit_depth(png_ptr, info_ptr);
	color_type=png_get_color_type(png_ptr, info_ptr);
	if (color_type == PNG_COLOR_TYPE_PALETTE)
        	png_set_expand(png_ptr);
    	if (color_type == PNG_COLOR_TYPE_GRAY &&
        	bit_depth < 8) png_set_expand(png_ptr);
	if (png_get_valid(png_ptr, info_ptr,
        	PNG_INFO_tRNS)){
		png_set_expand(png_ptr); /* Legacy version of
		png_set_tRNS_to_alpha(png_ptr); */
		bytes_per_pixel++;
	}
	if (color_type == PNG_COLOR_TYPE_GRAY ||
		color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png_ptr);
	if (bit_depth==16){
#ifndef REPACK_16
#ifdef C_LITTLE_ENDIAN
		/* We use native endianity only if unsigned short is 2-byte
		 * because otherwise we have to reassemble the buffer so we
		 * will leave in the libpng-native big endian.
		 */
		png_set_swap(png_ptr);
#endif /* #ifdef C_LITTLE_ENDIAN */
#endif /* #ifndef REPACK_16 */
		bytes_per_pixel*=sizeof(unsigned short);
	}
	png_set_interlace_handling(png_ptr);
	if (color_type==PNG_COLOR_TYPE_RGB_ALPHA
		||color_type==PNG_COLOR_TYPE_GRAY_ALPHA){
		if (bytes_per_pixel==3
			||bytes_per_pixel==3*sizeof(unsigned short))
			bytes_per_pixel=4*bytes_per_pixel/3;
	}
	cimg->width=png_get_image_width(png_ptr,info_ptr);
	cimg->height=png_get_image_height(png_ptr,info_ptr);
	cimg->buffer_bytes_per_pixel=bytes_per_pixel;
	if (png_get_sRGB(png_ptr, info_ptr, &intent)){
		gamma=sRGB_gamma;
	}
	else
 	{              
  		if (!png_get_gAMA(png_ptr, info_ptr, &gamma)){
			gamma=sRGB_gamma;
		}
	}
	cimg->red_gamma=gamma;
	cimg->green_gamma=gamma;
	cimg->blue_gamma=gamma;
	png_read_update_info(png_ptr,info_ptr);                 
	cimg->strip_optimized=0;
	if (header_dimensions_known(cimg))
		img_my_png_error(png_ptr, "bad image size");
}
Esempio n. 21
0
void PNGFile::_Load(std::istream &Stream)
{
	//Leemos y verificamos la firma del archivo para asegurarnos que sea un png
	png_bytep pFirma = new png_byte[8];
	Stream.read((char*)pFirma, sizeof(png_byte)*8);

	if( png_sig_cmp(pFirma, 0, 8) != 0 )
		throw std::exception();//"El archivo cargado no es un png");
	delete[] pFirma;


	m_pPNGReadStruct = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if ( m_pPNGReadStruct == NULL )//Si fallo la creacion del struct de lectura del png
		throw std::exception();//"No se pudo crear el struct de lectura de png");

	//Establecemos la funcion/callback que usare LibPNG para leer los datos
	png_set_read_fn(m_pPNGReadStruct,(png_voidp)&Stream, leerDatosfn);

	//Intentamos crear el encabezado del archivo png
	m_pHeader = png_create_info_struct(m_pPNGReadStruct);
	if ( m_pHeader == NULL ) 
	{
		png_destroy_read_struct(&m_pPNGReadStruct, (png_infopp)0, (png_infopp)0);//liberamos el png
		throw std::exception();//"No se pudo crear el encabezado del archivo png");
	}


	//Apuntara a cada fila de la imagen en m_EspacioColores... ver mas abajo una explicacion mas detallada
	png_bytep* ArregloFilas = NULL;

	//Informamos que si ocurre un error leyendo el archivo salte a este if
	if (setjmp(png_jmpbuf(m_pPNGReadStruct))) {
		png_destroy_read_struct(&m_pPNGReadStruct, &m_pHeader,(png_infopp)0);//liberamos el png y el encabezado
		if (ArregloFilas != NULL) 
			delete [] ArregloFilas;
		if (m_ArregloColores != NULL) 
			delete [] m_ArregloColores;

		throw std::exception();//"Sucedio un error leyendo el archivo png");
	}

	//Avisamos a libpng que la firma ya fue leida y que lea el encabezado
    png_set_sig_bytes(m_pPNGReadStruct, 8);

    //Leemos el encabezado del png
    png_read_info(m_pPNGReadStruct, m_pHeader);

	//Leemos las dimensiones de la imagen del encabezado
	m_Width  = png_get_image_width (m_pPNGReadStruct, m_pHeader);

    m_Height = png_get_image_height(m_pPNGReadStruct, m_pHeader);

    //Bits por canal de la imagen(NO POR PIXEL, SINO POR CANAL... EN GENERAL 1 PIXEL TIENE MUCHOS CANALES)
    png_uint_32 bitdepth   = png_get_bit_depth(m_pPNGReadStruct, m_pHeader);
    //Numero de canales de la imagen
    png_uint_32 channels   = png_get_channels(m_pPNGReadStruct, m_pHeader);
    //Tipo de espacio de colores... luego lo convertiremos a m_EspacioColores
    png_uint_32 color_type = png_get_color_type(m_pPNGReadStruct, m_pHeader);

	//Si el formato de la imagen no es R8_G8_B8_ o R8_G8_B8_A8 intentamos convertirla a
	//estos usando funciones de LibPNG
	switch (color_type)
	{
		case PNG_COLOR_TYPE_RGB:
			m_EspacioColores = ImageFile::R8_G8_B8;
			break;
		case PNG_COLOR_TYPE_RGBA:
			m_EspacioColores = ImageFile::R8_G8_B8_A8;
			break;
        case PNG_COLOR_TYPE_PALETTE:
            png_set_palette_to_rgb(m_pPNGReadStruct);
			m_EspacioColores = ImageFile::R8_G8_B8;
            channels = 3;//ahora tendremos 3 canales
            break;
        case PNG_COLOR_TYPE_GRAY:
			png_set_gray_to_rgb(m_pPNGReadStruct);
			m_EspacioColores = ImageFile::R8_G8_B8;
			bitdepth = 8;
			channels = 3;//ahora tendremos 3 canales
            break;
		default:
			throw std::exception();//"La implementacion de PNGFile no soporta el espacio de colores de la imagen que se esta cargando");
    }

    //Si la imagen tiene transparencia la convertimos al canal alpha
    if (png_get_valid(m_pPNGReadStruct, m_pHeader, PNG_INFO_tRNS)) {
        png_set_tRNS_to_alpha(m_pPNGReadStruct);
        channels+=1;//Un canal mas
    }

	//Si cada canal tiene 16 bits de profundidad lo convertimos a 8 bits
	//ya que nuestros formatos son de 8 bits de profundidad
    if( bitdepth == 16 )
        png_set_strip_16(m_pPNGReadStruct);


	//LibPNG lee los datos de color por filas de la imagen
	//Para hacerlo requiere que le pasemos un arreglo de punteros a donde se almacenara cada 
	//fila de la imagen
    ArregloFilas = new png_bytep[m_Height];

    //Almacenamos el buffer donde se almacenara la imagen leida(ArregloFilas apuntara a direciones dentro de este buffer)
    m_ArregloColores = new unsigned char[m_Width * m_Height * (bitdepth * channels / 8)];

    //El tamaño que ocupa una fila de la imagen
    const unsigned int rowTotSize = m_Width * bitdepth * channels / 8;

	//Ahora apuntamos los punteros de ArregloFilas a las direciones de m_ArregloColores
	//donde cada elemento de ArregloFilas es la dir de una fila de la imagen
    for (unsigned int i = 0; i < m_Height; i++)
        ArregloFilas[i] = (png_bytep)m_ArregloColores + i*rowTotSize;

	//Aca leemos los datos de la imagen del archivo
	//Alamcena los cada fila en las direciones señaladas por ArregloFilas
	//que a su vez apuntan dentro de m_ArregloColores... lo cual significa
	//que luego de esto m_ArregloColores tendra los datos de la imagen como los deseamos
    png_read_image(m_pPNGReadStruct, ArregloFilas);
	
	//Limpiamos el arreglo de punteros a filas(NO LOS DATOS SINO SOLO LOS PUNTEROS)
    delete[] (png_bytep)ArregloFilas;
    png_destroy_read_struct(&m_pPNGReadStruct, &m_pHeader,(png_infopp)0);//liberamos el png y el encabezado


	if( Stream.bad() || Stream.fail() || Stream.eof() )
		throw std::exception();//"La carga del archivo bmp tuvo errores");
}
Esempio n. 22
0
static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_t *grpatch)
{
	png_structp png_ptr;
	png_infop png_info_ptr;
	png_uint_32 width, height;
	int bit_depth, color_type;
#ifdef PNG_SETJMP_SUPPORTED
#ifdef USE_FAR_KEYWORD
	jmp_buf jmpbuf;
#endif
#endif
	png_FILE_p png_FILE;
	char *pngfilename = va("md2/%s", filename);

	FIL_ForceExtension(pngfilename, ".png");
	png_FILE = fopen(pngfilename, "rb");
	if (!png_FILE)
	{
		//CONS_Debug(DBG_RENDER, "M_SavePNG: Error on opening %s for loading\n", filename);
		return 0;
	}

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
		PNG_error, PNG_warn);
	if (!png_ptr)
	{
		CONS_Debug(DBG_RENDER, "PNG_Load: Error on initialize libpng\n");
		fclose(png_FILE);
		return 0;
	}

	png_info_ptr = png_create_info_struct(png_ptr);
	if (!png_info_ptr)
	{
		CONS_Debug(DBG_RENDER, "PNG_Load: Error on allocate for libpng\n");
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		fclose(png_FILE);
		return 0;
	}

#ifdef USE_FAR_KEYWORD
	if (setjmp(jmpbuf))
#else
	if (setjmp(png_jmpbuf(png_ptr)))
#endif
	{
		//CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename);
		png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);
		fclose(png_FILE);
		Z_Free(grpatch->mipmap.grInfo.data);
		return 0;
	}
#ifdef USE_FAR_KEYWORD
	png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf);
#endif

	png_init_io(png_ptr, png_FILE);

#ifdef PNG_SET_USER_LIMITS_SUPPORTED
	png_set_user_limits(png_ptr, 2048, 2048);
#endif

	png_read_info(png_ptr, png_info_ptr);

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

	if (bit_depth == 16)
		png_set_strip_16(png_ptr);

	if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png_ptr);
	else if (color_type == PNG_COLOR_TYPE_PALETTE)
		png_set_palette_to_rgb(png_ptr);

	if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_tRNS))
		png_set_tRNS_to_alpha(png_ptr);
	else if (color_type != PNG_COLOR_TYPE_RGB_ALPHA && color_type != PNG_COLOR_TYPE_GRAY_ALPHA)
	{
#if PNG_LIBPNG_VER < 10207
		png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
#else
		png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
#endif
	}

	png_read_update_info(png_ptr, png_info_ptr);

	{
		png_uint_32 i, pitch = png_get_rowbytes(png_ptr, png_info_ptr);
		png_bytep PNG_image = Z_Malloc(pitch*height, PU_HWRCACHE, &grpatch->mipmap.grInfo.data);
		png_bytepp row_pointers = png_malloc(png_ptr, height * sizeof (png_bytep));
		for (i = 0; i < height; i++)
			row_pointers[i] = PNG_image + i*pitch;
		png_read_image(png_ptr, row_pointers);
		png_free(png_ptr, (png_voidp)row_pointers);
	}

	png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL);

	fclose(png_FILE);
	*w = (int)width;
	*h = (int)height;
	return GR_RGBA;
}