Example #1
0
/**
  The constructor loads the named PNG image from the given png filename.
  <P>The destructor free all memory and server resources that are used by
  the image.
*/
void LoadPNG(const char *png) // I - File to read
{
  int		i;			// Looping var
  FILE		*fp;			// File pointer
  int		channels;		// Number of color channels
  png_structp	pp;			// PNG read pointer
  png_infop	info;			// PNG info pointers
  png_bytep	*rows;			// PNG row pointers


  // Open the PNG file...
  if ((fp = fopen(png, "rb")) == NULL) return;

  // Setup the PNG data structures...
  pp   = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  info = png_create_info_struct(pp);

  if (setjmp(pp->jmpbuf))
  {
	  int debug = 1;
	  return;
  }

  // Initialize the PNG read "engine"...
  png_init_io(pp, fp);

  // Get the image dimensions and convert to grayscale or RGB...
  png_read_info(pp, info);

  if (info->color_type == PNG_COLOR_TYPE_PALETTE)
    png_set_expand(pp);

  if (info->color_type & PNG_COLOR_MASK_COLOR)
    channels = 3;
  else
    channels = 1;

  if ((info->color_type & PNG_COLOR_MASK_ALPHA) || info->num_trans)
    channels ++;

  int w = (int)(info->width);
  int h = (int)(info->height);
  int d = channels;
  pictureWidth = w;
  pictureHeight = h;

  if (info->bit_depth < 8)
  {
    png_set_packing(pp);
    png_set_expand(pp);
  }
  else if (info->bit_depth == 16)
    png_set_strip_16(pp);

#  if defined(HAVE_PNG_GET_VALID) && defined(HAVE_PNG_SET_TRNS_TO_ALPHA)
  // Handle transparency...
  if (png_get_valid(pp, info, PNG_INFO_tRNS))
    png_set_tRNS_to_alpha(pp);
#  endif // HAVE_PNG_GET_VALID && HAVE_PNG_SET_TRNS_TO_ALPHA

  unsigned char *array = (unsigned char *)pictureS;

  // Allocate pointers...
  rows = new png_bytep[h];

  for (i = 0; i < h; i ++)
    rows[i] = (png_bytep)(array + i * w * d); // we flip it

  // Read the image, handling interlacing as needed...
  for (i = png_set_interlace_handling(pp); i > 0; i --)
    png_read_rows(pp, rows, NULL, h);

#ifdef WIN32
  // Some Windows graphics drivers don't honor transparency when RGB == white
  if (channels == 4) 
  {
    // Convert RGB to 0 when alpha == 0...
    unsigned char *ptr = (unsigned char *)array;
    for (i = w * h; i > 0; i --, ptr += 4)
      if (!ptr[3]) ptr[0] = ptr[1] = ptr[2] = 0;
  }
#endif // WIN32

  if (channels == 3)
  {
	  unsigned char *array2 = new unsigned char[pictureWidth * pictureHeight * 4];
	  for (int i = w * h - 1; i >= 0; --i)
	  {
		  array2[i*4+0] = array[i*3+0];
		  array2[i*4+1] = array[i*3+1];
		  array2[i*4+2] = array[i*3+2];
		  array2[i*4+3] = 255;
	  }
	  memcpy(array, array2, w * h * 4);
	  delete[] array2;
  }

  // Free memory and return...
  delete[] rows;

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

  fclose(fp);
}
Example #2
0
void* replaceBootImage(AbstractFile* imageWrapper, const unsigned int* key, const unsigned int* iv, AbstractFile* png, size_t *fileSize) {
	AbstractFile* imageFile;
	unsigned char header[8];
	InfoIBootIM* info;
	png_uint_32 i;
	png_bytepp row_pointers;
	
	uint8_t* imageBuffer;
	void* buffer;

	png->read(png, header, 8);
	if(png_sig_cmp(header, 0, 8) != 0) {
		XLOG(0, "error: not a valid png file\n");
		return NULL;
	}
	png->seek(png, 0);

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

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

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

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		XLOG(0, "error reading png\n");
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		free(buffer);
		return NULL;
	}

	png_set_read_fn(png_ptr, png, pngRead);

	png_read_info(png_ptr, info_ptr);
	
	if(info_ptr->bit_depth > 8) {
		XLOG(0, "warning: bit depth per channel is greater than 8 (%d). Attempting to strip, but image quality will be degraded.\n", info_ptr->bit_depth);
	}
	
	if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY || info_ptr->color_type == PNG_COLOR_TYPE_RGB) {
		XLOG(0, "notice: attempting to add dummy transparency channel\n");
	}
	
	if(info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
		XLOG(0, "notice: attempting to expand palette into full rgb\n");
	}
	
	png_set_expand(png_ptr);
	png_set_strip_16(png_ptr);
	png_set_bgr(png_ptr);
	png_set_add_alpha(png_ptr, 0x0, PNG_FILLER_AFTER);
	png_set_invert_alpha(png_ptr);
	
	png_read_update_info(png_ptr, info_ptr);
	

	if(info_ptr->width > 320 || info_ptr->height > 480) {
		XLOG(0, "error: dimensions out of range, must be within 320x480, not %lux%lu\n", info_ptr->width, info_ptr->height);
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		return NULL;
	}

	if(info_ptr->bit_depth != 8) {
		XLOG(0, "error: bit depth per channel must be 8 not %d!\n", info_ptr->bit_depth);
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		return NULL;
	}

	if(info_ptr->color_type != PNG_COLOR_TYPE_GRAY_ALPHA && info_ptr->color_type != PNG_COLOR_TYPE_RGB_ALPHA) {
		XLOG(0, "error: incorrect color type, must be greyscale with alpha, or rgb with alpha\n");
		if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY || info_ptr->color_type == PNG_COLOR_TYPE_RGB) {
			XLOG(0, "It appears you're missing an alpha channel. Add transparency to your image\n");
		}
		if(info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
			XLOG(0, "This PNG is saved with the palette color type rather than ARGB.\n");
		}
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);

		return NULL;
	}

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

	png_read_image(png_ptr, row_pointers);
	png_read_end(png_ptr, end_info);
	
	buffer = malloc(1);
	*fileSize = 0;

	if(key != NULL) {
		imageFile = duplicateAbstractFile2(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize), key, iv, NULL);
	} else {	
		imageFile = duplicateAbstractFile(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize));
	}
	info = (InfoIBootIM*) (imageFile->data);
	
	info->header.width = (uint16_t) info_ptr->width;
	info->header.height = (uint16_t) info_ptr->height;
	if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
		info->header.format = IBOOTIM_GREY;
	} else {
		info->header.format = IBOOTIM_ARGB;
	}
	
	imageFile->write(imageFile, imageBuffer, info_ptr->height * info_ptr->rowbytes);
	
	imageFile->close(imageFile);

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

	png->close(png);
	
	free(row_pointers);

	free(imageBuffer);

	return buffer;
}
Example #3
0
	int Read ( byte **data, int *width, int *height )
	{
		// Setup the pointers
		*data = NULL;
		*width = 0;
		*height = 0;

		// Make sure we're actually reading PNG data.
		const int SIGNATURE_LEN = 8;

		byte ident[SIGNATURE_LEN];
		memcpy (ident, buf, SIGNATURE_LEN);

		if ( !png_check_sig (ident, SIGNATURE_LEN) )
		{
			ri->Printf (PRINT_ERROR, "PNG signature not found in given image.");
			return 0;
		}

		png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, png_print_error, png_print_warning);
		if ( png_ptr == NULL )
		{
			ri->Printf (PRINT_ERROR, "Could not allocate enough memory to load the image.");
			return 0;
		}

		info_ptr = png_create_info_struct (png_ptr);
		if ( setjmp (png_jmpbuf (png_ptr)) )
		{
			return 0;
		}

		// We've read the signature
		offset += SIGNATURE_LEN;

		// Setup reading information, and read header
		png_set_read_fn (png_ptr, (png_voidp)this, &user_read_data);
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
		// This generic "ignore all, except required chunks" requires 1.6.0 or newer"
		png_set_keep_unknown_chunks (png_ptr, PNG_HANDLE_CHUNK_NEVER, NULL, -1);
#endif
		png_set_sig_bytes (png_ptr, SIGNATURE_LEN);
		png_read_info (png_ptr, info_ptr);

		png_uint_32 width_;
		png_uint_32 height_;
		int depth;
		int colortype;

		png_get_IHDR (png_ptr, info_ptr, &width_, &height_, &depth, &colortype, NULL, NULL, NULL);

		// While modern OpenGL can handle non-PoT textures, it's faster to handle only PoT
		// so that the graphics driver doesn't have to fiddle about with the texture when uploading.
		if ( !IsPowerOfTwo (width_) || !IsPowerOfTwo (height_) )
		{
			ri->Printf (PRINT_ERROR, "Width or height is not a power-of-two.\n");
			return 0;
		}

		// This function is equivalent to using what used to be LoadPNG32. LoadPNG8 also existed,
		// but this only seemed to be used by the RMG system which does not work in JKA. If this
		// does need to be re-implemented, then colortype should be PNG_COLOR_TYPE_PALETTE or
		// PNG_COLOR_TYPE_GRAY.
		if ( colortype != PNG_COLOR_TYPE_RGB && colortype != PNG_COLOR_TYPE_RGBA )
		{
			ri->Printf (PRINT_ERROR, "Image is not 24-bit or 32-bit.");
			return 0;
		}

		// Read the png data
		if ( colortype == PNG_COLOR_TYPE_RGB )
		{
			// Expand RGB -> RGBA
			png_set_add_alpha (png_ptr, 0xff, PNG_FILLER_AFTER);
		}

		png_read_update_info (png_ptr, info_ptr);

		// We always assume there are 4 channels. RGB channels are expanded to RGBA when read.
		byte *tempData = (byte *)ri->Z_Malloc (width_ * height_ * 4, TAG_TEMP_PNG, qfalse, 4);
		if ( !tempData )
		{
			ri->Printf (PRINT_ERROR, "Could not allocate enough memory to load the image.");
			return 0;
		}

		// Dynamic array of row pointers, with 'height' elements, initialized to NULL.
		byte **row_pointers = (byte **)ri->Hunk_AllocateTempMemory (sizeof (byte *) * height_);
		if ( !row_pointers )
		{
			ri->Printf (PRINT_ERROR, "Could not allocate enough memory to load the image.");

			ri->Z_Free (tempData);
			
			return 0;
		}

		// Re-set the jmp so that these new memory allocations can be reclaimed
		if ( setjmp (png_jmpbuf (png_ptr)) )
		{
			ri->Hunk_FreeTempMemory (row_pointers);
			ri->Z_Free (tempData);
			return 0;
		}

		for ( unsigned int i = 0, j = 0; i < height_; i++, j += 4 )
		{
			row_pointers[i] = tempData + j * width_;
		}

		png_read_image (png_ptr, row_pointers);

		// Finish reading
		png_read_end (png_ptr, NULL);

		ri->Hunk_FreeTempMemory (row_pointers);

		// Finally assign all the parameters
		*data = tempData;
		*width = width_;
		*height = height_;

		return 1;
	}
Example #4
0
SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
{
	SDL_Surface *volatile surface;
	png_structp png_ptr;
	png_infop info_ptr;
	png_uint_32 width, height;
	int bit_depth, color_type, interlace_type;
	Uint32 Rmask;
	Uint32 Gmask;
	Uint32 Bmask;
	Uint32 Amask;
	SDL_Palette *palette;
	png_bytep *volatile row_pointers;
	int row, i;
	volatile int ckey = -1;
	png_color_16 *transv;

	/* Initialize the data we will clean up when we're done */
	png_ptr = NULL; info_ptr = NULL; row_pointers = NULL; surface = NULL;

	/* Check to make sure we have something to do */
	if ( ! src ) {
		goto done;
	}

	/* Create the PNG loading context structure */
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
					  NULL,NULL,NULL);
	if (png_ptr == NULL){
		IMG_SetError("Couldn't allocate memory for PNG file");
		goto done;
	}

	 /* Allocate/initialize the memory for image information.  REQUIRED. */
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		IMG_SetError("Couldn't create image information for PNG file");
		goto done;
	}

	/* Set error handling if you are using setjmp/longjmp method (this is
	 * the normal method of doing things with libpng).  REQUIRED unless you
	 * set up your own error handlers in png_create_read_struct() earlier.
	 */
	if ( setjmp(png_ptr->jmpbuf) ) {
		IMG_SetError("Error reading the PNG file.");
		goto done;
	}

	/* Set up the input control */
	png_set_read_fn(png_ptr, src, png_read_data);

	/* Read PNG header info */
	png_read_info(png_ptr, info_ptr);
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
			&color_type, &interlace_type, NULL, NULL);

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

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

	/* scale greyscale values to the range 0..255 */
	if(color_type == PNG_COLOR_TYPE_GRAY)
		png_set_expand(png_ptr);

	/* For images with a single "transparent colour", set colour key;
	   if more than one index has transparency, or if partially transparent
	   entries exist, use full alpha channel */
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
	        int num_trans;
		Uint8 *trans;
		png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans,
			     &transv);
		if(color_type == PNG_COLOR_TYPE_PALETTE) {
		    /* Check if all tRNS entries are opaque except one */
		    int i, t = -1;
		    for(i = 0; i < num_trans; i++)
			if(trans[i] == 0) {
			    if(t >= 0)
				break;
			    t = i;
			} else if(trans[i] != 255)
			    break;
		    if(i == num_trans) {
			/* exactly one transparent index */
			ckey = t;
		    } else {
			/* more than one transparent index, or translucency */
			png_set_expand(png_ptr);
		    }
		} else
		    ckey = 0; /* actual value will be set later */
	}

	if ( color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
		png_set_gray_to_rgb(png_ptr);

	png_read_update_info(png_ptr, info_ptr);

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

	/* Allocate the SDL surface to hold the image */
	Rmask = Gmask = Bmask = Amask = 0 ; 
	if ( color_type != PNG_COLOR_TYPE_PALETTE ) {
		if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
			Rmask = 0x000000FF;
			Gmask = 0x0000FF00;
			Bmask = 0x00FF0000;
			Amask = (info_ptr->channels == 4) ? 0xFF000000 : 0;
		} else {
		        int s = (info_ptr->channels == 4) ? 0 : 8;
			Rmask = 0xFF000000 >> s;
			Gmask = 0x00FF0000 >> s;
			Bmask = 0x0000FF00 >> s;
			Amask = 0x000000FF >> s;
		}
	}
	surface = SDL_AllocSurface(SDL_SWSURFACE, width, height,
			bit_depth*info_ptr->channels, Rmask,Gmask,Bmask,Amask);
	if ( surface == NULL ) {
		IMG_SetError("Out of memory");
		goto done;
	}

	if(ckey != -1) {
	        if(color_type != PNG_COLOR_TYPE_PALETTE)
			/* FIXME: Should these be truncated or shifted down? */
		        ckey = SDL_MapRGB(surface->format,
			                 (Uint8)transv->red,
			                 (Uint8)transv->green,
			                 (Uint8)transv->blue);
	        SDL_SetColorKey(surface, SDL_SRCCOLORKEY, ckey);
	}

	/* Create the array of pointers to image data */
	row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*height);
	if ( (row_pointers == NULL) ) {
		IMG_SetError("Out of memory");
		SDL_FreeSurface(surface);
		surface = NULL;
		goto done;
	}
	for (row = 0; row < (int)height; row++) {
		row_pointers[row] = (png_bytep)
				(Uint8 *)surface->pixels + row*surface->pitch;
	}

	/* Read the entire image in one go */
	png_read_image(png_ptr, row_pointers);

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

	/* Load the palette, if any */
	palette = surface->format->palette;
	if ( palette ) {
	    if(color_type == PNG_COLOR_TYPE_GRAY) {
		palette->ncolors = 256;
		for(i = 0; i < 256; i++) {
		    palette->colors[i].r = i;
		    palette->colors[i].g = i;
		    palette->colors[i].b = i;
		}
	    } else if (info_ptr->num_palette > 0 ) {
		palette->ncolors = info_ptr->num_palette; 
		for( i=0; i<info_ptr->num_palette; ++i ) {
		    palette->colors[i].b = info_ptr->palette[i].blue;
		    palette->colors[i].g = info_ptr->palette[i].green;
		    palette->colors[i].r = info_ptr->palette[i].red;
		}
	    }
	}

