Example #1
0
static FtkBitmap* load_png (const char *filename)
{
	FtkColor  bg = {0};
	unsigned int x = 0;
	unsigned int y = 0;
	png_byte bit_depth = 0;
	unsigned int width = 0;
	unsigned int height = 0;
	int number_of_passes = 0;
	png_byte color_type = 0;

	png_infop info_ptr = NULL;
	png_structp png_ptr = NULL;
	png_bytep * row_pointers = NULL;
	
	char header[8];	   // 8 is the maximum size that can be checked
	int rowbytes = 0;
	FtkColor* dst = NULL;
	unsigned char* src = NULL;
	FtkBitmap* bitmap = NULL;

	FILE *fp = fopen(filename, "rb");
	return_val_if_fail(fp, NULL);

	bg.a = 0xff;

	fread(header, 1, 8, fp);
	return_val_if_fail(png_sig_cmp(header, 0, 8) == 0, NULL);

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

	info_ptr = png_create_info_struct(png_ptr);
	return_val_if_fail(info_ptr, NULL);

	return_val_if_fail(setjmp(png_jmpbuf(png_ptr)) == 0, NULL);

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

	png_read_info(png_ptr, info_ptr);

	width = png_get_image_width(png_ptr, info_ptr);
	height = png_get_image_height(png_ptr, info_ptr);
	color_type = png_get_color_type(png_ptr, info_ptr);
	bit_depth = png_get_bit_depth(png_ptr, info_ptr);

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

	return_val_if_fail(setjmp(png_jmpbuf(png_ptr)) == 0, NULL);
	
	rowbytes = png_get_rowbytes(png_ptr,info_ptr);
	row_pointers = (png_bytep*) FTK_ZALLOC(sizeof(png_bytep) * height);

	for (y=0; y<height; y++) 
	{
		row_pointers[y] = (png_byte*) FTK_ZALLOC(rowbytes);
	}

	png_read_image(png_ptr, row_pointers);

	fclose(fp);
	
	bitmap = ftk_bitmap_create(width, height, bg);
	dst = ftk_bitmap_lock(bitmap);

	if (color_type == PNG_COLOR_TYPE_RGBA)
	{
		unsigned int w = width;
		unsigned int h = height;
		for(y = 0; y < h; y++)
		{
			src = row_pointers[y];
			for(x = 0; x < w; x++)
			{
				if(src[3])
				{
					dst->r = src[0];
					dst->g = src[1];
					dst->b = src[2];
					dst->a = src[3];
				}
				else
				{
					dst->r = 0xff;
					dst->g = 0xff;
					dst->b = 0xff;
					dst->a = 0;
				}
				src +=4;
				dst++;
			}
		}
	}
	else if(color_type == PNG_COLOR_TYPE_RGB)
	{
		unsigned int w = width;
		unsigned int h = height;
		for(y = 0; y < h; y++)
		{
			src = row_pointers[y];
			for(x = 0; x < w; x++)
			{
				dst->r = src[0];
				dst->g = src[1];
				dst->b = src[2];
				dst->a = 0xff;
				src += 3;
				dst++;
			}
		}
	}
	else
	{
		assert(!"not supported.");
	}

	for(y = 0; y < height; y++)
	{
		FTK_FREE(row_pointers[y]);
	}
	FTK_FREE(row_pointers);

	return bitmap;
}
Example #2
0
png_bytep readpng_get_image(png_structp* png_ptr, png_infop* info_ptr, png_infop* end_ptr)
{
        //test for
        if(setjmp(png_jmpbuf(*png_ptr)))
        {
                png_destroy_read_struct(png_ptr, info_ptr, NULL);
                std::cerr << "error during setjmp" << std::endl;
                return NULL;
        }

        png_uint_32 width, height;
        int bit_depth, color_type;
        png_uint_32 numrowbytes;
        png_bytep dataBlock;

        // gamma correction start (optional)
        double display_exponent = 2.2; //standard in most systems + standard in imageprocessing
        int envGamma = 0;
        if(envGamma)
                display_exponent = (double)envGamma;


        double gamma;

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

        // gamma correction end
       
       
        png_get_IHDR(*png_ptr, *info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);


        //transform the png to a standard format
        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);

        png_read_update_info(*png_ptr, *info_ptr);
        //end

        //proccessing for the dataBlock (pixeldata)
        numrowbytes = png_get_rowbytes(*png_ptr, *info_ptr);
        png_bytep row_pointers[height];

        dataBlock = (png_bytep)malloc(sizeof(png_byte)*numrowbytes*height);
        for(png_uint_32 i = 0; i<height; i++)
                row_pointers[i] = dataBlock + i*numrowbytes;


        png_read_image(*png_ptr, row_pointers);
        //end

        //optional reading of end in end_ptr and test for consistence
        png_read_end(*png_ptr, NULL);
        
        return dataBlock;
}
Example #3
0
pictw_t *
spng_read(session_t *ps, const char *path) {
	assert(path);

	char sig[SPNG_SIGBYTES] = "";
	pictw_t *pictw = NULL;
	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	FILE *fp = fopen(path, "rb");
	bool need_premultiply = false;
	if (unlikely(!fp)) {
		printfef("(\"%s\"): Failed to open file.", path);
		goto spng_read_end;
	}
	if (unlikely(SPNG_SIGBYTES != fread(&sig, 1, SPNG_SIGBYTES, fp))) {
		printfef("(\"%s\"): Failed to read %d-byte signature.",
				path, SPNG_SIGBYTES);
		goto spng_read_end;
	}
	if (unlikely(png_sig_cmp((png_bytep) sig, 0, SPNG_SIGBYTES))) {
		printfef("(\"%s\"): PNG signature invalid.", path);
		goto spng_read_end;
	}
	png_ptr = allocchk(png_create_read_struct(PNG_LIBPNG_VER_STRING,
				NULL, NULL, NULL));
	info_ptr = allocchk(png_create_info_struct(png_ptr));
	if (setjmp(png_jmpbuf(png_ptr)))
		goto spng_read_end;
	png_init_io(png_ptr, fp);
	png_set_sig_bytes(png_ptr, SPNG_SIGBYTES);
	png_read_info(png_ptr, info_ptr);
	png_uint_32 width = 0, height = 0;

	// Set transformations
	int bit_depth = 0, color_type = 0;
	{
		int interlace_type = 0;
		png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
				&color_type, &interlace_type, NULL, NULL);

		// Scale or strip 16-bit colors
		if (bit_depth == 16) {
			printfdf("(\"%s\"): Scaling 16-bit colors.", path);
#if PNG_LIBPNG_VER >= 10504
			png_set_scale_16(png_ptr);
#else
			png_set_strip_16(png_ptr);
#endif
			bit_depth = 8;
		}

		/* if (bit_depth < 8)
			png_set_packing(png_ptr); */

		// No idea why this is needed...
		png_set_bgr(png_ptr);

		// Convert palette to RGB
		if (color_type == PNG_COLOR_TYPE_PALETTE) {
			printfdf("(\"%s\"): Converting palette PNG to RGB.", path);
			png_set_palette_to_rgb(png_ptr);
			color_type = PNG_COLOR_TYPE_RGB;
		}

		if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
			printfdf("(\"%s\"): Converting rDNS to full alpha.", path);
			png_set_tRNS_to_alpha(png_ptr);
		}

		if (color_type == PNG_COLOR_TYPE_GRAY
				|| PNG_COLOR_TYPE_GRAY_ALPHA == color_type) {
			printfdf("(\"%s\"): Converting gray (+ alpha) PNG to RGB.", path);
			png_set_gray_to_rgb(png_ptr);
			if (PNG_COLOR_TYPE_GRAY == color_type)
				color_type = PNG_COLOR_TYPE_RGB;
			else
				color_type = PNG_COLOR_TYPE_RGB_ALPHA;
		}

		/*
		if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
			printfdf("(\"%s\"): Converting 1/2/4 bit gray PNG to 8-bit.", path);
#if PNG_LIBPNG_VER >= 10209
			png_set_expand_gray_1_2_4_to_8(png_ptr);
#else
			png_set_gray_1_2_4_to_8(png_ptr);
#endif
			bit_depth = 8;
		}
		*/

		// Somehow XImage requires 24-bit visual to use 32 bits per pixel
		if (color_type == PNG_COLOR_TYPE_RGB) {
			printfdf("(\"%s\"): Appending filler alpha values.", path);
			png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
		}

		// Premultiply alpha
		if (PNG_COLOR_TYPE_RGB_ALPHA == color_type) {
#if PNG_LIBPNG_VER >= 10504
			png_set_alpha_mode(png_ptr, PNG_ALPHA_STANDARD, 1.0);
#else
			need_premultiply = true;
#endif
		}

		/*
		int number_passes = 1;
#ifdef PNG_READ_INTERLACING_SUPPORTED
		number_passes = png_set_interlace_handling(png_ptr);
#endif */

		if (PNG_INTERLACE_NONE != interlace_type)
			png_set_interlace_handling(png_ptr);
	}

	png_read_update_info(png_ptr, info_ptr);

	int depth = 0;
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
				&color_type, NULL, NULL, NULL);
	switch (color_type) {
		case PNG_COLOR_TYPE_GRAY:       depth = 1 * bit_depth; break;
		case PNG_COLOR_TYPE_RGB:        depth = 3 * bit_depth; break;
		case PNG_COLOR_TYPE_RGB_ALPHA:  depth = 4 * bit_depth; break;
		default:                        assert(0); break;
	}

	// Read data and fill to Picture
	{
		int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
		png_bytep row_pointers[height];
		memset(row_pointers, 0, sizeof(row_pointers));
		row_pointers[0] = png_malloc(png_ptr, rowbytes * height);
		for (int row = 1; row < height; row++)
			row_pointers[row] = row_pointers[row - 1] + rowbytes;
		png_read_image(png_ptr, row_pointers);
		if (need_premultiply)
			for (int row = 0; row < height; row++)
				simg_data32_premultiply(row_pointers[row], width);
		if (unlikely(!(pictw = simg_data_to_pictw(ps, width, height, depth,
							row_pointers[0], rowbytes)))) {
			printfef("(\"%s\"): Failed to create Picture.", path);
			goto spng_read_end;
		}
	}

