Example #1
0
void pgeTextureSave(pgeTexture *texture, const char* filename)
{
	if(texture == 0)
		return;
		
	if(texture->data == 0 || texture->width == 0 || texture->height == 0)
		return;
		
	int swizzled = texture->swizzled;
	
	if(swizzled)
		pgeTextureUnswizzle(texture);
	
	png_structp png_ptr;
	png_infop info_ptr;
	FILE* fp;
	unsigned char* line;

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	
	if(!png_ptr)
		return;
	
	info_ptr = png_create_info_struct(png_ptr);
	
	if(!info_ptr)
	{
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		
		return;
	}
	
	unsigned int col_type = PNG_COLOR_TYPE_RGBA;

	fp = fopen(filename, "wb");
	if (!fp) return;
	
	png_init_io(png_ptr, fp);
	png_set_IHDR(png_ptr, info_ptr, texture->width, texture->height, 8, col_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
	png_write_info(png_ptr, info_ptr);
	
	line = (unsigned char*) pgeMalloc(texture->width * 4);
	
	if(line == 0)
	{
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		fclose(fp);
		
		return;
	}
	
	unsigned char* src = (unsigned char*)texture->data;
	unsigned char* src8 = (unsigned char*)src;
	unsigned short* src16 = (unsigned short*)src;
	unsigned int* src32 = (unsigned int*)src;

	unsigned int i, x, y;
	
	for(y = 0; y < texture->height; y++)
	{
		unsigned int swap = 0;
		src8 = (unsigned char*)src;
		src16 = (unsigned short*)src;
		src32 = (unsigned int*)src;
		
		for(i = 0, x = 0; x < texture->width; x++)
		{
			unsigned int r = 0, g = 0, b = 0, a = 0;
			unsigned short col16;
			unsigned int col32;
			unsigned char col8;
			
			switch(texture->format)
			{
				case PGE_PIXEL_FORMAT_5650:
					col16 = *src16++;
					RGBA5650(col16,r,g,b,a);
					break;
					
				case PGE_PIXEL_FORMAT_5551:
					col16 = *src16++;
					RGBA5551(col16,r,g,b,a);
					break;
					
				case PGE_PIXEL_FORMAT_4444:
					col16 = *src16++;
					RGBA4444(col16,r,g,b,a);
					break;
					
				case PGE_PIXEL_FORMAT_8888:
					col32 = *src32++;
					RGBA8888(col32,r,g,b,a);
					break;
					
				case PGE_PIXEL_FORMAT_T4:
					col8 = *src8;
					
					if(swap == 0)
						col8 &= 0xF;
					else
					{
						col8 >>= 4;
						src8++;
					}
					
					swap ^= 1;
					pgeTexturePaletteGet(texture, col8, &r, &g, &b, &a);
					break;
					
				case PGE_PIXEL_FORMAT_T8:
					col8 = *src8++;
					pgeTexturePaletteGet(texture, col8, &r, &g, &b, &a);
					break;
					
				case PGE_PIXEL_FORMAT_T16:
				case PGE_PIXEL_FORMAT_T32:
				default:
					break;
			}
			
			line[i++] = r;
			line[i++] = g;
			line[i++] = b;
			line[i++] = a;
		}
		
		png_write_row(png_ptr, line);
		src += ((texture->textureWidth*texture->bits) >> 3);
	}
	
	pgeFree(line);
	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
	fclose(fp);
	
	if(swizzled)
		pgeTextureSwizzle(texture);
}
Example #2
0
int read_png_file(const char *file, int32 *pwidth, int32 *pheight, uint8 **image_data_ptr)
{
	FILE         *infile;         /* PNG file pointer */
	png_structp   png_ptr;        /* internally used by libpng */
	png_infop     info_ptr;       /* user requested transforms */
	
	uint8 *image_data;      /* raw png image data */
	char         sig[8];           /* PNG signature array */
	/*char         **row_pointers;   */
	
	int           bit_depth;
	int           color_type;
	
	png_uint_32 width;            /* PNG image width in pixels */
	png_uint_32 height;           /* PNG image height in pixels */
	unsigned int rowbytes;         /* raw bytes at row n in image */
	
	image_data = NULL;
	int i;
	png_bytepp row_pointers = NULL;
	
	/* Open the file. */
	infile = fopen(file, "rb");
	if (!infile) {
		
		return 0;
	}
	
	
	/*
	 * 		13.3 readpng_init()
	 */
	
	/* Check for the 8-byte signature */
	fread(sig, 1, 8, infile);
	
	if (png_sig_cmp((unsigned char *) sig, 0, 8) != 0) {
		fclose(infile);
		return 0;
	}
	
	/* 
	 * Set up the PNG structs 
	 */
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) {
		fclose(infile);
		return 4;    /* out of memory */
	}
	
	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
		fclose(infile);
		return 4;    /* out of memory */
	}
	
	
	/*
	 * block to handle libpng errors, 
	 * then check whether the PNG file had a bKGD chunk
	 */
	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		fclose(infile);
		return 0;
	}
	
	/* 
	 * takes our file stream pointer (infile) and 
	 * stores it in the png_ptr struct for later use.
	 */
	/* png_ptr->io_ptr = (png_voidp)infile;*/
	png_init_io(png_ptr, infile);
	
	/*
	 * lets libpng know that we already checked the 8 
	 * signature bytes, so it should not expect to find 
	 * them at the current file pointer location
	 */
	png_set_sig_bytes(png_ptr, 8);
	
	/* Read the image info.*/
	
	/*
	 * reads and processes not only the PNG file's IHDR chunk 
	 * but also any other chunks up to the first IDAT 
	 * (i.e., everything before the image data).
	 */
	
	/* read all the info up to the image data  */
	png_read_info(png_ptr, info_ptr);
	
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, 
				 &color_type, NULL, NULL, NULL);
	
	*pwidth = width;
	*pheight = height;

	if (bit_depth > 8) {
		png_set_strip_16(png_ptr);
	}
#if defined(__DAVAENGINE_WIN32__)
	if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr);
#endif
    
	if (color_type == PNG_COLOR_TYPE_GRAY ||
		color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
		png_set_gray_to_rgb(png_ptr);
		png_set_filler(png_ptr, 0xFFFF, PNG_FILLER_AFTER);
	}
	if (color_type == PNG_COLOR_TYPE_PALETTE) {
		png_set_palette_to_rgb(png_ptr);
		png_set_filler(png_ptr, 0xFFFF, PNG_FILLER_AFTER);
	}

	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
	{
		png_set_tRNS_to_alpha(png_ptr);
		if (CommandLineParser::Instance()->GetVerbose())
			printf("*** TOCHECK: convert tRNS to alpha\n");
	}

	if (color_type == PNG_COLOR_TYPE_RGB)
	{	
		if (CommandLineParser::Instance()->GetVerbose())
			printf("*** Converting %s from RGB to RGBA\n", file);
		png_set_filler(png_ptr, 0xFFFF, PNG_FILLER_AFTER);
	}
		
	/* Update the png info struct.*/
	png_read_update_info(png_ptr, info_ptr);
	
	/* Rowsize in bytes. */
	rowbytes = png_get_rowbytes(png_ptr, info_ptr);
	
	char string_format[16];
	strcpy(string_format, "undefined");
	if (color_type == PNG_COLOR_TYPE_RGBA)
	{
		strcpy(string_format, "RGBA");
	}
	
	
	if (CommandLineParser::Instance()->GetVerbose())
	{
		printf("* Reading PNG file: %s format: %s bit_depth:%d bytes_per_pixel:%d\n", 
		   file,
		   string_format,
		   bit_depth,
		   rowbytes / width);
	}	
	
	/* Allocate the image_data buffer. */
	// printf("r/w: %d %d\n" , rowbytes / width, bit_depth); 
	
	
	if ((image_data = new uint8 [rowbytes * height]) ==NULL) 
	{
		memset(image_data, 0, rowbytes * height);
		png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
		return 4;
    }
	
	if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) 
	{
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        delete [] (image_data);
        image_data = NULL;
        return 4;
    }
	
	
    /* set the individual row_pointers to point at the correct offsets */
	
    for (i = 0;  i < (int)height;  ++i)
        row_pointers[i] = image_data + i*rowbytes;
	
	
    /* now we can go ahead and just read the whole image */
    png_read_image(png_ptr, row_pointers);
	
    /* and we're done!  (png_read_end() can be omitted if no processing of
     * post-IDAT text/time/etc. is desired) */
	
	/* Clean up. */
	free(row_pointers);
	
	/* Clean up. */
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	fclose(infile);
	
	*image_data_ptr = image_data;
	
	return 1;
}
/* Read a PNG file.  You may want to return an error code if the read
 * fails (depending upon the failure).  There are two "prototypes" given
 * here - one where we are given the filename, and we need to open the
 * file, and the other where we are given an open file (possibly with
 * some or all of the magic bytes read - see comments above).
 */