done:	/* Clean up and return */
	png_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : (png_infopp)0,
								(png_infopp)0);
	if ( row_pointers ) {
		free(row_pointers);
	}
	return(surface); 
}
Example #5
0
static gint
gegl_buffer_import_png (GeglBuffer  *gegl_buffer,
                        GInputStream *stream,
                        gint         dest_x,
                        gint         dest_y,
                        gint        *ret_width,
                        gint        *ret_height,
                        const Babl  *format, // can be NULL
                        GError **err)
{
  gint           width;
  gint           bit_depth;
  gint           bpp;
  gint           number_of_passes=1;
  png_uint_32    w;
  png_uint_32    h;
  png_structp    load_png_ptr;
  png_infop      load_info_ptr;
  guchar        *pixels;
  /*png_bytep     *rows;*/


  unsigned   int i;
  png_bytep  *row_p = NULL;

  g_return_val_if_fail(stream, -1);

  if (!check_valid_png_header(stream, err))
    {
      return -1;
    }

  load_png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, error_fn, NULL);

  if (!load_png_ptr)
    {
      return -1;
    }

  load_info_ptr = png_create_info_struct (load_png_ptr);
  if (!load_info_ptr)
    {
      png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL);
      return -1;
    }

  if (setjmp (png_jmpbuf (load_png_ptr)))
    {
      png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL);
      g_free (row_p);
      return -1;
    }

  png_set_read_fn(load_png_ptr, stream, read_fn);

  png_set_sig_bytes (load_png_ptr, 8); // we already read header
  png_read_info (load_png_ptr, load_info_ptr);
  {
    int color_type;
    int interlace_type;

    png_get_IHDR (load_png_ptr,
                  load_info_ptr,
                  &w, &h,
                  &bit_depth,
                  &color_type,
                  &interlace_type,
                  NULL, NULL);
    width = w;
    if (ret_width)
      *ret_width = w;
    if (ret_height)
      *ret_height = h;

    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
      {
        png_set_expand (load_png_ptr);
        bit_depth = 8;
      }

    if (png_get_valid (load_png_ptr, load_info_ptr, PNG_INFO_tRNS))
      {
        png_set_tRNS_to_alpha (load_png_ptr);
        color_type |= PNG_COLOR_MASK_ALPHA;
      }

    switch (color_type)
      {
        case PNG_COLOR_TYPE_GRAY:
          bpp = 1;
          break;
        case PNG_COLOR_TYPE_GRAY_ALPHA:
          bpp = 2;
          break;
        case PNG_COLOR_TYPE_RGB:
          bpp = 3;
          break;
        case PNG_COLOR_TYPE_RGB_ALPHA:
          bpp = 4;
          break;
        case (PNG_COLOR_TYPE_PALETTE | PNG_COLOR_MASK_ALPHA):
          bpp = 4;
          break;
        case PNG_COLOR_TYPE_PALETTE:
          bpp = 3;
          break;
        default:
          g_warning ("color type mismatch");
          png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL);
          return -1;
      }

    if (color_type == PNG_COLOR_TYPE_PALETTE)
      png_set_palette_to_rgb (load_png_ptr);

    if (bit_depth == 16)
      bpp = bpp << 1;

    if (!format)
      format = get_babl_format(bit_depth, color_type);

#if BYTE_ORDER == LITTLE_ENDIAN
    if (bit_depth == 16)
      png_set_swap (load_png_ptr);
#endif

    if (interlace_type == PNG_INTERLACE_ADAM7)
      number_of_passes = png_set_interlace_handling (load_png_ptr);

    if (png_get_valid (load_png_ptr, load_info_ptr, PNG_INFO_gAMA))
      {
        gdouble gamma;
        png_get_gAMA (load_png_ptr, load_info_ptr, &gamma);
        png_set_gamma (load_png_ptr, 2.2, gamma);
      }
    else
      {
        png_set_gamma (load_png_ptr, 2.2, 0.45455);
      }

    png_read_update_info (load_png_ptr, load_info_ptr);
  }

  pixels = g_malloc0 (width*bpp);

  {
    gint           pass;
    GeglRectangle  rect;

    for (pass=0; pass<number_of_passes; pass++)
      {
        for(i=0; i<h; i++)
          {
            gegl_rectangle_set (&rect, 0, i, width, 1);

            if (pass != 0)
              gegl_buffer_get (gegl_buffer, &rect, 1.0, format, pixels, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);

            png_read_rows (load_png_ptr, &pixels, NULL, 1);
            gegl_buffer_set (gegl_buffer, &rect, 0, format, pixels,
                             GEGL_AUTO_ROWSTRIDE);
          }
      }
  }


  png_read_end (load_png_ptr, NULL);
  png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL);

  g_free (pixels);

  return 0;
}
Example #6
0
bool initSludge (char * filename) {
	int a = 0;
	mouseCursorAnim = makeNullAnim ();

	FILE * fp = openAndVerify (filename, 'G', 'E', ERROR_BAD_HEADER, gameVersion);
	if (! fp) return false;

	if (fgetc (fp)) {
		numBIFNames = get2bytes (fp);
		allBIFNames = new char * [numBIFNames];
		if (! checkNew (allBIFNames)) return false;

		for (int fn = 0; fn < numBIFNames; fn ++) {
			allBIFNames[fn] = readString (fp);
		}
		numUserFunc = get2bytes (fp);
		allUserFunc = new char * [numUserFunc];
		if (! checkNew (allUserFunc)) return false;

		for (int fn = 0; fn < numUserFunc; fn ++) {
			allUserFunc[fn] = readString (fp);
		}
		if (gameVersion >= VERSION(1,3)) {
			numResourceNames = get2bytes (fp);
			allResourceNames = new char * [numResourceNames];
			if (! checkNew (allResourceNames)) return false;

			for (int fn = 0; fn < numResourceNames; fn ++) {
				allResourceNames[fn] = readString (fp);
			}
		}
	}
	winWidth = get2bytes (fp);
	winHeight = get2bytes (fp);
	specialSettings = fgetc (fp);

	desiredfps = 1000/fgetc (fp);

	delete[] readString (fp); // Unused - was used for registration purposes.

	size_t bytes_read = fread (& fileTime, sizeof (FILETIME), 1, fp);
	if (bytes_read != sizeof (FILETIME) && ferror (fp)) {
		debugOut("Reading error in initSludge.\n");
	}

	char * dataFol = (gameVersion >= VERSION(1,3)) ? readString(fp) : joinStrings ("", "");

	gameSettings.numLanguages = (gameVersion >= VERSION(1,3)) ? (fgetc (fp)) : 0;
	makeLanguageTable (fp);

	if (gameVersion >= VERSION(1,6))
	{
		fgetc(fp);
		// aaLoad
		fgetc (fp);
		getFloat (fp);
		getFloat (fp);
	}

	char * checker = readString (fp);

	if (strcmp (checker, "okSoFar")) return fatal (ERROR_BAD_HEADER, filename);
	delete checker;
	checker = NULL;

    unsigned char customIconLogo = fgetc (fp);

	if (customIconLogo & 1) {
		// There is an icon - read it!
		int n;

		long file_pointer = ftell (fp);

		png_structp png_ptr;
		png_infop info_ptr, end_info;

		int fileIsPNG = true;

		// Is this a PNG file?

		char tmp[10];
		bytes_read = fread(tmp, 1, 8, fp);
		if (bytes_read != 8 && ferror (fp)) {
			debugOut("Reading error in initSludge.\n");
		}
		if (png_sig_cmp((png_byte *) tmp, 0, 8)) {
			// No, it's old-school HSI
			fileIsPNG = false;
			fseek(fp, file_pointer, SEEK_SET);

			iconW = get2bytes (fp);
			iconH = get2bytes (fp);
		} else {
			// Read the PNG header

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

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

			end_info = png_create_info_struct(png_ptr);
			if (!end_info) {
				png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
				return false;
			}
			png_init_io(png_ptr, fp);		// Tell libpng which file to read
			png_set_sig_bytes(png_ptr, 8);	// 8 bytes already read

			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);

			iconW = width;
			iconH = height;

			if (bit_depth < 8) png_set_packing(png_ptr);
			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 == 16) png_set_strip_16(png_ptr);

			png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);

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

		}

        gameIcon = new unsigned char [iconW*iconH*4];
        if (! gameIcon) return fatal ("Can't reserve memory for game icon.");

        int32_t transCol = 63519;
        Uint8 *p = (Uint8 *) gameIcon;

        if (fileIsPNG) {
            unsigned char * row_pointers[iconH];
            for (int i = 0; i<iconH; i++)
                row_pointers[i] = p + 4*i*iconW;

            png_read_image(png_ptr, (png_byte **) row_pointers);
            png_read_end(png_ptr, NULL);
            png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        } else {

            for (int t2 = 0; t2 < iconH; t2 ++) {
                int t1 = 0;
                while (t1 < iconW) {
                    unsigned short c = (unsigned short) get2bytes (fp);
                    if (c & 32) {
                        n = fgetc (fp) + 1;
                        c -= 32;
                    } else {
                        n = 1;
                    }
                    while (n --) {
                       *p++ = (Uint8) redValue(c);
                        *p++ = (Uint8) greenValue(c);
                        *p++ = (Uint8) blueValue(c);
                        *p++ = (Uint8) (c == transCol) ? 0 : 255;

                        t1++;
                    }
                }
            }
        }
	}

	if (customIconLogo & 2) {
		// There is an logo - read it!
		int n;

		long file_pointer = ftell (fp);

		png_structp png_ptr;
		png_infop info_ptr, end_info;

		int fileIsPNG = true;

		// Is this a PNG file?

		char tmp[10];
		bytes_read = fread(tmp, 1, 8, fp);
		if (bytes_read != 8 && ferror (fp)) {
			debugOut("Reading error in initSludge.\n");
		}
		if (png_sig_cmp((png_byte *) tmp, 0, 8)) {
			// No, it's old-school HSI
			fileIsPNG = false;
			fseek(fp, file_pointer, SEEK_SET);

			logoW = get2bytes (fp);
			logoH = get2bytes (fp);
		} else {
			// Read the PNG header

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

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

			end_info = png_create_info_struct(png_ptr);
			if (!end_info) {
				png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
				return false;
			}
			png_init_io(png_ptr, fp);		// Tell libpng which file to read
			png_set_sig_bytes(png_ptr, 8);	// 8 bytes already read

			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);

			logoW = width;
			logoH = height;

			if (bit_depth < 8) png_set_packing(png_ptr);
			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 == 16) png_set_strip_16(png_ptr);
#ifdef WIN32
            // Windows wants a BGR bitmap
            if (color_type == PNG_COLOR_TYPE_RGB ||
                color_type == PNG_COLOR_TYPE_RGB_ALPHA)
                    png_set_bgr(png_ptr);
#endif

			png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);

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

		}

        if ((logoW != 310) || (logoH != 88)) return fatal ("Game logo have wrong dimensions. (Should be 310x88)");

        gameLogo = new unsigned char [logoW*logoH*4];
        if (! gameLogo) return fatal ("Can't reserve memory for game logo.");

        // int32_t transCol = 63519;
        Uint8 *p = (Uint8 *) gameLogo;

        if (fileIsPNG) {
            unsigned char * row_pointers[logoH];
            for (int i = 0; i<logoH; i++)
                row_pointers[i] = p + 4*i*logoW;

            png_read_image(png_ptr, (png_byte **) row_pointers);
            png_read_end(png_ptr, NULL);
            png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        } else {

            for (int t2 = 0; t2 < logoH; t2 ++) {
                int t1 = 0;
                while (t1 < logoW) {
                    unsigned short c = (unsigned short) get2bytes (fp);
                    if (c & 32) {
                        n = fgetc (fp) + 1;
                        c -= 32;
                    } else {
                        n = 1;
                    }
                    while (n --) {
#ifdef WIN32
                        // Windows wants a BGR bitmap
                       *p++ = (Uint8) blueValue(c);
                        *p++ = (Uint8) greenValue(c);
                        *p++ = (Uint8) redValue(c);
#else
                       *p++ = (Uint8) redValue(c);
                        *p++ = (Uint8) greenValue(c);
                        *p++ = (Uint8) blueValue(c);
#endif
                        *p++ = (Uint8) /*(c == transCol) ? 0 :*/ 255;

                        t1++;
                    }
                }
            }
        }
	}

 	numGlobals = get2bytes (fp);

	globalVars = new variable[numGlobals];
	if (! checkNew (globalVars)) return false;
	for (a = 0; a < numGlobals; a ++) initVarNew (globalVars[a]);

	// Get the original (untranslated) name of the game and convert it to Unicode.
	// We use this to find saved preferences and saved games.
	setFileIndices (fp, gameSettings.numLanguages, 0);
	char * gameNameOrig = getNumberedString(1);

	char * gameName = encodeFilename (gameNameOrig);

	delete gameNameOrig;

	changeToUserDir ();

#ifdef _WIN32
	mkdir (gameName);
#else
	mkdir (gameName, 0000777);
#endif

	if (chdir (gameName)) return fatal ("This game's preference folder is inaccessible!\nI can't access the following directory (maybe there's a file with the same name, or maybe it's read-protected):", gameName);

	delete [] gameName;
	
	// Get user settings
	readIniFile (filename);

	// There's no startup window on Linux and respecting this 
	// option from the ini file would disable commandline options.
#if defined __unix__ && !(defined __APPLE__)
		if (! showSetupWindow()) return 0;
		saveIniFile (filename);
#else
	if (! gameSettings.noStartWindow) {
		if (! showSetupWindow()) return 0;
		saveIniFile (filename);
	}