spng_read_end:
	if (png_ptr)
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	if (fp)
		fclose(fp);

	return pictw;
}
Example #4
0
File: pngload.c Project: A600/xbmc
int
loadpng (char *file_name, int *w, int *h, unsigned int ***buf)
{
	FILE   *fp;
	png_uint_32 width, height;
	int     bit_depth,

		color_type, interlace_type, compression_type, filter_type;
	int     rowbytes;

	png_structp png_ptr;
	png_infop info_ptr;
	png_infop end_info;

	int     x, y;
	unsigned int **row_pointers;

	/* OUVERTURE DU FICHIER */

	fp = fopen (file_name, "rb");

	if (!fp) {
		// fprintf (stderr, "Couldn't open file\n");
		return 1;
	}

	/* CREATION DES STRUCTURES */
	png_ptr = png_create_read_struct
		(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, NULL, NULL);
	if (!png_ptr) {
		fprintf (stderr, "Memory error\n");
		return 1;
	}

	info_ptr = png_create_info_struct (png_ptr);
	if (!info_ptr) {
		png_destroy_read_struct (&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
		fprintf (stderr, "Read error 1\n");
		return 1;
	}

	end_info = png_create_info_struct (png_ptr);
	if (!end_info) {
		png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL);
		fprintf (stderr, "Read error 2\n");
		return 1;
	}

	/* CHARGEMENT DE L'IMAGE */
	if (setjmp (png_ptr->jmpbuf)) {
		png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
		fclose (fp);
		fprintf (stderr, "Erreur de chargement\n");
		return 1;
	}

	png_init_io (png_ptr, fp);
	png_set_read_status_fn (png_ptr, NULL);

	png_read_info (png_ptr, info_ptr);

	png_get_IHDR (png_ptr, info_ptr, &width, &height,
								&bit_depth, &color_type, &interlace_type,
								&compression_type, &filter_type);
/*
	printf ("taille : %dx%d\n",width,height);
	printf ("depth  : %d\n",bit_depth);
	printf ("color type : ");
	switch (color_type) {
		case PNG_COLOR_TYPE_GRAY:
			printf ("PNG_COLOR_TYPE_GRAY (bit depths 1, 2, 4, 8, 16)\n");
			break;
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			printf ("PNG_COLOR_TYPE_GRAY_ALPHA (bit depths 8, 16)\n");
			break;
		case PNG_COLOR_TYPE_PALETTE:
			printf ("PNG_COLOR_TYPE_PALETTE (bit depths 1, 2, 4, 8)\n");
			break;
		case PNG_COLOR_TYPE_RGB:
			printf ("PNG_COLOR_TYPE_RGB (bit_depths 8, 16)\n");
			break;
		case PNG_COLOR_TYPE_RGB_ALPHA:
			printf ("PNG_COLOR_TYPE_RGB_ALPHA (bit_depths 8, 16)\n");
			break;
	}
  */
	// printf ("PNG_COLOR_MASK_ALPHA   : %x\n", PNG_COLOR_MASK_ALPHA);
	// printf ("PNG_COLOR_MASK_COLOR   : %x\n", PNG_COLOR_MASK_COLOR);
	// printf ("PNG_COLOR_MASK_PALETTE : %x\n", PNG_COLOR_MASK_PALETTE);

	if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8)
		png_set_palette_to_rgb (png_ptr);

	if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
		png_set_expand_gray_1_2_4_to_8 (png_ptr);
	else if (color_type == PNG_COLOR_TYPE_GRAY ||
					 color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
			png_set_gray_to_rgb (png_ptr);

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

	png_read_update_info (png_ptr, info_ptr);

//      printf ("channels : %d\n", png_get_channels (png_ptr, info_ptr));
	rowbytes = png_get_rowbytes (png_ptr, info_ptr);
//      printf ("rowbytes : %d\n", rowbytes);

	row_pointers = (unsigned int **) malloc (height * sizeof (unsigned int *));

	for (y = 0; y < height; y++)
		row_pointers[y] = (unsigned int *) malloc (4 * width);
	png_read_image (png_ptr, (png_bytepp) row_pointers);

	// for (y=0;y<height;y++) {
//              for (x=0;x<width;x++) {
//                      if (row_pointers[y][x] & 0xf000)
	// printf ("%x ",(((unsigned int**)row_pointers)[y][x])&0xf);
	// else
//                              printf (" ");
	// }
	// printf ("\n");
	// }

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

	(*buf) = (unsigned int **) malloc (height * sizeof (void *));

	for (y = 0; y < height; y++) {
		(*buf)[y] = (unsigned int *) malloc (width * 4);
		for (x = 0; x < width; x++)
			(*buf)[y][x] = row_pointers[y][x];
	}
	*w = width;
	*h = height;

	return 0;
}
TextureReturn png_texture_load(const char * file_name, int * width, int * height)
{
    // This function was originally written by David Grayson for
    // https://github.com/DavidEGrayson/ahrs-visualizer

    png_byte header[8];

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

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

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

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

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

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

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

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

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

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

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

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

    if (width){ *width = temp_width; }
    if (height){ *height = temp_height; }

    //printf("%s: %lux%lu %d\n", file_name, temp_width, temp_height, color_type);

    if (bit_depth != 8)
    {
        fprintf(stderr, "%s: Unsupported bit depth %d.  Must be 8.\n", file_name, bit_depth);
        return TextureReturn();
    }

    GLint format;
    switch(color_type)
    {
    case PNG_COLOR_TYPE_RGB:
        format = GL_RGB;
        break;
    case PNG_COLOR_TYPE_RGB_ALPHA:
        format = GL_RGBA;
        break;
    default:
        fprintf(stderr, "%s: Unknown libpng color type %d.\n", file_name, color_type);
        return TextureReturn();
    }

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

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

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

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

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

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

    // read the png into image_data through row_pointers
    png_read_image(png_ptr, row_pointers);
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    fclose(fp);
	*width = temp_width;
	*height = temp_height;
	TextureReturn thing;
	thing.format = format;
	thing.pixels = image_data;
	return thing;/*
    // Generate the OpenGL texture object
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, format, temp_width, temp_height, 0, format, GL_UNSIGNED_BYTE, image_data);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    // clean up
    free(row_pointers);
    return texture;*/
}
Example #6
0
int image_png_load(MediaScanImage *i) {
  int bit_depth, color_type, num_passes, x, y;
  int ofs;
  volatile unsigned char *ptr = NULL; // volatile = won't be rolled back if longjmp is called
  PNGData *p = (PNGData *)i->_png;

  if (setjmp(png_jmpbuf(p->png_ptr))) {
    if (ptr != NULL)
      free((void *)ptr);
    image_png_destroy(i);
    return 0;
  }

  // XXX If reusing the object a second time, we need to completely create a new png struct

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

  if (color_type == PNG_COLOR_TYPE_PALETTE) {
    png_set_expand(p->png_ptr); // png_set_palette_to_rgb(p->png_ptr);
    i->channels = 4;
  }
  else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
    png_set_expand(p->png_ptr); // png_set_expand_gray_1_2_4_to_8(p->png_ptr);
  else if (png_get_valid(p->png_ptr, p->info_ptr, PNG_INFO_tRNS))
    png_set_expand(p->png_ptr); // png_set_tRNS_to_alpha(p->png_ptr);

  if (bit_depth == 16)
    png_set_strip_16(p->png_ptr);
  else if (bit_depth < 8)
    png_set_packing(p->png_ptr);

  // Make non-alpha RGB/Palette 32-bit and Gray 16-bit for easier handling
  if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
    png_set_add_alpha(p->png_ptr, 0xFF, PNG_FILLER_AFTER);
  }

  num_passes = png_set_interlace_handling(p->png_ptr);

  LOG_DEBUG("png bit_depth %d, color_type %d, channels %d, num_passes %d\n",
            bit_depth, color_type, i->channels, num_passes);

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

  image_alloc_pixbuf(i, i->width, i->height);

  ptr = (unsigned char *)malloc(png_get_rowbytes(p->png_ptr, p->info_ptr));

  ofs = 0;

  if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { // Grayscale (Alpha)
    if (num_passes == 1) {      // Non-interlaced
      for (y = 0; y < i->height; y++) {
        png_read_row(p->png_ptr, (unsigned char *)ptr, NULL);
        for (x = 0; x < i->width; x++) {
          i->_pixbuf[ofs++] = COL_FULL(ptr[x * 2], ptr[x * 2], ptr[x * 2], ptr[x * 2 + 1]);
        }
      }
    }
    else if (num_passes == 7) { // Interlaced
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 0, 8, 0, 8);
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 0, 8, 4, 8);
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 4, 8, 0, 4);
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 0, 4, 2, 4);
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 2, 4, 0, 2);
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 0, 2, 1, 2);
      image_png_interlace_pass_gray(i, (unsigned char *)ptr, 1, 2, 0, 1);
    }
  }
  else {                        // RGB(A)
    if (num_passes == 1) {      // Non-interlaced
      for (y = 0; y < i->height; y++) {
        png_read_row(p->png_ptr, (unsigned char *)ptr, NULL);
        for (x = 0; x < i->width; x++) {
          i->_pixbuf[ofs++] = COL_FULL(ptr[x * 4], ptr[x * 4 + 1], ptr[x * 4 + 2], ptr[x * 4 + 3]);
        }
      }
    }
    else if (num_passes == 7) { // Interlaced
      // The first pass will return an image 1/8 as wide as the entire image
      // (every 8th column starting in column 0)
      // and 1/8 as high as the original (every 8th row starting in row 0)
      image_png_interlace_pass(i, (unsigned char *)ptr, 0, 8, 0, 8);

      // The second will be 1/8 as wide (starting in column 4)
      // and 1/8 as high (also starting in row 0)
      image_png_interlace_pass(i, (unsigned char *)ptr, 0, 8, 4, 8);

      // The third pass will be 1/4 as wide (every 4th pixel starting in column 0)
      // and 1/8 as high (every 8th row starting in row 4)
      image_png_interlace_pass(i, (unsigned char *)ptr, 4, 8, 0, 4);

      // The fourth pass will be 1/4 as wide and 1/4 as high
      // (every 4th column starting in column 2, and every 4th row starting in row 0)
      image_png_interlace_pass(i, (unsigned char *)ptr, 0, 4, 2, 4);

      // The fifth pass will return an image 1/2 as wide,
      // and 1/4 as high (starting at column 0 and row 2)
      image_png_interlace_pass(i, (unsigned char *)ptr, 2, 4, 0, 2);

      // The sixth pass will be 1/2 as wide and 1/2 as high as the original
      // (starting in column 1 and row 0)
      image_png_interlace_pass(i, (unsigned char *)ptr, 0, 2, 1, 2);

      // The seventh pass will be as wide as the original, and 1/2 as high,
      // containing all of the odd numbered scanlines.
      image_png_interlace_pass(i, (unsigned char *)ptr, 1, 2, 0, 1);
    }
    else {
      FATAL("Unsupported PNG interlace type (%d passes)\n", num_passes);
    }
  }

  free((void *)ptr);

  // This is not required, so we can save some time by not reading post-image chunks
  //png_read_end(p->png_ptr, p->info_ptr);

  return 1;
}
Example #7
0
int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) {
	unsigned char header[8];
	png_structp png;
	png_infop   info;
	png_infop   endinfo;
	png_bytep   data;
   png_bytep  *row_p;
   double	fileGamma;

	png_uint_32 width, height;
	int depth, color;

	png_uint_32 i;

	if (pinfo == NULL) return 0;

	fread(header, 1, 8, fp);
	if (!png_check_sig(header, 8)) return 0;

	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	info = png_create_info_struct(png);
	endinfo = png_create_info_struct(png);

	// DH: added following lines
	if (setjmp(png->jmpbuf))
	{
		png_destroy_read_struct(&png, &info, &endinfo);
		return 0;
	}
	// ~DH

	png_init_io(png, fp);
	png_set_sig_bytes(png, 8);
	png_read_info(png, info);
	png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);

	pinfo->Width  = width;
	pinfo->Height = height;
	pinfo->Depth  = depth;

	/*--GAMMA--*/
	checkForGammaEnv();
	if (png_get_gAMA(png, info, &fileGamma))
		png_set_gamma(png, screenGamma, fileGamma);
	else
		png_set_gamma(png, screenGamma, 1.0/2.2);

	png_read_update_info(png, info);

	data = (png_bytep) malloc(png_get_rowbytes(png, info)*height);
	row_p = (png_bytep *) malloc(sizeof(png_bytep)*height);

	for (i = 0; i < height; i++) {
		if (StandardOrientation)
			row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i];
		else
			row_p[i] = &data[png_get_rowbytes(png, info)*i];
	}

	png_read_image(png, row_p);
	free(row_p);

	if (color == PNG_COLOR_TYPE_PALETTE) {
		int cols;
		png_get_PLTE(png, info, (png_colorp *) &pinfo->Palette, &cols);
	}
	else {
		pinfo->Palette = NULL;
	}

	if (color&PNG_COLOR_MASK_ALPHA) {
		if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY_ALPHA)
			pinfo->Components = 2;
		else
			pinfo->Components = 4;
		pinfo->Alpha = 8;
	}
	else {
		if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY)
			pinfo->Components = 1;
		else
			pinfo->Components = 3;
		pinfo->Alpha = 0;
	}

	pinfo->Data = data;

   png_read_end(png, endinfo);
	png_destroy_read_struct(&png, &info, &endinfo);

	return 1;
}
Example #8
0
/**
 * @brief Gets the pitch of a png.
 */
