Esempio n. 1
0
void LoadPNG( const char *name, byte **pic, int *width, int *height,
	      int *numLayers, int *numMips, int *bits, byte alphaByte )
{
	int          bit_depth;
	int          color_type;
	png_uint_32  w;
	png_uint_32  h;
	unsigned int row;
//	size_t          rowbytes;
	png_infop    info;
	png_structp  png;
	png_bytep    *row_pointers;
	byte         *data;
	byte         *out;
//	int             size;

	// load png
	ri.FS_ReadFile( name, ( void ** ) &data );

	if ( !data )
	{
		return;
	}

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

	if ( !png )
	{
		ri.Printf( PRINT_WARNING, "LoadPNG: png_create_write_struct() failed for (%s)\n", name );
		ri.FS_FreeFile( data );
		return;
	}

	// allocate/initialize the memory for image information.  REQUIRED
	info = png_create_info_struct( png );

	if ( !info )
	{
		ri.Printf( PRINT_WARNING, "LoadPNG: png_create_info_struct() failed for (%s)\n", name );
		ri.FS_FreeFile( data );
		png_destroy_read_struct( &png, ( png_infopp ) NULL, ( png_infopp ) NULL );
		return;
	}

	/*
	 * Set error handling if you are using the setjmp/longjmp method (this is
	 * the common 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 ) ) )
	{
		// if we get here, we had a problem reading the file
		ri.Printf( PRINT_WARNING, "LoadPNG: first exception handler called for (%s)\n", name );
		ri.FS_FreeFile( data );
		png_destroy_read_struct( &png, ( png_infopp ) & info, ( png_infopp ) NULL );
		return;
	}

	//png_set_write_fn(png, buffer, png_write_data, png_flush_data);
	png_set_read_fn( png, data, png_read_data );

	png_set_sig_bytes( png, 0 );

	// 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, info );

	// get picture info
	png_get_IHDR( png, info, ( png_uint_32 * ) &w, ( png_uint_32 * ) &h, &bit_depth, &color_type, NULL, NULL, NULL );

	// tell libpng to strip 16 bit/color files down to 8 bits/color
	png_set_strip_16( png );

	// expand paletted images to RGB triplets
	if ( color_type & PNG_COLOR_MASK_PALETTE )
	{
		png_set_expand( png );
	}

	// expand gray-scaled images to RGB triplets
	if ( !( color_type & PNG_COLOR_MASK_COLOR ) )
	{
		png_set_gray_to_rgb( png );
	}

	// expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel
	//if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
	//  png_set_gray_1_2_4_to_8(png);

	// 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, info, PNG_INFO_tRNS ) )
	{
		png_set_tRNS_to_alpha( png );
	}

	// if there is no alpha information, fill with alphaByte
	if ( !( color_type & PNG_COLOR_MASK_ALPHA ) )
	{
		png_set_filler( png, alphaByte, PNG_FILLER_AFTER );
	}

	// expand pictures with less than 8bpp to 8bpp
	if ( bit_depth < 8 )
	{
		png_set_packing( png );
	}

	// update structure with the above settings
	png_read_update_info( png, info );

	// allocate the memory to hold the image
	*width = w;
	*height = h;
	*pic = out = ( byte * ) ri.Z_Malloc( w * h * 4 );

	row_pointers = ( png_bytep * ) ri.Hunk_AllocateTempMemory( sizeof( png_bytep ) * h );

	// set a new exception handler
	if ( setjmp( png_jmpbuf( png ) ) )
	{
		ri.Printf( PRINT_WARNING, "LoadPNG: second exception handler called for (%s)\n", name );
		ri.Hunk_FreeTempMemory( row_pointers );
		ri.FS_FreeFile( data );
		png_destroy_read_struct( &png, ( png_infopp ) & info, ( png_infopp ) NULL );
		return;
	}

	//rowbytes = png_get_rowbytes(png, info);

	for ( row = 0; row < h; row++ )
	{
		row_pointers[ row ] = ( png_bytep )( out + ( row * 4 * w ) );
	}

	// read image data
	png_read_image( png, row_pointers );

	// read rest of file, and get additional chunks in info
	png_read_end( png, info );

	// clean up after the read, and free any memory allocated
	png_destroy_read_struct( &png, &info, ( png_infopp ) NULL );

	ri.Hunk_FreeTempMemory( row_pointers );
	ri.FS_FreeFile( data );
}
Esempio n. 2
0
bool ImageLoaderPNG::ReadData() {
  
  const int kNumSigBytesToRead = 8;
  uint8 pngSigBuf[kNumSigBytesToRead];
  memcpy(pngSigBuf, m_RawData, kNumSigBytesToRead);

  const int numSigNoMatch = png_sig_cmp(pngSigBuf, 0, kNumSigBytesToRead);
  if(numSigNoMatch) {
    ReportError("Incorrect PNG signature");
    return false;
  }

  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if(!png_ptr) {
    ReportError("Could not create read struct");
    return false;
  }

  png_infop info_ptr = png_create_info_struct(png_ptr);
  if(!info_ptr) {
    ReportError("Could not create info struct");
    png_destroy_read_struct(&png_ptr, NULL, NULL);
    return false;
  }

  // Read from our buffer, not a file pointer...
  png_set_read_fn(png_ptr, this, PNGStreamReader::ReadDataFromStream);

  // Make sure to tell libpng how many bytes we've read...
  png_set_sig_bytes(png_ptr, kNumSigBytesToRead);

  png_read_info(png_ptr, info_ptr);

  int bitDepth = 0;
  int colorType = -1;

  if( 1 != png_get_IHDR(png_ptr, info_ptr, 
    (png_uint_32 *)(&m_Width), (png_uint_32 *)(&m_Height), 
    &bitDepth, &colorType, 
    NULL, NULL, NULL) 
  ) {
    ReportError("Could not read PNG header");
    png_destroy_read_struct(&png_ptr, NULL, NULL);
    return false;
  }

  if(bitDepth != 8) {
    ReportError("Only 8-bit images currently supported.");
    png_destroy_read_struct(&png_ptr, NULL, NULL);
    return false;
  }

  const int numPixels = m_Width * m_Height;
  png_size_t bpr = png_get_rowbytes(png_ptr, info_ptr);
  png_bytep rowData = new png_byte[bpr];

  switch(colorType) {
    default:
      ReportError("PNG color type unsupported");
      png_destroy_read_struct(&png_ptr, NULL, NULL);
      delete [] rowData;
      return false;

    case PNG_COLOR_TYPE_PALETTE:
    {
      m_RedChannelPrecision = bitDepth;
      m_RedData = new unsigned char[numPixels];
      m_GreenChannelPrecision = bitDepth;
      m_GreenData = new unsigned char[numPixels];
      m_BlueChannelPrecision = bitDepth;
      m_BlueData = new unsigned char[numPixels];

      png_colorp palette;
      int nPaletteEntries;
      png_uint_32 ret = png_get_PLTE(png_ptr, info_ptr, &palette, &nPaletteEntries);
      if(ret != PNG_INFO_PLTE) {
        memset(m_BlueData, 0, numPixels);
        memset(m_RedData, 0, numPixels);
        memset(m_GreenData, 0, numPixels);
        assert(!"Couldn't find PLTE chunk");
        break;
      }

      for(uint32 i = 0; i < m_Height; i++) {
        png_read_row(png_ptr, rowData, NULL);
        unsigned int rowOffset = i * m_Width;
        for(uint32 j = 0; j < m_Width; j++) {
          assert(rowData[j] < nPaletteEntries);
          const png_color &c = palette[::std::min<unsigned char>(rowData[j], nPaletteEntries - 1)];
          m_RedData[rowOffset + j] = c.red;
          m_GreenData[rowOffset + j] = c.green;
          m_BlueData[rowOffset + j] = c.blue;
        }
      }
    }
    break;

    case PNG_COLOR_TYPE_GRAY: {
      m_RedChannelPrecision = bitDepth;
      m_RedData = new unsigned char[numPixels];
      m_GreenChannelPrecision = bitDepth;
      m_GreenData = new unsigned char[numPixels];
      m_BlueChannelPrecision = bitDepth;
      m_BlueData = new unsigned char[numPixels];

      for(uint32 i = 0; i < m_Height; i++) {
  
        png_read_row(png_ptr, rowData, NULL);

        unsigned int rowOffset = i * m_Width;
  
        unsigned int byteIdx = 0;
        for(uint32 j = 0; j < m_Width; j++) {
          m_RedData[rowOffset + j] = rowData[byteIdx];
          m_GreenData[rowOffset + j] = rowData[byteIdx];
          m_BlueData[rowOffset + j] = rowData[byteIdx];
          byteIdx++;
        }

        assert(byteIdx == bpr);
      }
    }
    break;

    case PNG_COLOR_TYPE_RGB:
      m_RedChannelPrecision = bitDepth;
      m_RedData = new unsigned char[numPixels];
      m_GreenChannelPrecision = bitDepth;
      m_GreenData = new unsigned char[numPixels];
      m_BlueChannelPrecision = bitDepth;
      m_BlueData = new unsigned char[numPixels];

      for(uint32 i = 0; i < m_Height; i++) {
  
        png_read_row(png_ptr, rowData, NULL);

        unsigned int rowOffset = i * m_Width;
  
        unsigned int byteIdx = 0;
        for(uint32 j = 0; j < m_Width; j++) {
          m_RedData[rowOffset + j] = rowData[byteIdx++];
          m_GreenData[rowOffset + j] = rowData[byteIdx++];
          m_BlueData[rowOffset + j] = rowData[byteIdx++];
        }

        assert(byteIdx == bpr);
      }
    break;

    case PNG_COLOR_TYPE_RGB_ALPHA:
      m_RedChannelPrecision = bitDepth;
      m_RedData = new unsigned char[numPixels];
      m_GreenChannelPrecision = bitDepth;
      m_GreenData = new unsigned char[numPixels];
      m_BlueChannelPrecision = bitDepth;
      m_BlueData = new unsigned char[numPixels];
      m_AlphaChannelPrecision = bitDepth;
      m_AlphaData = new unsigned char[numPixels];

      for(uint32 i = 0; i < m_Height; i++) {
  
        png_read_row(png_ptr, rowData, NULL);

        unsigned int rowOffset = i * m_Width;
  
        unsigned int byteIdx = 0;
        for(uint32 j = 0; j < m_Width; j++) {
          m_RedData[rowOffset + j] = rowData[byteIdx++];
          m_GreenData[rowOffset + j] = rowData[byteIdx++];
          m_BlueData[rowOffset + j] = rowData[byteIdx++];
          m_AlphaData[rowOffset + j] = rowData[byteIdx++];
        }

        assert(byteIdx == bpr);
      }
    break;

    case PNG_COLOR_TYPE_GRAY_ALPHA:
      m_RedChannelPrecision = bitDepth;
      m_RedData = new unsigned char[numPixels];
      m_AlphaChannelPrecision = bitDepth;
      m_AlphaData = new unsigned char[numPixels];

      for(uint32 i = 0; i < m_Height; i++) {
  
        png_read_row(png_ptr, rowData, NULL);

        unsigned int rowOffset = i * m_Width;
  
        unsigned int byteIdx = 0;
        for(uint32 j = 0; j < m_Width; j++) {
          m_RedData[rowOffset + j] = rowData[byteIdx++];
          m_AlphaData[rowOffset + j] = rowData[byteIdx++];
        }

        assert(byteIdx == bpr);
      }
    break;
  }

  // Cleanup
  delete [] rowData;
  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  return true;
}
Esempio n. 3
0
/* This routine is based in part on the Chapter 13 demo code in "PNG: The
 *  Definitive Guide" (http://www.cdrom.com/pub/png/pngbook.html).
 */
BGD_DECLARE(gdImagePtr) gdImageCreateFromPngCtx (gdIOCtx * infile)
{
  png_byte sig[8];
  png_structp png_ptr;
  png_infop info_ptr;
  png_uint_32 width, height, rowbytes;
  int bit_depth, color_type, interlace_type;
  int num_palette, num_trans;
  png_colorp palette;
  png_color_16p trans_gray_rgb;
  png_color_16p trans_color_rgb;
  png_bytep trans;
  png_bytep image_data = NULL;
  png_bytepp row_pointers = NULL;
  gdImagePtr im = NULL;
  int i, j, *open = NULL;
  volatile int transparent = -1;
  volatile int palette_allocated = FALSE;

  /* Make sure the signature can't match by dumb luck -- TBB */
  /* GRR: isn't sizeof(infile) equal to the size of the pointer? */
  memset (infile, 0, sizeof (infile));

  /* first do a quick check that the file really is a PNG image; could
   * have used slightly more general png_sig_cmp() function instead */
  gdGetBuf (sig, 8, infile);
  if (!png_check_sig (sig, 8))
    return NULL;		/* bad signature */

#ifndef PNG_SETJMP_NOT_SUPPORTED
  png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, &gdPngJmpbufStruct,
				    gdPngErrorHandler, NULL);
#else
  png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
#endif
  if (png_ptr == NULL)
    {
      fprintf (stderr, "gd-png error: cannot allocate libpng main struct\n");
      return NULL;
    }

  info_ptr = png_create_info_struct (png_ptr);
  if (info_ptr == NULL)
    {
      fprintf (stderr, "gd-png error: cannot allocate libpng info struct\n");
      png_destroy_read_struct (&png_ptr, NULL, NULL);
      return NULL;
    }

  /* we could create a second info struct here (end_info), but it's only
   * useful if we want to keep pre- and post-IDAT chunk info separated
   * (mainly for PNG-aware image editors and converters) */

  /* setjmp() must be called in every non-callback function that calls a
   * PNG-reading libpng function */
#ifndef PNG_SETJMP_NOT_SUPPORTED
  if (setjmp (gdPngJmpbufStruct.jmpbuf))
    {
      fprintf (stderr, "gd-png error: setjmp returns error condition\n");
      png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
      return NULL;
    }
#endif

  png_set_sig_bytes (png_ptr, 8);	/* we already read the 8 signature bytes */

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

  png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
		&interlace_type, NULL, NULL);
  if ((color_type == PNG_COLOR_TYPE_RGB) ||
      (color_type == PNG_COLOR_TYPE_RGB_ALPHA))
    {
      im = gdImageCreateTrueColor ((int) width, (int) height);
    }
  else
    {
      im = gdImageCreate ((int) width, (int) height);
    }
  if (im == NULL)
    {
      fprintf (stderr, "gd-png error: cannot allocate gdImage struct\n");
      png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
      gdFree (image_data);
      gdFree (row_pointers);
      return NULL;
    }

  if (bit_depth == 16)
    png_set_strip_16 (png_ptr);
  else if (bit_depth < 8)
    png_set_packing (png_ptr);	/* expand to 1 byte per pixel */
  switch (color_type)
    {
    case PNG_COLOR_TYPE_PALETTE:
      png_get_PLTE (png_ptr, info_ptr, &palette, &num_palette);
#ifdef DEBUG
      fprintf (stderr, "gd-png color_type is palette, colors: %d\n",
	       num_palette);
#endif /* DEBUG */
      if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
	{
	  /* gd 2.0: we support this rather thoroughly now. Grab the
	     first fully transparent entry, if any, as the value of 
	     the simple-transparency index, mostly for backwards
	     binary compatibility. The alpha channel is where it's
	     really at these days. */
	  int firstZero = 1;
	  png_get_tRNS (png_ptr, info_ptr, &trans, &num_trans, NULL);
	  for (i = 0; i < num_trans; ++i)
	    {
	      im->alpha[i] = gdAlphaMax - (trans[i] >> 1);
	      if ((trans[i] == 0) && (firstZero))
		{
		  /* 2.0.5: long-forgotten patch from Wez Furlong */
		  transparent = i;
		  firstZero = 0;
		}
	    }
	}
      break;

    case PNG_COLOR_TYPE_GRAY:
    case PNG_COLOR_TYPE_GRAY_ALPHA:
      /* create a fake palette and check for single-shade transparency */
      if ((palette =
	   (png_colorp) gdMalloc (256 * sizeof (png_color))) == NULL)
	{
	  fprintf (stderr, "gd-png error: cannot allocate gray palette\n");
	  png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
	  return NULL;
	}
      palette_allocated = TRUE;
      if (bit_depth < 8)
	{
	  num_palette = 1 << bit_depth;
	  for (i = 0; i < 256; ++i)
	    {
	      j = (255 * i) / (num_palette - 1);
	      palette[i].red = palette[i].green = palette[i].blue = j;
	    }
	}
      else
	{
	  num_palette = 256;
	  for (i = 0; i < 256; ++i)
	    {
	      palette[i].red = palette[i].green = palette[i].blue = i;
	    }
	}
      if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
	{
	  png_get_tRNS (png_ptr, info_ptr, NULL, NULL, &trans_gray_rgb);
	  if (bit_depth == 16)	/* png_set_strip_16() not yet in effect */
	    transparent = trans_gray_rgb->gray >> 8;
	  else
	    transparent = trans_gray_rgb->gray;
	  /* Note slight error in 16-bit case:  up to 256 16-bit shades
	   * may get mapped to a single 8-bit shade, and only one of them
	   * is supposed to be transparent.  IOW, both opaque pixels and
	   * transparent pixels will be mapped into the transparent entry.
	   * There is no particularly good way around this in the case
	   * that all 256 8-bit shades are used, but one could write some
	   * custom 16-bit code to handle the case where there are gdFree
	   * palette entries.  This error will be extremely rare in
	   * general, though.  (Quite possibly there is only one such
	   * image in existence.) */
	}
      break;

    case PNG_COLOR_TYPE_RGB:
    case PNG_COLOR_TYPE_RGB_ALPHA:
      /* gd 2.0: we now support truecolor. See the comment above
         for a rare situation in which the transparent pixel may not
         work properly with 16-bit channels. */
      if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
	{
	  png_get_tRNS (png_ptr, info_ptr, NULL, NULL, &trans_color_rgb);
	  if (bit_depth == 16)	/* png_set_strip_16() not yet in effect */
	    transparent = gdTrueColor (trans_color_rgb->red >> 8,
				       trans_color_rgb->green >> 8,
				       trans_color_rgb->blue >> 8);
	  else
	    transparent = gdTrueColor (trans_color_rgb->red,
				       trans_color_rgb->green,
				       trans_color_rgb->blue);
	}
int res_create_surface_png(const char* name, gr_surface* pSurface) {
    GGLSurface* surface = NULL;
    int result = 0;
    unsigned char header[8];
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;

    FILE* fp = fopen(name, "rb");
    if (fp == NULL) {
        char resPath[256];
        if (gr_get_rotation() % 180 == 0)
            snprintf(resPath, sizeof(resPath)-1, "/res/portrait/%s.png", name);
        else
            snprintf(resPath, sizeof(resPath)-1, "/res/landscape/%s.png", name);

        resPath[sizeof(resPath)-1] = '\0';
        fp = fopen(resPath, "rb");
        if (fp == NULL)
        {
            result = -1;
            goto exit;
        }
    }

    size_t bytesRead = fread(header, 1, sizeof(header), fp);
    if (bytesRead != sizeof(header)) {
        result = -2;
        goto exit;
    }

    if (png_sig_cmp(header, 0, sizeof(header))) {
        result = -3;
        goto exit;
    }

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
        result = -4;
        goto exit;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        result = -5;
        goto exit;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        result = -6;
        goto exit;
    }

    png_set_packing(png_ptr);

    png_init_io(png_ptr, fp);
    png_set_sig_bytes(png_ptr, sizeof(header));
    png_read_info(png_ptr, info_ptr);

    size_t width = info_ptr->width;
    size_t height = info_ptr->height;
    size_t stride = 4 * width;
    size_t pixelSize = stride * height;

    int color_type = info_ptr->color_type;
    int bit_depth = info_ptr->bit_depth;
    int channels = info_ptr->channels;
    if (!(bit_depth == 8 &&
          ((channels == 3 && color_type == PNG_COLOR_TYPE_RGB) ||
           (channels == 4 && color_type == PNG_COLOR_TYPE_RGBA) ||
           (channels == 1 && color_type == PNG_COLOR_TYPE_PALETTE)))) {
        result = -7;
        goto exit;
    }

    surface = malloc(sizeof(GGLSurface) + pixelSize);
    if (surface == NULL) {
        result = -8;
        goto exit;
    }
    unsigned char* pData = (unsigned char*) (surface + 1);
    surface->version = sizeof(GGLSurface);
    surface->width = width;
    surface->height = height;
    surface->stride = width; /* Yes, pixels, not bytes */
    surface->data = pData;
    surface->format = (channels == 3) ?
            GGL_PIXEL_FORMAT_RGBX_8888 : GGL_PIXEL_FORMAT_RGBA_8888;

    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(png_ptr);
    }

    int y;
    if (channels < 4) {
        for (y = 0; y < (int) height; ++y) {
            unsigned char* pRow = pData + y * stride;
            png_read_row(png_ptr, pRow, NULL);

            int x;
            for(x = width - 1; x >= 0; x--) {
                int sx = x * 3;
                int dx = x * 4;
                unsigned char r = pRow[sx];
                unsigned char g = pRow[sx + 1];
                unsigned char b = pRow[sx + 2];
                unsigned char a = 0xff;
                pRow[dx    ] = r; // r
                pRow[dx + 1] = g; // g
                pRow[dx + 2] = b; // b
                pRow[dx + 3] = a;
            }
        }
    } else {
        for (y = 0; y < (int) height; ++y) {
            unsigned char* pRow = pData + y * stride;
            png_read_row(png_ptr, pRow, NULL);
        }
    }

    *pSurface = (gr_surface) surface;