#endif

	// Now set file indices properly to the chosen language.
	languageNum = getLanguageForFileB ();
	if (languageNum < 0) return fatal ("Can't find the translation data specified!");
	setFileIndices (NULL, gameSettings.numLanguages, languageNum);

	if (dataFol[0]) {
		char *dataFolder = encodeFilename(dataFol);
#ifdef _WIN32
		mkdir (dataFolder);
#else
		mkdir (dataFolder, 0000777);
#endif

		if (chdir (dataFolder)) return fatal ("This game's data folder is inaccessible!\nI can't access the following directory (maybe there's a file with the same name, or maybe it's read-protected):", dataFolder);

		delete dataFolder;
	}

 	positionStatus (10, winHeight - 15);

	return true;
}
Example #7
0
GLubyte* 
glmReadPNG(const char* filename, GLboolean alpha, int* width_ret, int* height_ret, int* type_ret)
{
  png_structp png_ptr;
  png_infop info_ptr;
  png_uint_32 width, height;
  
  int bit_depth, color_type, interlace_type;
  FILE *fp;
  unsigned char *buffer;
  int y, bytes_per_row;
  int channels;
  int format;
  png_bytepp row_pointers;
printf("62");
  if ((fp = fopen(filename, "rb")) == NULL) {
    printf("64");
    pngerror = ERR_OPEN;
    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,
      (void *)user_error_ptr, user_error_fn, user_warning_fn);*/

  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
				   NULL, err_callback, warn_callback);
  
  if (png_ptr == NULL) {
    pngerror = ERR_MEM;
    fclose(fp);
    return 0;
  }

  /* Allocate/initialize the memory for image information.  REQUIRED. */
  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL) {
    pngerror = ERR_MEM;
    fclose(fp);
    png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
    return 0;
  }
  
  /* 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.
   */

  buffer = NULL;

  if (setjmp(setjmp_buffer)) {
    pngerror = ERR_PNGLIB;
    /* 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 */

    if (buffer) free(buffer);
    return NULL;
  }
  
  /* Set up the input control if you are using standard C streams */
  png_init_io(png_ptr, fp);

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

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

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

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

  /* strip alpha bytes from the input data without combining with th
   * background (not recommended) */
  /* png_set_strip_alpha(png_ptr); */
  
  /* extract multiple pixels with bit depths of 1, 2, and 4 from a single
   * byte into separate bytes (useful for paletted and grayscale images).
   */
  /* png_set_packing(png_ptr); */

  /* change the order of packed pixels to least significant bit first
   * (not useful if you are using png_set_packing). */
  /* png_set_packswap(png_ptr); */
  
  /* expand paletted colors into true RGB triplets */
  if (color_type == PNG_COLOR_TYPE_PALETTE)
    png_set_expand(png_ptr);

  /* expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
    png_set_expand(png_ptr);
  
  /* expand paletted or RGB images with transparency to full alpha channels
   * so the data will be available as RGBA quartets */
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
    png_set_expand(png_ptr);
  
  /* Add filler (or alpha) byte (before/after each RGB triplet) */
  /* png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); */

  png_read_update_info(png_ptr, info_ptr);

  channels = png_get_channels(png_ptr, info_ptr);

  /* allocate the memory to hold the image using the fields of info_ptr. */
  
  bytes_per_row = png_get_rowbytes(png_ptr, info_ptr);

  
  buffer = (unsigned char*) malloc(bytes_per_row*height);

  format = channels;

  row_pointers = (png_bytepp) malloc(height*sizeof(png_bytep));
  for (y = 0; y < height; y++) {
    row_pointers[height-y-1] = buffer + y*bytes_per_row;
  }
  
  png_read_image(png_ptr, row_pointers);
  png_read_end(png_ptr, info_ptr);
  
  free(row_pointers);

  /* 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 */
  if (buffer) {
    *width_ret = width;
    *height_ret = height;
    switch(format) {
    case 1:
	*type_ret = GL_LUMINANCE;
	break;
    case 2:
	*type_ret = GL_LUMINANCE_ALPHA;
	break;
    case 3:
	*type_ret = GL_RGB;
	break;
    case 4:
	*type_ret = GL_RGBA;
	break;
    }
    pngerror = ERR_NO_ERROR;
  }
  else {
    pngerror = ERR_MEM;
  }
  return buffer;
}
bool SkPNGImageDecoderMy::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap,
                                 Mode mode) {
    png_structp png_ptr;
    png_infop info_ptr;

    if (onDecodeInit(sk_stream, &png_ptr, &info_ptr) == false) {
        return false;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        return false;
    }

    PNGAutoClean autoClean(png_ptr, info_ptr);

    png_uint_32 origWidth, origHeight;
    int bit_depth, color_type, interlace_type;
    png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth,
            &color_type, &interlace_type, int_p_NULL, int_p_NULL);

    SkBitmap::Config    config;
    bool                hasAlpha = false;
    bool                doDither = this->getDitherImage();
    SkPMColor           theTranspColor = 0; // 0 tells us not to try to match

    if (getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha,
                &doDither, &theTranspColor) == false) {
        return false;
    }

    const int sampleSize = this->getSampleSize();
    SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize);

    decodedBitmap->setConfig(config, sampler.scaledWidth(),
                             sampler.scaledHeight(), 0);
    if (SkImageDecoder::kDecodeBounds_Mode == mode) {
        return true;
    }

    // from here down we are concerned with colortables and pixels

    // we track if we actually see a non-opaque pixels, since sometimes a PNG sets its colortype
    // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we
    // draw lots faster if we can flag the bitmap has being opaque
    bool reallyHasAlpha = false;
    SkColorTable* colorTable = NULL;

    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        decodePalette(png_ptr, info_ptr, &hasAlpha,
                &reallyHasAlpha, &colorTable);
    }

    SkAutoUnref aur(colorTable);

    if (!this->allocPixelRef(decodedBitmap,
                             SkBitmap::kIndex8_Config == config ?
                                colorTable : NULL)) {
        return false;
    }

    SkAutoLockPixels alp(*decodedBitmap);

    /* Add filler (or alpha) byte (before/after each RGB triplet) */
    if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) {
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
    }

    /* Turn on interlace handling.  REQUIRED if you are not using
    * png_read_image().  To see how to handle interlacing passes,
    * see the png_read_row() method below:
    */
    const int number_passes = interlace_type != PNG_INTERLACE_NONE ?
                        png_set_interlace_handling(png_ptr) : 1;

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

    if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) {
        for (int i = 0; i < number_passes; i++) {
            for (png_uint_32 y = 0; y < origHeight; y++) {
                uint8_t* bmRow = decodedBitmap->getAddr8(0, y);
                png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
            }
        }
    } else {
        SkScaledBitmapSampler::SrcConfig sc;
        int srcBytesPerPixel = 4;

        if (colorTable != NULL) {
            sc = SkScaledBitmapSampler::kIndex;
            srcBytesPerPixel = 1;
        } else if (hasAlpha) {
            sc = SkScaledBitmapSampler::kRGBA;
        } else {
            sc = SkScaledBitmapSampler::kRGBX;
        }

        /*  We have to pass the colortable explicitly, since we may have one
            even if our decodedBitmap doesn't, due to the request that we
            upscale png's palette to a direct model
         */
        SkAutoLockColors ctLock(colorTable);
        if (!sampler.begin(decodedBitmap, sc, doDither, ctLock.colors())) {
            return false;
        }
        const int height = decodedBitmap->height();

        if (number_passes > 1) {
            SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel);
            uint8_t* base = (uint8_t*)storage.get();
            size_t rb = origWidth * srcBytesPerPixel;

            for (int i = 0; i < number_passes; i++) {
                uint8_t* row = base;
                for (png_uint_32 y = 0; y < origHeight; y++) {
                    uint8_t* bmRow = row;
                    png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1);
                    row += rb;
                }
            }
            // now sample it
            base += sampler.srcY0() * rb;
            for (int y = 0; y < height; y++) {
                reallyHasAlpha |= sampler.next(base);
                base += sampler.srcDY() * rb;
            }
        } else {
            SkAutoMalloc storage(origWidth * srcBytesPerPixel);
            uint8_t* srcRow = (uint8_t*)storage.get();
            skip_src_rows(png_ptr, srcRow, sampler.srcY0());

            for (int y = 0; y < height; y++) {
                uint8_t* tmp = srcRow;
                png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1);
                reallyHasAlpha |= sampler.next(srcRow);
                if (y < height - 1) {
                    skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1);
                }
            }

            // skip the rest of the rows (if any)
            png_uint_32 read = (height - 1) * sampler.srcDY() +
                               sampler.srcY0() + 1;
            SkASSERT(read <= origHeight);
            skip_src_rows(png_ptr, srcRow, origHeight - read);
        }
    }

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

    if (0 != theTranspColor) {
        reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor);
    }
    decodedBitmap->setIsOpaque(!reallyHasAlpha);
    return true;
}
int main(int argc, char *argv[])
{
char filename1[MAXNAMELENGTH], filename2[MAXNAMELENGTH];
int idx, k, j;
FILE *fd, *lut=NULL;
byte *imgarr;
int userfill=-1;
int colorstyle=GRAYSCALE;
int red, green, blue, alpha;
int redarr[256], greenarr[256], bluearr[256], alphaarr[256];
unsigned char lutname[MAXNAMELENGTH];
unsigned char verbose=FALSE;

png_structp png_ptr;
png_infop info_ptr;
png_colorp png_palette;
png_colorp dest_pal;
unsigned char *png_trans;

png_structp in_png_ptr;
png_infop in_info_ptr;
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
FILE *fp;

png_uint_32  i, rowbytes;
byte  *image_data = NULL;
png_bytepp  row_pointers = NULL;
int bytesperpixel;
int found;

int num_not_found=0;
int rednotfound[MAX_NOT_FOUND], greennotfound[MAX_NOT_FOUND], bluenotfound[MAX_NOT_FOUND];
int return_code=0;

  filename1[0] = '\0';
  filename2[0] = '\0';
  lutname[0] = '\0';

  if (argc < 2) {
    fprintf(stderr, "Usage: RGBApng2Palpng [-v] -lut=<ColorMap file (must contain RGBA)> -fill=<LUT index value> -of=<output palette PNG file> <input RGBA PNG file>\n");
    exit(-1);
  }

  for (j=1; j<argc; j++)
    if ( strcmp(argv[j], "-v") == 0 ) {
      fprintf(stderr, "Verbose mode requested.\n");
      verbose = TRUE;
    }

  for (j=1; j<argc; j++) {
    if (strstr(argv[j], "-of=") == argv[j] ) {
        if ( sscanf(argv[j], "-of=%s", filename2) != 1 ) {
          fprintf(stderr, "Cannot read output file\n");
          exit(-1);
        }
        if (verbose)
          fprintf(stderr, "Output file: %s\n", filename2);
    } else if (strstr(argv[j], "-lut=") == argv[j] ) {
        if ( sscanf(argv[j], "-lut=%s", lutname) != 1 ) {
          fprintf(stderr, "Cannot parse LUT name\n");
          exit(-1);
        }
        if (verbose)
          fprintf(stderr, "Color LUT: %s\n", lutname);
        colorstyle = COLOR;
    } else if (strstr(argv[j], "-fill=") == argv[j] ) {
        if (sscanf(argv[j], "-fill=%d", &userfill) != 1) {
          fprintf(stderr, "Cannot read user fill value\n");
          exit(-1);
        }
        if ( userfill < 0 || userfill > 255 ) {
          fprintf(stderr, "User fill value must be between 0 and 255\n");
          exit(-1);
        }
        if (verbose)
          fprintf(stderr, "User fill value: %d\n", userfill);
    } else if ( strlen(filename2) == 0 &&
                strcmp(argv[j], "-") == 0 ) {
        strcpy(filename2, "stdout");
        if (verbose)
          fprintf(stderr, "Output file: %s\n", filename2);
    } else if ( strcmp(argv[j], "-v") != 0 ) {
        strcpy(filename1, argv[j]);
        if (verbose)
          fprintf(stderr, "Input file: %s\n", filename1);
    }
  }

  if ( strlen(filename1) == 0  ||
       strlen(filename2) == 0  ||
       strlen(lutname) == 0  ||
       userfill < 0 ) {
    fprintf(stderr, "Unable to get all arguments\n");
    exit(-1);
  }

  if ((fp = fopen(filename1, "rb")) == NULL) {
    fprintf(stderr, "Unable to open input file: %s\n", filename1);
    exit(-1);
  }

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

  if (in_png_ptr == NULL) {
    fclose(fp);
    fprintf(stderr, "Could not allocate PNG read struct\n");
    return (-1);
  }

  in_info_ptr = png_create_info_struct(in_png_ptr);
  if (in_info_ptr == NULL) {
    fclose(fp);
    png_destroy_read_struct(&in_png_ptr, png_infopp_NULL, png_infopp_NULL);
    fprintf(stderr, "Could not allocate input PNG info struct\n");
    return (-1);
  }

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

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

  png_read_info(in_png_ptr, in_info_ptr);

  png_get_IHDR(in_png_ptr, in_info_ptr, &width, &height, &bit_depth, &color_type,
       &interlace_type, int_p_NULL, int_p_NULL);

  if (verbose) {
    fprintf(stderr, "Width: %d\n", width);
    fprintf(stderr, "Height: %d\n", height);
    fprintf(stderr, "Bit Depth: %d\n", bit_depth);
    switch(color_type) {
          case 0:
            fprintf(stderr, "Color Type: Gray (0)\n");
            break;
          case 3:
            fprintf(stderr, "Color Type: Palette (3)\n");
            break;
          case 2:
            fprintf(stderr, "Color Type: RGB (2)\n");
            break;
          case 6:
            fprintf(stderr, "Color Type: RGB Alpha (6)\n");
            break;
          case 4:
            fprintf(stderr, "Color Type: Gray Alpha (4)\n");
            break;
          default:
            fprintf(stderr, "Unknown Color Type: %d\n", color_type);
    }
    switch(interlace_type) {
          case 0:
            fprintf(stderr, "Interlace Type: None (0)\n");
            break;
          case 1:
            fprintf(stderr, "Interlace Type: Adam7 (1)\n");
            break;
          default:
            fprintf(stderr, "Unknown Interlace Type: %d\n", interlace_type);
    }
  }

  rowbytes = png_get_rowbytes(in_png_ptr, in_info_ptr);

  if ( verbose ) fprintf(stderr, "Number of bytes per row: %d\n", rowbytes);

  if ((image_data = (byte *)malloc(rowbytes*height)) == NULL) {
    png_destroy_read_struct(&in_png_ptr, &in_info_ptr, NULL);
    exit(-1);
  }

  if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) {
    png_destroy_read_struct(&in_png_ptr, &in_info_ptr, NULL);
    free(image_data);
    image_data = NULL;
    exit(-1);
  }

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

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

  png_read_image(in_png_ptr, row_pointers);

  imgarr = (byte *) malloc(height * width * sizeof(byte));

  png_palette = (png_colorp)malloc( 256 * sizeof( png_color) );
  dest_pal = png_palette;
  if (colorstyle == GRAYSCALE)
    for (j=0; j<256; j++) {
      dest_pal->red = dest_pal->green = dest_pal->blue = j;
      dest_pal++;
      
      redarr[j] = greenarr[j] = bluearr[j] = j;
      alphaarr[j] = 255;
  } else {
    if ( (lut = fopen(lutname, "r")) != NULL ) {
    	if (strlen(lutname) > 4 && ((!strcmp(lutname + strlen(lutname) - 4, ".xml")))) {
    		fprintf(stderr, "Opening colormap file %s\n", lutname);

    		if (lut) {
    			int size = 1024, pos;
    			int c;
    			int j = 0;
    			char *buffer = (char *)malloc(size);
    			const char *entry_key = "ColorMapEntry";
    			const char *rgb_key = "rgb=";
    			const char *transparent_key = "transparent=";
    			const char *true_str = "\"true\"";
    			
    			do { // read all lines in file
					pos = 0;
					do { // read one line
					c = fgetc(lut);
					if(c != EOF) buffer[pos++] = (char)c;
						if(pos >= size - 1) { // increase buffer length - leave room for 0
							size *=2;
							buffer = (char*)realloc(buffer, size);
						}
					} while(c != EOF && c != '\n');
					buffer[pos] = 0;

					char *entry = strstr(buffer,entry_key);
					char *rgb = strstr(buffer,rgb_key);
					char *transparent = strstr(buffer,transparent_key);
					
					// GIBS colormap RGB values
					if (rgb != NULL && entry != NULL) {
	        			char rgb_string[11];
						int rgb_length = strlen(rgb);
						int rgb_pos = pos - rgb_length;
						memcpy(rgb_string, &buffer[rgb_pos+5], 11);
						rgb_string[11] = '\0';
						// break rgb string into int values
						int rgb_array[3];
						int i = 0;
						char *rgb_values = strtok(rgb_string, ",");
						while (rgb_values != NULL) {
							rgb_array[i++] = strtol(rgb_values,NULL,10);
							rgb_values = strtok(NULL, ",");
						}
						red = rgb_array[0]; green = rgb_array[1]; blue = rgb_array[2];
						dest_pal->red = red;
						dest_pal->green = green;
						dest_pal->blue = blue;

						alpha = strstr(transparent, true_str) != NULL ? 0 : 255;
						
						dest_pal++;
						redarr[j] = red;
						greenarr[j] = green;
						bluearr[j] = blue;
						alphaarr[j] = alpha;
						if ( verbose ) fprintf(stderr, "RGBA: %d %d %d %d \n", redarr[j], greenarr[j] , bluearr[j], alphaarr[j]);
						j++;
					}
    			} while(c != EOF);;
    		    fclose(lut);
    		    free(buffer);
    		}

    	} else {
			for (j=0; j<256; j++)
			  if ( fscanf(lut, "%d %d %d %d", &red, &green, &blue, &alpha) != 4 ) {
				  fprintf(stderr, "Cannot read color index %d in LUT file\n", j);
				  exit(-1);
			  } else {
				  dest_pal->red = red;
				  dest_pal->green = green;
				  dest_pal->blue = blue;
				  dest_pal++;
				  
				  redarr[j] = red;
				  greenarr[j] = green;
				  bluearr[j] = blue;
				  alphaarr[j] = alpha;
			  }
			fclose(lut);
    	}
    } else {
        fprintf(stderr, "Cannot open LUT file %s.\n", lutname);
        exit(-1);
    }
  }

  png_trans = (unsigned char *)malloc(256 * sizeof(unsigned char));
  for (j=0; j<256; j++) {
    png_trans[j] = alphaarr[j];
  }

  switch(color_type) {
    case(PNG_COLOR_TYPE_GRAY): bytesperpixel = 1;
                               break;
    case(PNG_COLOR_TYPE_PALETTE): bytesperpixel = 1;
                               break;
    case(PNG_COLOR_TYPE_RGB): bytesperpixel = 3;
                               break;
    case(PNG_COLOR_TYPE_RGB_ALPHA): bytesperpixel = 4;
                               break;
    case(PNG_COLOR_TYPE_GRAY_ALPHA): bytesperpixel = 2;
                               break;
    default:
            fprintf(stderr, "Unknown Color Type: %d\n", color_type);
            exit(-1);
  }

  if ( color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_RGB_ALPHA ) {
    fprintf(stderr, "Color Type must be RGB or RGBA.\n");
    exit(-1);
  }
  
  if ( verbose ) fprintf(stderr, "Bytes per Pixel: %d\n", bytesperpixel);

  for (i = 0;  i < height;  i++) {
    for (j = 0;  j < width;  j++) {

      idx = i*width+j;
      red = image_data[i*width*bytesperpixel+j*bytesperpixel];
      green = image_data[i*width*bytesperpixel+j*bytesperpixel+1];
      blue = image_data[i*width*bytesperpixel+j*bytesperpixel+2];
  
      found = FALSE;
      for (k = 0;  k < 256;  k++) {

        if ( red == redarr[k] &&
             green == greenarr[k] &&
             blue == bluearr[k] ) {
              imgarr[idx] = (unsigned char) k;
              found = TRUE;
              break;
        }
      }
      if ( !found ) {
        imgarr[idx] = (unsigned char) userfill;
        found = FALSE;
        if ( num_not_found < MAX_NOT_FOUND ) {
          for (k = 0; k < num_not_found; k++) {
            if ( red == rednotfound[k] &&
                 green == greennotfound[k] &&
                 blue == bluenotfound[k] ) {
              found = TRUE;
              break;
            }
          }
          if ( !found ) {
            rednotfound[num_not_found] = red;
            greennotfound[num_not_found] = green;
            bluenotfound[num_not_found] = blue;
            num_not_found++;
          }
        }
      }
    }
  }

  if ( num_not_found > 0 ) {
    return_code = num_not_found;
    fprintf(stderr, "%d Colors in image not found in color table\n", num_not_found);
    for (k = 0; k < num_not_found; k++) {
      fprintf(stderr, "%3d %3d %3d\n", rednotfound[k], greennotfound[k], bluenotfound[k]);
    }
  }

  // Done with the read, clean up
  free(row_pointers);
  row_pointers = NULL;

  png_read_end(in_png_ptr, NULL);
  
  free(image_data);
  image_data = NULL;

  fclose(fp);

  // Start the write

  if (strcmp(filename2, "stdout") == 0)
    fd = stdout;
  else if ( (fd = fopen(filename2, "wb")) == NULL ) {
    fprintf(stderr, "Cannot open file %s.\n", filename2);
    exit(-1);
  }

  // Initialize write structure
  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (png_ptr == NULL) {
    fprintf(stderr, "Could not allocate PNG write struct\n");
    exit(-1);
  }

  // Initialize info structure
  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL) {
    fprintf(stderr, "Could not allocate PNG info struct\n");
    exit(-1);
  }

  if (setjmp(png_jmpbuf(png_ptr))) {
    fprintf(stderr, "Error during PNG init_io\n");
    exit(-1);
  }

  png_init_io(png_ptr, fd);

  if (setjmp(png_jmpbuf(png_ptr))) {
    fprintf(stderr, "Error during PNG set header\n");
    exit(-1);
  }

  // Write header (8 bit colour depth)
  png_set_IHDR(png_ptr, info_ptr, width, height,
         8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
         PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

  if (setjmp(png_jmpbuf(png_ptr))) {
    fprintf(stderr, "Error during PNG set pallette\n");
    exit(-1);
  }

  png_set_PLTE(png_ptr, info_ptr, png_palette, 256);

  if (setjmp(png_jmpbuf(png_ptr))) {
    fprintf(stderr, "Error during PNG set transparency\n");
    exit(-1);
  }

  png_set_tRNS(png_ptr, info_ptr, png_trans, 256, NULL);

  if (setjmp(png_jmpbuf(png_ptr))) {
    fprintf(stderr, "Error during PNG write info\n");
    exit(-1);
  }

  png_write_info(png_ptr, info_ptr);

  if (setjmp(png_jmpbuf(png_ptr))) {
    fprintf(stderr, "Error during PNG write row\n");
    exit(-1);
  }

  for (k=0; k<height; k++) {
    idx = k * width;
    png_write_row(png_ptr, &imgarr[idx]);
  }

  if (setjmp(png_jmpbuf(png_ptr))) {
    fprintf(stderr, "Error during PNG write end\n");
    exit(-1);
  }

  // End write
  png_write_end(png_ptr, NULL);

  fclose(fd);
  free(imgarr);
  free(png_palette);
  free(png_trans);

  if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
  if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL);

  return return_code;

}
Example #10
0
int fh_png_load(const char *name, unsigned char *buffer, int x, int y)
{
	static const png_color_16 my_background = {0, 0, 0, 0, 0};

	png_structp png_ptr;
	png_infop info_ptr;
	png_uint_32 width, height;
	unsigned int i;
	int bit_depth, color_type, interlace_type;
	int number_passes, pass;
	png_byte * fbptr;
	FILE * fh;

	if (!(fh = fopen(name, "rb")))
		return(FH_ERROR_FILE);

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL) 
		return(FH_ERROR_FORMAT);
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL)
	{
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		fclose(fh); 
		return(FH_ERROR_FORMAT);
	}

	if (setjmp(png_ptr->jmpbuf))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		fclose(fh); 
		return(FH_ERROR_FORMAT);
	}

	png_init_io(png_ptr, fh);

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

	if (color_type == PNG_COLOR_TYPE_PALETTE)
	{
		png_set_palette_to_rgb(png_ptr);
		png_set_background(png_ptr, (png_color_16 *)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
		/* other possibility for png_set_background: use png_get_bKGD */
	}

	if (color_type == PNG_COLOR_TYPE_GRAY        ||
	    color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
	{
		png_set_gray_to_rgb(png_ptr);
		png_set_background(png_ptr, (png_color_16 *)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
	}

	if (color_type & PNG_COLOR_MASK_ALPHA)
		png_set_strip_alpha(png_ptr);

	if (bit_depth < 8)
		png_set_packing(png_ptr);

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

/* on Intel PC ?:
	if (bit_depth == 16)
		png_set_swap(png_ptr);
*/

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

	if (width * 3 != png_get_rowbytes(png_ptr, info_ptr))
	{
		printf("[png.cpp]: Error processing %s - please report (including image).\n", name);
		return(FH_ERROR_FORMAT);
	}

	for(pass = 0; pass < number_passes; pass++)
	{
		fbptr = (png_byte *)buffer;
		for (i = 0; i < height; i++, fbptr += width * 3)
		{
			png_read_row(png_ptr, fbptr, NULL);
		}
	}
	png_read_end(png_ptr, info_ptr);
	png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
	fclose(fh);
	return(FH_ERROR_OK);
}
Example #11
0
void t_RenderClass::loadTexture(int target, const char *filename)
{
   FILE *theFile = fopen(filename,"rb");

   if (!theFile)
   {
      LOGI("Fopen failed");
      exit(1);
   }

   char header[8];
   fread(header,1,8,theFile);

   if (ferror(theFile))
   {
      LOGI("Fread failed");
      exit(1);
   }

   if (png_sig_cmp((png_byte *) header,0,8))
   {
      LOGI("The file is not a png\n");
      exit(1);
   }

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

   if (!png_ptr)
   {
      printf("Failed initialization of png_ptr\n");
      exit(1);
   }

   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);
      printf("Info ptr creation failed\n");
      exit(1);
   }

   png_infop end_info = png_create_info_struct(png_ptr);

   if (!end_info)
   {
      png_destroy_read_struct(&png_ptr, &info_ptr,
                              (png_infopp)NULL);
      printf("Info ptr creation failed\n");
      exit(1);
   }

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

   png_read_info(png_ptr,info_ptr);
   int width = png_get_image_width(png_ptr,info_ptr);
   int height = png_get_image_width(png_ptr,info_ptr);
   int depth = png_get_bit_depth(png_ptr,info_ptr);
   int rowbytes = png_get_rowbytes(png_ptr, info_ptr);

   png_byte* image_data = new png_byte[rowbytes * height];

   png_bytep *row_pointers = new png_bytep [height];

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


   LOGI("I have read the image with width %d, height %d, depth %d, rowbytes %d\n",width,height,depth,rowbytes);

   png_read_image(png_ptr,row_pointers);

   png_read_end(png_ptr,NULL);
   png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);


   glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,image_data);
   checkGlError("glClear");

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   checkGlError("glClear");

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   checkGlError("glClear");

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   checkGlError("glClear");

   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   checkGlError("glClear");
}
Example #12
0
uint8_t* ImageDecoder::decodePNGImpl(png_structp pngPtr, uint32_t* width, uint32_t* height)
{
	png_bytep* rowPtrs = NULL;
	uint8_t* outData = NULL;
	png_infop infoPtr = png_create_info_struct(pngPtr);
	if (!infoPtr)
	{
		LOG(LOG_ERROR,"Couldn't initialize png info struct");
		png_destroy_read_struct(&pngPtr, (png_infopp)0, (png_infopp)0);
		return NULL;
	}

	if (setjmp(png_jmpbuf(pngPtr)))
	{
		png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0);
		if (rowPtrs != NULL) delete [] rowPtrs;
		if (outData != NULL) delete [] outData;

		LOG(LOG_ERROR,"error during reading of the png file");

		return NULL;
	}

	png_read_info(pngPtr, infoPtr);

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

	//bits per CHANNEL! note: not per pixel!
	png_uint_32 bitdepth = png_get_bit_depth(pngPtr, infoPtr);
	//Number of channels
	png_uint_32 channels = png_get_channels(pngPtr, infoPtr);
	//Color type. (RGB, RGBA, Luminance, luminance alpha... palette... etc)
	png_uint_32 color_type = png_get_color_type(pngPtr, infoPtr);

	// Transform everything into 24 bit RGB
	switch (color_type)
	{
		case PNG_COLOR_TYPE_PALETTE:
			png_set_palette_to_rgb(pngPtr);
			// png_set_palette_to_rgb wil convert into 32
			// bit, but we don't want the alpha
			png_set_strip_alpha(pngPtr);
			break;
		case PNG_COLOR_TYPE_GRAY:
			if (bitdepth < 8)
				png_set_gray_to_rgb(pngPtr);
			break;
	}

	if (bitdepth == 16)
	{
		png_set_strip_16(pngPtr);
	}

	if (channels > 3)
	{
		LOG(LOG_NOT_IMPLEMENTED, "Alpha channel not supported in PNG");
		png_set_strip_alpha(pngPtr);
	}

	// Update the infoPtr to reflect the transformations set
	// above. Read new values by calling png_get_* again.
	png_read_update_info(pngPtr, infoPtr);

	//bitdepth = png_get_bit_depth(pngPtr, infoPtr);
	//color_type = png_get_color_type(pngPtr, infoPtr);

	channels = png_get_channels(pngPtr, infoPtr);
	if (channels != 3)
	{
		// Should never get here because of the
		// transformations
		LOG(LOG_NOT_IMPLEMENTED, "Unexpected number of channels in PNG!");

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

		return NULL;
	}

	const unsigned int stride = png_get_rowbytes(pngPtr, infoPtr);

	outData = new uint8_t[(*height) * stride];
	rowPtrs = new png_bytep[(*height)];
	for (size_t i = 0; i < (*height); i++)
	{
		rowPtrs[i] = (png_bytep)outData + i* stride;
	}

	png_read_image(pngPtr, rowPtrs);
	png_read_end(pngPtr, NULL);
	png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0);
	delete[] (png_bytep)rowPtrs;

	return outData;
}
Example #13
0
unsigned char *read_png_file(const char* file_name, int *width, int *height,
                             int *stride) {

   png_byte color_type;
   png_byte bit_depth;

   png_structp png_ptr;
   png_infop info_ptr;
   int number_of_passes;
   png_bytep* row_pointers;
   int y;

   unsigned char header[8];   // 8 is the maximum size that can be checked
   unsigned char *buf;
   FILE *fp;

   /* open file and test for it being a png */
   fp = fopen(file_name, "rb");
   if (!fp) return NULL;

   fread(header, 1, 8, fp);
   if (png_sig_cmp(header, 0, 8)) {
      roadmap_log (ROADMAP_ERROR,
         "[read_png_file] File %s is not recognized as a PNG file",
         file_name);
      fclose(fp);
      return NULL;
   }

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

   if (!png_ptr) {
      roadmap_log (ROADMAP_ERROR,
                  "[read_png_file] png_create_read_struct failed");
      fclose(fp);
      return NULL;
   }

   info_ptr = png_create_info_struct(png_ptr);

   if (!info_ptr) {
      roadmap_log (ROADMAP_ERROR,
            "[read_png_file] png_create_info_struct failed");
      fclose(fp);
      return NULL;
   }

   if (setjmp(png_jmpbuf(png_ptr))) {
      roadmap_log (ROADMAP_ERROR, "[read_png_file] Error during init_io");
      fclose(fp);
      return NULL;
   }

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

   png_read_info(png_ptr, info_ptr);

   *width = info_ptr->width;
   *height = info_ptr->height;
   *stride = info_ptr->rowbytes;
   color_type = info_ptr->color_type;
   bit_depth = info_ptr->bit_depth;

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

   /* read file */
   if (setjmp(png_jmpbuf(png_ptr))) {
      roadmap_log (ROADMAP_ERROR, "[read_png_file] Error during read_image");
      fclose(fp);
      return NULL;
   }

   row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * *height);
   buf = malloc (*height * info_ptr->rowbytes);
   for (y=0; y<*height; y++) {
      row_pointers[y] = (png_byte*) (buf + y * info_ptr->rowbytes);
   }

   png_read_image(png_ptr, row_pointers);
   png_read_end(png_ptr, NULL);
   png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
   free (row_pointers);

   fclose(fp);

   return buf;
}
Example #14
0
unsigned char *readpng_get_image( png_store* pngdata)
{
    double  gamma;
    png_uint_32  i, rowbytes;
    png_bytepp  row_pointers = NULL;
    png_structp png_ptr = pngdata->png_ptr;
    png_infop info_ptr = pngdata->info_ptr;
    int color_type = pngdata->colortype;
    int bit_depth = pngdata->bitdepth;
    int height = pngdata->height;
    double display_exponent = DISPLAY_EXPONENT;
    int *pChannels = &(pngdata->channels);
    unsigned long *pRowbytes = &(pngdata->rowbytes);
    unsigned char * image_data;
    /* setjmp() must be called in every function that calls a PNG-reading
     * libpng function */

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

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

    if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_expand(png_ptr);
    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
        png_set_expand(png_ptr);
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_expand(png_ptr);
    if (bit_depth == 16)
        png_set_strip_16(png_ptr);
    if (color_type == PNG_COLOR_TYPE_GRAY ||
        color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);


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

    if (png_get_gAMA(png_ptr, info_ptr, &gamma))
        png_set_gamma(png_ptr, display_exponent, gamma);


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

    png_read_update_info(png_ptr, info_ptr);

    *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    *pChannels = (int)png_get_channels(png_ptr, info_ptr);

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

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

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

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

    png_read_image(png_ptr, row_pointers);


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

//    free(row_pointers);
//    row_pointers = NULL;

    png_read_end(png_ptr, NULL);

    pngdata->image_data = image_data;
    pngdata->row_pointers =  row_pointers;

    return image_data;
}
Example #15
0
void PNGAPI
png_read_png(png_structp png_ptr, png_infop info_ptr,
                           int transforms,
                           voidp params)
{
   int row;

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

   /* png_read_info() gives us all of the information from the
    * PNG file before the first IDAT (image data chunk).
    */
   png_read_info(png_ptr, info_ptr);
   if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
      png_error(png_ptr, "Image is too high to process with png_read_png()");

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

   transforms = transforms; /* quiet compiler warnings */
   params = params;

}
Example #16
0
int
png_include_image (pdf_ximage *ximage, FILE *png_file)
{
  pdf_obj  *stream;
  pdf_obj  *stream_dict;
  pdf_obj  *colorspace, *mask, *intent;
  png_bytep stream_data_ptr;
  int       trans_type;
  ximage_info info;
  /* Libpng stuff */
  png_structp png_ptr;
  png_infop   png_info_ptr;
  png_byte    bpc, color_type;
  png_uint_32 width, height, rowbytes;

  pdf_ximage_init_image_info(&info);

  stream      = NULL;
  stream_dict = NULL;
  colorspace  = mask = intent = NULL;

  rewind (png_file);
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, warn);
  if (png_ptr == NULL ||
      (png_info_ptr = png_create_info_struct (png_ptr)) == NULL) {
    WARN("%s: Creating Libpng read/info struct failed.", PNG_DEBUG_STR);
    if (png_ptr)
      png_destroy_read_struct(&png_ptr, NULL, NULL);
    return -1;
  }