#ifdef open_file /* prototype 1 */
void read_png(char *file_name)  /* We need to open the file */
{
   png_structp png_ptr;
   png_infop info_ptr;
   unsigned int sig_read = 0;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
   FILE *fp;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

   png_color_16 my_background, *image_background;

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

   /* Some suggestions as to how to get a screen gamma value
    *
    * Note that screen gamma is the display_exponent, which includes
    * the CRT_exponent and any correction for viewing conditions
    */
   if (/* We have a user-defined screen gamma value */)
   {
      screen_gamma = user-defined screen_gamma;
   }
   /* This is one way that applications share the same screen gamma value */
   else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
Example #4
0
pngdata_t * loadpng(const char * path, int cutoff) {

	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep * row_pointers;
	int width, height, rowbytes;
	int x, y;
        unsigned char header[8];    // 8 is the maximum size that can be checked
	png_byte* ptr;
	FILE *fp;
	int type = 0;
	int lb;
	uint8_t * bitmap;

        /* open file and test for it being a png */
        fp = fopen(path, "rb");
        if (!fp)
                abort_("[read_png_file] File %s could not be opened for reading", path);
        fread(header, 1, 8, fp);
        if (png_sig_cmp(header, 0, 8))
                abort_("[read_png_file] File %s is not recognized as a PNG file", path);

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

        if (!png_ptr)
                abort_("[read_png_file] png_create_read_struct failed");

        info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr)
                abort_("[read_png_file] png_create_info_struct failed");

        if (setjmp(png_jmpbuf(png_ptr)))
                abort_("[read_png_file] Error during init_io");

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

        png_read_info(png_ptr, info_ptr);

	if (png_get_channels(png_ptr, info_ptr) == 1
	    && png_get_bit_depth(png_ptr, info_ptr) == 1) {
		type = 1;
	} else if (png_get_channels(png_ptr, info_ptr) == 4
	    && png_get_bit_depth(png_ptr, info_ptr) == 8) {
		type = 2;
	}

	if (type == 0) {
		fprintf(stderr, "Invalid PNG! Only mono or 4x8-bit RGBA PNG files are allowed\n");
		exit(1);
	}

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

        png_read_update_info(png_ptr, info_ptr);

        /* read file */
        if (setjmp(png_jmpbuf(png_ptr)))
                abort_("[read_png_file] Error during read_image");

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

        rowbytes = type == 1 ? (width / 8) + (width % 8 > 0) : width << 2;

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

        png_read_image(png_ptr, row_pointers);

        fclose(fp);

	lb = (height / 8) + (height % 8 > 0);
	bitmap = malloc(width*lb);
	memset(bitmap, 0, width*lb);

	#define heat_on(x, y) bitmap[(x*lb)+(y/8)] |= 1 << (7-(y%8))

  for (y=0; y<height; y++) {
    png_byte* row = row_pointers[y];
    for (x=0; x<width; x++) {
			if (type == 1) {
				ptr = &(row[x/8]);
        if ((ptr[0] & (1 << (7-(x%8)))) == 0) {
          heat_on(x, y);
        }
			} else {
        // Color 0 (red?)
        ptr = &(row[(x<<2)]);
        if (ptr[0] < cutoff) { // Adjust the cutoff (0 to 255). Any pixel darker (lower) than this will be black. Higher will be white. This can be used to turn anti-aliased pngs into monochrome with some desirable cutoff for black and white.
          heat_on(x, y);
        }
        // Color 1 (green?)
        ptr = &(row[(x<<2)+1]);
        if (ptr[0] < cutoff) {
          heat_on(x, y);
        }
        // Color 2 (blue?)
        ptr = &(row[(x<<2)+2]);
        if (ptr[0] < cutoff) {
          heat_on(x, y);
        }
        //        if ((ptr[0] & (1 << (7-(x%8)))) == 0) {
        //          heat_on(x, y);
        ///        }
			}
    }
  }
  
  /*

  for (y=0; y<height; y++) {
    png_byte* row = row_pointers[y+height*2];
    for (x=0; x<width; x++) {
      ptr = &(row[(x<<2)]);
      if ((ptr[0] & (1 << (7-(x%8)))) == 0) {
        heat_on(x, y+height*2);
      }
    }
  }
  */

	pngdata_t * ret = malloc(sizeof(pngdata_t));
	ret->w = height;
	ret->h = width;
	ret->data = bitmap;
	return ret;
}
Example #5
0
void CachedTexture::reload() {
    //..... load file ......
    GLenum internal_format = GL_RGB;
    GLenum data_format = GL_RGB;
    unsigned char *data = NULL;
    if (filename.size() >= 4 && filename.substr(filename.size()-4,4) == ".png") {
        //Load a png file, as per the libpng docs:
        FILE *fp = fopen(filename.c_str(), "rb");
        if (!fp) {
            cerr << "  cannot open file." << endl;
            return;
        }
        png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL);
        if (!png) {
            cerr << "  cannot alloc read struct." << endl;
            fclose(fp);
            return;
        }
        png_infop info = png_create_info_struct(png);
        if (!info) {
            cerr << "  cannot alloc info struct." << endl;
            png_destroy_read_struct(&png, (png_infopp)NULL, (png_infopp)NULL);
            fclose(fp);
            return;
        }
        png_bytep *row_pointers = NULL;
        if (setjmp(png_jmpbuf(png))) {
            cerr << "  png interal error." << endl;
            png_destroy_read_struct(&png, &info, (png_infopp)NULL);
            if (data != NULL) delete[] data;
            if (row_pointers != NULL) delete[] row_pointers;
            fclose(fp);
            return;
        }
        png_init_io(png, fp);
        png_read_info(png, info);
        w = png_get_image_width(png, info);
        h = png_get_image_height(png, info);
        {   //find power-of-two dimensions...
            tw = 1;
            while (tw < w) tw *= 2;
            th = 1;
            while (th < h) th *= 2;
        }
        if (!pad && (tw != w || th != h)) {
            if (!have_ARB_texture_non_power_of_two()) {
                cerr << "WARNING: trying to load texture of size " << w << " x " << h << ", but non-power-of-two textures not supported." << endl;
            }
            tw = w;
            th = h;
        }
        if (png_get_color_type(png, info) == PNG_COLOR_TYPE_PALETTE)
            png_set_palette_to_rgb(png);
        if (png_get_bit_depth(png, info) < 8)
            png_set_packing(png);
        if (png_get_bit_depth(png,info) == 16)
            png_set_strip_16(png);
        png_read_update_info(png, info);
        unsigned int rowbytes = png_get_rowbytes(png, info);
        //Make sure it's the format we think it is...
        bool problem = false;
        if (png_get_color_type(png, info) == PNG_COLOR_TYPE_GRAY) {
            data_format = internal_format = GL_LUMINANCE;
            if (rowbytes != w*1) problem = true;
        } else if (png_get_color_type(png, info) == PNG_COLOR_TYPE_GRAY_ALPHA) {
            data_format = internal_format = GL_LUMINANCE_ALPHA;
            if (rowbytes != w*2) problem = true;
        } else if (png_get_color_type(png, info) == PNG_COLOR_TYPE_PALETTE || png_get_color_type(png, info) == PNG_COLOR_TYPE_RGB) {
            data_format = internal_format = GL_RGB;
            if (rowbytes != w*3) problem = true;
        } else if (png_get_color_type(png, info) == PNG_COLOR_TYPE_RGB_ALPHA) {
            data_format = internal_format = GL_RGBA;
            if (rowbytes != w*4) problem = true;
        } else {
            cerr << "  unknown color format." << endl;
            problem = true;
        }
        if (problem) {
            cerr << "  color format problem. (rowbytes: " << rowbytes << " w:" << w << ")" << endl;
            png_destroy_read_struct(&png, &info, NULL);
            fclose(fp);
            return;
        }

        unsigned int pixelbytes = rowbytes / w;
        assert(rowbytes == pixelbytes * w); //sanity check, should have bailed earlier if this was the case.
        data = new uint8_t[th*tw*pixelbytes];
        row_pointers = new png_bytep[th];
        if (flip) {
            //texture origin goes top-left, as in most images:
            for (unsigned int r = 0; r < th; ++r) {
                row_pointers[r] = (png_bytep)(data + r*pixelbytes*tw);
            }
        } else {
            //texture origin goes bottom-left, as GL says:
            for (unsigned int r = 0; r < th; ++r) {
                row_pointers[th-1-r] = (png_bytep)(data + r*tw*pixelbytes);
            }
        }
        png_read_image(png, row_pointers);
        png_destroy_read_struct(&png, &info, NULL);
        fclose(fp);
        delete[] row_pointers;

        if (pad && h != 0 && w != 0) {
            //duplicate the last column accross the texture:
            for (unsigned int r = 0; r < h; ++r) {
                for (unsigned int c = w; c < tw; ++c) {
                    memcpy(&(data[(r*tw+c)*pixelbytes]), &(data[(r*tw+w-1)*pixelbytes]),pixelbytes);
                }
            }
            //duplicate the last row down the texture:
            for (unsigned int r = h; r < th; ++r) {
                memcpy(&(data[r*pixelbytes*tw]), &(data[(h-1)*pixelbytes*tw]), pixelbytes*tw);
            }
        }
    } else {
        //well, not a supported image type I'm afraid.
        cerr << "  unknown image type." << endl;
        return;
    }

    glGenTextures(1, &obj);
    glBindTexture(GL_TEXTURE_2D, obj);
    glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_2D, 0, internal_format, tw, th, 0, data_format, GL_UNSIGNED_BYTE, data);
    glBindTexture(GL_TEXTURE_2D, 0);
    glPopClientAttrib();
    delete[] data;

    loaded = true;
    gl_errors("CachedTexture::reload()");

}
Example #6
0
void savePNG(const char* file_name)
{
	png_structp png_ptr;
	png_infop info_ptr;

	/* create file */
    FILE *fp = fopen(file_name, "wb");
    if (!fp)
            abort_("[write_png_file] File %s could not be opened for writing", file_name);


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

    if (!png_ptr)
            abort_("[write_png_file] png_create_write_struct failed");

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
            abort_("[write_png_file] png_create_info_struct failed");

    if (setjmp(png_jmpbuf(png_ptr)))
            abort_("[write_png_file] Error during init_io");

    png_init_io(png_ptr, fp);

    /* write header */
    if (setjmp(png_jmpbuf(png_ptr)))
            abort_("[write_png_file] Error during writing header");

	png_set_IHDR(png_ptr, info_ptr, pictureWidth, pictureHeight,
					8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
                    PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

    png_write_info(png_ptr, info_ptr);


    /* write bytes */
    if (setjmp(png_jmpbuf(png_ptr)))
            abort_("[write_png_file] Error during writing bytes");

	png_bytep * row_pointers;
		
	unsigned char *array = new unsigned char[pictureWidth * pictureHeight * 4];
	for (int i = pictureWidth * pictureHeight; i >= 0; --i)
	{
		array[i*4+0] = ((unsigned char*)pictureWriteOut)[i*4+0];
		array[i*4+1] = ((unsigned char*)pictureWriteOut)[i*4+1];
		array[i*4+2] = ((unsigned char*)pictureWriteOut)[i*4+2];
		array[i*4+3] = ((unsigned char*)pictureWriteOut)[i*4+3];
	}


	// Allocate pointers...
	row_pointers = new png_bytep[pictureHeight];

	for (int i = 0; i < pictureHeight; i ++)
		row_pointers[i] = (png_bytep)(array + (i) * pictureWidth * 4); // we flip it

	png_write_image(png_ptr, row_pointers);

    /* end write */
    if (setjmp(png_jmpbuf(png_ptr)))
            abort_("[write_png_file] Error during end of write");
	
    png_write_end(png_ptr, NULL);

    /* cleanup heap allocation */
    free(row_pointers);

    fclose(fp);
}
Example #7
0
int readpng_init(FILE *infile, png_store *pngdata)
{
    unsigned char sig[8];
    long width,height;
    int  bit_depth, color_type;
 

    /* first do a quick check that the file really is a PNG image; could
     * have used slightly more general png_sig_cmp() function instead */

    size_t fr = fread(sig, 1, 8, infile);
    if(fr != 1*8)
        return 1;   /* bad signature */

    if (!png_check_sig(sig, 8))
        return 1;   /* bad signature */


    /* could pass pointers to user-defined error handlers instead of NULLs: */

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
        return 4;   /* out of memory */

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


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


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

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


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

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


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

    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
      NULL, NULL, NULL);
	pngdata->width = width;
	pngdata->height = height;
	pngdata->bitdepth = bit_depth;
	pngdata->colortype = color_type;
	pngdata->png_ptr = png_ptr;
	pngdata->info_ptr = info_ptr;

    /* OK, that's all we need for now; return happy */

    return 0;
}
Example #8
0
Py::Object
_image_module::readpng(const Py::Tuple& args) {
  
  args.verify_length(1);
  std::string fname = Py::String(args[0]);
  
  png_byte header[8];	// 8 is the maximum size that can be checked
  
  FILE *fp = fopen(fname.c_str(), "rb");
  if (!fp)
    throw Py::RuntimeError(Printf("_image_module::readpng could not open PNG file %s for reading", fname.c_str()).str());
  
  fread(header, 1, 8, fp);
  if (png_sig_cmp(header, 0, 8))
    throw Py::RuntimeError("_image_module::readpng: file not recognized as a PNG file");
  
  
  /* initialize stuff */
  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  
  if (!png_ptr)
    throw Py::RuntimeError("_image_module::readpng:  png_create_read_struct failed");
  
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr)
    throw Py::RuntimeError("_image_module::readpng:  png_create_info_struct failed");
  
  if (setjmp(png_jmpbuf(png_ptr)))
    throw Py::RuntimeError("_image_module::readpng:  error during init_io");
  
  png_init_io(png_ptr, fp);
  png_set_sig_bytes(png_ptr, 8);
  
  png_read_info(png_ptr, info_ptr);
  
  png_uint_32 width = info_ptr->width;
  png_uint_32 height = info_ptr->height;
  
  // convert misc color types to rgb for simplicity
  if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY ||
      info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    png_set_gray_to_rgb(png_ptr);  
  else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    png_set_palette_to_rgb(png_ptr);
  
  
  int bit_depth = info_ptr->bit_depth;
  if (bit_depth == 16)  png_set_strip_16(png_ptr);
  
  
  png_set_interlace_handling(png_ptr);
  png_read_update_info(png_ptr, info_ptr);
  
  bool rgba = info_ptr->color_type == PNG_COLOR_TYPE_RGBA;
  if ( (info_ptr->color_type != PNG_COLOR_TYPE_RGB) && !rgba) {
    std::cerr << "Found color type " << (int)info_ptr->color_type  << std::endl;
    throw Py::RuntimeError("_image_module::readpng: cannot handle color_type");
  }
  
  /* read file */
  if (setjmp(png_jmpbuf(png_ptr)))
    throw Py::RuntimeError("_image_module::readpng: error during read_image");
  
  png_bytep row_pointers[height];
  
  for (png_uint_32 row = 0; row < height; row++)
    row_pointers[row] = new png_byte[png_get_rowbytes(png_ptr,info_ptr)];
  
  png_read_image(png_ptr, row_pointers);
  
  
  
  int dimensions[3];
  dimensions[0] = height;  //numrows
  dimensions[1] = width;   //numcols
  dimensions[2] = 4;
  
  PyArrayObject *A = (PyArrayObject *) PyArray_FromDims(3, dimensions, PyArray_FLOAT);
  
  
  for (png_uint_32 y = 0; y < height; y++) {
    png_byte* row = row_pointers[y];
    for (png_uint_32 x = 0; x < width; x++) {
      
      png_byte* ptr = (rgba) ? &(row[x*4]) : &(row[x*3]);
      size_t offset = y*A->strides[0] + x*A->strides[1];
      //if ((y<10)&&(x==10)) std::cout << "r = " << ptr[0] << " " << ptr[0]/255.0 << std::endl;
      *(float*)(A->data + offset + 0*A->strides[2]) = ptr[0]/255.0;
      *(float*)(A->data + offset + 1*A->strides[2]) = ptr[1]/255.0;
      *(float*)(A->data + offset + 2*A->strides[2]) = ptr[2]/255.0;
      *(float*)(A->data + offset + 3*A->strides[2]) = rgba ? ptr[3]/255.0 : 1.0;
    }
  }
  
  //free the png memory
  png_read_end(png_ptr, info_ptr);
  png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
  fclose(fp);
  for (png_uint_32 row = 0; row < height; row++)
    delete [] row_pointers[row];
  return Py::asObject((PyObject*)A);
}
int
load_png_graphics (char *txt_filename, char *png_filename)
{
    png_uint_32 row;
    png_structp png_ptr;
    png_infop info_ptr;
    unsigned int sig_read = 0;
    png_uint_32 width, height;
    int bit_depth, color_type, interlace_type;
    FILE *fp, *txt_fp;
    png_bytep *row_pointers;

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

    if ((txt_fp = fopen(txt_filename, "r")) == NULL)
	return (ERROR);

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

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

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

   /* Set error handling if you are using the setjmp/longjmp method (this is
    * the normal method of doing things with libpng).  REQUIRED unless you
    * set up your own error handlers in the png_create_read_struct() earlier.
    */
    if (setjmp(png_jmpbuf(png_ptr))) {
	/* Free all of the memory associated with the png_ptr and info_ptr */
#if defined (commentout)
	png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
#endif
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	fclose(fp);
	/* If we get here, we had a problem reading the file */
	return (ERROR);
    }

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

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

    /* OK, you're doing it the hard way, with the lower-level functions */
    /* The call to png_read_info() gives us all of the information from the
    * PNG file before the first IDAT (image data chunk).  REQUIRED
    */
    png_read_info(png_ptr, info_ptr);

#if defined (commentout)
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
	&interlace_type, int_p_NULL, int_p_NULL);