exit:
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    if (fp != NULL) {
        fclose(fp);
    }
    if (result < 0) {
        if (surface) {
            free(surface);
        }
    }
    return result;
}
Esempio n. 5
0
bool ImageLoader::ReadPNG(ImageLoaderParams &ImgInfo)
{
	// Set up libpng reading.
	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, PNGErrorFn, PNGWarnFn);
	if (!png_ptr)
		return false;
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		return false;
	}
	png_infop end_info = png_create_info_struct(png_ptr);
	if (!end_info)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		return false;
	}
	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		return false;
	}
	// We read using a FILE*; this could be changed.
	File::IOFile file;
	if (!file.Open(ImgInfo.Path, "rb"))
	{
		return false;
	}
	png_init_io(png_ptr, file.GetHandle());
	png_set_sig_bytes(png_ptr, 0);
	// Process PNG header, etc.
	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);
	// Force RGB (8 or 16-bit).
	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 (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png_ptr);
	// Force 8-bit RGB.
	if (bit_depth == 16)
		png_set_strip_16(png_ptr);
	// Force alpha channel (combined with the above, 8-bit RGBA).
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_tRNS_to_alpha(png_ptr);
	else if ((color_type & PNG_COLOR_MASK_ALPHA) == 0)
		png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
	png_read_update_info(png_ptr, info_ptr);
	ImgInfo.Width = width;
	ImgInfo.Height = height;
	ImgInfo.data_size = width * height * 4;
	ImgInfo.dst = ImgInfo.request_buffer_delegate(ImgInfo.data_size, false);
	std::vector<u8*> row_pointers(height);
	u8* row_pointer = ImgInfo.dst;
	for (unsigned i = 0; i < height; ++i)
	{
		row_pointers[i] = row_pointer;
		row_pointer += width * 4;
	}
	png_read_image(png_ptr, row_pointers.data());
	png_read_end(png_ptr, end_info);
	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	return true;
}
Esempio n. 6
0
RawImage* ImageFactory::loadPNG(const char *filename)
{		
	int outWidth, outHeight;
	bool outHasAlpha;
    png_structp png_ptr;
    png_infop info_ptr;
    unsigned int sig_read = 0;
    int color_type, interlace_type;
    FILE* fp = fopen(filename, "rb");
		
    if (fp == NULL)
        return NULL;

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

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

    /* 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, NULL, NULL);
        return NULL;
    }

    /* 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, NULL);
        fclose(fp);
        /* If we get here, we had a
         * problem reading the file */
        return NULL;
    }

    /* Set up the output control if
     * you are using standard C streams */
    png_init_io(png_ptr, fp);

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

    /*
     * 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_TRANSFORM_STRIP_16 |
     * PNG_TRANSFORM_PACKING  forces 8 bit
     * PNG_TRANSFORM_EXPAND forces to
     *  expand a palette into RGB
     */
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL);
	png_uint_32 width, height;
	int bit_depth;
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);

    outWidth = width;
    outHeight = height;
    switch (color_type) {
        case PNG_COLOR_TYPE_RGBA:
            outHasAlpha = true;
            break;
        case PNG_COLOR_TYPE_RGB:
            outHasAlpha = false;
            break;
        default:
            printf("Color type %d not supported.", color_type);
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            fclose(fp);
            return NULL;
    }
    unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
    //*outData = (unsigned char*) malloc(row_bytes * outHeight);
	GLubyte *outData = (unsigned char*) malloc(row_bytes * outHeight);

    png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

    for (int i = 0; i < outHeight; i++) {
        // note that png is ordered top to
        // bottom, but OpenGL expect it bottom to top
        // so the order or swapped
        memcpy(outData+(row_bytes * (outHeight-1-i)), row_pointers[i], row_bytes);
    }

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

    /* Close the file */
    fclose(fp);

	
    /* That's it */
    return new RawImage(outWidth, outHeight, outHasAlpha, outData);
}
Esempio n. 7
0
BMGError ReadPNGInfo( const char *filename,
        struct BMGImageStruct * volatile img )
{
    jmp_buf             err_jmp;
    int                 error;