#if PNG_LIBPNG_VER >= 10603
  /* ignore possibly incorrect CMF bytes */
  png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON);
#endif

  /* Inititializing file IO. */
  png_init_io (png_ptr, png_file);

  /* Read PNG info-header and get some info. */
  png_read_info(png_ptr, png_info_ptr);
  color_type = png_get_color_type  (png_ptr, png_info_ptr);
  width      = png_get_image_width (png_ptr, png_info_ptr);
  height     = png_get_image_height(png_ptr, png_info_ptr);
  bpc        = png_get_bit_depth   (png_ptr, png_info_ptr);

  /* We do not need 16-bpc color. Ask libpng to convert down to 8-bpc. */
  if (bpc > 8) {
    png_set_strip_16(png_ptr);
    bpc = 8;
  }
  /* Ask libpng to gamma-correct.
   * It is wrong to assume screen gamma value 2.2 but...
   * We do gamma correction here only when uncalibrated color space is used. 
   */
  if (!png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP) &&
      !png_get_valid(png_ptr, png_info_ptr, PNG_INFO_sRGB) &&
      !png_get_valid(png_ptr, png_info_ptr, PNG_INFO_cHRM) &&
      !png_get_valid(png_ptr, png_info_ptr, PNG_INFO_sRGB) &&
       png_get_valid(png_ptr, png_info_ptr, PNG_INFO_gAMA)) {
    double G = 1.0;
    png_get_gAMA (png_ptr, png_info_ptr, &G);
    png_set_gamma(png_ptr, 2.2, G);
  }

  trans_type = check_transparency(png_ptr, png_info_ptr);
  /* check_transparency() does not do updata_info() */
  png_read_update_info(png_ptr, png_info_ptr);
  rowbytes = png_get_rowbytes(png_ptr, png_info_ptr);

  /* Values listed below will not be modified in the remaining process. */
  info.width  = width;
  info.height = height;
  info.bits_per_component = bpc;

  if (compat_mode)
    info.xdensity = info.ydensity = 72.0 / 100.0;
  else
  {
    png_uint_32 xppm = png_get_x_pixels_per_meter(png_ptr, png_info_ptr);
    png_uint_32 yppm = png_get_y_pixels_per_meter(png_ptr, png_info_ptr);

    if (xppm > 0)
      info.xdensity = 72.0 / 0.0254 / xppm;
    if (yppm > 0)
      info.ydensity = 72.0 / 0.0254 / yppm;
  }

  stream      = pdf_new_stream (STREAM_COMPRESS);
  stream_dict = pdf_stream_dict(stream);

  stream_data_ptr = (png_bytep) NEW(rowbytes*height, png_byte);
  read_image_data(png_ptr, stream_data_ptr, height, rowbytes);

  /* Non-NULL intent means there is valid sRGB chunk. */
  intent = get_rendering_intent(png_ptr, png_info_ptr);
  if (intent)
    pdf_add_dict(stream_dict, pdf_new_name("Intent"), intent);

  switch (color_type) {
  case PNG_COLOR_TYPE_PALETTE:

    colorspace = create_cspace_Indexed(png_ptr, png_info_ptr);

    switch (trans_type) {
    case PDF_TRANS_TYPE_BINARY:
      /* Color-key masking */
      mask = create_ckey_mask(png_ptr, png_info_ptr);
      break;
    case PDF_TRANS_TYPE_ALPHA:
      /* Soft mask */
      mask = create_soft_mask(png_ptr, png_info_ptr, stream_data_ptr, width, height);
      break;
    default:
      /* Nothing to be done here.
       * No tRNS chunk or image already composited with background color.
       */
      break;
    }
    break;
  case PNG_COLOR_TYPE_RGB:
  case PNG_COLOR_TYPE_RGB_ALPHA:

    if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP))
      colorspace = create_cspace_ICCBased(png_ptr, png_info_ptr);
    else if (intent) {
      colorspace = create_cspace_sRGB(png_ptr, png_info_ptr);
    } else {
      colorspace = create_cspace_CalRGB(png_ptr, png_info_ptr);
    }
    if (!colorspace)
      colorspace = pdf_new_name("DeviceRGB");

    switch (trans_type) {
    case PDF_TRANS_TYPE_BINARY:
      mask = create_ckey_mask(png_ptr, png_info_ptr);
      break;
    /* rowbytes changes 4 to 3 at here */
    case PDF_TRANS_TYPE_ALPHA:
      mask = strip_soft_mask(png_ptr, png_info_ptr,
                             stream_data_ptr, &rowbytes, width, height);
      break;
    default:
      mask = NULL;
    }
    info.num_components = 3;
    break;

  case PNG_COLOR_TYPE_GRAY:
  case PNG_COLOR_TYPE_GRAY_ALPHA:

    if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP))
      colorspace = create_cspace_ICCBased(png_ptr, png_info_ptr);
    else if (intent) {
      colorspace = create_cspace_sRGB(png_ptr, png_info_ptr);
    } else {
      colorspace = create_cspace_CalGray(png_ptr, png_info_ptr);
    }
    if (!colorspace)
      colorspace = pdf_new_name("DeviceGray");

    switch (trans_type) {
    case PDF_TRANS_TYPE_BINARY:
      mask = create_ckey_mask(png_ptr, png_info_ptr);
      break;
    case PDF_TRANS_TYPE_ALPHA:
      mask = strip_soft_mask(png_ptr, png_info_ptr,
                             stream_data_ptr, &rowbytes, width, height);
      break;
    default:
      mask = NULL;
    }
    info.num_components = 1;
    break;

  default:
    WARN("%s: Unknown PNG colortype %d.", PNG_DEBUG_STR, color_type);
  }
  pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace);

  pdf_add_stream(stream, stream_data_ptr, rowbytes*height);
  RELEASE(stream_data_ptr);

  if (mask) {
    if (trans_type == PDF_TRANS_TYPE_BINARY)
      pdf_add_dict(stream_dict, pdf_new_name("Mask"), mask);
    else if (trans_type == PDF_TRANS_TYPE_ALPHA) {
      pdf_add_dict(stream_dict, pdf_new_name("SMask"), pdf_ref_obj(mask));
      pdf_release_obj(mask);
    } else {
      WARN("%s: Unknown transparency type...???", PNG_DEBUG_STR);
      pdf_release_obj(mask);
    }
  }

  /* Finally read XMP Metadata
   * See, XMP Specification Part 3, Storage in Files
   * http://www.adobe.com/jp/devnet/xmp.html
   *
   * We require libpng version >= 1.6.14 since prior versions
   * of libpng had a bug that incorrectly treat the compression
   * flag of iTxt chunks.
   */