#endif
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
	&interlace_type, NULL, NULL);

    printf ("PNG Header: %d x %d, bd=%d, ct=%d\n", height, width,
	bit_depth, color_type);

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

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

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

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

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

   /* Require color fmt w/ palette */
   if (color_type != PNG_COLOR_TYPE_PALETTE) {
	printf ("Error - png image wasn't PNG_COLOR_TYPE_PALETTE\n");
	/* Free all of the memory associated with the png_ptr and info_ptr */
#if defined (commentout)
	png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
#endif
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	fclose(fp);
	/* If we get here, we had a problem reading the file */
	return (ERROR);
   }

   /* Require 1 byte per pixel */
   if (bit_depth != 8) {
	printf ("Error - png image wasn't bit_depth = 8\n");
	/* Free all of the memory associated with the png_ptr and info_ptr */
#if defined (commentout)
	png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
#endif
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
	fclose(fp);
	/* If we get here, we had a problem reading the file */
	return (ERROR);
   }

    /* The easiest way to read the image: */
    row_pointers = malloc (sizeof(void*)*height);
    for (row = 0; row < height; row++) {
	row_pointers[row] = png_malloc(png_ptr, 
	    png_get_rowbytes(png_ptr, info_ptr));
    }

    png_read_image(png_ptr, row_pointers);

#if defined (commentout)
    for (col = 0; col < 16; col++) {
	printf (" %02x ",row_pointers[0][col]);
    }
    printf ("\n");

    for (col = 0; col < 16; col++) {
	printf ("%3d ",row_pointers[0][col]);
    }
    printf ("\n");
#endif

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

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

    /* get the icons out of the png */