    FILE * volatile     file = NULL;
    int                 BitDepth;
    int                 ColorType;
    int                 InterlaceType;
    unsigned char       signature[8];
    png_structp volatile png_ptr = NULL;
    png_infop   volatile info_ptr = NULL;
    png_infop   volatile end_info = NULL;
    png_uint_32         Width, Height;

    /* error handler */
    error = setjmp( err_jmp );
    if (error != 0)
    {
        if (end_info != NULL)
            png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info);
        else if (info_ptr != NULL)
            png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, NULL);
        else if (png_ptr != NULL)
            png_destroy_read_struct((png_structp *) &png_ptr, NULL, NULL);
        if (img)
            FreeBMGImage(img);
        if (file)
            fclose(file);
        SetLastBMGError((BMGError) error);
        return (BMGError) error;
    }

    if ( img == NULL )
        longjmp ( err_jmp, (int)errInvalidBMGImage );

    file = fopen( filename, "rb" );
    if ( !file || fread( signature, 1, 8, file ) != 8)
        longjmp ( err_jmp, (int)errFileOpen );

    /* check the signature */
    if ( png_sig_cmp( signature, 0, 8 ) != 0 )
        longjmp( err_jmp, (int)errUnsupportedFileFormat );

    /* create a pointer to the png read structure */
    png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
    if ( !png_ptr )
        longjmp( err_jmp, (int)errMemoryAllocation );

    /* create a pointer to the png info structure */
    info_ptr = png_create_info_struct( png_ptr );
    if ( !info_ptr )
        longjmp( err_jmp, (int)errMemoryAllocation );

    /* create a pointer to the png end-info structure */
    end_info = png_create_info_struct(png_ptr);
    if (!end_info)
        longjmp( err_jmp, (int)errMemoryAllocation );

    /* bamboozle the PNG longjmp buffer */
    /*generic PNG error handler*/
    /* error will always == 1 which == errLib */
//    error = png_setjmp(png_ptr);
    error = setjmp( png_jmpbuf( png_ptr ) );
    if ( error > 0 )
        longjmp( err_jmp, error );

    /* set function pointers in the PNG library, for read callbacks */
    png_set_read_fn(png_ptr, (png_voidp) file, user_read_data);

    /*let the read functions know that we have already read the 1st 8 bytes */
    png_set_sig_bytes( png_ptr, 8 );

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

    /* extract the data we need to form the HBITMAP from the PNG header */
    png_get_IHDR( png_ptr, info_ptr, &Width, &Height, &BitDepth, &ColorType,
        &InterlaceType, NULL, NULL);

    img->width = (unsigned int) Width;
    img->height = (unsigned int) Height;

    img->bits_per_pixel = (unsigned char)32;
    img->scan_width = Width * 4;

    img->palette_size = (unsigned short)0;
    img->bytes_per_palette_entry = 4U;
    img->bits = NULL;

    png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info);
    fclose( file );

    return BMG_OK;
}
Esempio n. 8
0
File: fifoman.c Progetto: dezi/raspi
int read_png_file(uint8_t *data[ 4 ], int linesize[ 4 ],
                  int *width, int *height, enum AVPixelFormat *pix_fmt,
                  const char *filename, void *log_ctx)
{
	png_structp png_ptr;
	png_infop info_ptr;
	int number_of_passes;
	png_bytep *row_pointers;	
	png_bytep image_data;	
	png_byte color_type;
	png_byte bit_depth;
	char header[ 8 ];
	int rowbytes;
	int res = 0;
	
	FILE *fp = fopen(filename,"rb");
	if (! fp) return -1;
 	
	while (true)
	{
		fread(header,1,8,fp);
		
		if (png_sig_cmp(header,0,8)) 
		{ 
			res = -1; 
			break;
		}
		
		png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);

		if (! png_ptr)
		{
			res = -1; 
			break;
		}

		info_ptr = png_create_info_struct(png_ptr);
		
		if (! info_ptr)
		{
			res = -1; 
			break;
		}

		if (setjmp(png_jmpbuf(png_ptr)))
		{
			res = -1; 
			break;
		}

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

		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);
		*pix_fmt = AV_PIX_FMT_RGBA;
		
		color_type = png_get_color_type(png_ptr,info_ptr);
		bit_depth  = png_get_bit_depth (png_ptr,info_ptr);

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

		if (setjmp(png_jmpbuf(png_ptr)))
		{
			res = -1; 
			break;
		}

		rowbytes = png_get_rowbytes(png_ptr,info_ptr);
		image_data = (png_bytep) malloc(rowbytes * *height);
		row_pointers = (png_bytep *) malloc(sizeof(png_bytep) * *height);
		
		int y;
		
		for (y = 0; y < *height; y++)
		{
			row_pointers[ y ] = image_data + (y * rowbytes);
		}

		png_read_image(png_ptr,row_pointers);
	
		data[ 0 ] = image_data;
		data[ 1 ] = 0;
		data[ 2 ] = 0;
		data[ 3 ] = 0;
		
		linesize[ 0 ] = rowbytes;
		linesize[ 1 ] = 0;
		linesize[ 2 ] = 0;
		linesize[ 3 ] = 0;
		
		break;
	}
	
	fclose(fp);
	
	return res;
}
Esempio n. 9
0
image_t *load_png(char *png) {
	int width = 0;
	int height = 0;
	FILE *f = NULL;
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	png_infop end_info = NULL;
	png_uint_32 rowbytes = 0;
	image_t *image = NULL;

	f = open_png(png);
	if (f == NULL)
		goto err;

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

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

	end_info = png_create_info_struct(png_ptr);
	if (!end_info)
		goto err;

	if (setjmp(png_jmpbuf(png_ptr))) {
		printf("[read_png_file] Error during read_image");
		goto err;
	}

	png_init_io(png_ptr, f);
	png_set_sig_bytes(png_ptr, HEADER_SIZE);
	png_read_info(png_ptr, info_ptr);
	rowbytes = png_get_rowbytes(png_ptr, info_ptr);
	width = png_get_image_width(png_ptr, info_ptr);
	height = png_get_image_height(png_ptr, info_ptr);

	if (png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGBA) {
		printf("Error: PNG format is not RGBA\n");
		goto err;
	}

	if (setjmp(png_jmpbuf(png_ptr))) {
		printf("[read_png_file] Error during read_image");
		goto err;
	}

	image = make_image(width, height, rowbytes);
	if (image == NULL)
		goto err;
	png_read_image(png_ptr, image->rows);
	png_read_end(png_ptr, end_info);

	done: if (f != NULL)
		fclose(f);
	if (png_ptr != NULL)
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	return image;
	err: free_image(image);
	image = NULL;
	goto done;
}
Esempio n. 10
0
/* create a new finfo record, open FITS file */
static Finfo FinfoNew(char *fname)
{
  int len;
  char *e=NULL;
  char *f=NULL;
  char *s=NULL;
#if FITS2PNG
  int i;
  unsigned char header[8];
  /* use volatile to make gcc [-Wclobbered] happy (because of setjmp below) */
  volatile Finfo finfo;	  
#else
  Finfo finfo;	  
#endif


  /* sanity check */
  if( !fname ) return NULL;
  /* return existing finfo, if possible */
  if( (finfo=FinfoLookup(fname)) ) return finfo;
  /* allocate record */
  if( !(finfo = (Finfo)xcalloc(sizeof(FinfoRec), 1)) ){
    fprintf(stderr, "ERROR: can't allocate rec for image\n");
    return NULL;
  }
  /* save file name */
  finfo->fname = xstrdup(fname);
  /* check for file type */
  if( (s = strrchr(fname, '.')) && !strcasecmp(s, ".png") ){
    /* its a PNG */
    finfo->ftype = FTYPE_PNG;
  } else {
    /* assume FITS type */
    finfo->ftype = FTYPE_FITS;
  }
  /* open file */
  switch(finfo->ftype){
  case FTYPE_PNG:
#if FITS2PNG
    /* code taken from "PNG: The Definitive Guide" by Greg Roelofs,
       Chapter 13 "Reading PNG Images" */
    /* set data path */
    datapath = getenv("JS9_DATAPATH");
    /* look for path of the PNG file */
    s = Find(fname, "r", NULL, datapath);
    if( s && *s ){
      if( !(finfo->fp = fopen(s, "rb")) ){
	fprintf(stderr, "ERROR: can't open PNG file '%s'\n", fname);
	goto error;
      }
      fread(header, 1, 8, finfo->fp);
      if( png_sig_cmp(header, 0, 8) ){
	fprintf(stderr, "ERROR: not recognized as a PNG file '%s'\n", fname);
	goto error;
      }
      /* initialize stuff */
      finfo->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
					      NULL, NULL, NULL);
      if( !finfo->png_ptr ){
	fprintf(stderr, "ERROR: png_create_read_struct failed '%s'\n", fname);
	goto error;
      }
      finfo->info_ptr = png_create_info_struct(finfo->png_ptr);
      if( !finfo->info_ptr ){
	fprintf(stderr, "ERROR: png_create_info_struct failed '%s'\n", fname);
	goto error;
      }
      if( setjmp(png_jmpbuf(finfo->png_ptr)) ){
	fprintf(stderr, "ERROR: during png init_io '%s'\n", fname);
	goto error;
      }
      png_init_io(finfo->png_ptr, finfo->fp);
      png_set_sig_bytes(finfo->png_ptr, 8);
      png_read_info(finfo->png_ptr, finfo->info_ptr);
      /* get the text chunks that come before the image */
      if( png_get_text(finfo->png_ptr, finfo->info_ptr,
		       &(finfo->text_ptr), &(finfo->num_text)) > 0 ){
	/* process all known PNG keywords */
	for(i=0; i<finfo->num_text; i++){
	  if( !strcmp(finfo->text_ptr[i].key, FITSFILE) ){
	    finfo->fitsfile = xstrdup(finfo->text_ptr[i].text);
	    /* remove the extension that was used to generate png */
	    s = strchr(finfo->fitsfile, '[');
	    if( s ){
	      *s = '\0';
	    }
	  }
	}
      }
    } else {
      fprintf(stderr, "ERROR: can't find PNG file '%s' [data path: %s]\n",
	      fname, datapath?datapath:"none");
      goto error;
    }
#else
    fprintf(stderr,
	    "ERROR: for fits2png support, build JS9 using --with-png\n");
    goto error;
#endif
    break;
    /* look for an error */
  case FTYPE_FITS:
    /* fits file can have an extension */
    f = FileRoot(fname);
    /* set data path */
    datapath = getenv("JS9_DATAPATH");
    /* look for path of the FITS file */
    s = Find(f, "r", NULL, datapath);
    xfree(f);
    if( s && *s ){
      len = strlen(s) + 1;
      /* construct full path to fits file + extension */
      e = FileExtension(fname);
      if( e ){
        len += strlen(e);
      }
      finfo->fitsfile = xmalloc(len);
      strcpy(finfo->fitsfile, s);
      if( e ){
        strcat(finfo->fitsfile, e);
      }
      xfree(s);
    } else {
      fprintf(stderr, "ERROR: can't find FITS file '%s' [data path: %s]\n",
	      fname, datapath?datapath:"none");
      goto error;
    }
    break;
  default:
    fprintf(stderr, "ERROR: unknown file type '%s'\n", fname);
    goto error;
    break;
  }
  /* add this finfo to end of list of existing finfos */
  FinfoListAdd(&finfohead, finfo);
  /* return the news */
  return finfo;