#if PNG_LIBPNG_VER >= 10614
  if (pdf_get_version() >= 4) {
    png_textp text_ptr;
    pdf_obj  *XMP_stream, *XMP_stream_dict;
    int       i, num_text;
    int       have_XMP = 0;

    num_text = png_get_text(png_ptr, png_info_ptr, &text_ptr, NULL);
    for (i = 0; i < num_text; i++) {
      if (!memcmp(text_ptr[i].key, "XML:com.adobe.xmp", 17)) {
        /* XMP found */
        if (text_ptr[i].compression != PNG_ITXT_COMPRESSION_NONE ||
            text_ptr[i].itxt_length == 0)
          WARN("%s: Invalid value(s) in iTXt chunk for XMP Metadata.", PNG_DEBUG_STR);
        else if (have_XMP)
          WARN("%s: Multiple XMP Metadata. Don't know how to treat it.", PNG_DEBUG_STR);
        else {
          /* We compress XMP metadata for included images here.
           * It is not recommended to compress XMP metadata for PDF documents but
           * we compress XMP metadata for included images here to avoid confusing
           * application programs that only want PDF document global XMP metadata
           * and scan for that.
           */
          XMP_stream = pdf_new_stream(STREAM_COMPRESS);
          XMP_stream_dict = pdf_stream_dict(XMP_stream);
          pdf_add_dict(XMP_stream_dict,
                       pdf_new_name("Type"), pdf_new_name("Metadata"));
          pdf_add_dict(XMP_stream_dict,
                       pdf_new_name("Subtype"), pdf_new_name("XML"));
          pdf_add_stream(XMP_stream, text_ptr[i].text, text_ptr[i].itxt_length);
          pdf_add_dict(stream_dict,
                       pdf_new_name("Metadata"), pdf_ref_obj(XMP_stream));
          pdf_release_obj(XMP_stream);
          have_XMP = 1;
        }
      }
    }
  }