int npng_pitch( npng_t *npng )
{
   /* Make sure loaded info. */
   return png_get_rowbytes( npng->png_ptr, npng->info_ptr );
}
void PngReader::read(unsigned x0, unsigned y0,ImageData32& image)
{
    FILE *fp=fopen(fileName_.c_str(),"r");
    if (!fp) throw ImageReaderException("cannot open image file "+fileName_);

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

    if (!png_ptr)
    {
        fclose(fp);
        throw ImageReaderException("failed to allocate png_ptr");
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_read_struct(&png_ptr,0,0);
        fclose(fp);
        throw ImageReaderException("failed to create info_ptr");
    }

    png_init_io(png_ptr, fp);
    png_read_info(png_ptr, info_ptr);

    if (color_type_ == PNG_COLOR_TYPE_PALETTE)
        png_set_expand(png_ptr);
    if (color_type_ == PNG_COLOR_TYPE_GRAY && bit_depth_ < 8)
        png_set_expand(png_ptr);
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_expand(png_ptr);
    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);

    // quick hack -- only work in >=libpng 1.2.7
    png_set_add_alpha(png_ptr,1,1);

    double gamma;
    if (png_get_gAMA(png_ptr, info_ptr, &gamma))
        png_set_gamma(png_ptr, 2.2, gamma);

    png_read_update_info(png_ptr, info_ptr);

    //START read image rows
    unsigned w=std::min((unsigned)image.width(),width_);
    unsigned h=std::min((unsigned)image.height(),height_);

    unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr);
    unsigned char* row= new unsigned char[rowbytes];
    for (unsigned i=0; i<height_; ++i)
    {
        png_read_row(png_ptr,row,0);
        if (i>=y0 && i<h)
        {
            image.setRow(i-y0,(unsigned*) &row[x0],w);
        }
    }
    //END
    delete [] row;
    png_read_end(png_ptr,0);
    png_destroy_read_struct(&png_ptr, &info_ptr,0);
    fclose(fp);
}
Example #10
0
uint8_t* ImageDecoder::decodePNGImpl(png_structp pngPtr, uint32_t* width, uint32_t* height, bool* hasAlpha)
{
	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);
			break;
		case PNG_COLOR_TYPE_GRAY:
			if (bitdepth < 8)
				png_set_gray_to_rgb(pngPtr);
			break;
	}

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

	*hasAlpha = (channels > 3);

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

	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 #11
0
char* Model::load_png(std::string fileName, int *width, int *height) {
    fileName = "Resources/" + fileName;
    FILE *png_file = fopen(fileName.c_str(), "rb");
    //assert(png_file.open);

    uint8_t header[PNG_SIG_BYTES];

    fread(header, 1, PNG_SIG_BYTES, png_file);
    assert(!png_sig_cmp(header, 0, PNG_SIG_BYTES));

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

    png_infop info_ptr = png_create_info_struct(png_ptr);
    assert(info_ptr);

    png_infop end_info = png_create_info_struct(png_ptr);
    assert(end_info);

    assert(!setjmp(png_jmpbuf(png_ptr)));
    png_init_io(png_ptr, png_file);
    png_set_sig_bytes(png_ptr, PNG_SIG_BYTES);
    png_read_info(png_ptr, info_ptr);

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

    png_uint_32 bit_depth, color_type;
    bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);

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

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

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

    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_tRNS_to_alpha(png_ptr);
    else
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);

    png_read_update_info(png_ptr, info_ptr);

    png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    png_uint_32 numbytes = rowbytes * (*height);
    png_byte* pixels = (png_byte*) malloc(numbytes);
    png_byte** row_ptrs = (png_byte**) malloc((*height) * sizeof (png_byte*));

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


    png_read_image(png_ptr, row_ptrs);

    free(row_ptrs);
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    fclose(png_file);

    return (char *) pixels;
}
Example #12
0
unsigned char* LoadPNGJPGFromMemory(const unsigned char* buffer, int len, int* width, int* height)
{
	const int number=8;
	// проверяем сигнатуру файла (первые number байт)
	if ( !png_check_sig((png_bytep)buffer, number) )
	{
		// неизвестный формат
		return LoadJPGWithAlphaFromMemory(buffer, len, width, height);
	}

	// создаем внутреннюю структуру png для работы с файлом
	// последние параметры - структура, для функции обработки ошибок и варнинга (последн. 2 параметра)
	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	// создаем структуру с информацией о файле
	png_infop info_ptr = png_create_info_struct(png_ptr);

	PNGBuffer pngBuffer;
	pngBuffer.data = (png_bytep)buffer;
	pngBuffer.position = 8;

	png_set_read_fn(png_ptr, (void*)&pngBuffer, PNGRead);

	// говорим библиотеке, что мы уже прочли number байт, когда проверяли сигнатуру
	png_set_sig_bytes(png_ptr, number);
	// читаем всю информацию о файле
	png_read_info(png_ptr, info_ptr);
	// Эта функция возвращает инфу из info_ptr
	png_uint_32 w = 0, h = 0;  // размер картинки в пикселях
	int bit_depth = 0;      // глубина цвета (одного из каналов, может быть 1, 2, 4, 8, 16)
	int color_type = 0;      // описывает какие каналы присутствуют:
	// PNG_COLOR_TYPE_GRAY, PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE,
	// PNG_COLOR_TYPE_RGB, PNG_COLOR_TYPE_RGB_ALPHA...
	// последние 3 параметра могут быть нулями и обозначают: тип фильтра, тип компрессии и тип смещения
	png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, 0, 0, 0);

	// png формат может содержать 16 бит на канал, но нам нужно только 8, поэтому сужаем канал
	if (bit_depth == 16) png_set_strip_16(png_ptr);
	// преобразуем файл если он содержит палитру в нормальный RGB
	if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) png_set_palette_to_rgb(png_ptr);
	// если в грэйскейле меньше бит на канал чем 8, то конвертим к нормальному 8-битному
	//if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr);
	// и добавляем полный альфа-канал
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);

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

	double gamma = 0.0f;
	// если есть информация о гамме в файле, то устанавливаем на 2.2
	if ( png_get_gAMA(png_ptr, info_ptr, &gamma) ) png_set_gamma(png_ptr, 2.2, gamma);
	// иначе ставим дефолтную гамму для файла в 0.45455 (good guess for GIF images on PCs)
	else png_set_gamma(png_ptr, 2.2, 0.45455);

	// после всех трансформаций, апдейтим информацию в библиотеке
	png_read_update_info(png_ptr, info_ptr);
	// опять получаем все размеры и параметры обновленной картинки
	png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, 0, 0, 0);

	// определяем кол-во байт нужных для того чтобы вместить строку
	png_uint_32 row_bytes = png_get_rowbytes(png_ptr, info_ptr);
	// теперь, мы можем выделить память чтобы вместить картинку
	png_byte* data = new png_byte[row_bytes * h];
	// выделяем память, для указателей на каждую строку
	png_byte **row_pointers = new png_byte * [h];
	// сопоставляем массив указателей на строчки, с выделенными в памяти (res)
	// т.к. изображение перевернутое, то указатели идут снизу вверх
	for (unsigned int i = 0; i < h; i++)
		row_pointers[i] = data + i * row_bytes; 
	// все, читаем картинку
	png_read_image(png_ptr, row_pointers);

	// освобождаем память от указателей на строки
	delete []row_pointers;
	// освобождаем память выделенную для библиотеки libpng
	png_destroy_read_struct(&png_ptr, &info_ptr, 0);

	*width=w;
	*height=h;

	return data;
}
Example #13
0
/*
ReadPNG - Reads the contents of a PNG file and stores the contents into
    BMGImageStruct

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

Outputs:
    img         - the BMGImageStruct containing the image data

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

Limitations:
    None.

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

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

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

    BMGError tmp;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    png_set_bgr(png_ptr);

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

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

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

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

    png_read_update_info( png_ptr, info_ptr );

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

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

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

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

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

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

    return BMG_OK;
}
Example #14
0
int PngDecoder::validate()
{
    if (png_sig_cmp((png_bytep)buf->data(), 0, PNG_HEADER_SIZE)) {
        std::cout << "[PngDecoder] error: %s is not a PNG." << std::endl;
        return -1;
    }
    buf->drain(PNG_HEADER_SIZE);

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
        std::cout << "[PngDecoder] error: png_create_read_struct returned 0." << std::endl;
        return -1;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        std::cout << "[PngDecoder] error: png_create_info_struct returned 0." << std::endl;
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        return -1;
    }

    end_info = png_create_info_struct(png_ptr);
    if (!end_info) {
        std::cout << "[PngDecoder] error: png_create_info_struct returned 0." << std::endl;
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
        return -1;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        std::cout << "[PngDecoder] error from libpng" << std::endl;
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        return -1;
    }

    png_set_read_fn(png_ptr, buf, pngDecoderReadFunction);

    png_set_sig_bytes(png_ptr, PNG_HEADER_SIZE);

    png_read_info(png_ptr, info_ptr);

    png_set_expand(png_ptr);
    png_set_strip_16(png_ptr);
    png_set_gray_to_rgb(png_ptr);
    png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
    png_set_interlace_handling(png_ptr);

    png_read_update_info(png_ptr, info_ptr);

    imgInfo.width    = png_get_image_width(png_ptr, info_ptr);
    imgInfo.height   = png_get_image_height(png_ptr, info_ptr);

    imgInfo.color_type = png_get_color_type(png_ptr, info_ptr);
    imgInfo.channels = png_get_channels(png_ptr, info_ptr);
    imgInfo.bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    imgInfo.interlance_type = png_get_interlace_type(png_ptr, info_ptr);
    imgInfo.rowbytes = png_get_rowbytes(png_ptr, info_ptr);

#ifdef _PNGDECODER_DEBUG
    std::cout << "[PngDecoder] Extracted w=" << imgInfo.width
              << " h="  << imgInfo.height
              << " color_type=" << imgInfo.color_type
              << " bit_depth="<< imgInfo.bit_depth
              << " rowbytes="<< imgInfo.rowbytes
              << " channels="<< imgInfo.channels
              << " interlance_type="<< imgInfo.interlance_type
              << std::endl;
#endif

    if (imgInfo.bit_depth != 8) {
        std::cout << "[PngDecoder] error: Unsupported bit depth=" << imgInfo.bit_depth <<". Must be 8." << std::endl;
        return -1;
    }

    switch(imgInfo.color_type) {
    case PNG_COLOR_TYPE_RGB:
        imgInfo.format = GL_RGB;
        break;
    case PNG_COLOR_TYPE_RGB_ALPHA:
        imgInfo.format = GL_RGBA;
        break;
    case PNG_COLOR_TYPE_PALETTE:
        if (imgInfo.color_type & PNG_COLOR_MASK_ALPHA) {
            imgInfo.format = GL_RGBA;
        } else if (imgInfo.color_type & PNG_COLOR_MASK_COLOR) {
            imgInfo.format = GL_RGB;
        }
        break;
    default:
        std::cout << "[PngDecoder] error: unknown libpng color type=" << imgInfo.color_type << " rgb=" << PNG_COLOR_TYPE_RGB << " rgba=" << PNG_COLOR_TYPE_RGBA << " palette=" << PNG_COLOR_TYPE_PALETTE << std::endl;
        return -1;
    }

    return 0;
}
Example #15
0
int fh_png_load(const char *name,unsigned char **buffer,int* /*xp*/,int* /*yp*/)
{
	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) {
		fclose(fh);
		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);
	}

	/* this test does not trigger for 8bit-paletted PNGs with newer libpng (1.2.36 at least),
	   but the data delivered is with alpha channel anyway, so always strip alpha for now
	 */