error:
  /* free up struct and return nothing */
  _FinfoFree(finfo);
  return NULL;
}
Esempio n. 11
0
bool CGLCG::loadPngImage(const TCHAR *name, int &outWidth, int &outHeight, bool &outHasAlpha, GLubyte **outData) {
    png_structp png_ptr;
    png_infop info_ptr;
    unsigned int sig_read = 0;
    int color_type, interlace_type;
    FILE *fp;

	if ((fp = _tfopen(name, TEXT("rb"))) == NULL)
        return false;

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

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

    /* 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 false;
    }

    /* 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 false;
    }

    /* Set up the output control if
     * you are using standard C streams */
    png_init_io(png_ptr, fp);

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

    /*
     * 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_TRANSFORM_STRIP_16 |
     * PNG_TRANSFORM_PACKING  forces 8 bit
     * PNG_TRANSFORM_EXPAND forces to
     *  expand a palette into RGB
     */
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, (png_voidp)NULL);

    outWidth = png_get_image_width(png_ptr, info_ptr);
    outHeight = png_get_image_height(png_ptr, info_ptr);
    switch (png_get_color_type(png_ptr, info_ptr)) {
        case PNG_COLOR_TYPE_RGBA:
            outHasAlpha = true;
            break;
        case PNG_COLOR_TYPE_RGB:
            outHasAlpha = false;
            break;
        default:
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
            fclose(fp);
            return false;
    }
    unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
    *outData = (unsigned char*) malloc(row_bytes * outHeight);

    png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

    for (int i = 0; i < outHeight; i++) {
        memcpy(*outData+(row_bytes * i), row_pointers[i], row_bytes);
    }

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

    /* Close the file */
    fclose(fp);

    /* That's it */
    return true;
}
Esempio n. 12
0
void Texture::InitWithFile(string& filepath) {
    FILE* fd = FileIO::OpenFileDescriptor(filepath);
    png_byte header[8];
    fread(header, 1, 8, fd);
    
    int is_png = !png_sig_cmp(header, 0, 8);
    if (!is_png) {
        printf("ERROR: %s is not a valid png file\n", filepath.c_str());
        fclose(fd);
        return;
    }
    
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
        fclose(fd);
        return;
    }
    
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
        fclose(fd);
        return;
    }
    
    png_infop end_info = png_create_info_struct(png_ptr);
    if (!end_info) {
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
        fclose(fd);
        return;
    }
    
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        fclose(fd);
        return;
    }
    png_init_io(png_ptr, fd);
    
    png_set_sig_bytes(png_ptr, 8);
    
    png_read_info(png_ptr, info_ptr);
    
    GLint bit_depth, color_type;
    
    png_get_IHDR(png_ptr, info_ptr, &m_width, &m_height, &bit_depth, &color_type, NULL, NULL, NULL);
    
    png_read_update_info(png_ptr, info_ptr);
    
    int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    
    png_byte *image_data = new png_byte[rowbytes * m_height];
    if (!image_data) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        fclose(fd);
        return;
    }
    
    png_bytep *row_pointers = new png_bytep[m_height];
    if (!row_pointers) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        delete[] image_data;
        fclose(fd);
        return;
    }
    
    for (GLuint i = 0; i < m_height; ++i) {
        row_pointers[i] = image_data + i * rowbytes;
    }
    
    png_read_image(png_ptr, row_pointers);
    
    glGenTextures(1, &m_glTextureID);
    m_dataType = GL_UNSIGNED_BYTE;
    m_pixelFormat = GL_RGBA;
    m_targetType = GL_TEXTURE_2D;
    
    glBindTexture(m_targetType, m_glTextureID);
    glTexImage2D(m_targetType,0, m_pixelFormat, m_width, m_height, 0, m_pixelFormat, m_dataType, (GLvoid*) image_data);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    delete[] image_data;
    delete[] row_pointers;
    fclose(fd);

}
Esempio n. 13
0
GLuint TextureManager::addFromPNG(const std::string& id, const std::string& texturePath)
{
	FILE *fp = fopen(texturePath.c_str(), "rb");
	if(!fp)
		return GL_INVALID_VALUE;
	png_byte header[8];
	fread(header, 1, 8, fp);
	if(png_sig_cmp(header, 0, 8))
	{
		fclose(fp);
		return GL_INVALID_VALUE;
	}

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

	png_infop info_ptr = png_create_info_struct(png_ptr);
	png_infop end_info = png_create_info_struct(png_ptr);
	if(!info_ptr || !end_info || setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(fp);
		return GL_INVALID_VALUE;
	}
	png_init_io(png_ptr, fp);
	png_set_sig_bytes(png_ptr, 8);
	png_read_info(png_ptr, info_ptr);
	int bit_depth, color_type;
	png_uint_32 twidth, theight;

	png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type, NULL, NULL, NULL);

	int width = twidth;
	int height = theight;

	png_read_update_info(png_ptr, info_ptr);

	int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
	png_byte *image_data = new png_byte[rowbytes * height];
	png_bytepp row_pointers = new png_bytep[height];

	if(!image_data || !row_pointers) {
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		delete[] image_data;
		fclose(fp);
		return GL_INVALID_VALUE;
	}

	for(int i = 0; i < height; ++i)
		row_pointers[height - 1 - i] = image_data + i * rowbytes;

	png_read_image(png_ptr, row_pointers);

	bool hasAlpha;
/*	switch (info_ptr->color_type) {
		case PNG_COLOR_TYPE_RGBA:
			hasAlpha = true;
			break;
		case PNG_COLOR_TYPE_RGB:
			hasAlpha = false;
			break;
		default:
			png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
			fclose(fp);
			return GL_INVALID_VALUE;
	}*/

	glGenTextures(1, &textures[id]);
	glBindTexture(GL_TEXTURE_2D, textures[id]);
	glTexImage2D(GL_TEXTURE_2D, 0, hasAlpha ? GL_RGBA : GL_RGB, width, height, 0, hasAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) image_data);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	delete[] image_data;
	delete[] row_pointers;
	fclose(fp);

	return true;
}
Esempio n. 14
0
short load_inp_png_file(ImageData& img, const std::string& fname_inp, ProgramOptions& opts)
{
    FILE* pngfile = fopen(fname_inp.c_str(),"rb");
    if (pngfile == NULL) {
        perror(fname_inp.c_str());
        return ERR_CANT_OPEN;
    }
    png_byte header[8];
    if (fread(header,8,1,pngfile) != 1) {
        perror(fname_inp.c_str());
        fclose(pngfile);
        return ERR_FILE_READ;
    }
    if (png_sig_cmp(header,0,8)) {
        LogErr("%s: Not a PNG file",fname_inp.c_str());
        fclose(pngfile);
        return ERR_BAD_FILE;
    }

    img.png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!img.png_ptr)
    {
        LogErr("%s: png_create_read_struct error",fname_inp.c_str());
        fclose(pngfile);
        return ERR_BAD_FILE;
    }

    img.info_ptr=png_create_info_struct(img.png_ptr);
    if (!img.info_ptr)
    {
        png_destroy_read_struct(&img.png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        LogErr("%s: png_create_info_struct error",fname_inp.c_str());
        fclose(pngfile);
        return ERR_BAD_FILE;
    }

    img.end_info=png_create_info_struct(img.png_ptr);
    if (!img.end_info)
    {
        png_destroy_read_struct(&img.png_ptr, &img.info_ptr, (png_infopp)NULL);
        LogErr("%s: png_create_info_struct error",fname_inp.c_str());
        fclose(pngfile);
        return ERR_BAD_FILE;
    }

    if (setjmp(png_jmpbuf(img.png_ptr)))
    {
        png_destroy_read_struct(&img.png_ptr, &img.info_ptr, &img.end_info);
        LogErr("%s: PNG error",fname_inp.c_str());
        fclose(pngfile);
        exit(1);
    }

    png_init_io(img.png_ptr, pngfile);
    png_set_sig_bytes(img.png_ptr,8);
    int trafo=PNG_TRANSFORM_PACKING|PNG_TRANSFORM_STRIP_16|PNG_TRANSFORM_EXPAND;
    png_read_png(img.png_ptr, img.info_ptr, trafo , NULL);

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

    if ((img.color_type & PNG_COLOR_MASK_COLOR)==0)
    {
        LogErr("%s: Grayscale image not supported",fname_inp.c_str());
        fclose(pngfile);
        return ERR_BAD_FILE;
    }

    fclose(pngfile);

    if (img.color_type==PNG_COLOR_TYPE_PALETTE)
    {
        LogErr("Invalid format. This shouldn't happen. PNG_TRANSFORM_EXPAND transforms image to RGB.");
        return ERR_BAD_FILE;
    }

    if (img.color_type & PNG_COLOR_MASK_ALPHA) {
        img.col_bits = 32;
    } else {
        img.col_bits = 24;
    }

    return ERR_OK;
}
Esempio n. 15
0
void *png_read_file(const char *name, png_uint_32 *_w, png_uint_32 *_h,
 check_w_h_constraint_t constraint, rgba_surface_allocator_t allocator)
{
  png_uint_32 i, w, h, stride;
  png_structp png_ptr = NULL;
  png_bytep *row_ptrs = NULL;
  png_infop info_ptr = NULL;
  void *pixels, *s = NULL;
  png_byte header[8];
  int type, bpp;
  FILE *f;

  f = fopen_unsafe(name, "rb");
  if(!f)
    goto exit_out;

  if(fread(header, 1, 8, f) < 8)
    goto exit_close;

  if(png_sig_cmp(header, 0, 8))
    goto exit_close;

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

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

  if(setjmp(png_ptr->jmpbuf))
    goto exit_free_close;

  png_init_io(png_ptr, f);
  png_set_sig_bytes(png_ptr, 8);
  png_read_info(png_ptr, info_ptr);
  png_get_IHDR(png_ptr, info_ptr, &w, &h, &bpp, &type, NULL, NULL, NULL);

  if(!constraint(w, h))
  {
    warn("Requested image '%s' failed dimension checks.\n", name);
    goto exit_free_close;
  }

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

  else if(type == PNG_COLOR_TYPE_GRAY_ALPHA || !(type & PNG_COLOR_MASK_COLOR))
    png_set_gray_to_rgb(png_ptr);

  else if(!(type & PNG_COLOR_MASK_COLOR) && bpp < 8)
    png_set_expand_gray_1_2_4_to_8(png_ptr);

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

  else if(bpp < 8)
    png_set_packing(png_ptr);

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

  else if(!(type & PNG_COLOR_MASK_ALPHA))
    png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);

  // FIXME: Are these necessary?
  png_read_update_info(png_ptr, info_ptr);
  png_get_IHDR(png_ptr, info_ptr, &w, &h, &bpp, &type, NULL, NULL, NULL);

  row_ptrs = cmalloc(sizeof(png_bytep) * h);
  if(!row_ptrs)
    goto exit_free_close;

  s = allocator(w, h, &stride, &pixels);
  if(!s)
    goto exit_free_close;

  for(i = 0; i < h; i++)
    row_ptrs[i] = (png_bytep)(unsigned char *)pixels + i * stride;

  png_read_image(png_ptr, row_ptrs);

  if(_w)
    *_w = w;
  if(_h)
    *_h = h;

exit_free_close:
  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  free(row_ptrs);
exit_close:
  fclose(f);
exit_out:
  return s;
}
Esempio n. 16
0
bool LoadPng(const char *name, int &iWidth, int &iHeight, bool &hasAlpha, GLubyte **outData)
{
  FILE *fp = NULL;
  fp = fopen(name, "rb");
  if (fp == NULL)
  {
    return false;
  }

  png_structp png_ptr;
  png_infop info_ptr;
  unsigned int sig_read = 0;
  int color_type, interlace_type;
  
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

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

  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 false;
  }

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

  png_init_io(png_ptr, fp);

  png_set_sig_bytes(png_ptr, sig_read);

  png_read_png(png_ptr, info_ptr, /*PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING |*/ PNG_TRANSFORM_EXPAND, png_voidp_NULL);

  iWidth = info_ptr->width;
  iHeight = info_ptr->height;
  switch (info_ptr->color_type)
  {
  case PNG_COLOR_TYPE_RGBA:
    hasAlpha = true;
  	break;
  case PNG_COLOR_TYPE_RGB:
    hasAlpha = false;
    break;
  default:
    printf("color type %d is not supported \n ", info_ptr->color_type);
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    fclose(fp);
    return false;
  }

  unsigned int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
  
  *outData = (unsigned char*)malloc(row_bytes * iHeight);

  png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

  for (int i = 0; i < iHeight; ++i)
  {
    memcpy(*outData + (row_bytes * (iHeight - 1- i)), row_pointers[i], row_bytes);
  }

  png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);

  fclose(fp);
  return true;
}
Esempio n. 17
0
SEXP read_png(SEXP sFn, SEXP sNative, SEXP sInfo) {
    SEXP res = R_NilValue, info_list = R_NilValue, info_tail = R_NilValue;
    const char *fn;
    char header[8];
    int native = asInteger(sNative), info = (asInteger(sInfo) == 1);
    FILE *f;
    read_job_t rj;
    png_structp png_ptr;
    png_infop info_ptr;
    
    if (TYPEOF(sFn) == RAWSXP) {
	rj.data = (char*) RAW(sFn);
	rj.len = LENGTH(sFn);
	rj.ptr = 0;
	rj.f = f = 0;
    } else {
	if (TYPEOF(sFn) != STRSXP || LENGTH(sFn) < 1) Rf_error("invalid filename");
	fn = CHAR(STRING_ELT(sFn, 0));
	f = fopen(fn, "rb");
	if (!f) Rf_error("unable to open %s", fn);
	if (fread(header, 1, 8, f) < 1 || png_sig_cmp((png_bytep) header, 0, 8)) {
	    fclose(f);
	    Rf_error("file is not in PNG format");
	}
	rj.f = f;
    }

    /* use our own error hanlding code and pass the fp so it can be closed on error */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)&rj, user_error_fn, user_warning_fn);
    if (!png_ptr) {
	if (f) fclose(f);
	Rf_error("unable to initialize libpng");
    }
    
    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
	if (f) fclose(f);
	png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
	Rf_error("unable to initialize libpng");
    }
    
    if (f) {
	png_init_io(png_ptr, f);
	png_set_sig_bytes(png_ptr, 8);
    } else
	png_set_read_fn(png_ptr, (png_voidp) &rj, user_read_data);