#ifdef LG
#undef LG
#endif
#define LG(typ,grp,id) load_png_graphic(typ,grp,id,txt_fp,row_pointers,height,width)

    LG(CST_GREEN,GROUP_BARE,LCT_GREEN_G);

    LG(CST_FIRE_1,GROUP_FIRE,LCT_FIRE_1_G);
    LG(CST_FIRE_2,GROUP_FIRE,LCT_FIRE_2_G);
    LG(CST_FIRE_3,GROUP_FIRE,LCT_FIRE_3_G);
    LG(CST_FIRE_4,GROUP_FIRE,LCT_FIRE_4_G);
    LG(CST_FIRE_5,GROUP_FIRE,LCT_FIRE_5_G);

    LG(CST_FIRE_DONE1,GROUP_FIRE,LCT_FIRE_DONE1_G);
    LG(CST_FIRE_DONE2,GROUP_FIRE,LCT_FIRE_DONE2_G);
    LG(CST_FIRE_DONE3,GROUP_FIRE,LCT_FIRE_DONE3_G);
    LG(CST_FIRE_DONE4,GROUP_FIRE,LCT_FIRE_DONE4_G);

    LG(CST_BURNT,GROUP_BURNT,LCT_BURNT_G);

    LG(CST_PARKLAND_PLANE,GROUP_PARKLAND,LCT_PARKLAND_PLANE_G);
    LG(CST_PARKLAND_LAKE,GROUP_PARKLAND,LCT_PARKLAND_LAKE_G);

    LG(CST_POWERL_H_L,GROUP_POWER_LINE,LCT_POWERL_H_L_G);
    LG(CST_POWERL_V_L,GROUP_POWER_LINE,LCT_POWERL_V_L_G);
    LG(CST_POWERL_LD_L,GROUP_POWER_LINE,LCT_POWERL_LD_L_G);
    LG(CST_POWERL_RD_L,GROUP_POWER_LINE,LCT_POWERL_RD_L_G);
    LG(CST_POWERL_LU_L,GROUP_POWER_LINE,LCT_POWERL_LU_L_G);
    LG(CST_POWERL_RU_L,GROUP_POWER_LINE,LCT_POWERL_RU_L_G);
    LG(CST_POWERL_LDU_L,GROUP_POWER_LINE,LCT_POWERL_LDU_L_G);
    LG(CST_POWERL_LDR_L,GROUP_POWER_LINE,LCT_POWERL_LDR_L_G);
    LG(CST_POWERL_LUR_L,GROUP_POWER_LINE,LCT_POWERL_LUR_L_G);
    LG(CST_POWERL_UDR_L,GROUP_POWER_LINE,LCT_POWERL_UDR_L_G);
    LG(CST_POWERL_LUDR_L,GROUP_POWER_LINE,LCT_POWERL_LUDR_L_G);
    LG(CST_POWERL_H_D,GROUP_POWER_LINE,LCT_POWERL_H_D_G);
    LG(CST_POWERL_V_D,GROUP_POWER_LINE,LCT_POWERL_V_D_G);
    LG(CST_POWERL_LD_D,GROUP_POWER_LINE,LCT_POWERL_LD_D_G);
    LG(CST_POWERL_RD_D,GROUP_POWER_LINE,LCT_POWERL_RD_D_G);
    LG(CST_POWERL_LU_D,GROUP_POWER_LINE,LCT_POWERL_LU_D_G);
    LG(CST_POWERL_RU_D,GROUP_POWER_LINE,LCT_POWERL_RU_D_G);
    LG(CST_POWERL_LDU_D,GROUP_POWER_LINE,LCT_POWERL_LDU_D_G);
    LG(CST_POWERL_LDR_D,GROUP_POWER_LINE,LCT_POWERL_LDR_D_G);
    LG(CST_POWERL_LUR_D,GROUP_POWER_LINE,LCT_POWERL_LUR_D_G);
    LG(CST_POWERL_UDR_D,GROUP_POWER_LINE,LCT_POWERL_UDR_D_G);
    LG(CST_POWERL_LUDR_D,GROUP_POWER_LINE,LCT_POWERL_LUDR_D_G);

    LG(CST_RAIL_LR,GROUP_RAIL,LCT_RAIL_LR_G);
    LG(CST_RAIL_LU,GROUP_RAIL,LCT_RAIL_LU_G);
    LG(CST_RAIL_LD,GROUP_RAIL,LCT_RAIL_LD_G);
    LG(CST_RAIL_UD,GROUP_RAIL,LCT_RAIL_UD_G);
    LG(CST_RAIL_UR,GROUP_RAIL,LCT_RAIL_UR_G);
    LG(CST_RAIL_DR,GROUP_RAIL,LCT_RAIL_DR_G);
    LG(CST_RAIL_LUR,GROUP_RAIL,LCT_RAIL_LUR_G);
    LG(CST_RAIL_LDR,GROUP_RAIL,LCT_RAIL_LDR_G);
    LG(CST_RAIL_LUD,GROUP_RAIL,LCT_RAIL_LUD_G);
    LG(CST_RAIL_UDR,GROUP_RAIL,LCT_RAIL_UDR_G);
    LG(CST_RAIL_LUDR,GROUP_RAIL,LCT_RAIL_LUDR_G);

    LG(CST_ROAD_LR,GROUP_ROAD,LCT_ROAD_LR_G);
    LG(CST_ROAD_LU,GROUP_ROAD,LCT_ROAD_LU_G);
    LG(CST_ROAD_LD,GROUP_ROAD,LCT_ROAD_LD_G);
    LG(CST_ROAD_UD,GROUP_ROAD,LCT_ROAD_UD_G);
    LG(CST_ROAD_UR,GROUP_ROAD,LCT_ROAD_UR_G);
    LG(CST_ROAD_DR,GROUP_ROAD,LCT_ROAD_DR_G);
    LG(CST_ROAD_LUR,GROUP_ROAD,LCT_ROAD_LUR_G);
    LG(CST_ROAD_LDR,GROUP_ROAD,LCT_ROAD_LDR_G);
    LG(CST_ROAD_LUD,GROUP_ROAD,LCT_ROAD_LUD_G);
    LG(CST_ROAD_UDR,GROUP_ROAD,LCT_ROAD_UDR_G);
    LG(CST_ROAD_LUDR,GROUP_ROAD,LCT_ROAD_LUDR_G);

    LG(CST_TRACK_LR,GROUP_TRACK,LCT_TRACK_LR_G);
    LG(CST_TRACK_LU,GROUP_TRACK,LCT_TRACK_LU_G);
    LG(CST_TRACK_LD,GROUP_TRACK,LCT_TRACK_LD_G);
    LG(CST_TRACK_UD,GROUP_TRACK,LCT_TRACK_UD_G);
    LG(CST_TRACK_UR,GROUP_TRACK,LCT_TRACK_UR_G);
    LG(CST_TRACK_DR,GROUP_TRACK,LCT_TRACK_DR_G);
    LG(CST_TRACK_LUR,GROUP_TRACK,LCT_TRACK_LUR_G);
    LG(CST_TRACK_LDR,GROUP_TRACK,LCT_TRACK_LDR_G);
    LG(CST_TRACK_LUD,GROUP_TRACK,LCT_TRACK_LUD_G);
    LG(CST_TRACK_UDR,GROUP_TRACK,LCT_TRACK_UDR_G);
    LG(CST_TRACK_LUDR,GROUP_TRACK,LCT_TRACK_LUDR_G);

    LG(CST_WATER,GROUP_WATER,LCT_WATER_G);
    LG(CST_WATER_D,GROUP_WATER,LCT_WATER_D_G);
    LG(CST_WATER_R,GROUP_WATER,LCT_WATER_R_G);
    LG(CST_WATER_U,GROUP_WATER,LCT_WATER_U_G);
    LG(CST_WATER_L,GROUP_WATER,LCT_WATER_L_G);
    LG(CST_WATER_LR,GROUP_WATER,LCT_WATER_LR_G);
    LG(CST_WATER_UD,GROUP_WATER,LCT_WATER_UD_G);
    LG(CST_WATER_LD,GROUP_WATER,LCT_WATER_LD_G);
    LG(CST_WATER_RD,GROUP_WATER,LCT_WATER_RD_G);
    LG(CST_WATER_LU,GROUP_WATER,LCT_WATER_LU_G);
    LG(CST_WATER_UR,GROUP_WATER,LCT_WATER_UR_G);
    LG(CST_WATER_LUD,GROUP_WATER,LCT_WATER_LUD_G);
    LG(CST_WATER_LRD,GROUP_WATER,LCT_WATER_LRD_G);
    LG(CST_WATER_LUR,GROUP_WATER,LCT_WATER_LUR_G);
    LG(CST_WATER_URD,GROUP_WATER,LCT_WATER_URD_G);
    LG(CST_WATER_LURD,GROUP_WATER,LCT_WATER_LURD_G);

    LG(CST_BLACKSMITH_0,GROUP_BLACKSMITH,LCT_BLACKSMITH_0_G);
    LG(CST_BLACKSMITH_1,GROUP_BLACKSMITH,LCT_BLACKSMITH_1_G);
    LG(CST_BLACKSMITH_2,GROUP_BLACKSMITH,LCT_BLACKSMITH_2_G);
    LG(CST_BLACKSMITH_3,GROUP_BLACKSMITH,LCT_BLACKSMITH_3_G);
    LG(CST_BLACKSMITH_4,GROUP_BLACKSMITH,LCT_BLACKSMITH_4_G);
    LG(CST_BLACKSMITH_5,GROUP_BLACKSMITH,LCT_BLACKSMITH_5_G);
    LG(CST_BLACKSMITH_6,GROUP_BLACKSMITH,LCT_BLACKSMITH_6_G);

    LG(CST_CRICKET_1,GROUP_CRICKET,LCT_CRICKET_1_G);
    LG(CST_CRICKET_2,GROUP_CRICKET,LCT_CRICKET_2_G);
    LG(CST_CRICKET_3,GROUP_CRICKET,LCT_CRICKET_3_G);
    LG(CST_CRICKET_4,GROUP_CRICKET,LCT_CRICKET_4_G);
    LG(CST_CRICKET_5,GROUP_CRICKET,LCT_CRICKET_5_G);
    LG(CST_CRICKET_6,GROUP_CRICKET,LCT_CRICKET_6_G);
    LG(CST_CRICKET_7,GROUP_CRICKET,LCT_CRICKET_7_G);

    LG(CST_FIRESTATION_1,GROUP_FIRESTATION,LCT_FIRESTATION_1_G);
    LG(CST_FIRESTATION_2,GROUP_FIRESTATION,LCT_FIRESTATION_2_G);
    LG(CST_FIRESTATION_3,GROUP_FIRESTATION,LCT_FIRESTATION_3_G);
    LG(CST_FIRESTATION_4,GROUP_FIRESTATION,LCT_FIRESTATION_4_G);
    LG(CST_FIRESTATION_5,GROUP_FIRESTATION,LCT_FIRESTATION_5_G);
    LG(CST_FIRESTATION_6,GROUP_FIRESTATION,LCT_FIRESTATION_6_G);
    LG(CST_FIRESTATION_7,GROUP_FIRESTATION,LCT_FIRESTATION_7_G);
    LG(CST_FIRESTATION_8,GROUP_FIRESTATION,LCT_FIRESTATION_8_G);
    LG(CST_FIRESTATION_9,GROUP_FIRESTATION,LCT_FIRESTATION_9_G);
    LG(CST_FIRESTATION_10,GROUP_FIRESTATION,LCT_FIRESTATION_10_G);

    LG(CST_HEALTH,GROUP_HEALTH,LCT_HEALTH_G);

    LG(CST_MARKET_EMPTY,GROUP_MARKET,LCT_MARKET_EMPTY_G);
    LG(CST_MARKET_LOW,GROUP_MARKET,LCT_MARKET_LOW_G);
    LG(CST_MARKET_MED,GROUP_MARKET,LCT_MARKET_MED_G);
    LG(CST_MARKET_FULL,GROUP_MARKET,LCT_MARKET_FULL_G);

    LG(CST_MILL_0,GROUP_MILL,LCT_MILL_0_G);
    LG(CST_MILL_1,GROUP_MILL,LCT_MILL_1_G);
    LG(CST_MILL_2,GROUP_MILL,LCT_MILL_2_G);
    LG(CST_MILL_3,GROUP_MILL,LCT_MILL_3_G);
    LG(CST_MILL_4,GROUP_MILL,LCT_MILL_4_G);
    LG(CST_MILL_5,GROUP_MILL,LCT_MILL_5_G);
    LG(CST_MILL_6,GROUP_MILL,LCT_MILL_6_G);

    LG(CST_MONUMENT_0,GROUP_MONUMENT,LCT_MONUMENT_0_G);
    LG(CST_MONUMENT_1,GROUP_MONUMENT,LCT_MONUMENT_1_G);
    LG(CST_MONUMENT_2,GROUP_MONUMENT,LCT_MONUMENT_2_G);
    LG(CST_MONUMENT_3,GROUP_MONUMENT,LCT_MONUMENT_3_G);
    LG(CST_MONUMENT_4,GROUP_MONUMENT,LCT_MONUMENT_4_G);
    LG(CST_MONUMENT_5,GROUP_MONUMENT,LCT_MONUMENT_5_G);

    LG(CST_POTTERY_0,GROUP_POTTERY,LCT_POTTERY_0_G);
    LG(CST_POTTERY_1,GROUP_POTTERY,LCT_POTTERY_1_G);
    LG(CST_POTTERY_2,GROUP_POTTERY,LCT_POTTERY_2_G);
    LG(CST_POTTERY_3,GROUP_POTTERY,LCT_POTTERY_3_G);
    LG(CST_POTTERY_4,GROUP_POTTERY,LCT_POTTERY_4_G);
    LG(CST_POTTERY_5,GROUP_POTTERY,LCT_POTTERY_5_G);
    LG(CST_POTTERY_6,GROUP_POTTERY,LCT_POTTERY_6_G);
    LG(CST_POTTERY_7,GROUP_POTTERY,LCT_POTTERY_7_G);
    LG(CST_POTTERY_8,GROUP_POTTERY,LCT_POTTERY_8_G);
    LG(CST_POTTERY_9,GROUP_POTTERY,LCT_POTTERY_9_G);
    LG(CST_POTTERY_10,GROUP_POTTERY,LCT_POTTERY_10_G);

    LG(CST_RECYCLE,GROUP_RECYCLE,LCT_RECYCLE_G);

    LG(CST_SCHOOL,GROUP_SCHOOL,LCT_SCHOOL_G);

    LG(CST_SHANTY,GROUP_SHANTY,LCT_SHANTY_G);

    LG(CST_SUBSTATION_R,GROUP_SUBSTATION,LCT_SUBSTATION_R_G);
    LG(CST_SUBSTATION_G,GROUP_SUBSTATION,LCT_SUBSTATION_G_G);
    LG(CST_SUBSTATION_RG,GROUP_SUBSTATION,LCT_SUBSTATION_RG_G);

    LG(CST_WINDMILL_1_G,GROUP_WINDMILL,LCT_WINDMILL_1_G_G);
    LG(CST_WINDMILL_2_G,GROUP_WINDMILL,LCT_WINDMILL_2_G_G);
    LG(CST_WINDMILL_3_G,GROUP_WINDMILL,LCT_WINDMILL_3_G_G);
    LG(CST_WINDMILL_1_RG,GROUP_WINDMILL,LCT_WINDMILL_1_RG_G);
    LG(CST_WINDMILL_2_RG,GROUP_WINDMILL,LCT_WINDMILL_2_RG_G);
    LG(CST_WINDMILL_3_RG,GROUP_WINDMILL,LCT_WINDMILL_3_RG_G);
    LG(CST_WINDMILL_1_R,GROUP_WINDMILL,LCT_WINDMILL_1_R_G);
    LG(CST_WINDMILL_2_R,GROUP_WINDMILL,LCT_WINDMILL_2_R_G);
    LG(CST_WINDMILL_3_R,GROUP_WINDMILL,LCT_WINDMILL_3_R_G);
    LG(CST_WINDMILL_1_W,GROUP_WINDMILL,LCT_WINDMILL_1_W_G);
    LG(CST_WINDMILL_2_W,GROUP_WINDMILL,LCT_WINDMILL_2_W_G);
    LG(CST_WINDMILL_3_W,GROUP_WINDMILL,LCT_WINDMILL_3_W_G);

    LG(CST_INDUSTRY_L_C,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_C_G);
    LG(CST_INDUSTRY_L_Q1,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_Q1_G);
    LG(CST_INDUSTRY_L_Q2,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_Q2_G);
    LG(CST_INDUSTRY_L_Q3,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_Q3_G);
    LG(CST_INDUSTRY_L_Q4,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_Q4_G);
    LG(CST_INDUSTRY_L_L1,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_L1_G);
    LG(CST_INDUSTRY_L_L2,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_L2_G);
    LG(CST_INDUSTRY_L_L3,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_L3_G);
    LG(CST_INDUSTRY_L_L4,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_L4_G);
    LG(CST_INDUSTRY_L_M1,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_M1_G);
    LG(CST_INDUSTRY_L_M2,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_M2_G);
    LG(CST_INDUSTRY_L_M3,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_M3_G);
    LG(CST_INDUSTRY_L_M4,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_M4_G);
    LG(CST_INDUSTRY_L_H1,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_H1_G);
    LG(CST_INDUSTRY_L_H2,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_H2_G);
    LG(CST_INDUSTRY_L_H3,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_H3_G);
    LG(CST_INDUSTRY_L_H4,GROUP_INDUSTRY_L,LCT_INDUSTRY_L_H4_G);

    LG(CST_RESIDENCE_LL,GROUP_RESIDENCE_LL,LCT_RESIDENCE_LL_G);
    LG(CST_RESIDENCE_ML,GROUP_RESIDENCE_ML,LCT_RESIDENCE_ML_G);
    LG(CST_RESIDENCE_HL,GROUP_RESIDENCE_HL,LCT_RESIDENCE_HL_G);
    LG(CST_RESIDENCE_LH,GROUP_RESIDENCE_LH,LCT_RESIDENCE_LH_G);
    LG(CST_RESIDENCE_MH,GROUP_RESIDENCE_MH,LCT_RESIDENCE_MH_G);
    LG(CST_RESIDENCE_HH,GROUP_RESIDENCE_HH,LCT_RESIDENCE_HH_G);

    LG(CST_UNIVERSITY,GROUP_UNIVERSITY,LCT_UNIVERSITY_G);

    LG(CST_COALMINE_EMPTY,GROUP_COALMINE,LCT_COALMINE_EMPTY_G);
    LG(CST_COALMINE_LOW,GROUP_COALMINE,LCT_COALMINE_LOW_G);
    LG(CST_COALMINE_MED,GROUP_COALMINE,LCT_COALMINE_MED_G);
    LG(CST_COALMINE_FULL,GROUP_COALMINE,LCT_COALMINE_FULL_G);

    LG(CST_COMMUNE_1,GROUP_COMMUNE,LCT_COMMUNE_1_G);
    LG(CST_COMMUNE_2,GROUP_COMMUNE,LCT_COMMUNE_2_G);
    LG(CST_COMMUNE_3,GROUP_COMMUNE,LCT_COMMUNE_3_G);
    LG(CST_COMMUNE_4,GROUP_COMMUNE,LCT_COMMUNE_4_G);
    LG(CST_COMMUNE_5,GROUP_COMMUNE,LCT_COMMUNE_5_G);
    LG(CST_COMMUNE_6,GROUP_COMMUNE,LCT_COMMUNE_6_G);
    LG(CST_COMMUNE_7,GROUP_COMMUNE,LCT_COMMUNE_7_G);
    LG(CST_COMMUNE_8,GROUP_COMMUNE,LCT_COMMUNE_8_G);
    LG(CST_COMMUNE_9,GROUP_COMMUNE,LCT_COMMUNE_9_G);
    LG(CST_COMMUNE_10,GROUP_COMMUNE,LCT_COMMUNE_10_G);
    LG(CST_COMMUNE_11,GROUP_COMMUNE,LCT_COMMUNE_11_G);
    LG(CST_COMMUNE_12,GROUP_COMMUNE,LCT_COMMUNE_12_G);
    LG(CST_COMMUNE_13,GROUP_COMMUNE,LCT_COMMUNE_13_G);
    LG(CST_COMMUNE_14,GROUP_COMMUNE,LCT_COMMUNE_14_G);

    LG(CST_EX_PORT,GROUP_PORT,LCT_EX_PORT_G);

    LG(CST_FARM_O0,GROUP_ORGANIC_FARM,LCT_FARM_O0_G);
    LG(CST_FARM_O1,GROUP_ORGANIC_FARM,LCT_FARM_O1_G);
    LG(CST_FARM_O2,GROUP_ORGANIC_FARM,LCT_FARM_O2_G);
    LG(CST_FARM_O3,GROUP_ORGANIC_FARM,LCT_FARM_O3_G);
    LG(CST_FARM_O4,GROUP_ORGANIC_FARM,LCT_FARM_O4_G);
    LG(CST_FARM_O5,GROUP_ORGANIC_FARM,LCT_FARM_O5_G);
    LG(CST_FARM_O6,GROUP_ORGANIC_FARM,LCT_FARM_O6_G);
    LG(CST_FARM_O7,GROUP_ORGANIC_FARM,LCT_FARM_O7_G);
    LG(CST_FARM_O8,GROUP_ORGANIC_FARM,LCT_FARM_O8_G);
    LG(CST_FARM_O9,GROUP_ORGANIC_FARM,LCT_FARM_O9_G);
    LG(CST_FARM_O10,GROUP_ORGANIC_FARM,LCT_FARM_O10_G);
    LG(CST_FARM_O11,GROUP_ORGANIC_FARM,LCT_FARM_O11_G);
    LG(CST_FARM_O12,GROUP_ORGANIC_FARM,LCT_FARM_O12_G);
    LG(CST_FARM_O13,GROUP_ORGANIC_FARM,LCT_FARM_O13_G);
    LG(CST_FARM_O14,GROUP_ORGANIC_FARM,LCT_FARM_O14_G);
    LG(CST_FARM_O15,GROUP_ORGANIC_FARM,LCT_FARM_O15_G);
    LG(CST_FARM_O16,GROUP_ORGANIC_FARM,LCT_FARM_O16_G);

    LG(CST_INDUSTRY_H_C,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_C_G);
    LG(CST_INDUSTRY_H_L1,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_L1_G);
    LG(CST_INDUSTRY_H_L2,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_L2_G);
    LG(CST_INDUSTRY_H_L3,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_L3_G);
    LG(CST_INDUSTRY_H_L4,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_L4_G);
    LG(CST_INDUSTRY_H_L5,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_L5_G);
    LG(CST_INDUSTRY_H_L6,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_L6_G);
    LG(CST_INDUSTRY_H_L7,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_L7_G);
    LG(CST_INDUSTRY_H_L8,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_L8_G);
    LG(CST_INDUSTRY_H_M1,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_M1_G);
    LG(CST_INDUSTRY_H_M2,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_M2_G);
    LG(CST_INDUSTRY_H_M3,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_M3_G);
    LG(CST_INDUSTRY_H_M4,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_M4_G);
    LG(CST_INDUSTRY_H_M5,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_M5_G);
    LG(CST_INDUSTRY_H_M6,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_M6_G);
    LG(CST_INDUSTRY_H_M7,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_M7_G);
    LG(CST_INDUSTRY_H_M8,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_M8_G);
    LG(CST_INDUSTRY_H_H1,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_H1_G);
    LG(CST_INDUSTRY_H_H2,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_H2_G);
    LG(CST_INDUSTRY_H_H3,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_H3_G);
    LG(CST_INDUSTRY_H_H4,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_H4_G);
    LG(CST_INDUSTRY_H_H5,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_H5_G);
    LG(CST_INDUSTRY_H_H6,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_H6_G);
    LG(CST_INDUSTRY_H_H7,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_H7_G);
    LG(CST_INDUSTRY_H_H8,GROUP_INDUSTRY_H,LCT_INDUSTRY_H_H8_G);

    LG(CST_OREMINE_1,GROUP_OREMINE,LCT_OREMINE_1_G);
    LG(CST_OREMINE_2,GROUP_OREMINE,LCT_OREMINE_2_G);
    LG(CST_OREMINE_3,GROUP_OREMINE,LCT_OREMINE_3_G);
    LG(CST_OREMINE_4,GROUP_OREMINE,LCT_OREMINE_4_G);
    LG(CST_OREMINE_5,GROUP_OREMINE,LCT_OREMINE_5_G);
    LG(CST_OREMINE_6,GROUP_OREMINE,LCT_OREMINE_6_G);
    LG(CST_OREMINE_7,GROUP_OREMINE,LCT_OREMINE_7_G);
    LG(CST_OREMINE_8,GROUP_OREMINE,LCT_OREMINE_8_G);

    LG(CST_POWERS_COAL_EMPTY,GROUP_COAL_POWER,LCT_POWERS_COAL_EMPTY_G);
    LG(CST_POWERS_COAL_LOW,GROUP_COAL_POWER,LCT_POWERS_COAL_LOW_G);
    LG(CST_POWERS_COAL_MED,GROUP_COAL_POWER,LCT_POWERS_COAL_MED_G);
    LG(CST_POWERS_COAL_FULL,GROUP_COAL_POWER,LCT_POWERS_COAL_FULL_G);

    LG(CST_POWERS_SOLAR,GROUP_SOLAR_POWER,LCT_POWERS_SOLAR_G);

    LG(CST_ROCKET_1,GROUP_ROCKET,LCT_ROCKET_1_G);
    LG(CST_ROCKET_2,GROUP_ROCKET,LCT_ROCKET_2_G);
    LG(CST_ROCKET_3,GROUP_ROCKET,LCT_ROCKET_3_G);
    LG(CST_ROCKET_4,GROUP_ROCKET,LCT_ROCKET_4_G);
    LG(CST_ROCKET_5,GROUP_ROCKET,LCT_ROCKET_5_G);
    LG(CST_ROCKET_6,GROUP_ROCKET,LCT_ROCKET_6_G);
    LG(CST_ROCKET_7,GROUP_ROCKET,LCT_ROCKET_7_G);
    LG(CST_ROCKET_FLOWN,GROUP_ROCKET,LCT_ROCKET_FLOWN_G);

    LG(CST_TIP_0,GROUP_TIP,LCT_TIP_0_G);
    LG(CST_TIP_1,GROUP_TIP,LCT_TIP_1_G);
    LG(CST_TIP_2,GROUP_TIP,LCT_TIP_2_G);
    LG(CST_TIP_3,GROUP_TIP,LCT_TIP_3_G);
    LG(CST_TIP_4,GROUP_TIP,LCT_TIP_4_G);
    LG(CST_TIP_5,GROUP_TIP,LCT_TIP_5_G);
    LG(CST_TIP_6,GROUP_TIP,LCT_TIP_6_G);
    LG(CST_TIP_7,GROUP_TIP,LCT_TIP_7_G);
    LG(CST_TIP_8,GROUP_TIP,LCT_TIP_8_G);

    // main_t