#if PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR <= 2 && PNG_LIBPNG_VER_RELEASE < 36
	if (color_type & PNG_COLOR_MASK_ALPHA)
#endif
		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);
		printf("           width: %lu rowbytes: %lu\n", width, png_get_rowbytes(png_ptr, info_ptr));
		fclose(fh);
		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 #16
0
void save_png_buffer(buffer_t &buf, std::string filename) {
	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep *row_pointers;
	png_byte color_type;

	int width, height, channels;
	width = buf.extent[0];
	height = buf.extent[1];
	channels = buf.extent[2];
	//im.copy_to_host();

	_assert(channels > 0 && channels < 5,
		"Can't write PNG files that have other than 1, 2, 3, or 4 channels\n");

	png_byte color_types[4] = {PNG_COLOR_TYPE_GRAY, PNG_COLOR_TYPE_GRAY_ALPHA,
														 PNG_COLOR_TYPE_RGB,  PNG_COLOR_TYPE_RGB_ALPHA
														};
	color_type = color_types[channels - 1];

	// open file
	FILE *f = fopen(filename.c_str(), "wb");
	_assert(f, "[write_png_file] File %s could not be opened for writing\n", filename.c_str());

	// initialize stuff
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	_assert(png_ptr, "[write_png_file] png_create_write_struct failed\n");

	info_ptr = png_create_info_struct(png_ptr);
	_assert(info_ptr, "[write_png_file] png_create_info_struct failed\n");

	_assert(!setjmp(png_jmpbuf(png_ptr)), "[write_png_file] Error during init_io\n");

	png_init_io(png_ptr, f);

	unsigned int bit_depth = 16;
	if (sizeof(uint8_t) == 1) {
		bit_depth = 8;
	}

	// write header
	_assert(!setjmp(png_jmpbuf(png_ptr)), "[write_png_file] Error during writing header\n");

	png_set_IHDR(png_ptr, info_ptr, width, height,
							bit_depth, color_type, PNG_INTERLACE_NONE,
							PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

	png_write_info(png_ptr, info_ptr);

	row_pointers = new png_bytep[height];

	// im.copyToHost(); // in case the image is on the gpu

	int c_stride = (channels == 1) ? 0 : width*height;
	uint8_t *srcPtr = buf.host;

	for (int y = 0; y < height; y++) {
		row_pointers[y] = new png_byte[png_get_rowbytes(png_ptr, info_ptr)];
		uint8_t *dstPtr = (uint8_t *)(row_pointers[y]);
		if (bit_depth == 16) {
			// convert to uint16_t
			for (int x = 0; x < width; x++) {
				for (int c = 0; c < channels; c++) {
					uint16_t out;
					convert(srcPtr[c*c_stride], out);
					*dstPtr++ = out >> 8;
					*dstPtr++ = out & 0xff;
				}
				srcPtr++;
			}
		} else if (bit_depth == 8) {
			// convert to uint8_t
			for (int x = 0; x < width; x++) {
				for (int c = 0; c < channels; c++) {
					uint8_t out;
					convert(srcPtr[c*c_stride], out);
					*dstPtr++ = out;
				}
				srcPtr++;
			}
		} else {
			_assert(bit_depth == 8 || bit_depth == 16, "We only support saving 8- and 16-bit images.");
		}
	}
Example #17
0
//int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) {
int  pngLoadRaw(const char* filename, pngRawInfo *pinfo, vsxf* filesystem) {
	unsigned char header[8];
	png_structp png;
	png_infop   info;
	png_infop   endinfo;
	png_bytep   data;
  png_bytep  *row_p;
  double fileGamma;
  vsxf_info i_filesystem;

	png_uint_32 width, height;
	int depth, color;

	png_uint_32 i;

	if (pinfo == NULL) {
    printf("error in png loader: pinfo is NULL %d\n",__LINE__);
    return 0;
  }
	i_filesystem.filesystem = filesystem;
	i_filesystem.fp = filesystem->f_open(filename,"rb");
	if (!i_filesystem.fp) {
    printf("error in png loader: i_filesystem.fp not valid on line %d\n",__LINE__);
    return 0;
  }
  
	filesystem->f_read(header, 8, i_filesystem.fp);
	if (!png_check_sig(header, 8)) {
    printf("error in %s on line %d\n",__FILE__,__LINE__);
    return 0;
  }

	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png) {
    printf("error in %s on line %d\n",__FILE__,__LINE__);
    return 0;
  }
	info = png_create_info_struct(png);
  if (!info)
  {
      png_destroy_read_struct(&png,(png_infopp)NULL,(png_infopp)NULL);
      printf("error in %s on line %d\n",__FILE__,__LINE__);
      return 0;
  }
  endinfo = png_create_info_struct(png);
  if (!endinfo)
  {
    png_destroy_read_struct(&png, &info, (png_infopp)NULL);
    printf("error in %s on line %d\n",__FILE__,__LINE__);
    return 0;
  }

  if (setjmp(png_jmpbuf(png)))
  {
    printf("error in png_jmpbuf %s on line %d\n",__FILE__,__LINE__);
    png_destroy_read_struct(&png, &info,&endinfo);
    filesystem->f_close(i_filesystem.fp);
    return 0;
  }

	png_set_read_fn(png, (png_bytep)(&i_filesystem), png_vsxf_read_data);
  png_set_sig_bytes(png, 8);
	png_read_info(png, info);
	png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);

	pinfo->Width  = width;
	pinfo->Height = height;
	pinfo->Depth  = depth;

	if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png);
		
  if (color == PNG_COLOR_TYPE_PALETTE)
			png_set_expand(png);

	/*--GAMMA--*/
	checkForGammaEnv();
	if (png_get_gAMA(png, info, &fileGamma))
		png_set_gamma(png, screenGamma, fileGamma);
	else
		png_set_gamma(png, screenGamma, 1.0/2.2);

	png_read_update_info(png, info);

	data = (png_bytep) malloc(png_get_rowbytes(png, info)*height);
	row_p = (png_bytep *) malloc(sizeof(png_bytep)*height);

	for (i = 0; i < height; i++) {
		if (StandardOrientation)
			row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i];
		else
			row_p[i] = &data[png_get_rowbytes(png, info)*i];
	}

	png_read_image(png, row_p);
	free(row_p);

	if (color == PNG_COLOR_TYPE_PALETTE) {
		int cols;
		png_get_PLTE(png, info, (png_colorp *) &pinfo->Palette, &cols);
	}
	else {
		pinfo->Palette = NULL;
	}

	if (color&PNG_COLOR_MASK_ALPHA) {
		if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY_ALPHA)
			pinfo->Components = 2;
		else
			pinfo->Components = 4;
		pinfo->Alpha = 8;
	}
	else {
		if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY)
			pinfo->Components = 1;
		else
			pinfo->Components = 3;
		pinfo->Alpha = 0;
	}

	pinfo->Data = data;

   png_read_end(png, endinfo);
	png_destroy_read_struct(&png, &info, &endinfo);
  filesystem->f_close(i_filesystem.fp);
	return 1;
}
Example #18
0
void load_png_buffer(std::string filename, buffer_t &buf) {
	png_byte header[8];
	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep *row_pointers;

	/* open file and test for it being a png */
	FILE *f = fopen(filename.c_str(), "rb");
	_assert(f, "File %s could not be opened for reading\n", filename.c_str());
	_assert(fread(header, 1, 8, f) == 8, "File ended before end of header\n");
	_assert(!png_sig_cmp(header, 0, 8), "File %s is not recognized as a PNG file\n", filename.c_str());

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

	_assert(png_ptr, "png_create_read_struct failed\n");

	info_ptr = png_create_info_struct(png_ptr);
	_assert(info_ptr, "png_create_info_struct failed\n");

	_assert(!setjmp(png_jmpbuf(png_ptr)), "Error during init_io\n");

	png_init_io(png_ptr, f);
	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_height(png_ptr, info_ptr);
	int channels = png_get_channels(png_ptr, info_ptr);
	int bit_depth = png_get_bit_depth(png_ptr, info_ptr);

	// Expand low-bpp images to have only 1 pixel per byte (As opposed to tight packing)
	if (bit_depth < 8) {
		png_set_packing(png_ptr);
	}

	if (channels != 1) {
		buf.extent[0] = width;
		buf.extent[1] = height;
		buf.extent[2] = channels;

		buf.stride[0] = 1;
		buf.stride[1] = width;
		buf.stride[2] = width*height;
	} else {
		buf.extent[0] = width;
		buf.extent[1] = height;

		buf.stride[0] = 1;
		buf.stride[1] = width;
	}

	if (bit_depth == 8) {
		buf.elem_size = 1;
	} else {
		buf.elem_size = 2;
	}

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

	// read the file
	_assert(!setjmp(png_jmpbuf(png_ptr)), "Error during read_image\n");

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

	png_read_image(png_ptr, row_pointers);

	fclose(f);

	_assert((bit_depth == 8) || (bit_depth == 16), "Can only handle 8-bit or 16-bit pngs\n");

	// convert the data to uint8_t

	int c_stride = (channels == 1) ? 0 : width*height;
	uint8_t *img = (uint8_t*)malloc(width*height*channels*sizeof(uint8_t));
	uint8_t *ptr = img;
	_assert(ptr, "Error alocation memory for buffer.");
	if (bit_depth == 8) {
		for (int y = 0; y < height; y++) {
			uint8_t *srcPtr = (uint8_t *)(row_pointers[y]);
			for (int x = 0; x < width;x++) {
				for (int c = 0; c < channels; c++) {
					convert(*srcPtr++, ptr[c*c_stride]);
				}
				ptr++;
			}
		}
	} else if (bit_depth == 16) {
		for (int y = 0; y < height; y++) {
			uint8_t *srcPtr = (uint8_t *)(row_pointers[y]);
			for (int x = 0; x < width; x++) {
				for (int c = 0; c < channels; c++) {
					uint16_t hi = (*srcPtr++) << 8;
					uint16_t lo = hi | (*srcPtr++);
					convert(lo, ptr[c*c_stride]);
				}
				ptr++;
			}
		}
	}

	// Fill buffer_t
	buf.host = img;

	// clean up
	for (int y = 0; y < height; y++) {
		delete[] row_pointers[y];
	}
	delete[] row_pointers;

	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

	buf.host_dirty = true;
}
Example #19
0
int image_png_compress(MediaScanImage *i, MediaScanThumbSpec *spec) {
  int j, x, y;
  int color_space = PNG_COLOR_TYPE_RGB_ALPHA;
  volatile unsigned char *ptr = NULL;
  png_structp png_ptr;
  png_infop info_ptr;
  Buffer *buf;

  if (!i->_pixbuf_size) {
    LOG_WARN("PNG compression requires pixbuf data (%s)\n", i->path);
    return 0;
  }

  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png_ptr) {
    FATAL("Could not initialize libpng\n");
  }

  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    png_destroy_write_struct(&png_ptr, NULL);
    FATAL("Could not initialize libpng\n");
  }

  // Initialize buffer for compressed data
  buf = (Buffer *)malloc(sizeof(Buffer));
  buffer_init(buf, BUF_SIZE);
  i->_dbuf = (void *)buf;

  png_set_write_fn(png_ptr, buf, image_png_write_buf, image_png_flush_buf);

  if (setjmp(png_jmpbuf(png_ptr))) {
    if (ptr != NULL)
      free((void *)ptr);
    return 0;
  }

  // Match output color space with input file
  switch (i->channels) {
    case 4:
    case 3:
      LOG_DEBUG("PNG output color space set to RGBA\n");
      color_space = PNG_COLOR_TYPE_RGB_ALPHA;
      break;
    case 2:
    case 1:
      LOG_DEBUG("PNG output color space set to gray alpha\n");
      color_space = PNG_COLOR_TYPE_GRAY_ALPHA;
      break;
  }

  png_set_IHDR(png_ptr, info_ptr, spec->width, spec->height, 8, color_space,
               PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

  png_write_info(png_ptr, info_ptr);

  ptr = (unsigned char *)malloc(png_get_rowbytes(png_ptr, info_ptr));

  j = 0;

  if (color_space == PNG_COLOR_TYPE_GRAY_ALPHA) {
    for (y = 0; y < spec->height; y++) {
      for (x = 0; x < spec->width; x++) {
        ptr[x * 2] = COL_BLUE(i->_pixbuf[j]);
        ptr[x * 2 + 1] = COL_ALPHA(i->_pixbuf[j]);
        j++;
      }
      png_write_row(png_ptr, (png_bytep) ptr);
    }
  }
  else {                        // RGB
    for (y = 0; y < spec->height; y++) {
      for (x = 0; x < spec->width; x++) {
        ptr[x * 4] = COL_RED(i->_pixbuf[j]);
        ptr[x * 4 + 1] = COL_GREEN(i->_pixbuf[j]);
        ptr[x * 4 + 2] = COL_BLUE(i->_pixbuf[j]);
        ptr[x * 4 + 3] = COL_ALPHA(i->_pixbuf[j]);
        j++;
      }
      png_write_row(png_ptr, (png_bytep) ptr);
    }
  }

  free((void *)ptr);

  png_write_end(png_ptr, info_ptr);

  png_destroy_write_struct(&png_ptr, &info_ptr);

  return 1;
}
    void initialize()
    {
        // Now it's time for some transformations.

        if( little_endian() )
        {
            if( this->_info._bit_depth == 16 )
            {
                // Swap bytes of 16 bit files to least significant byte first.
                png_set_swap( this->get()->_struct );
            }

            if( this->_info._bit_depth < 8 )
            {
                // swap bits of 1, 2, 4 bit packed pixel formats
                png_set_packswap( this->get()->_struct );
            }
        }

        if( this->_info._color_type == PNG_COLOR_TYPE_PALETTE )
        {
            png_set_palette_to_rgb( this->get()->_struct );
        }

        if( this->_info._num_trans > 0 )
        {
            png_set_tRNS_to_alpha( this->get()->_struct );
        }

        // Tell libpng to handle the gamma conversion for you.  The final call
        // is a good guess for PC generated images, but it should be configurable
        // by the user at run time by the user.  It is strongly suggested that
        // your application support gamma correction.
        if( this->_settings._apply_screen_gamma )
        {
            // png_set_gamma will change the image data!

#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
        png_set_gamma( this->get()->_struct
                     , this->_settings._screen_gamma
                     , this->_info._file_gamma
                     );
#else
        png_set_gamma( this->get()->_struct
                     , this->_settings._screen_gamma
                     , this->_info._file_gamma
                     );
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
        }

        // Interlaced images are not supported.
        this->_number_passes = png_set_interlace_handling( this->get()->_struct );
        io_error_if( this->_number_passes != 1
                   , "scanline_read_iterator cannot read interlaced png images."
                   );


        // The above transformation might have changed the bit_depth and color type.
        png_read_update_info( this->get()->_struct
                            , this->get()->_info
                            );

        this->_info._bit_depth = png_get_bit_depth( this->get()->_struct
                                                  , this->get()->_info
                                                  );

        this->_info._num_channels = png_get_channels( this->get()->_struct
                                                    , this->get()->_info
                                                    );

        this->_info._color_type = png_get_color_type( this->get()->_struct
                                                    , this->get()->_info
                                                    );

        this->_scanline_length = png_get_rowbytes( this->get()->_struct
                                                 , this->get()->_info
                                                 );
    }