#define add_info(K, V) { info_tail = SETCDR(info_tail, CONS(V, R_NilValue)); SET_TAG(info_tail, install(K)); }

    /* png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_EXPAND, NULL); */
    png_read_info(png_ptr, info_ptr);
    {
	png_uint_32 width, height;
	png_bytepp row_pointers;
	char *img_memory;
	SEXP dim;
	int bit_depth, color_type, interlace_type, compression_type, filter_method, rowbytes;
	int need_swap = 0;
	png_get_IHDR(png_ptr, info_ptr, &width, &height,
		     &bit_depth, &color_type, &interlace_type,
		     &compression_type, &filter_method);
	rowbytes = png_get_rowbytes(png_ptr, info_ptr);
#if VERBOSE_INFO
	Rprintf("png: %d x %d [%d], %d bytes, 0x%x, %d, %d\n", (int) width, (int) height, bit_depth, rowbytes,
		color_type, interlace_type, compression_type, filter_method);
#endif

	if (info) {
	    SEXP dv;
	    double d;
	    png_uint_32 rx, ry;
	    int ut, num_text = 0;
	    png_textp text_ptr;

	    info_tail = info_list = PROTECT(CONS((dv = allocVector(INTSXP, 2)), R_NilValue));
	    INTEGER(dv)[0] = (int) width;
	    INTEGER(dv)[1] = (int) height;
	    SET_TAG(info_list, install("dim"));
	    add_info("bit.depth", ScalarInteger(bit_depth));
	    switch(color_type) {
	    case PNG_COLOR_TYPE_GRAY: add_info("color.type", mkString("gray")); break;
	    case PNG_COLOR_TYPE_GRAY_ALPHA: add_info("color.type", mkString("gray + alpha")); break;
	    case PNG_COLOR_TYPE_PALETTE: add_info("color.type", mkString("palette")); break;
	    case PNG_COLOR_TYPE_RGB: add_info("color.type", mkString("RGB")); break;
	    case PNG_COLOR_TYPE_RGB_ALPHA: add_info("color.type", mkString("RGBA")); break;
	    default: add_info("color.type", ScalarInteger(color_type));
	    }
	    if (png_get_gAMA(png_ptr, info_ptr, &d)) add_info("gamma", ScalarReal(d));
#ifdef PNG_pHYs_SUPPORTED
	    if (png_get_pHYs(png_ptr, info_ptr, &rx, &ry, &ut)) {
		if (ut == PNG_RESOLUTION_METER) {
		    dv = allocVector(REALSXP, 2);
		    REAL(dv)[0] = ((double)rx) / 39.37008;
		    REAL(dv)[1] = ((double)ry) / 39.37008;
		    add_info("dpi", dv);
		} else if (ut == PNG_RESOLUTION_UNKNOWN)
		    add_info("asp", ScalarReal(rx / ry));
	    }
	    if (png_get_text(png_ptr, info_ptr, &text_ptr, &num_text)) {
		SEXP txt_key, txt_val = PROTECT(allocVector(STRSXP, num_text));
		if (num_text) {
		    int i;
		    setAttrib(txt_val, R_NamesSymbol, txt_key = allocVector(STRSXP, num_text));
		    for (i = 0; i < num_text; i++) {
			SET_STRING_ELT(txt_val, i, text_ptr[i].text ? mkChar(text_ptr[i].text) : NA_STRING);
			SET_STRING_ELT(txt_key, i, text_ptr[i].key ? mkChar(text_ptr[i].key) : NA_STRING);
		    }
		}
		add_info("text", txt_val);
		UNPROTECT(1);
	    }
#endif
	}

	/* on little-endian machines it's all well, but on big-endian ones we'll have to swap */
#if ! defined (__BIG_ENDIAN__) && ! defined (__LITTLE_ENDIAN__)   /* old compiler so have to use run-time check */
	{
	    char bo[4] = { 1, 0, 0, 0 };
	    int bi;
	    memcpy(&bi, bo, 4);
	    if (bi != 1)
		need_swap = 1;
	}
#endif
#ifdef __BIG_ENDIAN__
	need_swap = 1;
#endif

	/*==== set any transforms that we desire: ====*/
	/* palette->RGB - no discussion there */
	if (color_type == PNG_COLOR_TYPE_PALETTE)
	    png_set_palette_to_rgb(png_ptr);
	/* expand gray scale to 8 bits */
	if (color_type == PNG_COLOR_TYPE_GRAY &&
	    bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr);
	/* this should not be necessary but it's in the docs to guarantee 8-bit */
	if (bit_depth < 8)
	    png_set_packing(png_ptr);
	/* convert tRNS chunk into alpha */
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
	    png_set_tRNS_to_alpha(png_ptr);
	/* native format doesn't allow for 16-bit so it needs to be truncated */
	if (bit_depth == 16 && native) {
	    Rf_warning("Image uses 16-bit channels but R native format only supports 8-bit, truncating LSB."); 
	    png_set_strip_16(png_ptr);
	}
	/* for native output we need to a) convert gray to RGB, b) add alpha */
	if (native) {
	    if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png_ptr);
	    if (!(color_type & PNG_COLOR_MASK_ALPHA)) /* if there is no alpha, add it */
		png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER);
	}
#if 0 /* we use native (network) endianness since we read each byte anyway */
	/* on little-endian machines we need to swap 16-bit values - this is the inverse of need_swap as used for R! */
	if (!need_swap && bit_depth == 16)
	    png_set_swap(png_ptr);
#endif

	/* PNG wants up to call png_set_interlace_handling so it can get ready to de-interlace images */
	png_set_interlace_handling(png_ptr);

	/* all transformations are in place, so it's time to update the info structure so we can allocate stuff */
	png_read_update_info(png_ptr, info_ptr);

	/* re-read some important bits from the updated structure */
	rowbytes = png_get_rowbytes(png_ptr, info_ptr);
	bit_depth = png_get_bit_depth(png_ptr, info_ptr);
	color_type = png_get_color_type(png_ptr, info_ptr);

#if VERBOSE_INFO
	Rprintf("   -filter-> %d-bits, %d bytes, 0x%x\n", bit_depth, rowbytes, color_type);