#endif /* PNG_LIBPNG_VER */

  png_read_end(png_ptr, NULL);

  /* Cleanup */
  if (png_info_ptr)
    png_destroy_info_struct(png_ptr, &png_info_ptr);
  if (png_ptr)
    png_destroy_read_struct(&png_ptr, NULL, NULL);

  pdf_ximage_set_image(ximage, &info, stream);

  return 0;
}
Example #17
0
//Called in the gl thread
static void
gst_gl_bumper_init_resources (GstGLFilter * filter)
{
  GstGLBumper *bumper = GST_GL_BUMPER (filter);
  GstGLDisplay *display = filter->display;

  png_structp png_ptr;
  png_infop info_ptr;
  guint sig_read = 0;
  png_uint_32 width = 0;
  png_uint_32 height = 0;
  gint bit_depth = 0;
  gint color_type = 0;
  gint interlace_type = 0;
  png_FILE_p fp = NULL;
  guint y = 0;
  guchar *raw_data = NULL;
  guchar **rows = NULL;
  png_byte magic[8];
  gint n_read;

  if (!filter->display)
    return;

  /* BEGIN load png image file */

  if ((fp = fopen (bumper->location, "rb")) == NULL)
    LOAD_ERROR ("file not found");

  /* Read magic number */
  n_read = fread (magic, 1, sizeof (magic), fp);
  if (n_read != sizeof (magic)) {
    fclose (fp);
    LOAD_ERROR ("can't read PNG magic number");
  }

  /* Check for valid magic number */
  if (png_sig_cmp (magic, 0, sizeof (magic))) {
    fclose (fp);
    LOAD_ERROR ("not a valid PNG image");
  }

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

  if (png_ptr == NULL) {
    fclose (fp);
    LOAD_ERROR ("failed to initialize the png_struct");
  }

  png_set_error_fn (png_ptr, NULL, NULL, user_warning_fn);

  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);
    LOAD_ERROR ("failed to initialize the memory for image information");
  }

  png_init_io (png_ptr, fp);

  png_set_sig_bytes (png_ptr, sig_read);

  png_read_info (png_ptr, info_ptr);

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

  if (color_type != PNG_COLOR_TYPE_RGB) {
    fclose (fp);
    png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL);
    LOAD_ERROR ("color type is not rgb");
  }

  raw_data = (guchar *) malloc (sizeof (guchar) * width * height * 3);

  rows = (guchar **) malloc (sizeof (guchar *) * height);

  for (y = 0; y < height; ++y)
    rows[y] = (guchar *) (raw_data + y * width * 3);

  png_read_image (png_ptr, rows);

  free (rows);

  png_read_end (png_ptr, info_ptr);
  png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL);
  fclose (fp);

  /* END load png image file */

  bumper->bumpmap_width = width;
  bumper->bumpmap_height = height;

  glGenTextures (1, &bumper->bumpmap);
  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, bumper->bumpmap);
  glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
      bumper->bumpmap_width, bumper->bumpmap_height, 0,
      GL_RGB, GL_UNSIGNED_BYTE, raw_data);

  free (raw_data);
}
Example #18
0
bool  PngDecoder::readData( Mat& img )
{
    volatile bool result = false;
    AutoBuffer<uchar*> _buffer(m_height);
    uchar** buffer = _buffer;
    int color = img.channels() > 1;

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

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

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

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

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

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

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

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

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

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

            result = true;
        }
    }

    close();
    return result;
}
Example #19
0
static int readpng( FILE *f, GrContext *grc, int use_alpha )
{
  png_struct *png_ptr = NULL;
  png_info *info_ptr = NULL;
  png_byte buf[8];
  png_byte *png_pixels = NULL;
  png_byte **row_pointers = NULL;
  png_byte *pix_ptr = NULL;
  png_uint_32 row_bytes;
  png_uint_32 width;
  png_uint_32 height;
  int bit_depth;
  int color_type;
  int alpha_present;
  int i, x, y, r, g, b;
  int alpha = 0, ro, go, bo;
  int maxwidth, maxheight;
  GrColor *pColors = NULL;

  /* is it a PNG file? */
  if( fread( buf,1,8,f ) != 8 ) return -1;
  if( ! png_check_sig( buf,8 ) ) return -1;

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

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

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

  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,&width,&height,&bit_depth,
                &color_type,NULL,NULL,NULL);

  /* tell libpng to strip 16 bit/color files down to 8 bits/color */
  if( bit_depth == 16 )
    png_set_strip_16( png_ptr );
  /* expand paletted colors into true RGB triplets */
  if( color_type == PNG_COLOR_TYPE_PALETTE )
    png_set_expand( png_ptr );
  /* expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
  if( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 )
    png_set_expand( png_ptr );
  /* expand paletted or RGB images with transparency to full alpha channels
     so the data will be available as RGBA quartets. */
  if( png_get_valid( png_ptr,info_ptr,PNG_INFO_tRNS ) )
    png_set_expand( png_ptr );
  /* transform grayscale images into rgb */
  if( color_type == PNG_COLOR_TYPE_GRAY ||
      color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
    png_set_gray_to_rgb( png_ptr );

  /* we don't do gamma correction by now */

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

  if( color_type == PNG_COLOR_TYPE_RGB )
    alpha_present = 0;
  else if( color_type == PNG_COLOR_TYPE_RGB_ALPHA )
    alpha_present = 1;
  else{
    png_destroy_read_struct( &png_ptr,&info_ptr,NULL );
    return -1;
    }

  row_bytes = png_get_rowbytes( png_ptr,info_ptr );

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

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

  for( i=0; i<height; i++ )
    row_pointers[i] = png_pixels + i * row_bytes;

  png_read_image (png_ptr, row_pointers);

  png_read_end (png_ptr, info_ptr);

  png_destroy_read_struct( &png_ptr,&info_ptr,NULL );

  /* write data to context */
  maxwidth = (width > GrSizeX()) ? GrSizeX() : width;
  maxheight = (height > GrSizeY()) ? GrSizeY() : height;

  pColors = malloc( maxwidth * sizeof(GrColor) );
  if( pColors == NULL ){
    free( row_pointers );
    row_pointers = NULL;
    free( png_pixels );
    png_pixels = NULL;
    return -1;
    }

  for( y=0; y<maxheight; y++ ){
    pix_ptr = row_pointers[y];
    if( alpha_present && use_alpha ){
      memcpy( pColors,GrGetScanline( 0,maxwidth-1,y ),
              sizeof(GrColor)*maxwidth );
      }
    for( x=0; x<width; x++ ){
      r = *pix_ptr++;
      g = *pix_ptr++;
      b = *pix_ptr++;
      alpha = 0;
      if( alpha_present )
        alpha = *pix_ptr++;
      if( x < maxwidth ){
        if( alpha_present && use_alpha ){
          if (alpha == 0) {
            GrQueryColor( pColors[x],&r,&g,&b );
          }
          else if (alpha != 255) { // if a==255, rgb not modified
            float f1, f2;
            f1 = (alpha/255.0);
            f2 = ((255-alpha)/255.0);
            GrQueryColor( pColors[x],&ro,&go,&bo );
            r = (r * f1) + (ro * f2);
            g = (g * f1) + (go * f2);
            b = (b * f1) + (bo * f2);
          }
        }
        pColors[x] = GrAllocColor( r,g,b );
        }
      }
    GrPutScanline( 0,maxwidth-1,y,pColors,GrWRITE );
    }

  if( pColors) free( pColors );
  if( row_pointers ) free( row_pointers );
  if( png_pixels ) free( png_pixels );

  return 0;
}
Example #20
0
struct ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags)
{
	struct ImBuf *ibuf = NULL;
	png_structp png_ptr;
	png_infop info_ptr;
	unsigned char *pixels = NULL;
	png_bytepp row_pointers = NULL;
	png_uint_32 width, height;
	int bit_depth, color_type;
	PNGReadStruct ps;

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

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

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

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

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

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

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

	// png_set_sig_bytes(png_ptr, 8);

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

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

	bytesperpixel = png_get_channels(png_ptr, info_ptr);

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

	if (ibuf) {
		ibuf->ftype = PNG;
		ibuf->profile = IB_PROFILE_SRGB;

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

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

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

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

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

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

		png_read_image(png_ptr, row_pointers);

		// copy image data

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

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

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

		png_read_end(png_ptr, info_ptr);
	}

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