#undef LG

#if defined (commentout)
    /* PROCESS IMAGE HERE */
    while (!feof(txt_fp)) {
	char buf[128];
	char *fnp,*rip,*cip;
	int ri,ci;

	/* Get line from text file */
	fgets (buf,128,txt_fp);

	/* Tokenize */
	fnp = strtok(buf," \t");
	if (!fnp || *fnp == '#') continue;
	if (*fnp == '@') break;
	rip = strtok(NULL," \t");
	if (!rip) continue;
	cip = strtok(NULL," \t");
	if (!cip) continue;
	ri = atoi(rip);
	ci = atoi(cip);

	/* Copy icon */
	if (!strcmp(fnp,LCT_GREEN_G)) {
	    int r,c;
	    char* p;
            main_types[CST_GREEN].graphic=malloc(16*16);
	    p = main_types[CST_GREEN].graphic;
	    for (r=ri*16;r<ri*16+16;r++) {
	    for (c=ci*16;c<ci*16+16;c++) {
		*p++ = row_pointers[r][c];
	    } }
	}
    }
#endif

    /* Free the memory */
    for (row = 0; row < height; row++) {
	png_free(png_ptr, row_pointers[row]);
    }
    free(row_pointers);

    /* clean up after the read, and free any memory allocated - REQUIRED */
#if defined (commentout)
    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
#endif
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    /* that's it */
    return (OK);
}
unsigned char *_loadImageRGBApng(char *fileName, int *width, int *height) {
  // open the file
  FILE *fp = fopen(fileName, "rb");
  if (!fp)
    return _loadImgError(width, height);

  // read the header
  const int HEADER_LENGTH = 8;
  png_byte header[HEADER_LENGTH];
  fread(header, 1, HEADER_LENGTH, fp);
  if (png_sig_cmp(header, 0, HEADER_LENGTH))
    return _loadImgError(width, height);

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

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

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

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

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

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

  // read the image info, get some info
  png_read_info(png_ptr, info_ptr);
  *width = png_get_image_width(png_ptr, info_ptr);
  *height = png_get_image_height(png_ptr, info_ptr);
  int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  png_byte color_type = png_get_color_type(png_ptr, info_ptr);
  
  // force the image into RGBA, 8 bits per channel
  if (color_type != PNG_COLOR_TYPE_RGBA)
    png_set_expand(png_ptr);
  if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    png_set_gray_to_rgb(png_ptr);
  if (bit_depth < 8)
    png_set_packing(png_ptr);
  else if (bit_depth == 16)
    png_set_strip_16(png_ptr);
  if (color_type != PNG_COLOR_TYPE_RGBA)
    png_set_filler(png_ptr, 255, PNG_FILLER_AFTER);  
  png_read_update_info(png_ptr, info_ptr);

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

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

  // deallocate memory and return
  fclose(fp);
  png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
  return buffer;
}
Example #11
0
Py::Object 
Image::write_png(const Py::Tuple& args)
{
  //small memory leak in this function - JDH 2004-06-08
  _VERBOSE("Image::write_png");
  
  args.verify_length(1);
  
  std::string fileName = Py::String(args[0]);
  const char *file_name = fileName.c_str();
  FILE *fp;
  png_structp png_ptr;
  png_infop info_ptr;
  struct        png_color_8_struct sig_bit;
  png_uint_32 row;
  
  //todo: allocate on heap
  png_bytep row_pointers[rowsOut];
  for (row = 0; row < rowsOut; ++row) {
    row_pointers[row] = bufferOut + row * colsOut * 4;
  }
  
  fp = fopen(file_name, "wb");
  if (fp == NULL) 
    throw Py::RuntimeError(Printf("Could not open file %s", file_name).str());
  
  
  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (png_ptr == NULL) {
    fclose(fp);
    throw Py::RuntimeError("Could not create write struct");
  }
  
  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL) {
    fclose(fp);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    throw Py::RuntimeError("Could not create info struct");
  }
  
  if (setjmp(png_ptr->jmpbuf)) {
    fclose(fp);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    throw Py::RuntimeError("Error building image");
  }
  
  png_init_io(png_ptr, fp);
  png_set_IHDR(png_ptr, info_ptr,
	       colsOut, rowsOut, 8,
	       PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
	       PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
  
  // this a a color image!
  sig_bit.gray = 0;
  sig_bit.red = 8;
  sig_bit.green = 8;
  sig_bit.blue = 8;
  /* if the image has an alpha channel then */
  sig_bit.alpha = 8;
  png_set_sBIT(png_ptr, info_ptr, &sig_bit);
  
  png_write_info(png_ptr, info_ptr);
  png_write_image(png_ptr, row_pointers);
  png_write_end(png_ptr, info_ptr);
  png_destroy_write_struct(&png_ptr, &info_ptr);
  fclose(fp);
  
  return Py::Object();
}
int res_create_surface(const char* name, gr_surface* pSurface) {
    char resPath[256];
    GGLSurface* surface = NULL;
    int result = 0;
    unsigned char header[8];
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;

    *pSurface = NULL;

    snprintf(resPath, sizeof(resPath)-1, "/res/images/%s.png", name);
    resPath[sizeof(resPath)-1] = '\0';
    FILE* fp = fopen(resPath, "rb");
    if (fp == NULL) {
        result = -1;
        goto exit;
    }

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

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

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

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

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

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

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

    size_t width = info_ptr->width;
    size_t height = info_ptr->height;
    size_t stride = (color_type == PNG_COLOR_TYPE_GRAY ? 1 : 4) * width;
    size_t pixelSize = stride * height;

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

    int alpha = 0;
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(png_ptr);
    }
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
        png_set_tRNS_to_alpha(png_ptr);
        alpha = 1;
    }
    if (color_type == PNG_COLOR_TYPE_GRAY) {
        alpha = 1;
    }

    unsigned int y;
    if (channels == 3 || (channels == 1 && !alpha)) {
        for (y = 0; y < height; ++y) {
            unsigned char* pRow = pData + y * stride;
            png_read_row(png_ptr, pRow, NULL);

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

    *pSurface = (gr_surface) surface;

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

    if (fp != NULL) {
        fclose(fp);
    }
    if (result < 0) {
        if (surface) {
            free(surface);
        }
    }
    return result;
}
int res_create_localized_surface(const char* name, gr_surface* pSurface) {
    char resPath[256];
    GGLSurface* surface = NULL;
    int result = 0;
    unsigned char header[8];
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;

    *pSurface = NULL;

    snprintf(resPath, sizeof(resPath)-1, "/res/images/%s.png", name);
    resPath[sizeof(resPath)-1] = '\0';
    FILE* fp = fopen(resPath, "rb");
    if (fp == NULL) {
        result = -1;
        goto exit;
    }

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

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

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

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

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

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

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

    int color_type = info_ptr->color_type;
    int bit_depth = info_ptr->bit_depth;
    int channels = info_ptr->channels;

    if (!(bit_depth == 8 &&
          (channels == 1 && color_type == PNG_COLOR_TYPE_GRAY))) {
        return -7;
        goto exit;
    }

    unsigned char* row = malloc(width);
    int y;
    for (y = 0; y < height; ++y) {
        png_read_row(png_ptr, row, NULL);
        int w = (row[1] << 8) | row[0];
        int h = (row[3] << 8) | row[2];
        int len = row[4];
        char* loc = row+5;

        if (y+1+h >= height || matches_locale(loc)) {
            printf("  %20s: %s (%d x %d @ %d)\n", name, loc, w, h, y);

            surface = malloc(sizeof(GGLSurface));
            if (surface == NULL) {
                result = -8;
                goto exit;
            }
            unsigned char* pData = malloc(w*h);

            surface->version = sizeof(GGLSurface);
            surface->width = w;
            surface->height = h;
            surface->stride = w; /* Yes, pixels, not bytes */
            surface->data = pData;
            surface->format = GGL_PIXEL_FORMAT_A_8;

            int i;
            for (i = 0; i < h; ++i, ++y) {
                png_read_row(png_ptr, row, NULL);
                memcpy(pData + i*w, row, w);
            }

            *pSurface = (gr_surface) surface;
            break;
        } else {
            int i;
            for (i = 0; i < h; ++i, ++y) {
                png_read_row(png_ptr, row, NULL);
            }
        }
    }

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

    if (fp != NULL) {
        fclose(fp);
    }
    if (result < 0) {
        if (surface) {
            free(surface);
        }
    }
    return result;
}
Example #14
0
void pgeTextureScreenshot(const char* filename)
{
	png_structp png_ptr;
	png_infop info_ptr;
	FILE* fp;
	unsigned char* line;

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	
	if(!png_ptr)
		return;
	
	info_ptr = png_create_info_struct(png_ptr);
	
	if(!info_ptr)
	{
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		return;
	}
	
	unsigned int col_type = PNG_COLOR_TYPE_RGBA;

	fp = fopen(filename, "wb");
	if (!fp) return;
	
	png_init_io(png_ptr, fp);
	png_set_IHDR(png_ptr, info_ptr, 480, 272, 8, col_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
	png_write_info(png_ptr, info_ptr);
	
	line = (unsigned char*) pgeMalloc(480 * 4);
	
	if(line == 0)
	{
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		fclose(fp);
		return;
	}
	
	unsigned char* src = (unsigned char*)pgeGfxGetFramebuffer();
	unsigned char* src8 = (unsigned char*)src;
	unsigned short* src16 = (unsigned short*)src;
	unsigned int* src32 = (unsigned int*)src;

	int x, y, i;
	
	for(y = 0; y < 272; y++)
	{
		src8 = (unsigned char*)src;
		src16 = (unsigned short*)src;
		src32 = (unsigned int*)src;
		
		for (i = 0, x = 0; x < 480; x++)
		{
			unsigned int r = 0, g = 0, b = 0, a = 0;
			unsigned int col32;
			
			col32 = *src32++;
			RGBA8888(col32, r, g, b, a);
			
			line[i++] = r;
			line[i++] = g;
			line[i++] = b;
			line[i++] = 255;
		}
		
		png_write_row(png_ptr, line);
		src += ((512*32) >> 3);
	}
	
	pgeFree(line);
	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
	fclose(fp);	
}
Example #15
0
bool IGN_Create_PNG_JPR(LPCSTR mapname, long minx, long miny, long maxx, long maxy)
{
char tstring[256];
long bitmap_width = TILE_WIDTH*(maxx-minx)/1000;
long bitmap_size = bitmap_width*TILE_WIDTH;
unsigned char * bitmap_memory = (unsigned char *)malloc(bitmap_size);
CIGNTileDatabase	db;


	if (bitmap_memory == NULL) {
		printf("Couldn't allocate %d bytes of memory\n");
		return false;
	}


	// Create PNG header and write out palette
	sprintf(tstring, "%s.png", mapname);
	FILE * fp_png = fopen(tstring, "wb");
	if (fp_png == NULL) {
		printf("Couldn't open %s\n", tstring);
		return false;
	}
	
	// Create and initialize the png_struct with the desired error handler functions.
	png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL) {
		fclose(fp_png);
		return false;
	}
	
	/* Allocate/initialize the image information data.  REQUIRED */
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
		fclose(fp_png);
		return false;
	}
	
	/* Set error handling.  REQUIRED */
	if (setjmp(png_jmpbuf(png_ptr))) {
		/* If we get here, we had a problem reading the file */
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fclose(fp_png);
		return false;
	}

	/* set up the output control if you are using standard C streams */
	png_init_io(png_ptr, fp_png);
	
	/* Set the image information here.  Width and height are up to 2^31,
	 * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
	 * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
	 * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
	 * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
	 * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
	 * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
	 */
	png_set_IHDR(png_ptr, info_ptr, TILE_WIDTH*(maxx-minx)/1000, TILE_WIDTH*((maxy-miny)/1000), 8, PNG_COLOR_TYPE_PALETTE,
				PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

	/* set the palette if there is one.  REQUIRED for indexed-color images */
	png_colorp png_palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof (png_color));


	int i;
	BYTE * pal_ptr = (BYTE *)png_palette;
	BYTE * palette = ign_palette;
	for (i=0; i<256; i++) {
		*pal_ptr++ = palette[i*4 + 2];
		*pal_ptr++ = palette[i*4 + 1];
		*pal_ptr++ = palette[i*4 + 0];
	}

	/* ... set palette colors ... */
	png_set_PLTE(png_ptr, info_ptr, png_palette, PNG_MAX_PALETTE_LENGTH);
	/* You must not free palette here, because png_set_PLTE only makes a link to
	 * the palette that you malloced.  Wait until you are about to destroy
	 *the png structure. */
	
	/* Write the file header information.  REQUIRED */
	png_write_info(png_ptr, info_ptr);

CProgressWindow wndProgress;
wndProgress.Initialize();

wndProgress.ResetProgressBar("Tile:", (maxy-miny)/500*(maxx-minx)/500);


	for (int y=maxy-1000; y>=miny; y-=1000) {
		memset(bitmap_memory, 0x00, bitmap_size);
		for (int x=minx; x<maxx; x+=1000) {
			IGN_read_bmp(y, x, &db, bitmap_memory+(x-minx)/1000*TILE_WIDTH, bitmap_width);
		}


		// write row of PNG to file
		for (int x=0; x<TILE_WIDTH; x++) {
			png_write_row(png_ptr, bitmap_memory + x*bitmap_width);

			if (!wndProgress.ProgressBar()) return false;
		}
	}
	/* It is REQUIRED to call this to finish writing the rest of the file */
	png_write_end(png_ptr, info_ptr);

	png_free(png_ptr, png_palette);
	
	/* clean up after the write, and free any memory allocated */
	png_destroy_write_struct(&png_ptr, &info_ptr);

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

//	IGN_dumpjprfile(mapname, minx, miny, maxx, maxy, (maxx-minx)/1000 * TILE_WIDTH, (maxy-miny)/1000*TILE_WIDTH, NULL);
	free(bitmap_memory);
	return true;
}
Example #16
0
bool8 S9xDoScreenshot (int width, int height)
{
	Settings.TakeScreenshot = FALSE;

#ifdef HAVE_LIBPNG
	FILE		*fp;
	png_structp	png_ptr;
	png_infop	info_ptr;
	png_color_8	sig_bit;
	int			imgwidth, imgheight;
	const char	*fname;

	fname = S9xGetFilenameInc(".png", SCREENSHOT_DIR);

	fp = fopen(fname, "wb");
	if (!fp)
	{
		S9xMessage(S9X_ERROR, 0, "Failed to take screenshot.");
		return (FALSE);
	}

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr)
	{
		fclose(fp);
		remove(fname);
		S9xMessage(S9X_ERROR, 0, "Failed to take screenshot.");
		return (FALSE);
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
		fclose(fp);
		remove(fname);
		S9xMessage(S9X_ERROR, 0, "Failed to take screenshot.");
		return (FALSE);
	}

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fclose(fp);
		remove(fname);
		S9xMessage(S9X_ERROR, 0, "Failed to take screenshot.");
		return (FALSE);
	}

	imgwidth  = width;
	imgheight = height;

	if (Settings.StretchScreenshots == 1)
	{
		if (width > SNES_WIDTH && height <= SNES_HEIGHT_EXTENDED)
			imgheight = height << 1;
	}
	else
	if (Settings.StretchScreenshots == 2)
	{
		if (width  <= SNES_WIDTH)
			imgwidth  = width  << 1;
		if (height <= SNES_HEIGHT_EXTENDED)
			imgheight = height << 1;
	}

	png_init_io(png_ptr, fp);

	png_set_IHDR(png_ptr, info_ptr, imgwidth, imgheight, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

	sig_bit.red   = 5;
	sig_bit.green = 5;
	sig_bit.blue  = 5;
	png_set_sBIT(png_ptr, info_ptr, &sig_bit);
	png_set_shift(png_ptr, &sig_bit);

	png_write_info(png_ptr, info_ptr);

	png_set_packing(png_ptr);

	png_byte	*row_pointer = new png_byte[png_get_rowbytes(png_ptr, info_ptr)];
	uint16		*screen = GFX.Screen;

	for (int y = 0; y < height; y++, screen += GFX.RealPPL)
	{
		png_byte	*rowpix = row_pointer;

		for (int x = 0; x < width; x++)
		{
			uint32	r, g, b;

			DECOMPOSE_PIXEL(screen[x], r, g, b);

			*(rowpix++) = r;
			*(rowpix++) = g;
			*(rowpix++) = b;

			if (imgwidth != width)
			{
				*(rowpix++) = r;
				*(rowpix++) = g;
				*(rowpix++) = b;
			}
		}

		png_write_row(png_ptr, row_pointer);
		if (imgheight != height)
			png_write_row(png_ptr, row_pointer);
	}

	delete [] row_pointer;

	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);

	fclose(fp);

	fprintf(stderr, "%s saved.\n", fname);

	const char	*base = S9xBasename(fname);
	sprintf(String, "Saved screenshot %s", base);
	S9xMessage(S9X_INFO, 0, String);

	return (TRUE);