#endif

	/* allocate data fro row pointers and the image using R's allocation */
	row_pointers = (png_bytepp) R_alloc(height, sizeof(png_bytep));
	img_memory = R_alloc(height, rowbytes);
	{ /* populate the row pointers */
	    char *i_ptr = img_memory;
	    int i;
	    for (i = 0; i < height; i++, i_ptr += rowbytes)
	      row_pointers[i] = (png_bytep) i_ptr;
	}
	
	/* do the reading work */
	png_read_image(png_ptr, row_pointers);
	
	if (f) {
	    rj.f = 0;
	    fclose(f);
	}

	/* native output - vector of integers */
	if (native) {
	    int pln = rowbytes / width;
	    if (pln < 1 || pln > 4) {
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		Rf_error("native output for %d planes is not possible.", pln);
	    }

	    res = PROTECT(allocVector(INTSXP, width * height));
	    if (pln == 4) { /* 4 planes - efficient - just copy it all */
		int y, *idata = INTEGER(res);
		for (y = 0; y < height; idata += width, y++)
		    memcpy(idata, row_pointers[y], width * sizeof(int));

		if (need_swap) {
		    int *ide = idata;
		    idata = INTEGER(res);
		    for (; idata < ide; idata++)
			RX_swap32(*idata);
		}
	    } else if (pln == 3) { /* RGB */
		int x, y, *idata = INTEGER(res);
		for (y = 0; y < height; y++)
		    for (x = 0; x < rowbytes; x += 3)
			*(idata++) = R_RGB((unsigned int) row_pointers[y][x],
					   (unsigned int) row_pointers[y][x + 1],
					   (unsigned int) row_pointers[y][x + 2]);
	    } else if (pln == 2) { /* GA */
		int x, y, *idata = INTEGER(res);
		for (y = 0; y < height; y++)
		    for (x = 0; x < rowbytes; x += 2)
			*(idata++) = R_RGBA((unsigned int) row_pointers[y][x],
					    (unsigned int) row_pointers[y][x],
					    (unsigned int) row_pointers[y][x],
					    (unsigned int) row_pointers[y][x + 1]);
	    } else { /* gray */
		int x, y, *idata = INTEGER(res);
		for (y = 0; y < height; y++)
		    for (x = 0; x < rowbytes; x++)
			*(idata++) = R_RGB((unsigned int) row_pointers[y][x],
					   (unsigned int) row_pointers[y][x],
					   (unsigned int) row_pointers[y][x]);
	    }
	    dim = allocVector(INTSXP, 2);
	    INTEGER(dim)[0] = height;
	    INTEGER(dim)[1] = width;
	    setAttrib(res, R_DimSymbol, dim);
	    setAttrib(res, R_ClassSymbol, mkString("nativeRaster"));
	    setAttrib(res, install("channels"), ScalarInteger(pln));
	    UNPROTECT(1);
	} else {
	    int x, y, p, pln = rowbytes / width, pls = width * height;
	    double * data;
	    if (bit_depth == 16) {
		res = PROTECT(allocVector(REALSXP, (rowbytes * height) / 2));
		pln /= 2;
	    } else
		res = PROTECT(allocVector(REALSXP, rowbytes * height));

	    data = REAL(res);
	    if (bit_depth == 16)
		for(y = 0; y < height; y++)
		    for (x = 0; x < width; x++)
			for (p = 0; p < pln; p++)
			    data[y + x * height + p * pls] = ((double)(
								       (((unsigned int)(((unsigned char *)row_pointers[y])[2 * (x * pln + p)])) << 8) |
								        ((unsigned int)(((unsigned char *)row_pointers[y])[2 * (x * pln + p) + 1]))
								       )) / 65535.0;
	    else 
		for(y = 0; y < height; y++)
		    for (x = 0; x < width; x++)
			for (p = 0; p < pln; p++)
			    data[y + x * height + p * pls] = ((double)row_pointers[y][x * pln + p]) / 255.0;
	    dim = allocVector(INTSXP, (pln > 1) ? 3 : 2);
	    INTEGER(dim)[0] = height;
	    INTEGER(dim)[1] = width;
	    if (pln > 1)
		INTEGER(dim)[2] = pln;
	    setAttrib(res, R_DimSymbol, dim);
	    UNPROTECT(1);
	}
    }

    if (info) {
	PROTECT(res);
	setAttrib(res, install("info"), info_list);
	UNPROTECT(2);
    }
    
    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);

    return res;
}
Esempio n. 18
0
uint8_t *PNG_unpack(SYS_FILEHANDLE infile, uint32_t *LX, uint32_t *LY, int *dwBitsPerPixel, rgb24_t *pClut, int options)
{
    uint8_t *out_buffer;
	uint32_t i;
	unsigned char sig[8];
	png_structp png_ptr;
	png_infop info_ptr;

	FIO_cur->fread(sig, 1, 8, infile);
	if (!png_check_sig(sig, 8))
	{
		return NULL;	/* bad signature */
	}
	png_ptr = png_create_read_struct_2(

	PNG_LIBPNG_VER_STRING,
	(png_voidp)NULL,
	(png_error_ptr)pngx_error,
	(png_error_ptr)pngx_warning,
	(png_voidp)NULL,
	(png_malloc_ptr)pngx_malloc,
	(png_free_ptr)pngx_free);

	png_init_io(png_ptr, (FILE*)infile);
	png_set_sig_bytes(png_ptr, 8);	/* we already read the 8 signature bytes */
	png_set_read_fn(png_ptr, (FILE*)infile, pngx_readm_pData);

if (!pClut)
		pClut = (rgb24_t*)MM_heap.malloc(3*256);

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

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

	out_buffer = 0;

	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE))
	{
		png_colorp palette;
		int num_palette;
		png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
		if (palette)
			sysMemCpy(pClut, palette, num_palette * 3);
	}
	else
	{
		for (i=0;i<256;i++)
			pClut[i].r = pClut[i].g = pClut[i].b = (uint8_t)i;
	}

	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA))
	{
		double gamma;
		png_get_gAMA(png_ptr, info_ptr, &gamma);
	}

	if (options & 1)
	{
		png_uint_32 width, height;
		int bit_depth, rowbytes;
		int color_type;
		uint8_t **row_pointers = NULL;

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

		if (bit_depth<8)
			png_set_packing(png_ptr);

		if ((color_type == PNG_COLOR_TYPE_RGB_ALPHA && bit_depth>8))
			png_set_bgr(png_ptr);

		png_read_update_info(png_ptr, info_ptr);
		rowbytes = png_get_rowbytes(png_ptr, info_ptr);

		out_buffer	 = (uint8_t*) MM_heap.malloc(height * rowbytes);
		row_pointers = (uint8_t**) MM_std.malloc(sizeof(char*)*height);
		SYS_ASSERT(row_pointers!=0);
		for (i=0;i<height;i++)
			row_pointers[i] = out_buffer + i * rowbytes;
		png_read_image(png_ptr, row_pointers);
		MM_std.free(row_pointers);
		png_read_end(png_ptr, NULL);

		*LX  = width;
		*LY  = height;
		*dwBitsPerPixel = (rowbytes<<3) / width;
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	}
	return out_buffer;
}
Esempio n. 19
0
// Read the PNG file using the libpng.  The low-level interface is used here
// because we want to do various transformations (including applying gama)
// which can't be done with the high-level interface.
// The scanline also begins at the bottom of
// the image (per SecondLife conventions) instead of at the top, so we
// must assign row-pointers in "reverse" order.
BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInfo *infop)
{
	try
	{
		// Create and initialize the png structures
		mReadPngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
			this, &errorHandler, NULL);
		if (mReadPngPtr == NULL)
		{
			throw "Problem creating png read structure";
		}

		// Allocate/initialize the memory for image information.
		mReadInfoPtr = png_create_info_struct(mReadPngPtr);

		// Set up the input control
		PngDataInfo dataPtr;
		dataPtr.mData = src;
		dataPtr.mOffset = 0;
		dataPtr.mDataSize = dataSize;

		png_set_read_fn(mReadPngPtr, &dataPtr, &readDataCallback);
		png_set_sig_bytes(mReadPngPtr, 0);

		// setup low-level read and get header information
		png_read_info(mReadPngPtr, mReadInfoPtr);
		png_get_IHDR(mReadPngPtr, mReadInfoPtr, &mWidth, &mHeight,
			&mBitDepth, &mColorType, &mInterlaceType,
			&mCompressionType, &mFilterMethod);

		// Normalize the image, then get updated image information
		// after transformations have been applied
		normalizeImage();
		updateMetaData();

		// If a raw object is supplied, read the PNG image into its
		// data space
		if (rawImage != NULL)
		{
			rawImage->resize(static_cast<U16>(mWidth),
				static_cast<U16>(mHeight), mChannels);
			U8 *dest = rawImage->getData();
			int offset = mWidth * mChannels;

			// Set up the row pointers and read the image
			mRowPointers = new U8* [mHeight];
			for (U32 i=0; i < mHeight; i++)
			{
				mRowPointers[i] = &dest[(mHeight-i-1)*offset];
			}

			png_read_image(mReadPngPtr, mRowPointers);

			// Finish up, ensures all metadata are updated
			png_read_end(mReadPngPtr, NULL);
		}

		// If an info object is supplied, copy the relevant info
		if (infop != NULL)
		{
			infop->mHeight = static_cast<U16>(mHeight);
			infop->mWidth = static_cast<U16>(mWidth);
			infop->mComponents = mChannels;
		}

		mFinalSize = dataPtr.mOffset;
	}
	catch (png_const_charp msg)
	{
		mErrorMessage = msg;
		releaseResources();
		return (FALSE);
	}

	// Clean up and return
	releaseResources();
	return (TRUE);
}
Esempio n. 20
0
bool
texture_png_read(Texture* tex)
{
  FILE *f;
  png_byte magic[8];

  f = fopen(tex->filename, "rb");
  if (!f) {
    fprintf (stderr, "error: couldn't open \"%s\"!\n", tex->filename);
    return false;
  }

  /* read magic number */
  fread(magic, 1, sizeof(magic), f);

  /* check for valid magic number */
  if (!png_check_sig(magic, sizeof(magic))) {
    fprintf(stderr, "error: \"%s\" is not a valid PNG image!\n",
          tex->filename);
    fclose(f);
    return false;
  }

  /* create a png read struct */
  png_structp png_ptr = png_create_read_struct(
        PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png_ptr) {
    fclose(f);
    return false;
  }

  /* create a png info struct */
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    fclose(f);
    png_destroy_read_struct(&png_ptr, NULL, NULL);
    return false;
  }

  /* initialize the setjmp for returning properly after a libpng
     error occured */
  if (setjmp(png_jmpbuf(png_ptr))) {
    fclose(f);
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    if (tex) {
      if (tex->data)
      free(tex->data);

      free(tex);
    }

    return false;
  }

  /* setup libpng for using standard C fread() function
     with our FILE pointer */
  png_init_io(png_ptr, f);

  /* tell libpng that we have already read the magic number */
  png_set_sig_bytes(png_ptr, sizeof(magic));

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

  /* get some usefull information from header */
  int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  int color_type = png_get_color_type(png_ptr, info_ptr);

  /* convert index color images to RGB images */
  if (color_type == PNG_COLOR_TYPE_PALETTE)
  png_set_palette_to_rgb(png_ptr);

  /* convert 1-2-4 bits grayscale images to 8 bits
     grayscale. */
  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
  png_set_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);
  else if (bit_depth < 8)
  png_set_packing(png_ptr);

  /* update info structure to apply transformations */
  png_read_update_info(png_ptr, info_ptr);

  /* retrieve updated information */
  png_get_IHDR(png_ptr, info_ptr,
        (png_uint_32*)(&tex->width),
        (png_uint_32*)(&tex->height),
        &bit_depth, &color_type,
        NULL, NULL, NULL);

  switch (color_type) {
    case PNG_COLOR_TYPE_GRAY:
      tex->format = GL_LUMINANCE;
      tex->internal_format = 1;
      break;

    case PNG_COLOR_TYPE_GRAY_ALPHA:
      tex->format = GL_LUMINANCE_ALPHA;
      tex->internal_format = 2;
      break;

    case PNG_COLOR_TYPE_RGB:
      tex->format = GL_RGB;
      tex->internal_format = 3;
      break;

    case PNG_COLOR_TYPE_RGB_ALPHA:
      tex->format = GL_RGBA;
      tex->internal_format = 4;
      break;

    default:
      printf("color type not found\n");
      break;
  }


  /* we can now allocate memory for storing pixel data */
  tex->data = (GLubyte*) malloc(sizeof(GLubyte) * tex->width
        * tex->height * tex->internal_format);

  png_bytep* row_pointers;

  /* setup a pointer array.  Each one points at the begening of a row. */
  row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * tex->height);

  int i;
  for (i = 0; i < tex->height; ++i) {
    row_pointers[i] = (png_bytep)(tex->data +
          ((tex->height - (i + 1)) * tex->width * tex->internal_format));
  }

  /* read pixel data using row pointers */
  png_read_image(png_ptr, row_pointers);

  /* we don't need row pointers anymore */
  free(row_pointers);

  /* finish decompression and release memory */
  png_read_end(png_ptr, NULL);
  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

  fclose(f);

  tex->state = 1;

  return true;

}
Esempio n. 21
0
/*
ReadPNG - Reads the contents of a PNG file and stores the contents into
    BMGImageStruct

Inputs:
    filename    - the name of the file to be opened

Outputs:
    img         - the BMGImageStruct containing the image data

Returns:
    BMGError - if the file could not be read or a resource error occurred
    BMG_OK   - if the file was read and the data was stored in img

Limitations:
    None.

Comments:
    2-bit images are converted to 4-bit images.
    16-bit images are converted to 8-bit images.
    gray scale images with alpha components are converted to 32-bit images
*/
BMGError ReadPNG( const char *filename,
        struct BMGImageStruct * volatile img )
{
    jmp_buf             err_jmp;
    int                 error;

    FILE * volatile     file = NULL;
    int                 BitDepth;
    int                 ColorType;
    int                 InterlaceType;
    unsigned char       signature[8];
    png_structp volatile png_ptr = NULL;
    png_infop   volatile info_ptr = NULL;
    png_infop   volatile end_info = NULL;
    png_color_16       *ImageBackground = NULL;
    png_bytep           trns = NULL;
    int                 NumTrans = 0;
    int                 i, k;
    png_color_16p       TransColors = NULL;
    png_uint_32         Width, Height;

    unsigned char      *bits;
    unsigned char** volatile rows = NULL;

    BMGError tmp;

    /* error handler */
    error = setjmp( err_jmp );
    if (error != 0)
    {
        if (end_info != NULL)
            png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info);
        else if (info_ptr != NULL)
            png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, NULL);
        else if (png_ptr != NULL)
            png_destroy_read_struct((png_structp *) &png_ptr, NULL, NULL);
        if (rows)
        {
            if (rows[0])
                free(rows[0]);
            free(rows);
        }
        if (img)
            FreeBMGImage(img);
        if (file)
            fclose(file);
        SetLastBMGError((BMGError) error);
        return (BMGError) error;
    }

    if ( img == NULL )
        longjmp ( err_jmp, (int)errInvalidBMGImage );

    file = fopen( filename, "rb" );
    if ( !file || fread( signature, 1, 8, file ) != 8)
        longjmp ( err_jmp, (int)errFileOpen );

    /* check the signature */
    if ( png_sig_cmp( signature, 0, 8 ) != 0 )
        longjmp( err_jmp, (int)errUnsupportedFileFormat );

    /* create a pointer to the png read structure */
    png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
    if ( !png_ptr )
        longjmp( err_jmp, (int)errMemoryAllocation );

    /* create a pointer to the png info structure */
    info_ptr = png_create_info_struct( png_ptr );
    if ( !info_ptr )
        longjmp( err_jmp, (int)errMemoryAllocation );

    /* create a pointer to the png end-info structure */
    end_info = png_create_info_struct(png_ptr);
    if (!end_info)
        longjmp( err_jmp, (int)errMemoryAllocation );

    /* bamboozle the PNG longjmp buffer */
    /*generic PNG error handler*/
    /* error will always == 1 which == errLib */