Example #21
0
int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) {
	GLint pack, unpack;
	unsigned char header[8];
	png_structp png;
	png_infop   info;
	png_infop   endinfo;
	png_bytep   data, data2;
   png_bytep  *row_p;
   double	fileGamma;

	png_uint_32 width, height, rw, rh;
	int depth, color;

	png_uint_32 i;

	fread(header, 1, 8, fp);
	if (!png_check_sig(header, 8)) return 0;

	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	info = png_create_info_struct(png);
	endinfo = png_create_info_struct(png);

	// DH: added following lines
	if (setjmp(png->jmpbuf))
	{
		png_destroy_read_struct(&png, &info, &endinfo);
		return 0;
	}
	// ~DH

	png_init_io(png, fp);
	png_set_sig_bytes(png, 8);
	png_read_info(png, info);
	png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);

	if (pinfo != NULL) {
		pinfo->Width  = width;
		pinfo->Height = height;
		pinfo->Depth  = depth;
	}

	if (MaxTextureSize == 0)
		glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTextureSize);

	#ifdef SUPPORTS_PALETTE_EXT
	#ifdef _WIN32
		if (PalettedTextures == -1)
			PalettedTextures = ExtSupported("GL_EXT_paletted_texture") && (strstr((const char *) glGetString(GL_VERSION), "1.1.0 3Dfx Beta") == NULL);

		if (PalettedTextures) {
			if (glColorTableEXT == NULL) {
				glColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT");
				if (glColorTableEXT == NULL)
					PalettedTextures = 0;
			}
		}
	#endif
	#endif

	if (PalettedTextures == -1)
		PalettedTextures = 0;

	if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png);

	if (color&PNG_COLOR_MASK_ALPHA && trans != PNG_ALPHA) {
		png_set_strip_alpha(png);
		color &= ~PNG_COLOR_MASK_ALPHA;
	}

	if (!(PalettedTextures && mipmap >= 0 && trans == PNG_SOLID))
		if (color == PNG_COLOR_TYPE_PALETTE)
			png_set_expand(png);

	/*--GAMMA--*/
	checkForGammaEnv();
	if (png_get_gAMA(png, info, &fileGamma))
		png_set_gamma(png, screenGamma, fileGamma);
	else
		png_set_gamma(png, screenGamma, 1.0/2.2);

	png_read_update_info(png, info);

	data = (png_bytep) malloc(png_get_rowbytes(png, info)*height);
	row_p = (png_bytep *) malloc(sizeof(png_bytep)*height);

	for (i = 0; i < height; i++) {
		if (StandardOrientation)
			row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i];
		else
			row_p[i] = &data[png_get_rowbytes(png, info)*i];
	}

	png_read_image(png, row_p);
	free(row_p);

	rw = SafeSize(width), rh = SafeSize(height);

	if (rw != width || rh != height) {
		const int channels = png_get_rowbytes(png, info)/width;

		data2 = (png_bytep) malloc(rw*rh*channels);

 		/* Doesn't work on certain sizes */
/* 		if (gluScaleImage(glformat, width, height, GL_UNSIGNED_BYTE, data, rw, rh, GL_UNSIGNED_BYTE, data2) != 0)
 			return 0;
*/
		Resize(channels, data, width, height, data2, rw, rh);

		width = rw, height = rh;
		free(data);
		data = data2;
	}

	{ /* OpenGL stuff */
		glGetIntegerv(GL_PACK_ALIGNMENT, &pack);
		glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack);
		glPixelStorei(GL_PACK_ALIGNMENT, 1);
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

		#ifdef SUPPORTS_PALETTE_EXT
		if (PalettedTextures && mipmap >= 0 && trans == PNG_SOLID && color == PNG_COLOR_TYPE_PALETTE) {
			png_colorp pal;
			int cols;
			GLint intf;

			if (pinfo != NULL) pinfo->Alpha = 0;
			png_get_PLTE(png, info, &pal, &cols);

			switch (cols) {
				case 1<<1:  intf = GL_COLOR_INDEX1_EXT;  break;
				case 1<<2:  intf = GL_COLOR_INDEX2_EXT;  break;
				case 1<<4:  intf = GL_COLOR_INDEX4_EXT;  break;
				case 1<<8:  intf = GL_COLOR_INDEX8_EXT;  break;
				case 1<<12: intf = GL_COLOR_INDEX12_EXT; break;
				case 1<<16: intf = GL_COLOR_INDEX16_EXT; break;
				default:
					/*printf("Warning: Colour depth %i not recognised\n", cols);*/
					return 0;
			}
			glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, cols, GL_RGB, GL_UNSIGNED_BYTE, pal);
			glTexImage2D(GL_TEXTURE_2D, mipmap, intf, width, height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data);
		}
		else
		#endif
		if (trans == PNG_SOLID || trans == PNG_ALPHA || color == PNG_COLOR_TYPE_RGB_ALPHA || color == PNG_COLOR_TYPE_GRAY_ALPHA) {
			GLenum glformat;
			GLint glcomponent;

			switch (color) {
				case PNG_COLOR_TYPE_GRAY:
				case PNG_COLOR_TYPE_RGB:
				case PNG_COLOR_TYPE_PALETTE:
					glformat = GL_RGB;
					glcomponent = 3;
					if (pinfo != NULL) pinfo->Alpha = 0;
					break;

				case PNG_COLOR_TYPE_GRAY_ALPHA:
				case PNG_COLOR_TYPE_RGB_ALPHA:
					glformat = GL_RGBA;
					glcomponent = 4;
					if (pinfo != NULL) pinfo->Alpha = 8;
					break;

				default:
					/*puts("glformat not set");*/
					return 0;
			}

			if (mipmap == PNG_BUILDMIPMAPS)
				Build2DMipmaps(glcomponent, width, height, glformat, data, 1);
			else if (mipmap == PNG_SIMPLEMIPMAPS)
				Build2DMipmaps(glcomponent, width, height, glformat, data, 0);
			else
				glTexImage2D(GL_TEXTURE_2D, mipmap, glcomponent, width, height, 0, glformat, GL_UNSIGNED_BYTE, data);
		}
		else {
			png_bytep p, endp, q;
			int r, g, b, a;

			p = data, endp = p+width*height*3;
			q = data2 = (png_bytep) malloc(sizeof(png_byte)*width*height*4);

			if (pinfo != NULL) pinfo->Alpha = 8;

			#define FORSTART \
				do { \
					r = *p++; /*red  */ \
					g = *p++; /*green*/ \
					b = *p++; /*blue */ \
					*q++ = r; \
					*q++ = g; \
					*q++ = b;

			#define FOREND \
					q++; \
				} while (p != endp);

			#define ALPHA *q

			switch (trans) {
				case PNG_CALLBACK:
					FORSTART
						ALPHA = AlphaCallback((unsigned char) r, (unsigned char) g, (unsigned char) b);
					FOREND
					break;

				case PNG_STENCIL:
					FORSTART
						if (r == StencilRed && g == StencilGreen && b == StencilBlue)
							ALPHA = 0;
						else
							ALPHA = 255;
					FOREND
					break;

				case PNG_BLEND1:
					FORSTART
						a = r+g+b;
						if (a > 255) ALPHA = 255; else ALPHA = a;
					FOREND
					break;

				case PNG_BLEND2:
					FORSTART
						a = r+g+b;
						if (a > 255*2) ALPHA = 255; else ALPHA = a/2;
					FOREND
					break;

				case PNG_BLEND3:
					FORSTART
						ALPHA = (r+g+b)/3;
					FOREND
					break;

				case PNG_BLEND4:
					FORSTART
						a = r*r+g*g+b*b;
						if (a > 255) ALPHA = 255; else ALPHA = a;
					FOREND
					break;

				case PNG_BLEND5:
					FORSTART
						a = r*r+g*g+b*b;
						if (a > 255*2) ALPHA = 255; else ALPHA = a/2;
					FOREND
					break;

				case PNG_BLEND6:
					FORSTART
						a = r*r+g*g+b*b;
						if (a > 255*3) ALPHA = 255; else ALPHA = a/3;
					FOREND
					break;

				case PNG_BLEND7:
					FORSTART
						a = r*r+g*g+b*b;
						if (a > 255*255) ALPHA = 255; else ALPHA = (int) sqrt(a);
					FOREND
					break;
			}

			#undef FORSTART
			#undef FOREND
			#undef ALPHA

			if (mipmap == PNG_BUILDMIPMAPS)
				Build2DMipmaps(4, width, height, GL_RGBA, data2, 1);
			else if (mipmap == PNG_SIMPLEMIPMAPS)
				Build2DMipmaps(4, width, height, GL_RGBA, data2, 0);
			else
				glTexImage2D(GL_TEXTURE_2D, mipmap, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);

			free(data2);
		}

		glPixelStorei(GL_PACK_ALIGNMENT, pack);
		glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
	} /* OpenGL end */

   png_read_end(png, endinfo);
	png_destroy_read_struct(&png, &info, &endinfo);

	free(data);

	return 1;
}
Example #22
0
bool PNGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames)
{
    png_byte header[8];
    RGBAImage *ret = NULL;

    CFile fp;
    if (!fp.Open(filename))
    {
        perror(filename.c_str());
        return false;
    }

    // read the header
    fp.Read(header, 8);

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

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

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

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

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

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

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

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

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

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

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

    //set it to 32bit pixeldepth
    png_color_8 sig_bit;
    sig_bit.red = 32;
    sig_bit.green = 32;
    sig_bit.blue = 32;
    // if the image has an alpha channel then
    sig_bit.alpha = 32;
    png_set_sBIT(png_ptr, info_ptr, &sig_bit);


    /* Add filler (or alpha) byte (before/after each RGB triplet) */
    png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);


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

    /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
    //png_set_swap_alpha(png_ptr);


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

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

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

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

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

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

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

    frames.user = NULL;
    DecodedFrame frame;

    frame.rgbaImage.pixels = (char *)image_data;
    frame.rgbaImage.height = temp_height;
    frame.rgbaImage.width = temp_width;
    frame.rgbaImage.bbp = 32;
    frame.rgbaImage.pitch = 4 * temp_width;
    frames.frameList.push_back(frame);
    // clean up
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    delete [] row_pointers;
    return true;
}
Example #23
0
pdf_obj *start_png_image (FILE *file, char *res_name)
{
  pdf_obj *result = NULL, *dict = NULL;
  png_structp png_ptr;
  png_infop info_ptr;
  unsigned long width, height;
  unsigned bit_depth, color_type;
  rewind (file);
  if (!(png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,    
					  NULL, NULL, NULL)) ||
      !(info_ptr = png_create_info_struct (png_ptr))) {
    fprintf (stderr, "\n\nLibpng failed to initialize\n");
    if (png_ptr)
      png_destroy_read_struct(&png_ptr, NULL, NULL);
    return NULL;
  }
  png_init_io (png_ptr, file);
  /*  png_set_sig_bytes (png_ptr, 0); */
  /* Read PNG header */
  png_read_info (png_ptr, info_ptr);
  {
    png_color_16 default_background;
    png_color_16p file_background;

    default_background.red=255; default_background.green=255;
    default_background.blue=255; default_background.gray=0;
    default_background.index = 0;

    width = png_get_image_width(png_ptr, info_ptr);
    height = png_get_image_height(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
    bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    /* Convert paletted images to true color */
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
      png_set_expand(png_ptr);
    }
    /* Limit image component depth to 8 bits */
    if (bit_depth == 16) {
      png_set_strip_16 (png_ptr);
    }
    if (png_get_bKGD(png_ptr, info_ptr, &file_background)) {
      png_set_background(png_ptr, file_background,
			 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
    } else {
      png_set_background(png_ptr, &default_background,
			 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
    }
  }
  { /* Read the image in raw RGB format */
    int i, rowbytes, pdf_bit_depth;
    png_bytep *rows;
    png_read_update_info(png_ptr, info_ptr);
    rows = NEW (height, png_bytep);
    rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    rows[0] = NEW (rowbytes*height, png_byte);
    for (i=1; i<height; i++) {
      rows[i] = rows[0] + rowbytes * i;
    }
    png_read_image(png_ptr, rows);
    result = pdf_new_stream(STREAM_COMPRESS);
    dict = pdf_stream_dict(result);
    pdf_add_dict (dict, pdf_new_name ("Width"),
		  pdf_new_number(width));
    pdf_add_dict (dict, pdf_new_name ("Height"),
		  pdf_new_number(height));
    if (color_type == PNG_COLOR_TYPE_GRAY) {
      pdf_bit_depth = bit_depth;
    } else {
      pdf_bit_depth = 8;
    }
    pdf_add_dict (dict, pdf_new_name ("BitsPerComponent"),
		  pdf_new_number(pdf_bit_depth));
    if (color_type == PNG_COLOR_TYPE_GRAY ||
	color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
      pdf_add_dict (dict, pdf_new_name ("ColorSpace"),
		    pdf_new_name ("DeviceGray"));
    } else{
      pdf_add_dict (dict, pdf_new_name ("ColorSpace"),
		    pdf_new_name ("DeviceRGB"));
    }
    pdf_add_stream (result, (char *)rows[0], rowbytes*height);
    RELEASE (rows[0]);
    RELEASE (rows);
  }
  { /* Cleanup  */
    if (info_ptr)
      png_destroy_info_struct(png_ptr, &info_ptr);
    if (png_ptr)
      png_destroy_read_struct(&png_ptr, NULL, NULL);
  }
  return result;
}
Example #24
0
void png_reader::read(unsigned x0, unsigned y0,image_data_32& image)
{
    FILE *fp=fopen(fileName_.c_str(),"rb");
    if (!fp) throw image_reader_exception("cannot open image file "+fileName_);

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

    if (!png_ptr)
    {
        fclose(fp);
        throw image_reader_exception("failed to allocate png_ptr");
    }

    // catch errors in a custom way to avoid the need for setjmp
    png_set_error_fn(png_ptr, png_get_error_ptr(png_ptr), user_error_fn, user_warning_fn);

    png_infop info_ptr;
    try
    {
        info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr)
        {
            png_destroy_read_struct(&png_ptr,0,0);
            fclose(fp);
            throw image_reader_exception("failed to create info_ptr");
        }
    }
    catch (std::exception const& ex)
    {
        png_destroy_read_struct(&png_ptr,0,0);
        fclose(fp);
        throw;
    }

    png_set_read_fn(png_ptr, (png_voidp)fp, png_read_data);
    png_read_info(png_ptr, info_ptr);

    if (color_type_ == PNG_COLOR_TYPE_PALETTE)
        png_set_expand(png_ptr);
    if (color_type_ == PNG_COLOR_TYPE_GRAY && bit_depth_ < 8)
        png_set_expand(png_ptr);
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_expand(png_ptr);
    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);

    // quick hack -- only work in >=libpng 1.2.7
    png_set_add_alpha(png_ptr,0xff,PNG_FILLER_AFTER); //rgba

    double gamma;
    if (png_get_gAMA(png_ptr, info_ptr, &gamma))
        png_set_gamma(png_ptr, 2.2, gamma);

    if (x0 == 0 && y0 == 0 && image.width() >= width_ && image.height() >= height_)
    {

        if (png_get_interlace_type(png_ptr,info_ptr) == PNG_INTERLACE_ADAM7)
        {
            png_set_interlace_handling(png_ptr); // FIXME: libpng bug?
            // according to docs png_read_image
            // "..automatically handles interlacing,
            // so you don't need to call png_set_interlace_handling()"
        }
        png_read_update_info(png_ptr, info_ptr);
        // we can read whole image at once
        // alloc row pointers
        boost::scoped_array<png_byte*> rows(new png_bytep[height_]);
        for (unsigned i=0; i<height_; ++i)
            rows[i] = (png_bytep)image.getRow(i);
        png_read_image(png_ptr, rows.get());
    }
    else
    {
        png_read_update_info(png_ptr, info_ptr);
        unsigned w=std::min(unsigned(image.width()),width_);
        unsigned h=std::min(unsigned(image.height()),height_);
        unsigned rowbytes=png_get_rowbytes(png_ptr, info_ptr);
        boost::scoped_array<png_byte> row(new png_byte[rowbytes]);
        //START read image rows
        for (unsigned i=0;i<height_;++i)
        {
            png_read_row(png_ptr,row.get(),0);
            if (i>=y0 && i<h)
            {
                image.setRow(i-y0,reinterpret_cast<unsigned*>(&row[x0]),w);
            }
        }
        //END
    }

    png_read_end(png_ptr,0);
    png_destroy_read_struct(&png_ptr, &info_ptr,0);
    fclose(fp);
}
Example #25
0
bool Texture::load2DPNG(const char *name, bool genMIPs)
{
	ASSERT(name);

	png_structp png_ptr;
	png_infop   info_ptr;
	png_uint_32 width, height;
	int32_t     bit_depth, color_type, stride;
	uint8_t     *buffer, *data;
	png_bytep   *row_pointers;
	uint32_t    size;
	GLint       internalFormat;
	GLenum      format;

	if (!VFS::load(name, VFS_BINARY, &buffer, &size))
		return false;

	if (size <= 8)
	{
		LOG_ERROR("Too small PNG file '%s'\n", name);
		delete[] buffer;
		return false;
	}

	if (png_sig_cmp((png_byte *)buffer, 0, 8))
	{
		LOG_ERROR("Wrong PNG format '%s'\n", name);
		delete[] buffer;
		return false;
	}

	if ((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
		NULL, PNGError, NULL)) == NULL)
	{
		LOG_ERROR("Failed to create PNG read struct\n");
		delete[] buffer;
		return false;
	}

	if ((info_ptr = png_create_info_struct(png_ptr)) == NULL)
	{
		LOG_ERROR("Failed to create PNG info struct\n");
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		delete[] buffer;
		return false;
	}

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		delete[] buffer;
		return false;
	}

	png_set_read_fn(png_ptr, (void *)(buffer + 8), PNGRead);
	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);

	png_set_strip_16(png_ptr);
	png_set_packing(png_ptr);

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

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

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

	//if (color_type == PNG_COLOR_TYPE_GRAY || 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,
		NULL, NULL, NULL);

	switch (color_type)
	{
		case PNG_COLOR_TYPE_GRAY:
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			internalFormat = GL_R8;
			format         = GL_RED;
		break;
		case PNG_COLOR_TYPE_RGB:
			internalFormat = GL_RGB8;
			format         = GL_RGB;
		break;
		case PNG_COLOR_TYPE_RGBA:
			internalFormat = GL_RGBA8;
			format         = GL_RGBA;
		break;
		default:
			LOG_ERROR("Unknown PNG color type %d in '%s'\n", color_type, name);
			png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
			delete[] buffer;
			return false;
	}

	stride = png_get_rowbytes(png_ptr, info_ptr);

	row_pointers = new png_bytep[height];
	ASSERT(row_pointers);

	data = new uint8_t[height * stride];
	ASSERT(data);

	for (uint32_t i = 0; i < height; ++i)
		row_pointers[i] = (png_bytep)data + i * stride;

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

	delete[] row_pointers;
	delete[] buffer;

	image2D(GL_PVOID(data), width, height, internalFormat, format,
		GL_UNSIGNED_BYTE, genMIPs);

	delete[] data;

	return true;
}
Example #26
0
/** 
Reads one PNG file. 
@param process Process the image data (0 for initial parameter determination)
@returns -1 on failure, 1 on sucess
*/
int decode_png(const char *pngname, int process, parameters_t *param)
{
  int num_pass = 1;
  int bit_depth, color_type;
  FILE *pngfile;
  //png_byte hdptr[8];

  /* Now open this PNG file, and examine its header to retrieve the 
     YUV4MPEG info that shall be written */
  pngfile = fopen(pngname, "rb");
  if (!pngfile)
    {
      perror("PNG file open failed:");
      return -1;
    }

  //fread(hdptr, 1, 8, pngfile);

#if 0 
  bool is_png = !png_sig_cmp(hdptr, 0, 8);
  if (!is_png)
    {
      mjpeg_error("%s is _no_ PNG file !\n");
      return -1;
    }
#endif
  
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png_ptr)
    mjpeg_error_exit1("%s: Could not allocate PNG read struct !", pngname);
  
  png_init_io(png_ptr, pngfile);
  //png_set_sig_bytes(png_ptr, 8);
  
  info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr)
    {
      png_destroy_read_struct(&png_ptr,
			      (png_infopp)NULL, (png_infopp)NULL);
      mjpeg_error_exit1("%s: Could not allocate PNG info struct !", pngname);
    }
  
  end_info = png_create_info_struct(png_ptr);
  if (!end_info)
    {
      png_destroy_read_struct(&png_ptr, &info_ptr,
			      (png_infopp)NULL);
      mjpeg_error_exit1("%s: Could not allocate PNG end info struct !", pngname);
    }
  
  if (setjmp(png_jmpbuf(png_ptr)))
    {
      png_destroy_read_struct(&png_ptr, &info_ptr,
			      &end_info);
      mjpeg_error("%s: Corrupted PNG file !", pngname);
      return -1;
    }
  
  if (process)
    png_set_read_user_transform_fn(png_ptr, png_separation);
  png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_STRIP_ALPHA, NULL);
  
  if (png_get_IHDR(png_ptr, info_ptr, &param->width, &param->height, &bit_depth,
		       //   &color_type, &interlace_type, &compression_type, &filter_type))
		   &color_type, NULL, NULL, NULL))	
    num_pass = png_set_interlace_handling(png_ptr);
  else
    mjpeg_error_exit1("PNG header reading failed !!\n");