#else
	fprintf(stderr, "Screenshot support not available (libpng was not found at build time).\n");
	return (FALSE);
#endif
}
Example #17
0
/**
  The constructor loads the named PNG image from the given png filename.
  <P>The destructor free all memory and server resources that are used by
  the image.
*/
void LoadPNG(const char *png) // I - File to read
{
  int		i;			// Looping var
  FILE		*fp;			// File pointer
  int		channels;		// Number of color channels
  png_structp	pp;			// PNG read pointer
  png_infop	info;			// PNG info pointers
  png_bytep	*rows;			// PNG row pointers


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  fclose(fp);
}
Example #18
0
static int qrwrap_writePNG(const char *outfile, QRcode *qrcode)
{
	static FILE *fp;
	png_structp png_ptr;
	png_infop info_ptr;
	unsigned char *row, *p, *q;
	int x, y, xx, yy, bit;
	int realwidth;
	const int margin = 0;
	const int size = 8;
	const int width = qrcode->width;

	realwidth = (width + margin * 2) * size;
	row = (unsigned char *)vj_malloc((realwidth + 7) / 8);
	if(row == NULL) {
		return 0;
	}

	fp = fopen(outfile, "wb");
	if(fp == NULL) {
		veejay_msg(VEEJAY_MSG_ERROR, "Unable to write QR code to file:%s", outfile);
		return 0;
	}
	

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if(png_ptr == NULL) {
		fclose(fp);
		return 0;
	}

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

	if(setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_write_struct(&png_ptr, &info_ptr);
		fclose(fp);
		return 0;
	}

	png_init_io(png_ptr, fp);
	png_set_IHDR(png_ptr, info_ptr,
			realwidth, realwidth,
			1,
			PNG_COLOR_TYPE_GRAY,
			PNG_INTERLACE_NONE,
			PNG_COMPRESSION_TYPE_DEFAULT,
			PNG_FILTER_TYPE_DEFAULT);
	png_write_info(png_ptr, info_ptr);

	/* top margin */
	veejay_memset(row, 0xff, (realwidth + 7) / 8);
	for(y=0; y<margin * size; y++) {
		png_write_row(png_ptr, row);
	}

	/* data */
	p = qrcode->data;
	for(y=0; y<width; y++) {
		bit = 7;
		veejay_memset(row, 0xff, (realwidth + 7) / 8);
		q = row;
		q += margin * size / 8;
		bit = 7 - (margin * size % 8);
		for(x=0; x<width; x++) {
			for(xx=0; xx<size; xx++) {
				*q ^= (*p & 1) << bit;
				bit--;
				if(bit < 0) {
					q++;
					bit = 7;
				}
			}
			p++;
		}
		for(yy=0; yy<size; yy++) {
			png_write_row(png_ptr, row);
		}
	}
	/* bottom margin */
	veejay_memset(row, 0xff, (realwidth + 7) / 8);
	for(y=0; y<margin * size; y++) {
		png_write_row(png_ptr, row);
	}

	png_write_end(png_ptr, info_ptr);
	png_destroy_write_struct(&png_ptr, &info_ptr);

	fclose(fp);
	free(row);

	return 0;
}
Example #19
0
int writepng(char* filename, png_store *pngdata)
{
	int code = 0;
	FILE *fp;
	png_structp png_ptr;
	png_infop info_ptr;
	png_bytep row;
	int width = pngdata->width;
	int height = pngdata->height;
//	float *buffer = pngdata->image_data;
	
	// Open file for writing (binary mode)
	fp = fopen(filename, "wb");
	if (fp == NULL) {
		fprintf(stderr, "Could not open file %s for writing\n", filename);
		code = 1;
		exit(1);
	}

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

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

	// Setup Exception handling
	if (setjmp(png_jmpbuf(png_ptr))) {
		fprintf(stderr, "Error during png creation\n");
		code = 1;
		exit(1);
	}

	png_init_io(png_ptr, fp);



	// Write header (8 bit colour depth)
	png_set_IHDR(png_ptr, info_ptr, width, height,
			pngdata->bitdepth, pngdata->colortype, PNG_INTERLACE_NONE,
			PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

	png_write_info(png_ptr, info_ptr);

	png_write_image(png_ptr,pngdata->row_pointers);	
	// End write
	png_write_end(png_ptr, NULL);
/*
	finalise:
	if (fp != NULL) fclose(fp);
	if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
	if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
	if (row != NULL) free(row);
*/
	return code;
}
Example #20
0
pointer PNG_READ_IMAGE(register context *ctx, int n, register pointer *argv)
{
  char *file_name;
  pointer ret, image_ptr;
  ckarg(1);
  if (isstring(argv[0])) file_name = argv[0]->c.str.chars;
  else error(E_NOSTRING);

  FILE *fp = fopen(file_name, "rb");
  if (!fp) {
    error(E_OPENFILE);
    return(NIL);
  }

  png_structp png_ptr;
  png_infop info_ptr;
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
  info_ptr = png_create_info_struct(png_ptr);

  if (setjmp(png_jmpbuf(png_ptr))) {
    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
    fclose(fp);
    error(E_EOF);
    return(NIL);
  }

  png_init_io(png_ptr, fp);
  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 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  int channels = png_get_channels(png_ptr, info_ptr);
  int color_type = png_get_color_type(png_ptr, info_ptr);
  //fprintf(stderr, "bit_depth = %d, channels %d, color_type =%d (pal:%d,gray:%d,rgb:%d,rgba:%d)\n", bit_depth, channels, color_type, PNG_COLOR_TYPE_PALETTE,PNG_COLOR_TYPE_GRAY,PNG_COLOR_TYPE_RGB,PNG_COLOR_TYPE_RGB_ALPHA);
  switch (color_type) {
  case PNG_COLOR_TYPE_PALETTE:
    png_set_palette_to_rgb(png_ptr);
    break;
  case PNG_COLOR_TYPE_GRAY:
    #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
    if ( bit_depth < 8) png_set_gray_to_rgb(png_ptr);
    #else
    if ( bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr);
    #endif
    break;
  case PNG_COLOR_TYPE_RGB:
    //png_set_bgr(png_ptr);
    if (bit_depth == 16) png_set_strip_16(png_ptr); // 16bit -> 8bit
    break;
  case PNG_COLOR_TYPE_RGB_ALPHA:
    if (bit_depth == 16) png_set_strip_16(png_ptr); // 16bit -> 8bit
    png_set_invert_alpha(png_ptr);
    //png_set_bgr(png_ptr);
    //png_set_strip_alpha(png_ptr);
    // RGBA -> rgb , GA -> g
    png_color_16 my_background = {0xff, 0xff, 0xff, 0xff, 0xff};
    png_set_background(png_ptr, &my_background,
                       PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);

    break;
  }
  png_read_update_info(png_ptr, info_ptr);
  width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr);;
  bit_depth = png_get_bit_depth(png_ptr, info_ptr); channels = png_get_channels(png_ptr, info_ptr);
  color_type = png_get_color_type(png_ptr, info_ptr);

  png_bytep * row_pointers = (png_bytep *)malloc(height*sizeof(png_bytep));
  int y, byte_per_scanline = png_get_rowbytes(png_ptr, info_ptr);
  image_ptr = makebuffer(height*byte_per_scanline);
  for(y=0;y<height;y++){
    row_pointers[y] = image_ptr->c.str.chars+y*byte_per_scanline;
  }
  png_read_image(png_ptr, row_pointers);
  free(row_pointers);
  png_read_end(png_ptr,info_ptr);
  png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
  fclose(fp);

  ret=cons(ctx,image_ptr,NIL);
  ret=cons(ctx,makeint(channels),ret);
  ret=cons(ctx,makeint(height),ret);
  ret=cons(ctx,makeint(width),ret);
  return (ret);
}
Example #21
0
int load_png_image(const char *filepath,
                   struct pngload_attribute *png_attr)
{
    FILE *fp;
    png_structp png_ptr;
    png_infop info_ptr;
    png_bytep* row_pointers;
    char buf[PNG_BYTES_TO_CHECK];
    int w, h, x, y, temp, color_type;

    fp = fopen( filepath, "rb" );
    if( fp == NULL ) { 
        return -1;
    }

    png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
    info_ptr = png_create_info_struct( png_ptr );

    setjmp( png_jmpbuf(png_ptr) ); 
    /* 读取PNG_BYTES_TO_CHECK个字节的数据 */
    temp = fread( buf, 1, PNG_BYTES_TO_CHECK, fp );
    /* 若读到的数据并没有PNG_BYTES_TO_CHECK个字节 */
    if( temp < PNG_BYTES_TO_CHECK ) {
        fclose(fp);
        png_destroy_read_struct( &png_ptr, &info_ptr, 0);
        return -3;
    }
    /* 检测数据是否为PNG的签名 */
    temp = png_sig_cmp( (png_bytep)buf, (png_size_t)0, PNG_BYTES_TO_CHECK );
    /* 如果不是PNG的签名,则说明该文件不是PNG文件 */
    if( temp != 0 ) {
        fclose(fp);
        png_destroy_read_struct( &png_ptr, &info_ptr, 0);
        return -4;
    }
        