//    error = png_setjmp(png_ptr);
    error = setjmp( png_jmpbuf( png_ptr ) );
    if ( error > 0 )
        longjmp( err_jmp, error );

    /* set function pointers in the PNG library, for read callbacks */
    png_set_read_fn(png_ptr, (png_voidp) file, user_read_data);

    /*let the read functions know that we have already read the 1st 8 bytes */
    png_set_sig_bytes( png_ptr, 8 );

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

    /* extract the data we need to form the HBITMAP from the PNG header */
    png_get_IHDR( png_ptr, info_ptr, &Width, &Height, &BitDepth, &ColorType,
        &InterlaceType, NULL, NULL);

    img->width = (unsigned int) Width;
    img->height = (unsigned int) Height;

    img->bits_per_pixel = (unsigned char)32;
    img->scan_width = Width * 4;

    /* convert 16-bit images to 8-bit images */
    if (BitDepth == 16)
        png_set_strip_16(png_ptr);

    /* These are not really required per Rice format spec,
     * but is done just in case someone uses them.
     */
    /* convert palette color to rgb color */
    if (ColorType == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(png_ptr);
        ColorType = PNG_COLOR_TYPE_RGB;
    }

    /* expand 1,2,4 bit gray scale to 8 bit gray scale */
    if (ColorType == PNG_COLOR_TYPE_GRAY && BitDepth < 8)
        png_set_expand_gray_1_2_4_to_8(png_ptr);

    /* convert gray scale or gray scale + alpha to rgb color */
    if (ColorType == PNG_COLOR_TYPE_GRAY ||
        ColorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
        png_set_gray_to_rgb(png_ptr);
        ColorType = PNG_COLOR_TYPE_RGB;
    }

    /* add alpha channel if any */
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
        png_set_tRNS_to_alpha(png_ptr);
        ColorType = PNG_COLOR_TYPE_RGB_ALPHA;
    }

    /* convert rgb to rgba */
    if (ColorType == PNG_COLOR_TYPE_RGB) {
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
        ColorType = PNG_COLOR_TYPE_RGB_ALPHA;
    }

    png_set_bgr(png_ptr);

    /* set the background color if one is found */
    if ( png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD) )
        png_get_bKGD(png_ptr, info_ptr, &ImageBackground);

    /* get the transparent color if one is there */
    if ( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) )
        png_get_tRNS( png_ptr, info_ptr, &trns, &NumTrans, &TransColors );

    img->palette_size = (unsigned short)0;
    img->bytes_per_palette_entry = 4U;

    tmp = AllocateBMGImage( img );
    if ( tmp != BMG_OK )
        longjmp( err_jmp, (int)tmp );

    png_read_update_info( png_ptr, info_ptr );

    /* create buffer to read data to */
    rows = (unsigned char **)malloc(Height*sizeof(unsigned char *));
    if ( !rows )
        longjmp( err_jmp, (int)errMemoryAllocation );

    k = png_get_rowbytes( png_ptr, info_ptr );
    rows[0] = (unsigned char *)malloc( Height*k*sizeof(char));
    if ( !rows[0] )
        longjmp( err_jmp, (int)errMemoryAllocation );

    for ( i = 1; i < (int)Height; i++ )
        rows[i] = rows[i-1] + k;

    /* read the entire image into rows */
    png_read_image( png_ptr, rows );

    bits = img->bits + (Height - 1) * img->scan_width;
    for ( i = 0; i < (int)Height; i++ )
    {
        memcpy(bits, rows[i], 4*Width);
        bits -= img->scan_width;
    }

    free( rows[0] );
    free( rows );
    png_read_end( png_ptr, info_ptr );
    png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info);
    fclose( file );

    return BMG_OK;
}
Esempio n. 22
0
Py::Object
_image_module::readpng(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());

  fread(header, 1, 8, fp);
  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[height];

   for (png_uint_32 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]) = ptr[0]/255.0;
      *(float*)(A->data + offset + 1*A->strides[2]) = ptr[1]/255.0;
      *(float*)(A->data + offset + 2*A->strides[2]) = ptr[2]/255.0;
      *(float*)(A->data + offset + 3*A->strides[2]) = rgba ? ptr[3]/255.0 : 1.0;
    }
  }
  
  //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 (png_uint_32 row = 0; row < height; row++)
    delete [] row_pointers[row];
  return Py::asObject((PyObject*)A);
}
Esempio n. 23
0
// This is the interesting function here. It sets up a PNG image as a texture.
void loadPngTex(char * fname , struct tImagePNG * pImagePNG , int *hasAlpha )
{
  // The header of the file will be saved in here
  char           buf[PNG_BYTES_TO_CHECK];
  
  // images infos
  int            bit_depth;
  int            cType;
  double         gamma;
  FILE          *fp;

  // Open the file and check correct opening
  /* Open the prospective PNG file. */
  if ((fp = fopen(fname, "rb")) == NULL) {
    printf( "Error: Could not open the texture file [%s]!" , fname ); throw 336;
  }
  
  // Read the PNG header, which is 8 bytes long.
  /* Read in some of the signature bytes */
  if (fread(buf, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK) {
    printf( "Error: Incorrect PNG texture file [%s]!" , fname ); throw 336;
  }

  // Check whether the file is a PNG file
  // png_sig_cmp() checks the given PNG header and returns 0 if it could
  // be the start of a PNG file. We can use 8 bytes at max for
  // this comparison.
  if(png_sig_cmp((png_byte*)buf, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0) {
    fclose( fp );
    printf( "Error: Not a PNG file [%s]!" , fname ); throw 337;
  }
  
  // Create / initialize the png_struct
  // The png_struct isn't directly accessed by the user (us).
  // We will later create a png_info from this to get access to the
  // PNG's infos.
  // The three 0's in the arg list could be pointers to user defined error
  // handling functions. 0 means we don't want to specify them, but use
  // libPNG's default error handling instead.
  png_infop info_ptr;
  png_structp png_ptr
    = png_create_read_struct(PNG_LIBPNG_VER_STRING,
			     NULL , NULL , NULL );
  if(!png_ptr) {
    fclose( fp );
    printf( "Error: Couldn't create PNG read structure [%s]!" , fname ); throw 338;
  }

  // Create / initialize the png_info
  // The png_info grants the user access to the PNG infos.
  info_ptr = png_create_info_struct(png_ptr);
  if(!info_ptr) {
    // We need to destroy the read_struct
    png_destroy_read_struct(&png_ptr, NULL, NULL);
    fclose( fp );
    printf( "Error: Couldn't create PNG info structure [%s]!" , fname ); throw 339;
  }
  
  // Setup error handler
  // This sets the point libPNG jumps back to is an error occurs.
  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 */
      printf( "Error: Couldn't setup PNG error handler [%s]!" , fname ); throw 340;
   }
  
  /* Set up the input control if you are using standard C streams */
  png_init_io(png_ptr, fp);
  
  // This tells libPNG that we have already read 8 bytes from the start
  // of the file (for the header check above).
  png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);

  // This reads the PNG file into the read and info structs
  /*
   * 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_info(png_ptr, info_ptr);

  // Get some basic infos about the image from png_info structure
  // width & height in px, bit depth
  // interlace_method, compression_method, & filter_method are ignored
  png_get_IHDR(png_ptr, info_ptr, &(pImagePNG->sizeX), &(pImagePNG->sizeY), 
	       &bit_depth, &cType, 0, 0, 0);

  // COLOR TYPE read and possible corrections - then reread
  // Color type: we handle RGB and RGB_ALPHA (with Alpha) 
  // GRAY (luminance) and GRAY_ALPHA (luminance with Alpha)
  cType = png_get_color_type(png_ptr, info_ptr);
  // strip the pixels of a PNG stream with 16 bits per channel to 8 bits per channel
  if (bit_depth == 16) {
    png_set_strip_16(png_ptr);
  }
  // set transformation in png_ptr such that paletted images are expanded to RGB, 
  // grayscale images of bit-depth less than 8 are expanded to 8-bit images
  // tRNS chunks are expanded to alpha channels
  if (cType == PNG_COLOR_TYPE_PALETTE) {
    png_set_expand(png_ptr);
  }
  if (bit_depth < 8) {
    png_set_expand(png_ptr);
  }
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
    png_set_expand(png_ptr);
  }
  // if required set gamma conversion
  if (png_get_gAMA(png_ptr, info_ptr, &gamma)) {
    png_set_gamma(png_ptr, (double) 2.2, gamma);
  }

  // After the image transformations have been registered update info_ptr data
  png_read_update_info(png_ptr, info_ptr);
  // Gets again width, height and the new bit-depth and color-type
  png_get_IHDR(png_ptr, info_ptr, &(pImagePNG->sizeX), &(pImagePNG->sizeY), 
	       &bit_depth, &cType, 0, 0, 0);

  // We now calculate the *bytes* per pixel from the color type and the
  // bits per pixel.
  if((cType == PNG_COLOR_TYPE_RGB) && (bit_depth == 8)) {
    pImagePNG->bytesPerPixel = 3;
    *hasAlpha = false;
  }
  else if((cType == PNG_COLOR_TYPE_RGB_ALPHA) && (bit_depth == 8)) {
    pImagePNG->bytesPerPixel = 4;
    *hasAlpha = true;
  }
  else if((cType == PNG_COLOR_TYPE_GRAY) && (bit_depth == 8)) {
    pImagePNG->bytesPerPixel = 1;
    *hasAlpha = false;
  }
  else if((cType == PNG_COLOR_TYPE_GRAY_ALPHA) && (bit_depth == 8)) {
    pImagePNG->bytesPerPixel = 2;
    *hasAlpha = true;
  }
  else {
    /* clean up after the read, and free any memory allocated - REQUIRED */
    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
    fclose( fp );
    printf( "Error: PNG image [%s] type (%d) bit depth (%d) is unsupported!" , fname , cType , bit_depth ); throw 336;
  }
  
  // rowbytes is the width x number of channels. channels is not used currently
  unsigned int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
  // unsigned int channels = png_get_channels(png_ptr, info_ptr);

  // Allocates memory to store the image
  pImagePNG->data = new GLubyte[pImagePNG->sizeY * rowbytes];

//   printf( "PNG image %ldx%ld (%d bitsperpixel/%d bytesPerPixel) size row %d total %ld\n" , 
// 	  pImagePNG->sizeX ,
// 	  pImagePNG->sizeY , bit_depth , pImagePNG->bytesPerPixel,
// 	  rowbytes , pImagePNG->sizeY * rowbytes);

  ////  Alternate solution without explicit row pointers
  //// and image read through png_get_rows
  // Returns a pointer to the array of array of png_bytes that holds the
  // image data.
  // png_byte **imageData = png_get_rows(png_ptr, info_ptr);
  //// must read row after row
  //   for( unsigned int i = 0 ; i < pImagePNG->sizeY ; i++ ) {
  //     printf( "Ind %d\n" , i );
  //     memcpy(&pImagePNG->data[(pImagePNG->sizeY - i - 1) * rowbytes],
  // 	   row[i], rowbytes);
  //  }

  ////  Alternate solution with explicit row pointers
  //// and image read through png_read_image
  // Allocates memory for an array of row-pointers
  png_byte ** row = new GLubyte * [pImagePNG->sizeY];
  // Sets the row-pointers to point at the correct offsets	
  for (unsigned int i = 0; i < pImagePNG->sizeY; i++) {
    row[i] = pImagePNG->data + (pImagePNG->sizeY - i - 1) * rowbytes;
  }
  // Reads the whole image
  png_read_image(png_ptr, row);
  // deallocate the now unuseful row pointers
  delete [] row;

  // Free the memory we used - we don't need it anymore
  /* clean up after the read, and free any memory allocated - REQUIRED */
  png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
  fclose( fp );
}
Esempio n. 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];
                        }
                    }
                }
            }
        }