	return(ibuf);
}
Example #21
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	png_structp png_ptr;
	png_infop info_ptr;
	png_uint_32 width, height;
	png_colorp png_palette;
	int color_type, palette_entries;
	int bit_depth, pixel_depth;		// pixel_depth = bit_depth * channels

	FIBITMAP *dib = NULL;
	RGBQUAD *palette = NULL;		// pointer to dib palette
	png_bytepp  row_pointers = NULL;
	int i;

    fi_ioStructure fio;
    fio.s_handle = handle;
	fio.s_io = io;
    
	if (handle) {
		try {		
			// check to see if the file is in fact a PNG file

			unsigned char png_check[PNG_BYTES_TO_CHECK];

			io->read_proc(png_check, PNG_BYTES_TO_CHECK, 1, handle);

			if (png_sig_cmp(png_check, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0)
				return NULL;	// Bad signature
			
			// create the chunk manage structure

			png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler);

			if (!png_ptr)
				return NULL;			

			// create the info structure

		    info_ptr = png_create_info_struct(png_ptr);

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

			// init the IO

			png_set_read_fn(png_ptr, &fio, _ReadProc);

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

			// because we have already read the signature...

			png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);

			// read the IHDR chunk

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

			// get image data type (assume standard image type)

			FREE_IMAGE_TYPE image_type = FIT_BITMAP;
			if (bit_depth == 16) {
				if ((pixel_depth == 16) && (color_type == PNG_COLOR_TYPE_GRAY)) {
					image_type = FIT_UINT16;
#ifndef FREEIMAGE_BIGENDIAN
					// turn on 16 bit byte swapping
					png_set_swap(png_ptr);
#endif
				} 
				else if ((pixel_depth == 48) && (color_type == PNG_COLOR_TYPE_RGB)) {
					image_type = FIT_RGB16;
#ifndef FREEIMAGE_BIGENDIAN
					// turn on 16 bit byte swapping
					png_set_swap(png_ptr);
#endif		
				} else {
					// tell libpng to strip 16 bit/color files down to 8 bits/color
					png_set_strip_16(png_ptr);
					bit_depth = 8;
				}
			}


			// set some additional flags

			switch(color_type) {
				case PNG_COLOR_TYPE_RGB:
				case PNG_COLOR_TYPE_RGB_ALPHA:
#ifndef FREEIMAGE_BIGENDIAN
					// flip the RGB pixels to BGR (or RGBA to BGRA)

					if(image_type == FIT_BITMAP)
						png_set_bgr(png_ptr);
#endif
					break;

				case PNG_COLOR_TYPE_PALETTE:
					// expand palette images to the full 8 bits from 2 bits/pixel

					if (pixel_depth == 2) {
						png_set_packing(png_ptr);
						pixel_depth = 8;
					}					

					break;

				case PNG_COLOR_TYPE_GRAY:
					// expand grayscale images to the full 8 bits from 2 bits/pixel

					if (pixel_depth == 2) {
						png_set_expand(png_ptr);
						pixel_depth = 8;
					}

					break;

				case PNG_COLOR_TYPE_GRAY_ALPHA:
					// expand 8-bit greyscale + 8-bit alpha to 32-bit

					png_set_gray_to_rgb(png_ptr);
#ifndef FREEIMAGE_BIGENDIAN
					// flip the RGBA pixels to BGRA

					png_set_bgr(png_ptr);
#endif
					pixel_depth = 32;

					break;

				default:
					throw "PNG format not supported";
			}

			// Get the background color to draw transparent and alpha images over.
			// Note that even if the PNG file supplies a background, you are not required to
			// use it - you should use the (solid) application background if it has one.

			png_color_16p image_background = NULL;
			RGBQUAD rgbBkColor;

			if (png_get_bKGD(png_ptr, info_ptr, &image_background)) {
				rgbBkColor.rgbRed      = (BYTE)image_background->red;
				rgbBkColor.rgbGreen    = (BYTE)image_background->green;
				rgbBkColor.rgbBlue     = (BYTE)image_background->blue;
				rgbBkColor.rgbReserved = 0;
			}

			// if this image has transparency, store the trns values

			png_bytep trans               = NULL;
			int num_trans                 = 0;
			png_color_16p trans_values    = NULL;
			png_uint_32 transparent_value = png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values);

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

			double gamma = 0;
			double screen_gamma = 2.2;

			if (png_get_gAMA(png_ptr, info_ptr, &gamma) && ( flags & PNG_IGNOREGAMMA ) != PNG_IGNOREGAMMA)
				png_set_gamma(png_ptr, screen_gamma, gamma);

			// all transformations have been registered; now update info_ptr data

			png_read_update_info(png_ptr, info_ptr);

			// color type may have changed, due to our transformations

			color_type = png_get_color_type(png_ptr,info_ptr);

			// create a DIB and write the bitmap header
			// set up the DIB palette, if needed

			switch (color_type) {
				case PNG_COLOR_TYPE_RGB:
					png_set_invert_alpha(png_ptr);

					if(image_type == FIT_BITMAP) {
						dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					} else {
						dib = FreeImage_AllocateT(image_type, width, height, pixel_depth);
					}
					break;

				case PNG_COLOR_TYPE_RGB_ALPHA :
					dib = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					break;

				case PNG_COLOR_TYPE_PALETTE :
					dib = FreeImage_Allocate(width, height, pixel_depth);

					png_get_PLTE(png_ptr,info_ptr, &png_palette,&palette_entries);

					palette = FreeImage_GetPalette(dib);

					// store the palette

					for (i = 0; i < palette_entries; i++) {
						palette[i].rgbRed   = png_palette[i].red;
						palette[i].rgbGreen = png_palette[i].green;
						palette[i].rgbBlue  = png_palette[i].blue;
					}

					// store the transparency table

					if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
						FreeImage_SetTransparencyTable(dib, (BYTE *)trans, num_trans);					

					break;

				case PNG_COLOR_TYPE_GRAY:
					dib = FreeImage_AllocateT(image_type, width, height, pixel_depth);

					if(pixel_depth <= 8) {
						palette = FreeImage_GetPalette(dib);
						palette_entries = 1 << pixel_depth;

						for (i = 0; i < palette_entries; i++) {
							palette[i].rgbRed   =
							palette[i].rgbGreen =
							palette[i].rgbBlue  = (i * 255) / (palette_entries - 1);
						}
					}
					// store the transparency table

					if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
						FreeImage_SetTransparencyTable(dib, (BYTE *)trans, num_trans);					

					break;

				default:
					throw "PNG format not supported";
			}

			// store the background color 
			if(image_background) {
				FreeImage_SetBackgroundColor(dib, &rgbBkColor);
			}

			// get physical resolution

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
				png_uint_32 res_x, res_y;
				
				// we'll overload this var and use 0 to mean no phys data,
				// since if it's not in meters we can't use it anyway

				int res_unit_type = 0;

				png_get_pHYs(png_ptr,info_ptr,&res_x,&res_y,&res_unit_type);

				if (res_unit_type == 1) {
					BITMAPINFOHEADER *bih = FreeImage_GetInfoHeader(dib);

					bih->biXPelsPerMeter = res_x;
					bih->biYPelsPerMeter = res_y;
				}
			}

			// get possible ICC profile

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) {
				png_charp profile_name = NULL;
				png_charp profile_data = NULL;
				png_uint_32 profile_length = 0;
				int  compression_type;

				png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &profile_length);

				// copy ICC profile data (must be done after FreeImage_Allocate)

				FreeImage_CreateICCProfile(dib, profile_data, profile_length);
			}


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

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

			if (!row_pointers) {
				if (palette)
					png_free(png_ptr, palette);				

				png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

				FreeImage_Unload(dib);
				return NULL;
			}

			// read in the bitmap bits via the pointer table

			for (png_uint_32 k = 0; k < height; k++)				
				row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k);			

			png_read_image(png_ptr, row_pointers);

			// check if the bitmap contains transparency, if so enable it in the header

			if (FreeImage_GetBPP(dib) == 32)
				if (FreeImage_GetColorType(dib) == FIC_RGBALPHA)
					FreeImage_SetTransparent(dib, TRUE);
				else
					FreeImage_SetTransparent(dib, FALSE);
				
			// cleanup

			if (row_pointers) {
				free(row_pointers);
				row_pointers = NULL;
			}

			// read the rest of the file, getting any additional chunks in info_ptr

			png_read_end(png_ptr, info_ptr);

			// get possible metadata (it can be located both before and after the image data)

			ReadMetadata(png_ptr, info_ptr, dib);

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

			return dib;
		} catch (const char *text) {
			if (png_ptr)
				png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
			
			if (row_pointers)
				free(row_pointers);

			if (dib)
				FreeImage_Unload(dib);			

			FreeImage_OutputMessageProc(s_format_id, text);
			
			return NULL;
		}
	}			

	return NULL;
}
Example #22
0
uint8 *readpng_get_image(uint32 *pChannels, uint32 *pRowbytes, uint32 *pWidth, uint32 *pHeight)
{
  png_uint_32  width, height;
  int  bit_depth, color_type;
  uint8  *image_data = NULL;
  png_uint_32  i, rowbytes;
  png_bytepp  row_pointers = NULL;


    /* alternatively, could make separate calls to png_get_image_width(),
     * etc., but want bit_depth and color_type for later [don't care about
     * compression_type and filter_type => NULLs] */

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

  *pWidth = width;
  *pHeight = height;

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

    if (color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_expand(png_ptr);
    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
        png_set_expand(png_ptr);
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_expand(png_ptr);
    if (bit_depth == 16)
        png_set_strip_16(png_ptr);
    if (color_type == PNG_COLOR_TYPE_GRAY ||
        color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);

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

    png_read_update_info(png_ptr, info_ptr);

    *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    *pChannels = (int)png_get_channels(png_ptr, info_ptr);

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

    Trace((stderr, "readpng_get_image:  channels = %d, rowbytes = %ld, height = %ld\n", *pChannels, rowbytes, height));


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

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

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

    png_read_image(png_ptr, row_pointers);

    free(row_pointers);
    row_pointers = NULL;

    png_read_end(png_ptr, NULL);

    return image_data;
}
static e_texture_t* e_loadpng(e_device_t* device,int mipmaps,fs_handle_t file)
{
	unsigned int width,height;
	unsigned int rowbytes;
	unsigned char* data;
	unsigned char** rows;
	unsigned int i;
	int bpp,type;
	int format;

	png_structp png;
	png_infop info;
	e_texture_t* texture;

	if(!e_checkpng(file))
		return 0;

	png=png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,(png_error_ptr)0,(png_error_ptr)0);
	if(!png)
		return 0;

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

	//Needed by libpng
	if(setjmp(png_jmpbuf(png)))
	{
        png_destroy_read_struct(&png,&info,0);
		if(rows)
			sys_free(rows);
		if(data)
			sys_free(data);
        return 0;
    }

	//Read up to image data
	png_set_read_fn(png,(png_voidp)file,e_readpng);
	png_set_sig_bytes(png,8);
	png_read_info(png,info);
	png_get_IHDR(png,info,&width,&height,&bpp,&type,0,0,0);

	if(width!=e_pow2(width)||
		height!=e_pow2(height))
		longjmp(png_jmpbuf(png),1);

	//Convert this image to fit the required format
	if(type==PNG_COLOR_TYPE_PALETTE)
		png_set_palette_to_rgb(png);
	if(type==PNG_COLOR_TYPE_GRAY||
        type==PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png);
	if(type==PNG_COLOR_TYPE_GRAY||bpp<8)
        png_set_expand(png);
    if(png_get_valid(png,info,PNG_INFO_tRNS))
        png_set_tRNS_to_alpha(png);

	png_read_update_info(png,info);
	rowbytes=png_get_rowbytes(png,info);

	//Allocate memory to store the image
	data=(unsigned char*)sys_alloc(rowbytes*height);
	if(!data)
		longjmp(png_jmpbuf(png),1);

	rows=(unsigned char**)sys_alloc(sizeof(unsigned char*)*height);
	if(!rows)
		longjmp(png_jmpbuf(png),1);

	for(i=0;i<height;i++)
		rows[i]=data+(height-(i+1))*rowbytes;

	//Read png
	png_read_image(png,rows);
	png_read_end(png,0);
	sys_free(rows);

	texture=(e_texture_t*)sys_alloc(sizeof(e_texture_t));
	texture->width=width;
	texture->height=height;

	glGenTextures(1,&texture->id);
	glBindTexture(GL_TEXTURE_2D,texture->id);

	texture->bpp=(type&PNG_COLOR_MASK_ALPHA)?32:24;
	format=(type&PNG_COLOR_MASK_ALPHA)?GL_RGBA:GL_RGB;
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	if(mipmaps)
		gluBuild2DMipmaps(GL_TEXTURE_2D,(type&PNG_COLOR_MASK_ALPHA)?4:3,texture->width,texture->height,format,GL_UNSIGNED_BYTE,data);
	else
		glTexImage2D(GL_TEXTURE_2D,0,format,texture->width,texture->height,0,format,GL_UNSIGNED_BYTE,data);

	sys_free(data);
	return texture;
}
Example #24
0
int svlImageCodecPNG::Read(svlSampleImage &image, const unsigned int videoch, const unsigned char *buffer, const size_t buffersize, bool noresize)
{
    if (videoch >= image.GetVideoChannels()) return SVL_FAIL;
    if (!buffer || buffersize < static_cast<unsigned int>(PNG_SIG_SIZE)) return SVL_FAIL;

    // check file for signature
    if (png_sig_cmp(const_cast<unsigned char*>(buffer), 0, PNG_SIG_SIZE) != 0) return SVL_FAIL;

    // create read structure
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    if (png_ptr == 0) return SVL_FAIL;

    // create info structure
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == 0) {
        png_destroy_read_struct(&png_ptr, reinterpret_cast<png_infopp>(0), reinterpret_cast<png_infopp>(0));
        return SVL_FAIL;
    }

    // setup error handling
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, reinterpret_cast<png_infopp>(0));
        return SVL_FAIL;
    }
    _PNG_source_memory source;
    source.buffer = const_cast<unsigned char*>(buffer + PNG_SIG_SIZE);
    source.buffersize = static_cast<unsigned int>(buffersize - PNG_SIG_SIZE);
    source.error = false;
    png_set_read_fn(png_ptr, &source, PNG_read_data_memory);

    png_set_sig_bytes(png_ptr, PNG_SIG_SIZE);
    png_read_info(png_ptr, info_ptr);

    // check file header
    const unsigned int width = static_cast<unsigned int>(png_get_image_width(png_ptr, info_ptr));
    const unsigned int height = static_cast<unsigned int>(png_get_image_height(png_ptr, info_ptr));
    const unsigned int row_stride = width * 3;

    if (width  < 1 || height < 1) return SVL_FAIL;

    // Allocate image buffer if not done yet
    if (static_cast<unsigned int>(width)  != image.GetWidth(videoch) ||
        static_cast<unsigned int>(height) != image.GetHeight(videoch)) {
        if (noresize) return SVL_FAIL;
        image.SetSize(videoch, static_cast<unsigned int>(width), static_cast<unsigned int>(height));
    }

    // allocate row buffer if not done yet
    if (!pngRows) {
        pngRows = new unsigned char*[height];
        pngRowsSize = height;
    }
    else if (pngRows && pngRowsSize < static_cast<unsigned int>(height)) {
        delete [] pngRows;
        pngRows = new unsigned char*[height];
        pngRowsSize = height;
    }

    // generate row pointer array
    unsigned char *dest = image.GetUCharPointer(videoch);
    for (unsigned int i = 0; i < height; i ++) {
        pngRows[i] = dest;
        dest += row_stride;
    }

    const unsigned int bitdepth = static_cast<unsigned int>(png_get_bit_depth(png_ptr, info_ptr));
    const unsigned int color_type = static_cast<unsigned int>(png_get_color_type(png_ptr, info_ptr));

    switch (color_type) {
        case PNG_COLOR_TYPE_PALETTE:
            png_set_palette_to_rgb(png_ptr);
        break;

        case PNG_COLOR_TYPE_GRAY:
            if (bitdepth < 8) {
#if PNG_LIBPNG_VER >= 10300
                png_set_expand_gray_1_2_4_to_8(png_ptr);
#else
                png_set_gray_1_2_4_to_8(png_ptr);
#endif
            }
        break;
    }
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
        png_set_tRNS_to_alpha(png_ptr);
    }
    if (bitdepth == 16) {
        png_set_strip_16(png_ptr);
    }
    png_set_bgr(png_ptr);

    // read image
    png_read_image(png_ptr, pngRows);

    // read ending
    png_read_end(png_ptr, info_ptr);

    if (color_type == PNG_COLOR_TYPE_GRAY) {
        // Gray8toRGB24 can do in-place conversion
        svlConverter::Gray8toRGB24(dest, dest, width * height);
    }

    // clean up
    png_destroy_read_struct(&png_ptr, &info_ptr,reinterpret_cast<png_infopp>(0));

    return SVL_OK;
}
Example #25
0
File: image.c Project: Miteam/jwm
ImageNode *LoadPNGImage(const char *fileName)
{

   static ImageNode *result;
   static FILE *fd;
   static unsigned char **rows;
   static png_structp pngData;
   static png_infop pngInfo;
   static png_infop pngEndInfo;

   unsigned char header[8];
   unsigned long rowBytes;
   int bitDepth, colorType;
   unsigned int x, y;
   png_uint_32 width;
   png_uint_32 height;

   Assert(fileName);

   result = NULL;
   fd = NULL;
   rows = NULL;
   pngData = NULL;
   pngInfo = NULL;
   pngEndInfo = NULL;

   fd = fopen(fileName, "rb");
   if(!fd) {
      return NULL;
   }

   x = fread(header, 1, sizeof(header), fd);
   if(x != sizeof(header) || png_sig_cmp(header, 0, sizeof(header))) {
      fclose(fd);
      return NULL;
   }

   pngData = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
   if(JUNLIKELY(!pngData)) {
      fclose(fd);
      Warning(_("could not create read struct for PNG image: %s"), fileName);
      return NULL;
   }

   if(JUNLIKELY(setjmp(png_jmpbuf(pngData)))) {
      png_destroy_read_struct(&pngData, &pngInfo, &pngEndInfo);
      if(fd) {
         fclose(fd);
      }
      if(rows) {
         ReleaseStack(rows);
      }
      DestroyImage(result);
      Warning(_("error reading PNG image: %s"), fileName);
      return NULL;
   }

   pngInfo = png_create_info_struct(pngData);
   if(JUNLIKELY(!pngInfo)) {
      png_destroy_read_struct(&pngData, NULL, NULL);
      fclose(fd);
      Warning(_("could not create info struct for PNG image: %s"), fileName);
      return NULL;
   }

   pngEndInfo = png_create_info_struct(pngData);
   if(JUNLIKELY(!pngEndInfo)) {
      png_destroy_read_struct(&pngData, &pngInfo, NULL);
      fclose(fd);
      Warning("could not create end info struct for PNG image: %s", fileName);
      return NULL;
   }

   png_init_io(pngData, fd);
   png_set_sig_bytes(pngData, sizeof(header));

   png_read_info(pngData, pngInfo);

   png_get_IHDR(pngData, pngInfo, &width, &height,
                &bitDepth, &colorType, NULL, NULL, NULL);
   result = CreateImage(width, height, 0);

   png_set_expand(pngData);

   if(bitDepth == 16) {
      png_set_strip_16(pngData);
   } else if(bitDepth < 8) {
      png_set_packing(pngData);
   }

   png_set_swap_alpha(pngData);
   png_set_filler(pngData, 0xFF, PNG_FILLER_BEFORE);

   if(colorType == PNG_COLOR_TYPE_GRAY
      || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
      png_set_gray_to_rgb(pngData);
   }

   png_read_update_info(pngData, pngInfo);

   rowBytes = png_get_rowbytes(pngData, pngInfo);
   rows = AllocateStack(result->height * sizeof(result->data));
   y = 0;
   for(x = 0; x < result->height; x++) {
      rows[x] = &result->data[y];
      y += rowBytes;
   }

   png_read_image(pngData, rows);

   png_read_end(pngData, pngInfo);
   png_destroy_read_struct(&pngData, &pngInfo, &pngEndInfo);

   fclose(fd);

   ReleaseStack(rows);
   rows = NULL;

   return result;

}
Example #26
0
Reference<Bitmap> StreamerPNG::loadBitmap(std::istream & input) {
	char header[8];
	input.read(header, 8);
	const int is_png = !png_sig_cmp(reinterpret_cast<png_byte *>(header), 0, 8);
	if(!is_png) {
		WARN("File is not a valid PNG image.");
		return nullptr;
	}

	// Set up the necessary structures for libpng.
	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
	if(!png_ptr) {
		return nullptr;
	}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if(!info_ptr) {
		png_destroy_read_struct(&png_ptr, static_cast<png_infopp>(nullptr), static_cast<png_infopp>(nullptr));
		return nullptr;
	}

	if(setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_read_struct(&png_ptr, &info_ptr, static_cast<png_infopp>(nullptr));
		return nullptr;
	}

	struct PNGFunctions {
			static void readData(png_structp read_ptr, png_bytep data, png_size_t length) {
				std::istream * in = reinterpret_cast<std::istream *>(png_get_io_ptr(read_ptr));
				if(in == nullptr || !in->good()) {
					png_error(read_ptr, "Error in input stream.");
				}
				in->read(reinterpret_cast<char *>(data), static_cast<std::streamsize>(length));
				if(in->gcount() != static_cast<std::streamsize>(length)) {
					png_error(read_ptr, "Requested amount of data could not be extracted from input stream");
				}
			}
	};

	png_set_read_fn(png_ptr, reinterpret_cast<png_voidp>(&input), PNGFunctions::readData);

	png_set_sig_bytes(png_ptr, 8);

	png_read_info(png_ptr, info_ptr);

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

	PixelFormat pixelFormat = PixelFormat::RGB;
	switch(color_type) {
		case PNG_COLOR_TYPE_GRAY:
			// Convert bpp less than 8 to 8 bits.
			if(bit_depth < 8) {
				png_set_expand_gray_1_2_4_to_8(png_ptr);
			}
			pixelFormat = PixelFormat::MONO;
			break;
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			// Convert grayscale with alpha to RGBA.
			png_set_expand(png_ptr);
			png_set_gray_to_rgb(png_ptr);
			pixelFormat = PixelFormat::RGBA;
			break;
		case PNG_COLOR_TYPE_PALETTE:
			// Convert color palette to RGB(A).
			png_set_expand(png_ptr);

			// Check if the color palette contains transparent colors.
#if PNG_LIBPNG_VER >= 10300
			if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)){
				pixelFormat = PixelFormat::RGBA;
			}
#else
			if(info_ptr->valid & PNG_INFO_tRNS) {
				pixelFormat = PixelFormat::RGBA;
			}