    /* 复位文件指针 */
    rewind( fp );
    /* 开始读文件 */
    png_init_io( png_ptr, fp ); 
    /* 读取PNG图片信息 */
    png_read_png( png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0 );
    /* 获取图像的色彩类型 */
    color_type = png_get_color_type( png_ptr, info_ptr );
    /* 获取图像的宽高 */
    png_attr->width = w = png_get_image_width( png_ptr, info_ptr );
    png_attr->height = h = png_get_image_height( png_ptr, info_ptr );
    printf("w=%d,h=%d\n", w, h);
    /* 获取图像的所有行像素数据,row_pointers里边就是rgba数据 */
    row_pointers = png_get_rows( png_ptr, info_ptr );
    unsigned char *data;
    int index = 0;

    /* 根据不同的色彩类型进行相应处理 */
    png_attr->color_type = color_type;
    switch( color_type ) {
    case PNG_COLOR_TYPE_RGB_ALPHA:
        printf("rgba\n");
        data = malloc(w*h*4);
        png_attr->buf = data;
        for( y=0; y<h; ++y ) {
            for( x=0; x<w*4; ) {
                /* 以下是RGBA数据,需要自己补充代码,保存RGBA数据 */
                data[index++] = row_pointers[y][x++]; // red
                data[index++] = row_pointers[y][x++]; // green
                data[index++] = row_pointers[y][x++]; // blue
                data[index++] = row_pointers[y][x++]; // alpha
            }
        }
        break;

    case PNG_COLOR_TYPE_RGB:
        printf("rgb\n");
        data = malloc(w*h*3);
        png_attr->buf = data;
        for( y=0; y<h; ++y ) {
            for( x=0; x<w*3; ) {
                data[index++] = row_pointers[y][x++]; // red
                data[index++] = row_pointers[y][x++]; // green
                data[index++] = row_pointers[y][x++]; // blue
            }
        }
        break;
        /* 其它色彩类型的图像就不读了 */
    default:
        fclose(fp);
        png_destroy_read_struct( &png_ptr, &info_ptr, 0);
        return -2;
    }
    png_destroy_read_struct( &png_ptr, &info_ptr, 0);
    return 0;
}
Example #22
0
static int save_png_to_file (bitmap_t *bitmap, const char *path)
{
    FILE * fp;
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    size_t x, y;
    png_byte ** row_pointers = NULL;
    /* "status" contains the return value of this function. At first
       it is set to a value which means 'failure'. When the routine
       has finished its work, it is set to a value which means
       'success'. */
    int status = -1;
    /* The following number is set by trial and error only. I cannot
       see where it it is documented in the libpng manual.
    */
    int pixel_size = 3;
    int depth = 8;

    fp = fopen (path, "wb");
    if (! fp) {
        goto fopen_failed;
    }

    png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {
        goto png_create_write_struct_failed;
    }

    info_ptr = png_create_info_struct (png_ptr);
    if (info_ptr == NULL) {
        goto png_create_info_struct_failed;
    }

    /* Set up error handling. */

    if (setjmp (png_jmpbuf (png_ptr))) {
        goto png_failure;
    }

    /* Set image attributes. */

    png_set_IHDR (png_ptr,
                  info_ptr,
                  bitmap->width,
                  bitmap->height,
                  depth,
                  PNG_COLOR_TYPE_RGB,
                  PNG_INTERLACE_NONE,
                  PNG_COMPRESSION_TYPE_DEFAULT,
                  PNG_FILTER_TYPE_DEFAULT);

    /* Initialize rows of PNG. */

    row_pointers = png_malloc (png_ptr, bitmap->height * sizeof (png_byte *));
    for (y = 0; y < bitmap->height; ++y) {
        png_byte *row =
            png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size);
        row_pointers[y] = row;
        for (x = 0; x < bitmap->width; ++x) {
            pixel_t * pixel = pixel_at (bitmap, x, y);
            *row++ = pixel->red;
            *row++ = pixel->green;
            *row++ = pixel->blue;
        }
    }

    /* Write the image data to "fp". */

    png_init_io (png_ptr, fp);
    png_set_rows (png_ptr, info_ptr, row_pointers);
    png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

    /* The routine has successfully written the file, so we set
       "status" to a value which indicates success. */

    status = 0;

    for (y = 0; y < bitmap->height; y++) {
        png_free (png_ptr, row_pointers[y]);
    }
    png_free (png_ptr, row_pointers);

png_failure:
png_create_info_struct_failed:
    png_destroy_write_struct (&png_ptr, &info_ptr);
png_create_write_struct_failed:
    fclose (fp);
fopen_failed:
    return status;
}
Example #23
0
int GImageWrite_Png(GImage *gi, FILE *fp, int progressive) {
    struct _GImage *base = gi->list_len==0?gi->u.image:gi->u.images[0];
    png_structp png_ptr;
    png_infop info_ptr;
    png_byte **rows;
    int i;
    int bit_depth;
    int color_type;
    int num_palette;
    png_bytep trans_alpha = NULL;
    png_color_16p trans_color = NULL;
    png_colorp palette = NULL;

   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
      (void *)NULL, user_error_fn, user_warning_fn);

   if (!png_ptr) {
return(false);
   }

   info_ptr = png_create_info_struct(png_ptr);
   if (!info_ptr) {
      png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
return(false);
   }

#if (PNG_LIBPNG_VER < 10500)
    if (setjmp(png_ptr->jmpbuf))
#else
   if (setjmp(*png_set_longjmp_fn(png_ptr, longjmp, sizeof (jmp_buf))))