Esempio n. 25
0
int read_header(const char *filename, dt_imageio_png_t *png)
{
  png->f = fopen(filename, "rb");

  if(!png->f) return 1;

  const size_t NUM_BYTES_CHECK = 8;
  png_byte dat[NUM_BYTES_CHECK];

  size_t cnt = fread(dat, 1, NUM_BYTES_CHECK, png->f);

  if(cnt != NUM_BYTES_CHECK || png_sig_cmp(dat, (png_size_t)0, NUM_BYTES_CHECK))
  {
    fclose(png->f);
    return 1;
  }

  png->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

  if(!png->png_ptr)
  {
    fclose(png->f);
    return 1;
  }

  png->info_ptr = png_create_info_struct(png->png_ptr);
  if(!png->info_ptr)
  {
    fclose(png->f);
    png_destroy_read_struct(&png->png_ptr, NULL, NULL);
    return 1;
  }

  if(setjmp(png_jmpbuf(png->png_ptr)))
  {
    fclose(png->f);
    png_destroy_read_struct(&png->png_ptr, &png->info_ptr, NULL);
    return 1;
  }

  png_init_io(png->png_ptr, png->f);

  // we checked some bytes
  png_set_sig_bytes(png->png_ptr, NUM_BYTES_CHECK);

  // image info
  png_read_info(png->png_ptr, png->info_ptr);

  png->bit_depth = png_get_bit_depth(png->png_ptr, png->info_ptr);
  png->color_type = png_get_color_type(png->png_ptr, png->info_ptr);

  // image input transformations

  // palette => rgb
  if(png->color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png->png_ptr);

  // 1, 2, 4 bit => 8 bit
  if(png->color_type == PNG_COLOR_TYPE_GRAY && png->bit_depth < 8)
  {
    png_set_expand_gray_1_2_4_to_8(png->png_ptr);
    png->bit_depth = 8;
  }

  // strip alpha channel
  if(png->color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png->png_ptr);

  // grayscale => rgb
  if(png->color_type == PNG_COLOR_TYPE_GRAY || png->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    png_set_gray_to_rgb(png->png_ptr);

  // reflect changes
  png_read_update_info(png->png_ptr, png->info_ptr);

  // png->bytespp = 3*bit_depth/8;
  png->width = png_get_image_width(png->png_ptr, png->info_ptr);
  png->height = png_get_image_height(png->png_ptr, png->info_ptr);

  return 0;
}
void LinuxAppPlatform::loadPNG(ImageData& imgData, const std::string& path, bool b) {
    std::cout << "loadPNG: " << path << " (from assets: " << b << ")\n";

    FILE* file = fopen(getImagePath(path, b).c_str(), "rb");
    if (file == NULL) {
        std::cout << "failed to open file\n";
        return;
    }

    png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png) {
        std::cout << "png_create_read_struct failed\n";
        abort();
        return;
    }

    png_infop info = png_create_info_struct(png);
    if (!info) {
        std::cout << "png_create_info_struct failed\n";
        abort();
        return;
    }

    unsigned char header[8];
    if(fread(header, 8, 1, file) != 1) {
        std::cout << "failed to read png header\n";
        return;
    }

    if(png_sig_cmp(header, 0, 8)) {
        std::cout << "header is invalid\n";
        return;
    }

    if (setjmp(png_jmpbuf(png))) {
        std::cout << "failed to load png\n";
        abort();
        return;
    }

    png_init_io(png, file);
    png_set_sig_bytes(png, 8);

    png_read_info(png, info);

    imgData.w = (int) png_get_image_width(png, info);
    imgData.h = (int) png_get_image_height(png, info);
    imgData.format = TextureFormat::U8888;
    imgData.mipLevel = 0;

    png_byte bitDepth = png_get_bit_depth(png, info);
    png_byte colorType = png_get_color_type(png, info);
    switch(colorType){
        case PNG_COLOR_TYPE_PALETTE:
            png_set_palette_to_rgb(png);
            break;
        case PNG_COLOR_TYPE_RGB:
            if(png_get_valid(png, info, PNG_INFO_tRNS)) {
                png_set_tRNS_to_alpha(png);
            } else {
                png_set_filler(png, 0xff, PNG_FILLER_AFTER);
            }
            break;

        case PNG_COLOR_TYPE_RGB_ALPHA:
            break;
        case PNG_COLOR_TYPE_GRAY:
            if(bitDepth < 8) {
                png_set_expand_gray_1_2_4_to_8(png);
            }

        default:
            std::cout << "png: unsupported color type\n";
    }
    if(bitDepth == 16) {
        png_set_strip_16(png);
    }
    png_read_update_info(png, info);

    png_size_t rowBytes = png_get_rowbytes(png, info);

    std::vector<char> data(rowBytes * imgData.h);

    png_byte* rows[imgData.h];
    for (int i = 0; i < imgData.h; i++) {
        rows[i] = (png_byte*) &data[i * rowBytes];
    }
    png_read_image(png, rows);

    fclose(file);

    {
        std::string empty;
        ((void **) &imgData.data)[0] = ((void **) &empty)[0];
        imgData.data = " ";
    }
    imgData.data = std::string(&data[0], rowBytes * imgData.h);
}
Esempio n. 27
0
int read_png_(char *file_name, int *w, int *h,  int *rw, int *rh, unsigned char *pixout[], bool forgl, int *numchannel)
{
   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, compression_type, filter_type;
   FILE *fp;

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

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

   if (png_ptr == NULL)
   {
      fclose(fp);
      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 */
   /* Set up the input control if you are using standard C streams */
   png_init_io(png_ptr, fp);

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

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

   // The following code transforms grayscale images of less than 8 to 8 bits,
   // changes paletted images to RGB, and adds a full alpha channel if there
   // is transparency information in a tRNS chunk. 
   if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) 
     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);

   if (bit_depth == 16) //ensure 8-bit
     png_set_strip_16(png_ptr);
   if (bit_depth < 8) //ensure 8-bit
     png_set_packing(png_ptr);

   if (forgl) { //width and height must be powers of 2.
     *rh = height; //set the real return vals first
     *rw = width;
     //these are probably the only likely ranges
     if (width > 512)
       width = 1024;
     else if (width > 256)
       width = 512;
     else 
       width = 256;
     if (height > 512)
       height = 1024;
     else if (height > 256)
       height = 512;
     else 
       height = 256;
   }
   
   //printf("colortype %d %d\n",color_type,PNG_COLOR_TYPE_RGBA); 
   *numchannel=3;
   if(color_type==PNG_COLOR_TYPE_RGBA||color_type==PNG_COLOR_TYPE_RGB_ALPHA)
     *numchannel=4;

   unsigned char *pixels = new unsigned char[width*height*sizeof(unsigned char)*(*numchannel)]; //for rgba
   png_byte **row_pointers = new png_byte*[height];
   for (unsigned int k = 0; k < height; k++)
     row_pointers[k] = pixels + (k)* 
       width*sizeof(unsigned char)*(*numchannel); //for r,g,b,a

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

   /* At this point you have read the entire image */

   //set return values
   *h = height;
   *w = width;
   *pixout = pixels;

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

   /* close the file */
   fclose(fp);

   /* that's it */
   return (OK);
}
Esempio n. 28
0
static unsigned char* _load_image_RGBA_png(const char *fileName, int *width, int *height)
{
    // open the file
    FILE *fp = fopen(fileName, "rb");
    if (!fp)
        return _load_img_error(width, height);

    // read the header
    const size_t HEADER_LENGTH = 8;
    png_byte header[HEADER_LENGTH];
    size_t n = fread(header, 1, HEADER_LENGTH, fp);
    if (n != HEADER_LENGTH || png_sig_cmp(header, 0, HEADER_LENGTH))
        return _load_img_error(width, height);

    // try to create the loading structures
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0,
      0);
    if (!png_ptr) {
        fclose(fp);
    return _load_img_error(width, height);
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_read_struct(&png_ptr, (png_infopp) 0, (png_infopp) 0);
        fclose(fp);
        return _load_img_error(width, height);
    }

    png_infop end_info = png_create_info_struct(png_ptr);
    if (!end_info) {
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)0);
        fclose(fp);
        return _load_img_error(width, height);
    }

    if (setjmp(png_ptr->jmpbuf)) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        fclose(fp);
        return _load_img_error(width, height);
    }

    // start the io
    png_init_io(png_ptr, fp);

    // indicate that we have already read some of the hearder
    png_set_sig_bytes(png_ptr, HEADER_LENGTH);

    // read the image info, get some 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);
    int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    png_byte color_type = png_get_color_type(png_ptr, info_ptr);

    // force the image into RGBA, 8 bits per channel
    if (color_type != PNG_COLOR_TYPE_RGBA)
        png_set_expand(png_ptr);
    if (color_type == PNG_COLOR_TYPE_GRAY ||
      color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);
    if (bit_depth < 8)
        png_set_packing(png_ptr);
    else if (bit_depth == 16)
        png_set_strip_16(png_ptr);
    if (color_type != PNG_COLOR_TYPE_RGBA)
        png_set_filler(png_ptr, 255, PNG_FILLER_AFTER);
    png_read_update_info(png_ptr, info_ptr);

    // make sure we're actually in rgba mode
    if ((int)png_get_rowbytes(png_ptr, info_ptr) != ((*width) * 4)) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        fclose(fp);
        return _load_img_error(width, height);
    }

    // finally, read the file
    unsigned char *buffer = (unsigned char *) malloc((*width) * (*height) * 4);
    png_bytep *row_pointers = new png_bytep[*height];
    for (int y = 0 ; y < (*height) ; y++) {
        row_pointers[y] = (png_byte *) (buffer + ((*height) - 1 - y) *
          (*width) * 4);
    }
    png_read_rows(png_ptr, row_pointers, 0, (long unsigned int) (*height));

    // deallocate memory and return
    fclose(fp);
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    return buffer;
}
Esempio n. 29
0
int main(int argc, char **argv)
{
	FILE *fin  = NULL;
	FILE *fout = NULL;
	char header[8];
	uint8_t *image_data = NULL;
	png_bytep *row_pointers = NULL;
	int i;

	if (argc < 3) ERR("too few arguments")

	if ((fin = fopen(argv[1], "rb")) == NULL) ERR("cannot open man, lame!");

	printf("%s opened\n", argv[1]);

	fread(header, 1, 8, fin);
	if (png_check_sig(header, 8) == 0) ERR("not a valid .png image")

	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) ERR("sdf");

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		ERR2("fssdfs");
	}

	if (setjmp(png_ptr->jmpbuf)) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        return 0;
    }

	png_init_io(png_ptr, fin);
    png_set_sig_bytes(png_ptr, 8);
    png_read_info(png_ptr, info_ptr);
	printf("width    : %d\n", info_ptr->width);
	printf("height   : %d\n", info_ptr->height);
	printf("bpp      : %d\n", info_ptr->bit_depth);
	printf("palette  : %d entries\n", info_ptr->num_palette);
	printf("rowbytes : %d\n", info_ptr->rowbytes);
/*	fclose(fin);
	return 0;

	png_infop end_info = png_create_info_struct(png_ptr);
	if (!end_info) {
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		ERR2("fjsh");
	}
*/
	// optional call to update palette with transformations
//	png_start_read_image(png_ptr);

	// optional call to update the info structure
//	png_read_update_info(png_ptr, info_ptr);
	if ((image_data = (uint8_t*)malloc(info_ptr->rowbytes*info_ptr->height)) == NULL) {
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return 0;
	}

	row_pointers = (png_bytep*)malloc(sizeof(png_bytep)*info_ptr->height);
	for (i=0;  i<info_ptr->height; ++i) row_pointers[i] = image_data + i*info_ptr->rowbytes;

	// the easiest way to read the image
	png_read_image(png_ptr, row_pointers);

	// void write_binimg(char *fname, uint8_t *data, png_color *pal_data, int pal_size, int width, int height, int bpp)
	char filename[256];
	strcpy(filename, argv[2]);
/*	write_binimg(strcat(filename, ".raw"), image_data, info_ptr->palette, info_ptr->num_palette,
		info_ptr->width, info_ptr->height, info_ptr->bit_depth);
*/
	write_2c(argv[2], image_data, info_ptr->palette, info_ptr->num_palette,
		info_ptr->width, info_ptr->height, info_ptr->bit_depth);

	// clean up after the read, and free any memory allocated
	png_read_destroy(png_ptr, info_ptr, (png_infop)0);
//	png_read_end(png_ptr, NULL);

i_am_done:
	if (image_data != NULL) free(image_data);
	if (row_pointers != NULL) free(row_pointers);
	if (fin != NULL) fclose(fin);
	if (fout != NULL) fclose(fout);

	return 0;
}
Esempio n. 30
0
CSize InformApp::GetImageSize(const char* path)
{
  CSize size(0,0);

  // Check if it's a PNG file
  CStdioFile imageFile;
  if (!imageFile.Open(path,CFile::modeRead|CFile::typeBinary))
    return size;
  png_byte fileHeader[8];
  imageFile.Read(fileHeader,8);
  bool isPNG = (png_sig_cmp(fileHeader,0,8) == 0);

  if (isPNG)
  {
    png_structp png_ptr = png_create_read_struct
      (PNG_LIBPNG_VER_STRING,(png_voidp)NULL,NULL,NULL);
    if (png_ptr == NULL)
      return size;
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL)
    {
      png_destroy_read_struct(&png_ptr,(png_infopp)NULL,(png_infopp)NULL);
      return size;
    }
    png_infop end_info = png_create_info_struct(png_ptr);
    if (end_info == NULL)
    {
      png_destroy_read_struct(&png_ptr,&info_ptr,(png_infopp)NULL);
      return size;
    }
    if (setjmp(png_jmpbuf(png_ptr)))
    {
      png_destroy_read_struct(&png_ptr,&info_ptr,&end_info);
      return size;
    }

    png_init_io(png_ptr,imageFile.m_pStream);
    png_set_sig_bytes(png_ptr,8);
    png_read_info(png_ptr,info_ptr);

    size.cx = png_get_image_width(png_ptr,info_ptr);
    size.cy = png_get_image_height(png_ptr,info_ptr);

    png_destroy_read_struct(&png_ptr,&info_ptr,&end_info);
    return size;
  }
  else
  {
    imageFile.SeekToBegin();

    struct jpeg_decompress_struct info;
    struct JPEGErrorInfo error;

    info.err = jpeg_std_error(&(error.base));
    error.base.error_exit = errorJPEGExit;
    error.base.output_message = outputJPEGMessage;
    if (setjmp(error.errorJump))
    {
      jpeg_destroy_decompress(&info);
      return size;
    }

    jpeg_create_decompress(&info);
    jpeg_stdio_src(&info,imageFile.m_pStream);

    jpeg_read_header(&info,TRUE);
    jpeg_calc_output_dimensions(&info);

    size.cx = info.output_width;
    size.cy = info.output_height;

    jpeg_destroy_decompress(&info);
    return size;
  }
}