#endif
			break;
		case PNG_COLOR_TYPE_RGB_ALPHA:
			pixelFormat = PixelFormat::RGBA;
			break;
		default:
			// Already set to RGB above.
			break;
	}
	// Convert 16 bpp to 8 bits.
	if (bit_depth == 16) {
		png_set_strip_16(png_ptr);
	}

	// Create the bitmap to store the data.
	Reference<Bitmap> bitmap = new Bitmap(width, height, pixelFormat);

	auto row_pointers = new png_bytep[height];
	const uint8_t bytes = pixelFormat.getBytesPerPixel();
	for (uint_fast32_t row = 0; row < height; ++row) {
		// Take over rows in the same order.
		row_pointers[row] = reinterpret_cast<png_bytep>(bitmap->data() + row * width * bytes);
	}

	// This function automatically handles interlacing.
	png_read_image(png_ptr, row_pointers);

	png_read_end(png_ptr, nullptr);
	png_destroy_read_struct(&png_ptr, &info_ptr, static_cast<png_infopp>(nullptr));
	png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
	delete [] row_pointers;

	return bitmap;
}
Example #27
0
File: lpng.c Project: lvshaco/lpng
static int
lload(lua_State *L) {
    int top = lua_gettop(L);
    FILE *fp; 
    struct png_source source;
    if (top == 1) {
        const char *filename = luaL_checkstring(L,1);
        fp = fopen(filename, "rb");
        if (fp == NULL) {
            return luaL_error(L, strerror(errno));
        }
        unsigned char header[PNGSIGSIZE];
        if (fread(header, 1, PNGSIGSIZE, fp) != PNGSIGSIZE) {
            return luaL_error(L, "png invalid");
        }
        if (png_sig_cmp(header, 0, PNGSIGSIZE)) {
            return luaL_error(L, "png sig invalid");
        }
        fseek(fp, 0, SEEK_SET);
    } else if (top == 2) {
        luaL_checktype(L,1,LUA_TLIGHTUSERDATA);
        void *data = lua_touserdata(L,1);
        size_t size = luaL_checkinteger(L,2);
        if (size < PNGSIGSIZE) {
            return luaL_error(L, "png invalid");
        }
        if (png_sig_cmp(data, 0, PNGSIGSIZE)) {
            return luaL_error(L, "png sig invalid");
        }
        source.data = data;
        source.size = size;
        source.offset = 0;
    } else {
        return luaL_error(L, "invalid argument number");
    }
    
    png_structp png_ptr;
    png_infop info_ptr;
    png_uint_32 width, height;
    int bit_depth, color_type, interlace_type;
    int step;//, type;

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

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

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

    if (top == 1)
        png_init_io(png_ptr, fp);
    else
        png_set_read_fn(png_ptr, (void *)&source, png_read_cb);

    //png_set_sig_bytes(png_ptr, PNGSIGSIZE);

    png_read_info(png_ptr, info_ptr);

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

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

    if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
        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) != 0)
        png_set_tRNS_to_alpha(png_ptr);

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

    if (bit_depth < 8)
        png_set_packing(png_ptr);

    png_read_update_info(png_ptr, info_ptr);
    bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
    switch (color_type) {
    case PNG_COLOR_TYPE_GRAY:
        // type = TEXTURE_DEPTH;
        step = 1;
        break;
    case PNG_COLOR_TYPE_RGB:
        //type = TEXTURE_RGB;
        step = 3;
        break;
    case PNG_COLOR_TYPE_RGB_ALPHA:
        //type = TEXTURE_RGBA;
        step = 4;
        break;
    default:
        return luaL_error(L, "png color type %d not support", color_type);
    } 

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

    png_size_t rowbytes = png_get_rowbytes(png_ptr,info_ptr);

    size_t bytes = rowbytes * height;
    uint8_t *buffer = (uint8_t *)malloc(bytes);
    int i;
    for (i=0; i<height; ++i) {
        row_pointers[i] = buffer + i*rowbytes;
    }
    
    png_read_image(png_ptr, row_pointers);

    png_read_end(png_ptr, info_ptr);

    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    free(row_pointers);

    switch (color_type) {
    case PNG_COLOR_TYPE_GRAY:
        lua_pushliteral(L,"GRAY");
        break;
    case PNG_COLOR_TYPE_RGB:
        lua_pushliteral(L,"RGB8");
        break;
    case PNG_COLOR_TYPE_RGBA:
        lua_pushliteral(L,"RGBA8");
        break;
    }
    lua_pushinteger(L,width);
    lua_pushinteger(L,height);
    int n = width * height * step;
    lua_createtable(L,n,0);
    for (i=0; i<n; ++i) {
        lua_pushinteger(L, buffer[i]);
        lua_rawseti(L, -2, i+1);
    }

    free(buffer);
    return 4;
}
Example #28
0
void LoadPNG (char *filename, byte **pic, int *width, int *height) 
{
	png_structp png;
	png_infop pnginfo;
	byte ioBuffer[8192];
	int len;
	byte *raw;
	*pic=0;

	len = ri.FS_LoadFile (filename, (void **)&raw);

	if (!raw)
	{
		ri.Con_Printf (PRINT_DEVELOPER, "Bad png file %s\n", filename);
		return;
	}

	if( png_sig_cmp(raw,0,4)) 
		return;  

	png = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
	if(!png) 
		return;

	pnginfo = png_create_info_struct( png );

	if(!pnginfo) 
	{
		png_destroy_read_struct(&png,&pnginfo,0);
		return;
	}
	png_set_sig_bytes(png,0/*sizeof( sig )*/);

	mypng_struct_create(); // creates the my_png struct

	my_png->tmpBuf = raw; //buf = whole file content
	my_png->tmpi=0; 

	png_set_read_fn(png,ioBuffer,fReadData );

	png_read_info( png, pnginfo );

	png_get_IHDR(png, pnginfo, &my_png->Width, &my_png->Height,&my_png->BitDepth, &my_png->ColorType, &my_png->Interlace, &my_png->Compression, &my_png->Filter );
	// ...removed bgColor code here...

	if (my_png->ColorType == PNG_COLOR_TYPE_PALETTE)  
		png_set_palette_to_rgb(png);
	if (my_png->ColorType == PNG_COLOR_TYPE_GRAY && my_png->BitDepth < 8) 
		png_set_gray_1_2_4_to_8(png);

	// Add alpha channel if present
	if(png_get_valid( png, pnginfo, PNG_INFO_tRNS ))
		png_set_tRNS_to_alpha(png); 

	// hax: expand 24bit to 32bit
	if (my_png->BitDepth == 8 && my_png->ColorType == PNG_COLOR_TYPE_RGB) 
		png_set_filler(png,255, PNG_FILLER_AFTER);

	if (( my_png->ColorType == PNG_COLOR_TYPE_GRAY) || (my_png->ColorType == PNG_COLOR_TYPE_GRAY_ALPHA ))
		png_set_gray_to_rgb( png );


	if (my_png->BitDepth < 8)
		png_set_expand (png);

	// update the info structure
	png_read_update_info( png, pnginfo );

	my_png->FRowBytes = png_get_rowbytes( png, pnginfo );
	my_png->BytesPerPixel = png_get_channels( png, pnginfo );  // DL Added 30/08/2000

	InitializeDemData();
	if((my_png->Data)&&(my_png->FRowPtrs)) 
		png_read_image(png, (png_bytepp)my_png->FRowPtrs);

	png_read_end(png, pnginfo); // read last information chunks

	png_destroy_read_struct(&png, &pnginfo, 0);


	//only load 32 bit by now...
	if (my_png->BitDepth == 8)
	{
		*pic= my_png->Data;
		*width = my_png->Width;
		*height = my_png->Height;
	}
	else
	{
		ri.Con_Printf (PRINT_DEVELOPER, "Bad png color depth: %s\n", filename);
		*pic = NULL;
		free(my_png->Data);
	}

	mypng_struct_destroy(true);
	ri.FS_FreeFile ((void *)raw);
}
Example #29
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	png_uint_32 width, height;
	int color_type;
	int bit_depth;
	int pixel_depth = 0;	// pixel_depth = bit_depth * channels

	FIBITMAP *dib = NULL;
	png_bytepp row_pointers = NULL;

    fi_ioStructure fio;
    fio.s_handle = handle;
	fio.s_io = io;
    
	if (handle) {
		BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;

		try {		
			// check to see if the file is in fact a PNG file

			BYTE png_check[PNG_BYTES_TO_CHECK];

			io->read_proc(png_check, PNG_BYTES_TO_CHECK, 1, handle);

			if (png_sig_cmp(png_check, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0) {
				return NULL;	// Bad signature
			}
			
			// create the chunk manage structure

			png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler);

			if (!png_ptr) {
				return NULL;			
			}

			// create the info structure

		    info_ptr = png_create_info_struct(png_ptr);

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

			// init the IO

			png_set_read_fn(png_ptr, &fio, _ReadProc);

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

			// because we have already read the signature...

			png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);

			// read the IHDR chunk

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

			// configure the decoder

			FREE_IMAGE_TYPE image_type = FIT_BITMAP;

			if(!ConfigureDecoder(png_ptr, info_ptr, flags, &image_type)) {
				throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
			}

			// update image info

			color_type = png_get_color_type(png_ptr, info_ptr);
			bit_depth = png_get_bit_depth(png_ptr, info_ptr);
			pixel_depth = bit_depth * png_get_channels(png_ptr, info_ptr);

			// create a dib and write the bitmap header
			// set up the dib palette, if needed

			switch (color_type) {
				case PNG_COLOR_TYPE_RGB:
				case PNG_COLOR_TYPE_RGB_ALPHA:
					dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					break;

				case PNG_COLOR_TYPE_PALETTE:
					dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
					if(dib) {
						png_colorp png_palette = NULL;
						int palette_entries = 0;

						png_get_PLTE(png_ptr,info_ptr, &png_palette, &palette_entries);

						palette_entries = MIN((unsigned)palette_entries, FreeImage_GetColorsUsed(dib));

						// store the palette

						RGBQUAD *palette = FreeImage_GetPalette(dib);
						for(int i = 0; i < palette_entries; i++) {
							palette[i].rgbRed   = png_palette[i].red;
							palette[i].rgbGreen = png_palette[i].green;
							palette[i].rgbBlue  = png_palette[i].blue;
						}
					}
					break;

				case PNG_COLOR_TYPE_GRAY:
					dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);

					if(dib && (pixel_depth <= 8)) {
						RGBQUAD *palette = FreeImage_GetPalette(dib);
						const int palette_entries = 1 << pixel_depth;

						for(int i = 0; i < palette_entries; i++) {
							palette[i].rgbRed   =
							palette[i].rgbGreen =
							palette[i].rgbBlue  = (BYTE)((i * 255) / (palette_entries - 1));
						}
					}
					break;

				default:
					throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
			}

			if(!dib) {
				throw FI_MSG_ERROR_DIB_MEMORY;
			}

			// store the transparency table

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
				// array of alpha (transparency) entries for palette
				png_bytep trans_alpha = NULL;
				// number of transparent entries
				int num_trans = 0;						
				// graylevel or color sample values of the single transparent color for non-paletted images
				png_color_16p trans_color = NULL;

				png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color);

				if((color_type == PNG_COLOR_TYPE_GRAY) && trans_color) {
					// single transparent color
					if (trans_color->gray < 256) { 
						BYTE table[256]; 
						memset(table, 0xFF, 256); 
						table[trans_color->gray] = 0; 
						FreeImage_SetTransparencyTable(dib, table, 256); 
					}
					// check for a full transparency table, too
					else if ((trans_alpha) && (pixel_depth <= 8)) {
						FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans);
					}

				} else if((color_type == PNG_COLOR_TYPE_PALETTE) && trans_alpha) {
					// transparency table
					FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans);
				}
			}

			// store the background color (only supported for FIT_BITMAP types)

			if ((image_type == FIT_BITMAP) && png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) {
				// Get the background color to draw transparent and alpha images over.
				// Note that even if the PNG file supplies a background, you are not required to
				// use it - you should use the (solid) application background if it has one.

				png_color_16p image_background = NULL;
				RGBQUAD rgbBkColor;

				if (png_get_bKGD(png_ptr, info_ptr, &image_background)) {
					rgbBkColor.rgbRed      = (BYTE)image_background->red;
					rgbBkColor.rgbGreen    = (BYTE)image_background->green;
					rgbBkColor.rgbBlue     = (BYTE)image_background->blue;
					rgbBkColor.rgbReserved = 0;

					FreeImage_SetBackgroundColor(dib, &rgbBkColor);
				}
			}

			// get physical resolution

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
				png_uint_32 res_x, res_y;
				
				// we'll overload this var and use 0 to mean no phys data,
				// since if it's not in meters we can't use it anyway

				int res_unit_type = PNG_RESOLUTION_UNKNOWN;

				png_get_pHYs(png_ptr,info_ptr, &res_x, &res_y, &res_unit_type);

				if (res_unit_type == PNG_RESOLUTION_METER) {
					FreeImage_SetDotsPerMeterX(dib, res_x);
					FreeImage_SetDotsPerMeterY(dib, res_y);
				}
			}

			// get possible ICC profile

			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) {
				png_charp profile_name = NULL;
				png_bytep profile_data = NULL;
				png_uint_32 profile_length = 0;
				int  compression_type;

				png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &profile_length);

				// copy ICC profile data (must be done after FreeImage_AllocateHeader)

				FreeImage_CreateICCProfile(dib, profile_data, profile_length);
			}

			// --- header only mode => clean-up and return

			if (header_only) {
				// get possible metadata (it can be located both before and after the image data)
				ReadMetadata(png_ptr, info_ptr, dib);
				if (png_ptr) {
					// clean up after the read, and free any memory allocated - REQUIRED
					png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
				}
				return dib;
			}

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

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

			if (!row_pointers) {
				png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
				FreeImage_Unload(dib);
				return NULL;
			}

			// read in the bitmap bits via the pointer table
			// allow loading of PNG with minor errors (such as images with several IDAT chunks)

			for (png_uint_32 k = 0; k < height; k++) {
				row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k);
			}

			png_set_benign_errors(png_ptr, 1);
			png_read_image(png_ptr, row_pointers);

			// check if the bitmap contains transparency, if so enable it in the header

			if (FreeImage_GetBPP(dib) == 32) {
				if (FreeImage_GetColorType(dib) == FIC_RGBALPHA) {
					FreeImage_SetTransparent(dib, TRUE);
				} else {
					FreeImage_SetTransparent(dib, FALSE);
				}
			}
				
			// cleanup

			if (row_pointers) {
				free(row_pointers);
				row_pointers = NULL;
			}

			// read the rest of the file, getting any additional chunks in info_ptr

			png_read_end(png_ptr, info_ptr);

			// get possible metadata (it can be located both before and after the image data)

			ReadMetadata(png_ptr, info_ptr, dib);

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

			return dib;

		} catch (const char *text) {
			if (png_ptr) {
				png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
			}
			if (row_pointers) {
				free(row_pointers);
			}
			if (dib) {
				FreeImage_Unload(dib);
			}
			FreeImage_OutputMessageProc(s_format_id, text);
			
			return NULL;
		}
	}			

	return NULL;
}
Example #30
0
static rt_bool_t rtgui_image_png_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load)
{
    png_uint_32 width;
    png_uint_32 height;
    int bit_depth;
    int color_type;
    double gamma;
    struct rtgui_image_png *png;

    png = (struct rtgui_image_png *) rtgui_malloc(sizeof(struct rtgui_image_png));
    png->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png->png_ptr == RT_NULL)
    {
        rtgui_free(png);
        return RT_FALSE;
    }

    png->info_ptr = png_create_info_struct(png->png_ptr);
    if (png->info_ptr == RT_NULL)
    {
        png_destroy_read_struct(&png->png_ptr, NULL, NULL);
        rtgui_free(png);
        return RT_FALSE;
    }

    png->filerw = file;
    png_set_read_fn(png->png_ptr, png->filerw, rtgui_image_png_read_data);

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

    /* set image information */
    image->w = width;
    image->h = height;
    image->engine = &rtgui_image_png_engine;
    image->data = png;

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

    /* Ignore background color */

    /* set gamma conversion */
    if (png_get_gAMA(png->png_ptr, png->info_ptr, &gamma))
        png_set_gamma(png->png_ptr, (double)2.2, gamma);

    png_read_update_info(png->png_ptr, png->info_ptr);

    if (load == RT_TRUE)
    {
        /* load all pixels */
        png->pixels = rtgui_malloc(image->w * image->h * sizeof(rtgui_color_t));
        if (png->pixels == RT_NULL)
        {
            png_read_end(png->png_ptr, RT_NULL);

            /* destroy png struct */
            png_destroy_info_struct(png->png_ptr, &png->info_ptr);
            png_destroy_read_struct(&png->png_ptr, RT_NULL, RT_NULL);

            /* release data */
            rtgui_free(png);
            return RT_FALSE;
        }

        rtgui_image_png_process(png->png_ptr, png->info_ptr, png);
    }
    else
    {
        png->pixels = RT_NULL;
    }

    return RT_TRUE;
}