#endif
   {
      png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
return(false);
   }

   png_init_io(png_ptr, fp);

   bit_depth = 8;
   num_palette = base->clut==NULL?2:base->clut->clut_len;
   if ( base->image_type==it_index || base->image_type==it_bitmap ) {
       color_type = PNG_COLOR_TYPE_PALETTE;
       if ( num_palette<=2 )
	   bit_depth=1;
       else if ( num_palette<=4 )
	   bit_depth=2;
       else if ( num_palette<=16 )
	   bit_depth=4;
   } else {
       color_type = PNG_COLOR_TYPE_RGB;
       if ( base->image_type == it_rgba )
	   color_type = PNG_COLOR_TYPE_RGB_ALPHA;
   }

   png_set_IHDR(png_ptr, info_ptr, base->width, base->height,
		bit_depth, color_type, progressive,
		PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
   if ( base->image_type==it_index || base->image_type==it_bitmap ) {
       palette = (png_color *) galloc(num_palette*sizeof(png_color));
       if ( base->clut==NULL ) {
	    palette[0].red = palette[0].green = palette[0].blue = 0;
	    palette[1].red = palette[1].green = palette[1].blue = 0xff;
       } else {
	   for ( i=0; i<num_palette; ++i ) {
		long col = base->clut->clut[i];
		palette[i].red = COLOR_RED(col);
		palette[i].green = COLOR_GREEN(col);
		palette[i].blue = COLOR_BLUE(col);
	   }
       }
       png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
       if ( num_palette<=16 )
	   png_set_packing(png_ptr);

       if ( base->trans!=-1 ) {
	  trans_alpha = galloc(1);
	  trans_alpha[0] = base->trans;
       }
   } else {
       if ( base->trans!=-1 ) {
	   trans_color = galloc(sizeof(png_color_16));
	   trans_color->red = COLOR_RED(base->trans);
	   trans_color->green = COLOR_GREEN(base->trans);
	   trans_color->blue = COLOR_BLUE(base->trans);
       }
   }
   if ( base->trans!=-1 ) {
       png_set_tRNS(png_ptr, info_ptr, trans_alpha, 1, trans_color);
   }
   png_write_info(png_ptr, info_ptr);

    if (color_type == PNG_COLOR_TYPE_RGB)
	png_set_filler(png_ptr, '\0', PNG_FILLER_BEFORE);

    rows = galloc(base->height*sizeof(png_byte *));
    for ( i=0; i<base->height; ++i )
	rows[i] = (png_byte *) (base->data + i*base->bytes_per_line);

    png_write_image(png_ptr,rows);

    png_write_end(png_ptr, info_ptr);

    if ( trans_alpha!=NULL ) gfree(trans_alpha);
    if ( trans_color!=NULL ) gfree(trans_color);
    if ( palette!=NULL ) gfree(palette);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    gfree(rows);
return( 1 );
}
Example #24
0
int
read_png(FILE *file, int filetype, F_pic *pic)
{
    register int    i, j;
    png_structp	    png_ptr;
    png_infop	    info_ptr;
    png_infop	    end_info;
    png_uint_32	    w, h, rowsize;
    int		    bit_depth, color_type, interlace_type;
    int		    compression_type, filter_type;
    png_bytep	   *row_pointers;
    char	   *ptr;
    int		    num_palette;
    png_colorp	    palette;
    png_color_16    background;

    /* make scale factor smaller for metric */
    float scale = (appres.INCHES ?
		    (float)PIX_PER_INCH :
		    2.54*PIX_PER_CM)/(float)DISPLAY_PIX_PER_INCH;
    
    /* read the png file here */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
		(png_voidp) NULL, NULL, NULL);
    if (!png_ptr) {
	close_picfile(file,filetype);
	return FileInvalid;
    }
		
    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
	png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
	close_picfile(file,filetype);
	return FileInvalid;
    }

    end_info = png_create_info_struct(png_ptr);
    if (!end_info) {
	png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
	close_picfile(file,filetype);
	return FileInvalid;
    }

    /* set long jump recovery here */
    if (setjmp(png_ptr->jmpbuf)) {
	/* if we get here there was a problem reading the file */
	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	close_picfile(file,filetype);
	return FileInvalid;
    }
	
    /* set up the input code */
    png_init_io(png_ptr, file);

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

    /* get width, height etc */
    png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type,
	&interlace_type, &compression_type, &filter_type);

    if (info_ptr->valid & PNG_INFO_gAMA)
	png_set_gamma(png_ptr, 2.2, info_ptr->gamma);
    else
	png_set_gamma(png_ptr, 2.2, 0.45);

    if (info_ptr->valid & PNG_INFO_bKGD)
	/* set the background to the one supplied */
	png_set_background(png_ptr, &info_ptr->background,
		PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
    else {
	/* blend the canvas background using the alpha channel */
	background.red   = x_bg_color.red >> 8;
	background.green = x_bg_color.green >> 8;
	background.blue  = x_bg_color.blue >> 8;
	background.gray  = 0;
	png_set_background(png_ptr, &background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 2.2);
    }

    /* set order to BGR (default is RGB) */
    if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA)
	png_set_bgr(png_ptr);

    /* strip 16-bit RGB values down to 8-bit */
    if (bit_depth == 16)
	png_set_strip_16(png_ptr);

    /* force to 8-bits per pixel if less than 8 */
    if (bit_depth < 8)
	png_set_packing(png_ptr);

    /* dither rgb files down to 8 bit palette */
    num_palette = 0;
    pic->pic_cache->transp = TRANSP_NONE;
    if (color_type & PNG_COLOR_MASK_COLOR) {
	png_uint_16p	histogram;

#ifdef USE_ALPHA
	/* we need to somehow give libpng a background color that it can
	   combine with the alpha information in each pixel to make the image */

	if (color_type & PNG_COLOR_MASK_ALPHA)
	    pic->pic_cache->transp = TRANSP_BACKGROUND;
#endif /* USE_ALPHA */

	if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) {
	    png_get_hIST(png_ptr, info_ptr, &histogram);
	    png_set_dither(png_ptr, palette, num_palette, 256, histogram, 0);
	}
    }
    if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
	/* expand to full range */
	png_set_expand(png_ptr);
	/* make a gray colormap */
	num_palette = 256;
	for (i = 0; i < num_palette; i++)
	    pic->pic_cache->cmap[i].red = pic->pic_cache->cmap[i].green = pic->pic_cache->cmap[i].blue = i;
    } else {
	/* transfer the palette to the object's colormap */
	for (i=0; i<num_palette; i++) {
	    pic->pic_cache->cmap[i].red   = palette[i].red;
	    pic->pic_cache->cmap[i].green = palette[i].green;
	    pic->pic_cache->cmap[i].blue  = palette[i].blue;
	}
    }
    rowsize = w;
    if (color_type == PNG_COLOR_TYPE_RGB ||
	color_type == PNG_COLOR_TYPE_RGB_ALPHA)
	    rowsize = w*3;

    /* allocate the row pointers and rows */
    row_pointers = (png_bytep *) malloc(h*sizeof(png_bytep));
    for (i=0; i<h; i++) {
	if ((row_pointers[i] = malloc(rowsize)) == NULL) {
	    for (j=0; j<i; j++)
		free(row_pointers[j]);
	    close_picfile(file,filetype);
	    return FileInvalid;
	}
    }

    /* finally, read the file */
    png_read_image(png_ptr, row_pointers);

    /* allocate the bitmap */
    if ((pic->pic_cache->bitmap=malloc(rowsize*h))==NULL) {
	close_picfile(file,filetype);
	return FileInvalid;
    }

    /* copy it to our bitmap */
    ptr = pic->pic_cache->bitmap;
    for (i=0; i<h; i++) {
	bcopy(row_pointers[i], ptr, rowsize);
	ptr += rowsize;
    }
    /* put in width, height */
    pic->pic_cache->bit_size.x = w;
    pic->pic_cache->bit_size.y = h;

    if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
	/* no palette, must use neural net to reduce to 256 colors with palette */
	if (!map_to_palette(pic)) {
	    close_picfile(file,filetype);
	    return FileInvalid;		/* out of memory or something */
	}
	pic->pic_cache->numcols = 256;
    } else {
	pic->pic_cache->numcols = num_palette;
    }

    /* clean up */
    png_read_end(png_ptr, end_info);
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    for (i=0; i<h; i++)
	free(row_pointers[i]);

    pic->pic_cache->subtype = T_PIC_PNG;
    pic->pixmap = None;
    pic->hw_ratio = (float) pic->pic_cache->bit_size.y / pic->pic_cache->bit_size.x;
    pic->pic_cache->size_x = pic->pic_cache->bit_size.x * scale;
    pic->pic_cache->size_y = pic->pic_cache->bit_size.y * scale;
    /* if monochrome display map bitmap */
    if (tool_cells <= 2 || appres.monochrome)
	map_to_mono(pic);

    close_picfile(file,filetype);
    return PicSuccess;
}
Example #25
0
void write_png_file(const char* file_name, int32 width, int32 height, uint8 * data)
{
	if (CommandLineParser::Instance()->GetVerbose())
		printf("* Writing PNG file (%d x %d): %s\n", width, height, file_name);
	
	png_byte color_type = PNG_COLOR_TYPE_RGBA;
	png_byte bit_depth = 8;
	png_color_8 sig_bit;
	
	png_structp png_ptr;
	png_infop info_ptr;
	
	png_bytep * row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
	for (int y = 0; y < height; y++)
	{
		row_pointers[y] = (png_byte*) &data[y * width * 4];
	}
	
	
	/* create file */
	FILE *fp = fopen(file_name, "wb");
	if (!fp)
		abort_("[write_png_file] File %s could not be opened for writing", file_name);
	
	
	/* initialize stuff */
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	
	if (!png_ptr)
		abort_("[write_png_file] png_create_write_struct failed");
	
	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
		abort_("[write_png_file] png_create_info_struct failed");
	
	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[write_png_file] Error during init_io");
	
	png_init_io(png_ptr, fp);
	
	
	/* write header */
	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[write_png_file] Error during writing header");
	
	png_set_IHDR(png_ptr, info_ptr, width, height,
				 bit_depth, color_type, PNG_INTERLACE_NONE,
				 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
	
	
	sig_bit.red = 8;
	sig_bit.green = 8;
	sig_bit.blue = 8;
	sig_bit.alpha = 8;

	png_set_sBIT(png_ptr, info_ptr, &sig_bit);
		
	png_write_info(png_ptr, info_ptr);
	png_set_shift(png_ptr, &sig_bit);
	png_set_packing(png_ptr);
	
	/* write bytes */
	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[write_png_file] Error during writing bytes");
	
	png_write_image(png_ptr, row_pointers);
	
	
	/* end write */
	if (setjmp(png_jmpbuf(png_ptr)))
		abort_("[write_png_file] Error during end of write");
	
	png_write_end(png_ptr, NULL);
	
	free(row_pointers);
	
	fclose(fp);
}
Example #26
0
int R2Image::
ReadPNG(const char *filename)
{
  // Open file
  FILE *fp = fopen(filename, "rb");
  if (!fp) {
    fprintf(stderr, "Unable to open PNG file %s\n", filename);
    return 0;
   }

  // Create and initialize the png_struct 
  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (png_ptr == NULL) {
    fclose(fp);
    return 0;
  }

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

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

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

  // Extract image info 
  png_byte color_type = png_get_color_type(png_ptr, info_ptr);
  width = png_get_image_width(png_ptr, info_ptr);
  height = png_get_image_height(png_ptr, info_ptr);

  // Set nchannels
  nchannels = 0;
  if (color_type == PNG_COLOR_TYPE_GRAY) nchannels = 1;
  else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) nchannels = 2;
  else if (color_type == PNG_COLOR_TYPE_RGB) nchannels = 3;
  else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) nchannels = 4;
  else { 
    fclose(fp);
    png_destroy_read_struct(&png_ptr, NULL, NULL);
    return 0;
  }

  // Allocate the pixels and row pointers 
  int rowsize = png_get_rowbytes(png_ptr, info_ptr);
  assert(rowsize >= width * nchannels);
  png_bytep buffer = new unsigned char [ height * rowsize * png_sizeof(png_bytep) ]; 
  png_bytep *row_pointers = (png_bytep *) png_malloc(png_ptr, height * png_sizeof(png_bytep));
  for (int i = 0; i < height; i++) row_pointers[i] = &buffer[ (height - i - 1) * rowsize ];

  // Read the pixels 
  png_read_image(png_ptr, row_pointers);

  // Finish reading 
  png_read_end(png_ptr, info_ptr);

  // Copy pixels from temporary buffer
  pixels = new double [ height * width * nchannels ];
  for (int j = 0; j < height; j++) {
    for (int i = 0; i < width * nchannels; i++) {
      pixels[j*width*nchannels + i] = buffer[j*width*nchannels + i] / 255.0;
    }
  }

  // Free the row pointers 
  png_free(png_ptr, row_pointers);

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

  // Close the file 
  fclose(fp);

  // Delete temporary buffer
  delete [] buffer;

  // Return success 
  return 1;
}
Example #27
0
int pixbuf2png(GdkPixbuf *pb, const char *output_png)
{
    int i;

    int width = gdk_pixbuf_get_width(pb);
    int height = gdk_pixbuf_get_height(pb);
    int n_channels = gdk_pixbuf_get_n_channels(pb);
    int rowstride = gdk_pixbuf_get_rowstride(pb);

    guchar *pixels = gdk_pixbuf_get_pixels(pb);
    guchar *pixels_out = MALLOC(sizeof(guchar)*width*height*4);

    //printf("pixbuf2png> opening: %s\n", output_png);
    FILE *fout = FOPEN(output_png, "wb");
    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                          NULL, NULL, NULL);
    if (!png_ptr) {
        asfPrintWarning("Couldn't open png file: %s\n", output_png);
        return FALSE;
    }

    //printf("pixbuf2png> png_create_info_struct\n");
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
        fclose(fout);
        asfPrintWarning("Couldn't open png info for %s\n", output_png);
        return FALSE;
    }

    //printf("pixbuf2png> setjmp\n");
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        fclose(fout);
        asfPrintWarning("Error writing the png: %s\n", output_png);
        return FALSE;
    }

    //printf("pixbuf2png> png_init_io\n");
    png_init_io(png_ptr, fout);

    //printf("pixbuf2png> png_set_IHDR\n");
    png_set_IHDR(png_ptr, info_ptr, width, height, 8,
                 PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

    //printf("pixbuf2png> png_write_info\n");
    png_write_info(png_ptr, info_ptr);

    // add a transparency byte to each pixel in the pixels_out buffer
    for (i=0; i<height; ++i) {
        int j;
        for (j=0; j<width; ++j) {
            // output: red=k, green=k+1, blue=k+2, alpha=k+3
            int out_k = 4*(j + i*width);
            // input: red=k, green=k+1, blue=k+2
            int in_k = j*n_channels + i*rowstride;

            // make it transparent, if the pixel is black
            // (i.e., all channels are 0)
            int trans = pixels[in_k] == 0 &&
                        pixels[in_k+1] == 0 && pixels[in_k+2] == 0;

            pixels_out[out_k] = pixels[in_k];
            pixels_out[out_k+1] = pixels[in_k+1];
            pixels_out[out_k+2] = pixels[in_k+2];
            pixels_out[out_k+3] = trans ? 0 : 255;
        }
    }

    //printf("pixbuf2png> row_pointers\n");
    png_bytep *row_pointers = MALLOC(sizeof(png_bytep)*height);
    for (i=0; i<height; ++i)
        row_pointers[i] = pixels_out + i*width*4;

    //printf("pixbuf2png> png_write_image\n");
    png_write_image(png_ptr, row_pointers);

    //printf("pixbuf2png> png_write_end\n");
    png_write_end(png_ptr, NULL);

    //printf("pixbuf2png> png_destroy_write_struct\n");
    png_destroy_write_struct(&png_ptr, &info_ptr);

    //printf("pixbuf2png> fclose\n");
    fclose(fout);

    //printf("pixbuf2png> freeing row pointers\n");
    FREE(row_pointers);
    FREE(pixels_out);

    return TRUE;
}
Example #28
0
int R2Image::
WritePNG(const char *filename) const
{
  // Open the file 
  FILE *fp = fopen(filename, "wb");
  if (fp == NULL) {
    fprintf(stderr, "Unable to open PNG file %s\n", filename);
    return 0;
  }
  
  // Create and initialize the png_struct 
  png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (png_ptr == NULL) {
    fclose(fp);
    return 0;
  }
  
  // Allocate/initialize the image information data. 
  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL) {
    png_destroy_write_struct(&png_ptr,  NULL);
    fclose(fp);
    return 0;
  }
  
  // Determine color type  
  png_byte color_type = 0;
  if (nchannels == 1) color_type = PNG_COLOR_TYPE_GRAY;
  else if (nchannels == 2) color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
  else if (nchannels == 3) color_type = PNG_COLOR_TYPE_RGB;
  else if (nchannels == 4) color_type = PNG_COLOR_TYPE_RGB_ALPHA;
  else { fprintf(stderr, "Invalid number of channels for %s\n", filename); return 0; }

  // Fill in the image data 
  png_set_IHDR(png_ptr, info_ptr, width, height,
    8, color_type, PNG_INTERLACE_NONE,
    PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

  // Set up the output control 
  png_init_io(png_ptr, fp);
  
  // Write the png info 
  png_write_info(png_ptr, info_ptr);

  // Copy pixels into temporary buffer
  int rowsize = width * nchannels;
  if ((rowsize % 4) != 0) rowsize = (rowsize / 4 + 1) * 4;
  png_bytep buffer = (png_bytep) png_malloc(png_ptr, height * rowsize * png_sizeof(png_byte));
  png_bytep *row_pointers = (png_bytep *) png_malloc(png_ptr, height * png_sizeof(png_bytep));
  for (int j = 0; j < height; j++) {
    row_pointers[j] = &buffer[ (height - j - 1) * rowsize ];
    for (int i = 0; i < width * nchannels; i++) {
      buffer[j*width*nchannels + i] = (png_byte) (255.0 * pixels[j*width*nchannels + i]);
    }
  }

  // Write the pixels 
  png_write_image(png_ptr, row_pointers);
  
  // Finish writing 
  png_write_end(png_ptr, info_ptr);
  
  // Free the temporary data 
  png_free(png_ptr, row_pointers);
  png_free(png_ptr, buffer);

  // Clean up after the write, and free any memory allocated 
  png_destroy_write_struct(&png_ptr, &info_ptr);

  // Close the file 
  fclose(fp);

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

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

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

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

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

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

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

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

    fclose(pngfile);

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

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

    return ERR_OK;
}
Example #30
0
static void
gst_snapshot_chain (GstPad * pad, GstData * _data)
{
  GstBuffer *buf = GST_BUFFER (_data);
  GstSnapshot *snapshot;
  guchar *data;
  gulong size;
  gint i;
  png_byte *row_pointers[MAX_HEIGHT];
  FILE *fp;

  g_return_if_fail (pad != NULL);
  g_return_if_fail (GST_IS_PAD (pad));
  g_return_if_fail (buf != NULL);

  snapshot = GST_SNAPSHOT (GST_OBJECT_PARENT (pad));

  data = GST_BUFFER_DATA (buf);
  size = GST_BUFFER_SIZE (buf);

  GST_DEBUG ("snapshot: have buffer of %d\n", GST_BUFFER_SIZE (buf));

  snapshot->cur_frame++;
  if (snapshot->cur_frame == snapshot->frame ||
      snapshot->snapshot_asked == TRUE) {
    snapshot->snapshot_asked = FALSE;

    GST_INFO ("dumpfile : %s\n", snapshot->location);
    fp = fopen (snapshot->location, "wb");
    if (fp == NULL)
      g_warning (" Can not open %s\n", snapshot->location);
    else {
      snapshot->png_struct_ptr =
          png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL,
          user_error_fn, user_warning_fn);
      if (snapshot->png_struct_ptr == NULL)
        g_warning ("Failed to initialize png structure");

      snapshot->png_info_ptr =
          png_create_info_struct (snapshot->png_struct_ptr);

      if (setjmp (snapshot->png_struct_ptr->jmpbuf))
        png_destroy_write_struct (&snapshot->png_struct_ptr,
            &snapshot->png_info_ptr);

      png_set_filter (snapshot->png_struct_ptr, 0,
          PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE);
      png_init_io (snapshot->png_struct_ptr, fp);
      png_set_compression_level (snapshot->png_struct_ptr, 9);
      png_set_IHDR (snapshot->png_struct_ptr,
          snapshot->png_info_ptr,
          snapshot->width,
          snapshot->height,
          snapshot->to_bpp / 3,
          PNG_COLOR_TYPE_RGB,
          PNG_INTERLACE_NONE,
          PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

      for (i = 0; i < snapshot->height; i++)
        row_pointers[i] = data + (snapshot->width * i * snapshot->to_bpp / 8);

      png_write_info (snapshot->png_struct_ptr, snapshot->png_info_ptr);
      png_write_image (snapshot->png_struct_ptr, row_pointers);
      png_write_end (snapshot->png_struct_ptr, NULL);
      png_destroy_info_struct (snapshot->png_struct_ptr,
          &snapshot->png_info_ptr);
      png_destroy_write_struct (&snapshot->png_struct_ptr, (png_infopp) NULL);
      fclose (fp);
    }
  }

  gst_pad_push (snapshot->srcpad, GST_DATA (buf));
}