#if 0 
  mjpeg_info("Reading info struct...\n");
  png_read_info(png_ptr, info_ptr);
  mjpeg_info("Done...\n");
  
  if (png_get_IHDR(png_ptr, info_ptr, &param->width, &param->height, &bit_depth,
		       //   &color_type, &interlace_type, &compression_type, &filter_type))
		   &color_type, NULL, NULL, NULL))	
    num_pass = png_set_interlace_handling(png_ptr);
  else
    mjpeg_error_exit1("PNG header reading failed !!\n");
  
  if (process)
    {
      printf("%d passes needed\n\n", num_pass);
      
      if (bit_depth != 8 && bit_depth != 16)
	{
	  mjpeg_error_exit1("Invalid bit_depth %d, only 8 and 16 bit allowed !!\n", bit_depth);
	}
      
      png_set_strip_16(png_ptr); // always has to strip the 16bit input, MPEG can't handle it	  
      png_set_strip_alpha(png_ptr); // Alpha can't be processed until Z/Alpha is integrated
      
      printf("\nAllocating row buffer...");
      png_set_read_user_transform_fn(png_ptr, png_separation);
      png_bytep row_buf = (png_bytep)png_malloc(png_ptr,
						png_get_rowbytes(png_ptr, info_ptr));
      
      for (int n=0; n < num_pass; n++)
	for (int y=0; y < sh_param->height; y++)
	  {
	    printf("Writing row data for pass %d\n", n);
	    png_read_rows(png_ptr, (png_bytepp)&row_buf, NULL, 1);
	  }
      
      png_free(png_ptr, row_buf);	      
    }
  png_read_end(png_ptr, info_ptr);
#endif  
  if (setjmp(png_ptr->jmpbuf)) {
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    return 2;
    }

  fclose(pngfile);

  return 1;
}
Example #27
0
color_image_t * color_image_png_load( FILE* fp, const char* file_name )
{
    // read the header
    png_byte header[8];
    fread(header, 1, 8, fp);
    
    if (png_sig_cmp(header, 0, 8))
    {
        err_printf( "error: %s is not a PNG.\n", file_name);
        fclose(fp);
        return 0;
    }
    
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
    {
        err_printf( "error: png_create_read_struct returned 0.\n");
        fclose(fp);
        return 0;
    }
    
    // create png info struct
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        err_printf( "error: png_create_info_struct returned 0.\n");
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        fclose(fp);
        return 0;
    }
    
    // create png info struct
    png_infop end_info = png_create_info_struct(png_ptr);
    if (!end_info)
    {
        err_printf( "error: png_create_info_struct returned 0.\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
        fclose(fp);
        return 0;
    }

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

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

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

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

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

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

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

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

    // Allocate the image_data as a big block, to be given to opengl
    png_byte * image_data;
    image_data = NEWA(png_byte, rowbytes * temp_height);
    assert(image_data!=NULL);

    // row_pointers is for pointing to image_data for reading the png with libpng
    png_bytep * row_pointers = NEWA(png_bytep, temp_height);
    assert(row_pointers!=NULL);

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

    // read the png into image_data through row_pointers
    png_read_image(png_ptr, row_pointers);
    
    // copy into color image
    color_image_t* image = color_image_new(temp_width,temp_height);
    if( color_type==0 ) {
      assert((unsigned)rowbytes == temp_width || !"error: not a proper gray png image");
      for(i=0; i<temp_width*temp_height; i++)
        image->c1[i] = image->c2[i] = image->c3[i] = image_data[i];
      
    }
    else if( color_type == 2 ) {
      assert((unsigned)rowbytes == 3*temp_width || !"error: not a proper color png image");
      for(i=0; i<temp_width*temp_height; i++) {
        image->c1[i] = image_data[3*i+0];
        image->c2[i] = image_data[3*i+1];
        image->c3[i] = image_data[3*i+2];
      }
    } else
      assert(!"error: unknown PNG color type" );
    
    // clean up
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    free(row_pointers);
    free(image_data);
    
    return image;
}
Example #28
0
unsigned char *sdlgl_load_png_file(const char *filename,
    int *image_w, int *image_h)
{
  /* -AJA- all these volatiles here may seem strange.  They are needed
   * because the ANSI C standard (which GCC adheres to) says that when
   * setjmp/longjmp is being used, only volatile local variables are
   * guaranteed to keep their state if longjmp() gets called.
   */
  FILE * volatile fp = NULL;
  unsigned char * volatile image_dat = NULL;
  png_bytep * volatile row_pointers = NULL;

  /* we take the address of these two, so we shouldn't need the
   * volatile.  (GCC complains about discarding qualifiers if the
   * volatile is there).
   */
  png_structp /*volatile*/ png_ptr = NULL;
  png_infop   /*volatile*/ info_ptr = NULL;

  char sig_buf[CHECK_PNG_BYTES];
  png_uint_32 width, height;
  int bit_depth, color_type, interlace_type;
  int row, stride;

  /* open the prospective PNG file */
#ifdef FILE_AREAS
  fp = fopen_datafile_area(FILE_AREA_SHARE, filename, RDBMODE, FALSE);
#else
  fp = fopen_datafile(filename, RDBMODE, FALSE);
#endif
  if (!fp)
  {
    sdlgl_warning("Failed to open file: %s\n", filename);
    return NULL;
  }

  /* read in some of the signature bytes */
  if (fread(sig_buf, 1, CHECK_PNG_BYTES, fp) != CHECK_PNG_BYTES)
  {
    sdlgl_warning("Failed to read from file: %s\n", filename);
    goto failed;
  }

  /* compare the first CHECK_PNG_BYTES bytes of the signature */
  if (png_sig_cmp(sig_buf, (png_size_t)0, CHECK_PNG_BYTES) != 0)
  {
    sdlgl_warning("File is not a PNG file: %s\n", filename);
    goto failed;
  }

  /* pass NULLs for the error functions -- thus use the setjump stuff
   */
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

  if (png_ptr == NULL)
  {
    sdlgl_warning("Problem within LibPNG (no memory ?)\n");
    goto failed;
  }

  /* allocate/initialize the memory for image information */
  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL)
  {
    sdlgl_warning("Out of memory with LibPNG\n");
    goto failed;
  }

  /* set error handling since we are using the setjmp/longjmp method
   * (this is the normal method of doing things with libpng).
   */
  if (setjmp(png_ptr->jmpbuf))
  {
    sdlgl_warning("Problem within LibPNG (unknown)\n");
    goto failed;
  }

  /* set up the input control since we're using standard C streams */
  png_init_io(png_ptr, fp);
  png_set_sig_bytes(png_ptr, CHECK_PNG_BYTES);

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

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

  *image_w = (int)width;
  *image_h = (int)height;

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

  /* expand paletted colors into true RGB triplets */
  if (color_type == PNG_COLOR_TYPE_PALETTE ||
      color_type == PNG_COLOR_TYPE_GRAY ||
      png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
  {
     png_set_expand(png_ptr);
  }

  /* set alpha position and filler value */
  png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
 
  /* let all the above calls take effect */
  png_read_update_info(png_ptr, info_ptr);
  
  /* allocate the memory for the image */
  stride = png_get_rowbytes(png_ptr, info_ptr);

  image_dat = (unsigned char *) alloc(height * stride);
  row_pointers = (png_bytep *) alloc(height * sizeof(png_bytep));
   
  for (row=0; row < height; row++)
  {
     row_pointers[row] = image_dat + row * stride;
  }

  /* now read in the image.  Yeah baby ! */
  png_read_image(png_ptr, row_pointers);
  png_read_end(png_ptr, info_ptr);

  /* free stuff & close the file */
  png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
  free(row_pointers);
  fclose(fp);

  return image_dat;

  /* -AJA- Normally I don't like gotos.  In this situation where there
   * are lots of points of possible failure and a growing set of
   * things to be undone, it makes for nicer code.
   */
failed:

  if (image_dat)
    free(image_dat);
  
  if (png_ptr)
  {
    /* assume NULLs not allowed (png docs don't say, bad bad) */
    if (info_ptr)
      png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
    else
      png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
  }

  if (row_pointers)
    free(row_pointers);

  if (fp)
    fclose(fp);
  
  return NULL;
}
Example #29
0
bool imagePNG( void const    *inData,     // input
               unsigned long  inSize,     // input
               void const    *&pixData,   // output
               unsigned short &width,     // output
               unsigned short &height,    // output
               void const    *&alpha )    // output : 0 if none, delete [] when done
{
   pixData = alpha = 0 ; width = height = 0 ;

   png_bytep pngData = (png_bytep)inData ;
   unsigned const pngLength = inSize ;
   if( 8 < pngLength )
   {
      if( 0 == png_sig_cmp( pngData, 0, pngLength ) )
      {
         png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
         {
            if( png_ptr )
            {
               png_infop info_ptr = png_create_info_struct(png_ptr);
               if( info_ptr )
               {
                  png_infop end_info = png_create_info_struct(png_ptr);
                  if( end_info )
                  {
                     if( 0 == setjmp( png_jmpbuf( png_ptr ) ) )
                     {
                        pngData_t pngFile ;
                        pngFile.data_   = pngData ;
                        pngFile.length_ = pngLength ;
                        
                        png_set_read_fn( png_ptr, &pngFile, pngRead );

                        png_read_info(png_ptr, info_ptr);
#ifdef __STANDALONE__
dumpPNGInfo( info_ptr );
#endif
                        int interlace_type, compression_type, filter_type;
                        png_uint_32 lWidth, lHeight;
                        int bit_depth, color_type;

                        png_get_IHDR( png_ptr, info_ptr, &lWidth, &lHeight,
                                      &bit_depth, &color_type, &interlace_type,
                                      &compression_type, &filter_type);
                        if( PNG_COLOR_MASK_PALETTE == ( PNG_COLOR_MASK_PALETTE & color_type ) )
                           png_set_palette_to_rgb( png_ptr );

                        png_read_update_info(png_ptr, info_ptr);

                        png_bytep *const row_pointers = new png_bytep[lHeight];
                        unsigned const rowBytes = png_get_rowbytes( png_ptr, info_ptr );

                        for( unsigned row = 0; row < lHeight; row++ )
                        {
                           row_pointers[row] = (png_bytep)png_malloc( png_ptr, rowBytes );
                        }
                        
                        png_read_image( png_ptr, row_pointers );

                        width  = (unsigned short)lWidth ;
                        height = (unsigned short)lHeight ;

                        fbDevice_t &fb = getFB();

                        unsigned char *const alphaChannel = ( color_type & PNG_COLOR_MASK_ALPHA )
                                                            ? new unsigned char [ width*height ]
                                                            : 0 ;

                        unsigned short *const pixMap = new unsigned short [ width*height ];
                        for( unsigned row = 0 ; row < height ; row++ )
                        {
                           unsigned char const *imgRow = row_pointers[row];
                           for( unsigned column = 0 ; column < width ; column++, imgRow += info_ptr->channels )
                           {
                              pixMap[row*width+column] = fb.get16( imgRow[0], imgRow[1], imgRow[2] );
                              if( alphaChannel )
                                 alphaChannel[row*width+column] = imgRow[3];
                           }
                        }

                        pixData = pixMap ;
                        alpha   = alphaChannel ;

                        for( unsigned row = 0; row < lHeight ; row++ )
                           png_free( png_ptr, row_pointers[row] );
                        
                        delete [] row_pointers ;
                     }
                     else
                        fprintf( stderr, "Internal PNG error\n" );

                     png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
                  }
               }
               else
                  png_destroy_read_struct( &png_ptr, 0, 0 );
            }
         }
      }
      else
         fprintf( stderr, "Not a PNG file\n" );
   }
   else
      fprintf( stderr, "PNG too short!\n" );

   return 0 != pixData ;

}
Example #30
0
bool ossimPngReader::initReader()
{
   bool result = true;
   
   ossim_uint32 height    = png_get_image_height(m_pngReadPtr, m_pngReadInfoPtr);
   ossim_uint32 width     = png_get_image_width(m_pngReadPtr, m_pngReadInfoPtr);
   m_bitDepth            = png_get_bit_depth(m_pngReadPtr, m_pngReadInfoPtr);
   m_pngColorType        = png_get_color_type(m_pngReadPtr, m_pngReadInfoPtr);
   
   m_imageRect = ossimIrect(0, 0, width  - 1, height - 1);
   
   if (m_bitDepth == 16)
   {
      // png_set_strip_16 (m_pngReadPtr);
      m_bytePerPixelPerBand = 2;
      m_outputScalarType = OSSIM_UINT16;
   }
   else
   {
      m_bytePerPixelPerBand = 1;
   }

   // Set the read mode from scalar and color type.
   if (m_outputScalarType == OSSIM_UINT8)
   {
      if ( (m_pngColorType == PNG_COLOR_TYPE_RGB_ALPHA) ||
           (m_pngColorType == PNG_COLOR_TYPE_GRAY_ALPHA) )
      {
         m_readMode = ossimPngRead8a;
      }
      else
      {
         m_readMode = ossimPngRead8;
      }
   }
   else
   {
      if ( (m_pngColorType == PNG_COLOR_TYPE_RGB_ALPHA) ||
           (m_pngColorType == PNG_COLOR_TYPE_GRAY_ALPHA) )
      {
         m_readMode = ossimPngRead16a;
      }
      else
      {
         m_readMode = ossimPngRead16;
      }

      // Set the swap flag.  PNG stores data in network byte order(big endian).
      if(ossim::byteOrder() == OSSIM_LITTLE_ENDIAN)
      {
         m_swapFlag = true;
      }
   }
   
   //---
   // If png_set_expand used:
   // Expand data to 24-bit RGB, or 8-bit grayscale,
   // with alpha if available.
   //---
   bool expandFlag = false;

   if ( m_pngColorType == PNG_COLOR_TYPE_PALETTE )
   {
      expandFlag = true;
   }
   if ( (m_pngColorType == PNG_COLOR_TYPE_GRAY) && (m_bitDepth < 8) )
   {
      expandFlag = true;
   }
   if ( png_get_valid(m_pngReadPtr, m_pngReadInfoPtr, PNG_INFO_tRNS) )
   {
      expandFlag = true;
   }

   //---
   // If png_set_packing used:
   // Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
   //---
   bool packingFlag = false;

   if ( (m_bitDepth < 8) && (m_pngColorType == PNG_COLOR_TYPE_GRAY) )
   {
      packingFlag = true;
   }

   if (expandFlag)
   {
       png_set_expand(m_pngReadPtr);
   }
   if (packingFlag)
   {
      png_set_packing(m_pngReadPtr);
   }

   // Gamma correction.
   // ossim_float64 gamma;
   // if (png_get_gAMA(m_pngReadPtr, m_pngReadInfoPtr, &gamma))
   // {
   //    png_set_gamma(png_ptr, display_exponent, gamma);
   // }

   //---
   // Turn on interlace handling... libpng returns just 1 (ie single pass)
   //  if the image is not interlaced
   //---
   m_interlacePasses = png_set_interlace_handling (m_pngReadPtr);

   //---
   // Update the info structures after the transformations take effect
   //---
   png_read_update_info (m_pngReadPtr, m_pngReadInfoPtr);

   // TODO:
   // Add check for image offsets.
   // Add check for resolution.
   // Add check for colormap.

   switch (m_pngColorType)
   {
      case PNG_COLOR_TYPE_RGB:           /* RGB */
      {
         m_numberOfInputBands  = 3;
         m_numberOfOutputBands = 3;
         break;
      }  
      case PNG_COLOR_TYPE_RGB_ALPHA:     /* RGBA */
      {
         m_numberOfInputBands  = 4;
         if (m_useAlphaChannelFlag)
         {
            m_numberOfOutputBands = 4;     
         }
         else
         {
            m_numberOfOutputBands = 3;    
         }         
         break;
      }
      case PNG_COLOR_TYPE_GRAY:          /* Grayscale */
      {
         m_numberOfInputBands = 1;
         m_numberOfOutputBands = 1;
         break;
      }  
      case PNG_COLOR_TYPE_GRAY_ALPHA:    /* Grayscale + alpha */
      {
         m_numberOfInputBands = 2;
         if (m_useAlphaChannelFlag)
         {
            m_numberOfOutputBands = 2;     
         }
         else
         {
            m_numberOfOutputBands = 1;
         }
        break;
      }
     case PNG_COLOR_TYPE_PALETTE:       /* Indexed */
     {
        m_numberOfInputBands  = 3;
        m_numberOfOutputBands = 3;
        break;
     }  
     default:                   /* Unknown type */
     {
        result = false;
     }
   }

   if ( result )
   {
      m_lineBufferSizeInBytes = png_get_rowbytes(m_pngReadPtr, m_pngReadInfoPtr);
      
      // Set the max pixel value.
      setMaxPixelValue();
      
      // Set to OSSIM_USHORT11 for use of specialized tile.
      if (m_maxPixelValue[0] == 2047.0)
      {
         m_outputScalarType = OSSIM_USHORT11;
      }

      // We're on row 0 or first line.
      m_currentRow = 0;
      
      if (traceDebug())
      {
         ossimNotify(ossimNotifyLevel_DEBUG)
            << "ossimPngReader::initReader DEBUG:"
            << "\nm_imageRect:                     " << m_imageRect
            << "\nm_bitDepth:                      " << int(m_bitDepth)
            << "\nm_pngColorType:                  "
            <<  getPngColorTypeString().c_str()
            << "\nm_numberOfInputBands:            " << m_numberOfInputBands
            << "\nm_numberOfOutputBands:           " << m_numberOfOutputBands
            << "\nm_bytePerPixelPerBand:           " << m_bytePerPixelPerBand
            << "\nm_lineBufferSizeInBytes:         " << m_lineBufferSizeInBytes
            << "\nm_interlacePasses:               " << m_interlacePasses
            << "\npalette expansion:                "
            << (expandFlag?"on":"off")
            << "\npacking (1,2,4 bit to one byte):  "
            << (packingFlag?"on":"off")
            << "\nm_readMode:                      " << m_readMode
            << "\nm_swapFlag:                      " << m_swapFlag
            << std::endl;
         
         for (ossim_uint32 band = 0; band < m_numberOfInputBands; ++band)
         {
            ossimNotify(ossimNotifyLevel_DEBUG)
               << "max[" << band << "]:  " << m_maxPixelValue[band]
               << std::endl;
         }
      }
   }

   return result;
   
} // End: ossimPngReader::initReader()