/****************************************************************************
 * NCSA Mosaic for the X Window System                                      *
 * Software Development Group                                               *
 * National Center for Supercomputing Applications                          *
 * University of Illinois at Urbana-Champaign                               *
 * 605 E. Springfield, Champaign IL 61820                                   *
 * mosaic@ncsa.uiuc.edu                                                     *
 *                                                                          *
 * Copyright (C) 1993, Board of Trustees of the University of Illinois      *
 *                                                                          *
 * NCSA Mosaic software, both binary and source (hereafter, Software) is    *
 * copyrighted by The Board of Trustees of the University of Illinois       *
 * (UI), and ownership remains with the UI.                                 *
 *                                                                          *
 * The UI grants you (hereafter, Licensee) a license to use the Software    *
 * for academic, research and internal business purposes only, without a    *
 * fee.  Licensee may distribute the binary and source code (if released)   *
 * to third parties provided that the copyright notice and this statement   *
 * appears on all copies and that no charge is associated with such         *
 * copies.                                                                  *
 *                                                                          *
 * Licensee may make derivative works.  However, if Licensee distributes    *
 * any derivative work based on or derived from the Software, then          *
 * Licensee will (1) notify NCSA regarding its distribution of the          *
 * derivative work, and (2) clearly notify users that such derivative       *
 * work is a modified version and not the original NCSA Mosaic              *
 * distributed by the UI.                                                   *
 *                                                                          *
 * Any Licensee wishing to make commercial use of the Software should       *
 * contact the UI, c/o NCSA, to negotiate an appropriate license for such   *
 * commercial use.  Commercial use includes (1) integration of all or       *
 * part of the source code into a product for sale or license by or on      *
 * behalf of Licensee to third parties, or (2) distribution of the binary   *
 * code or source code to third parties that need it to utilize a           *
 * commercial product sold or licensed by or on behalf of Licensee.         *
 *                                                                          *
 * UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR   *
 * ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED          *
 * WARRANTY.  THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE    *
 * USERS OF THIS SOFTWARE.                                                  *
 *                                                                          *
 * By using or copying this Software, Licensee agrees to abide by the       *
 * copyright law and all other applicable laws of the U.S. including, but   *
 * not limited to, export control laws, and the terms of this license.      *
 * UI shall have the right to terminate this license immediately by         *
 * written notice upon Licensee's breach of, or non-compliance with, any    *
 * of its terms.  Licensee may be held legally responsible for any          *
 * copyright infringement that is caused or encouraged by Licensee's        *
 * failure to abide by the terms of this license.                           *
 *                                                                          *
 * Comments and questions are welcome and can be sent to                    *
 * mosaic-x@ncsa.uiuc.edu.                                                  *
 ****************************************************************************/

/* Copyright (C) 1998, 1999, 2000, 2004 - The VMS Mosaic Project */

/* Author: DXP 

 A lot of this is copied from the PNGLIB file example.c

 Modified:

    August   1995 - Glenn Randers-Pehrson <glennrp@arl.mil>
                    Changed dithering to use a 6x6x6 color cube.

    March 21 1996 - DXP
                    Fixed some interlacing problems.
                  
*/

#include "../config.h"
#ifdef HAVE_PNG

#include "../libhtmlw/HTMLp.h"
#include <stdio.h>

#include "png.h"
#include "mosaic.h"
#include "readPNG.h"

#include <setjmp.h>

extern int browserSafeColors;
extern XColor BSColors[256];
extern int BSCnum;

#ifndef DISABLE_TRACE
extern int srcTrace;
extern int reportBugs;
#endif

static char *colors_256[] = {
"ffffff",
"ffffcc",
"ffff99",
"ffff66",
"ffff33",
"ffff00",
"ffddff",
"ffddcc",
"ffdd99",
"ffdd66",
"ffdd33",
"ffdd00",
"ffbbff",
"ffbbcc",
"ffbb99",
"ffbb66",
"ffbb33",
"ffbb00",
"ff99ff",
"ff99cc",
"ff9999",
"ff9966",
"ff9933",
"ff9900",
"ff66ff",
"ff66cc",
"ff6699",
"ff6666",
"ff6633",
"ff6600",
"ff33ff",
"ff33cc",
"ff3399",
"ff3366",
"ff3333",
"ff3300",
"ff00ff",
"ff00cc",
"ff0099",
"ff0066",
"ff0033",
"ff0000",
"ccffff",
"ccffcc",
"ccff99",
"ccff66",
"ccff33",
"ccff00",
"ccddff",
/* Make it a pure gray */
"dddddd",
"ccdd99",
"ccdd66",
"ccdd33",
"ccdd00",
"ccbbff",
/* Make it a pure gray */
"cccccc",
"ccbb99",
"ccbb66",
"ccbb33",
"ccbb00",
"cc99ff",
"cc99cc",
"cc9999",
"cc9966",
"cc9933",
"cc9900",
"cc66ff",
"cc66cc",
"cc6699",
"cc6666",
"cc6633",
"cc6600",
"cc33ff",
"cc33cc",
"cc3399",
"cc3366",
"cc3333",
"cc3300",
"cc00ff",
"cc00cc",
"cc0099",
"cc0066",
"cc0033",
"cc0000",
"99ffff",
"99ffcc",
"99ff99",
"99ff66",
"99ff33",
"99ff00",
"99ddff",
"99ddcc",
"99dd99",
"99dd66",
"99dd33",
"99dd00",
"99bbff",
"99bbcc",
"99bb99",
"99bb66",
"99bb33",
"99bb00",
"9999ff",
"9999cc",
"999999",
"999966",
"999933",
"999900",
"9966ff",
"9966cc",
"996699",
"996666",
"996633",
"996600",
"9933ff",
"9933cc",
"993399",
"993366",
"993333",
"993300",
"9900ff",
"9900cc",
"990099",
"990066",
"990033",
"990000",
"66ffff",
"66ffcc",
"66ff99",
"66ff66",
"66ff33",
"66ff00",
"66ddff",
"66ddcc",
"66dd99",
"66dd66",
"66dd33",
"66dd00",
"66bbff",
"66bbcc",
"66bb99",
"66bb66",
"66bb33",
"66bb00",
"6699ff",
"6699cc",
"669999",
"669966",
"669933",
"669900",
"6666ff",
"6666cc",
"666699",
"666666",
"666633",
"666600",
"6633ff",
"6633cc",
"663399",
"663366",
"663333",
"663300",
"6600ff",
"6600cc",
"660099",
"660066",
"660033",
"660000",
"33ffff",
"33ffcc",
"33ff99",
"33ff66",
"33ff33",
"33ff00",
"33ddff",
"33ddcc",
"33dd99",
"33dd66",
"33dd33",
"33dd00",
"33bbff",
"33bbcc",
"33bb99",
"33bb66",
"33bb33",
"33bb00",
"3399ff",
"3399cc",
"339999",
"339966",
"339933",
"339900",
"3366ff",
"3366cc",
"336699",
"336666",
"336633",
"336600",
"3333ff",
"3333cc",
"333399",
"333366",
"333333",
"333300",
"3300ff",
"3300cc",
"330099",
"330066",
"330033",
"330000",
"00ffff",
"00ffcc",
"00ff99",
"00ff66",
"00ff33",
"00ff00",
"00ddff",
"00ddcc",
"00dd99",
"00dd66",
"00dd33",
"00dd00",
"00bbff",
"00bbcc",
"00bb99",
"00bb66",
"00bb33",
"00bb00",
"0099ff",
"0099cc",
"009999",
"009966",
"009933",
"009900",
"0066ff",
"0066cc",
"006699",
"006666",
"006633",
"006600",
"0033ff",
"0033cc",
"003399",
"003366",
"003333",
"003300",
"0000ff",
"0000cc",
"000099",
"000066",
"000033",
"000000",
/* Four more grays */
"eeeeee",
"bbbbbb",
"aaaaaa",
"888888"
};

unsigned char *
ReadPNG(HTMLWidget hw, FILE *infile, int *width, int *height, XColor *colrs,
	int *bg, unsigned char **alpha)
{
    png_struct *png_ptr;
    png_info *info_ptr;
    png_color_16 my_background;
    png_byte buf[8];
    unsigned long bg_pixel = hw->core.background_pixel;
    XColor tmpcolr;
    double screen_gamma;
    png_byte * volatile png_pixels = NULL, ** volatile row_pointers = NULL;
    png_byte * volatile alpha_pixels = NULL;
    int intent;
    int i, j, h, w;
    int num;
    int has_alpha = 0;
    static png_color std_color_cube[256];
    static int initialized = 0;
    static int num_colors;

    /* First check to see if it's a valid PNG file.  If not, return.
     * We assume that infile is a valid filepointer */
    if ((fread(buf, 1, 8, infile) != 8) || png_sig_cmp(buf, 0, 8))
        return 0;

    /* Rewind it and start decoding */
    rewind(infile);

    /* Allocate the structures */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
        return 0;

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

    /* Establish the setjmp return context for png_error to use. */
    if (setjmp(png_ptr->jmpbuf)) {
        
#ifndef DISABLE_TRACE
        if (srcTrace || reportBugs) {
            fprintf(stderr, "\nlibpng read error!!!\n");
        }
#endif
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

        if (png_pixels)
            free((char *)png_pixels);
        if (row_pointers)
	    free((char *)row_pointers);

        return 0;
    }

    /* Set up the input control */
    png_init_io(png_ptr, infile);
    
    /* Read the file information */
    png_read_info(png_ptr, info_ptr);
    
    /* Setup other stuff using the fields of png_info. */
    *width = w = (int)png_ptr->width;
    *height = h = (int)png_ptr->height;

#ifndef DISABLE_TRACE
    if (srcTrace) {
        fprintf(stderr, "\nBEFORE\nheight = %d\n", h);
        fprintf(stderr, "width = %d\n", w);
        fprintf(stderr, "bit depth = %d\n", info_ptr->bit_depth);
        fprintf(stderr, "color type = %d\n", info_ptr->color_type);
	if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
            fprintf(stderr,"num colors = %d\n", info_ptr->num_palette);
        fprintf(stderr, "rowbytes = %d\n", (int)info_ptr->rowbytes);
    }
#endif

    /* Strip pixels in 16-bit images down to 8 bits */
    if (info_ptr->bit_depth == 16)
        png_set_strip_16(png_ptr);

    /* Expand grayscale images to the full 8 bits */
    if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY) ||
	(info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) {
	if (info_ptr->bit_depth < 8)
	    png_set_gray_1_2_4_to_8(png_ptr);
	/* Deal with pnglib insanity */
	png_set_strip_alpha(png_ptr);
    }
    /* Handle alpha channel later */
    if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
	(info_ptr->valid & PNG_INFO_tRNS)) {
	has_alpha = 1;

    /* Handle non-alpha transparency by setting a background value */
    } else if (info_ptr->valid & PNG_INFO_bKGD) {
	    /* This should be the current background color */
	    tmpcolr.pixel = bg_pixel;
	    XQueryColor(XtDisplay(hw), hw->core.colormap, &tmpcolr);
	    my_background.index = 0;
	    if (info_ptr->valid & PNG_INFO_bKGD) {
		my_background.gray = info_ptr->background.gray;
	    } else {
		my_background.gray = 127;
	    }
	    if (info_ptr->bit_depth < 16) {
		my_background.red = tmpcolr.red / 256;
		my_background.green = tmpcolr.green / 256;
		my_background.blue = tmpcolr.blue / 256;
	    } else {
		my_background.red = tmpcolr.red;
		my_background.green = tmpcolr.green;
		my_background.blue = tmpcolr.blue;
		if (!(info_ptr->valid & PNG_INFO_bKGD)) {
		    my_background.gray *= 256;
		}
	    }
	    if (!(info_ptr->color_type & PNG_COLOR_MASK_COLOR)) {
		my_background.red = my_background.green = my_background.blue =
		    my_background.index = my_background.gray;
	    }
	    png_set_background(png_ptr, &my_background,
			       PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
#ifndef DISABLE_TRACE
	    if (srcTrace) {
	        fprintf(stderr, "bg_index = %d\n",
		    (int)png_ptr->background.index);
	        if (!(info_ptr->color_type == PNG_COLOR_MASK_COLOR))
		    fprintf(stderr, "gray_bg = %d\n",
			(int)info_ptr->background.gray);
	    }
#endif
	    *bg = -2;
    }

    /* If it is an RGB image, then dither to browser safe colors
     * or its own palette. */
    if (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
        info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {

        if (!(info_ptr->valid & PNG_INFO_PLTE)) {
		/* Has no palette */
#ifndef DISABLE_TRACE
        	if (srcTrace) {
        		fprintf(stderr, "dithering (RGB->our colors)...\n");
        	}
#endif
		if (!initialized) {
		    initialized = 1;
		    if (browserSafeColors) {
			num_colors = BSCnum;
	                for (i=0; i < BSCnum; i++) {
               		    std_color_cube[i].red = BSColors[i].red >> 8;
                    	    std_color_cube[i].green = BSColors[i].green >> 8;
                	    std_color_cube[i].blue = BSColors[i].blue >> 8;
		        }
		    } else {
                	/* If there is is no valid palette, then we need
			 * to make one up */
			unsigned int r, g, b;
			char t[3];

			num_colors = 256;
			t[2] = 0;
			for (i=0; i < num_colors; i++) {
			    t[0] = colors_256[i][0];
			    t[1] = colors_256[i][1];
			    sscanf(t, "%x", &r);
			    t[0] = colors_256[i][2];
			    t[1] = colors_256[i][3];
			    sscanf(t, "%x", &g);
			    t[0] = colors_256[i][4];
			    t[1] = colors_256[i][5];
			    sscanf(t, "%x", &b);
			    std_color_cube[i].red = r;
			    std_color_cube[i].green = g;
			    std_color_cube[i].blue = b;
			}
		    }
                }
		num = num_colors;
		/* If needed, put background color in cube */
		if (*bg == -2) {
		    if (num == 256) {
			num--;
		    }
		    std_color_cube[num].red = my_background.red;
		    std_color_cube[num].green = my_background.green;
		    std_color_cube[num].blue = my_background.blue;
		    my_background.index = num++;
#ifndef DISABLE_TRACE
		    if (srcTrace) {
		        fprintf(stderr, "RGB bg_index = %d\n",
			    (int)png_ptr->background.index);

		    }
#endif
		}
                png_set_dither(png_ptr, std_color_cube, num, num, NULL, 1);
        } else {
#ifndef DISABLE_TRACE
            if (srcTrace) {
                fprintf(stderr, "dithering (RGB->file supplied palette)...\n");
            }
#endif
            png_set_dither(png_ptr, info_ptr->palette, 
                           info_ptr->num_palette,
                           (browserSafeColors ? BSCnum :
			    get_pref_int(eCOLORS_PER_INLINED_IMAGE)), 
                           info_ptr->hist, 1);
        }
    }

    /* PNG files pack pixels of bit depths 1, 2, and 4 into bytes as
     * small as they can. This expands pixels to 1 pixel per byte, and
     * if a transparency value is supplied, an alpha channel is built. */
    if (info_ptr->bit_depth < 8)
        png_set_packing(png_ptr);

    /* Have libpng handle the gamma conversion */
    if (png_get_sRGB(png_ptr, info_ptr, &intent)) {
	png_set_sRGB(png_ptr, info_ptr, intent);
    } else {
	if (get_pref_boolean(eUSE_SCREEN_GAMMA)) {
            screen_gamma = (double)(get_pref_float(eSCREEN_GAMMA));
            
#ifndef DISABLE_TRACE
            if (srcTrace) {
                fprintf(stderr, "screen gamma = %f\n", screen_gamma);
            }
#endif
            if (info_ptr->valid & PNG_INFO_gAMA) {
#ifndef DISABLE_TRACE
                if (srcTrace) {
                    fprintf(stderr, "setting gamma = %f\n", info_ptr->gamma);
                }
#endif
                png_set_gamma(png_ptr, screen_gamma, (double)info_ptr->gamma);
            } else {
#ifndef DISABLE_TRACE
                if (srcTrace) {
                    fprintf(stderr, "setting gamma = %f\n", 0.45455);
                }
#endif
                png_set_gamma(png_ptr, screen_gamma, (double)0.45455);
            }
	}
    }
    
    png_read_update_info(png_ptr, info_ptr);
    
    /* Allocate the pixel grid which we will need to send to 
     * png_read_image(). */
    png_pixels = (png_byte *)malloc(info_ptr->rowbytes * h * sizeof(png_byte));
    
    row_pointers = (png_byte **) malloc(h * sizeof(png_byte *));
    for (i=0; i < *height; i++) {
        row_pointers[i] = png_pixels + (info_ptr->rowbytes * i);
    }
    /* FINALLY - read the darn thing. */
    png_read_image(png_ptr, row_pointers);
    
    png_read_end(png_ptr, info_ptr);
    
#ifndef DISABLE_TRACE
    if (srcTrace) {
        fprintf(stderr, "\nAFTER\nheight = %d\n", (int)png_ptr->height);
        fprintf(stderr, "width = %d\n", (int)png_ptr->width);
        fprintf(stderr, "bit depth = %d\n", info_ptr->bit_depth);
        fprintf(stderr, "color type = %d\n", info_ptr->color_type);
	if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
            fprintf(stderr, "num colors = %d\n", info_ptr->num_palette);
        fprintf(stderr, "rowbytes = %d\n", (int)info_ptr->rowbytes);
	if (*bg == -2) {
            fprintf(stderr, "bg_index = %d\n", (int)info_ptr->background.index);
	    if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)
		fprintf(stderr,"gray_bg = %d\n",(int)info_ptr->background.gray);
	}
    }
#endif

    /* Now that we have the (transformed to 8-bit RGB) image, we have
     * to copy the resulting palette to our colormap. */
    if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) {
	if (info_ptr->valid & PNG_INFO_PLTE) {
            
            for (i=0; i < info_ptr->num_palette; i++) {
                colrs[i].red = info_ptr->palette[i].red << 8;
                colrs[i].green = info_ptr->palette[i].green << 8;
                colrs[i].blue = info_ptr->palette[i].blue << 8;
                colrs[i].pixel = i;
                colrs[i].flags = DoRed|DoGreen|DoBlue;
            }
#ifndef DISABLE_TRACE
	    if (srcTrace) {
		fprintf(stderr,"using palette map\n");
	    }
#endif
	    if (*bg == -2) {
		if (info_ptr->num_trans) {
		    *bg = 0;
		} else {
		    *bg = info_ptr->background.index;
		}
	    }
            
	} else {
#ifndef DISABLE_TRACE
	    if (srcTrace) {
		fprintf(stderr, "using std_color_cube map of %d colors\n", num);
	    }
#endif
            for (i=0; i < num; i++) {
                colrs[i].red = std_color_cube[i].red << 8;
                colrs[i].green = std_color_cube[i].green << 8;
                colrs[i].blue = std_color_cube[i].blue << 8;
                colrs[i].pixel = i;
                colrs[i].flags = DoRed|DoGreen|DoBlue;
            }	    
	    if (*bg == -2) {
		if (info_ptr->num_trans) {
		    *bg = 0;
		} else {
		    *bg = info_ptr->background.index;
		}
	    }
	}
    } else {
        /* Grayscale image */
        for (i=0; i < 256; i++ ) {
            colrs[i].red = i << 8;
            colrs[i].green = i << 8; 	    
            colrs[i].blue = i << 8;
            colrs[i].pixel = i;
            colrs[i].flags = DoRed|DoGreen|DoBlue;    
        }
    }
    
    free((char *)row_pointers);

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

    /* Now get the alpha channel by basically starting over */
    if (has_alpha) {
	unsigned char *a;

#ifndef DISABLE_TRACE
	if (srcTrace) {
	    fprintf(stderr, "Getting the Alpha channel\n");
	}
#endif
	/* Null it in case setjmp activated */
	row_pointers = NULL;

	rewind(infile);

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

	if (setjmp(png_ptr->jmpbuf)) {
#ifndef DISABLE_TRACE
	    if (srcTrace || reportBugs) {
		fprintf(stderr, "\nlibpng alpha read error!!!\n");
	    }
#endif
	    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

	    if (png_pixels)
		free((char *)png_pixels);
	    if (alpha_pixels)
		free((char *)alpha_pixels);
	    if (row_pointers)
		free((char *)row_pointers);

	    return 0;
	}

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

	/* Force to RGB with Alpha */
	png_set_expand(png_ptr);

	if (info_ptr->bit_depth == 16)
	    png_set_strip_16(png_ptr);

	if (info_ptr->bit_depth < 8)
	    png_set_packing(png_ptr);

	/* Make it all RGB */
	if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
	    (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)) {
	    png_set_gray_to_rgb(png_ptr);
	}
	if (png_get_sRGB(png_ptr, info_ptr, &intent)) {
	    png_set_sRGB(png_ptr, info_ptr, intent);
	} else {
	    if (get_pref_boolean(eUSE_SCREEN_GAMMA)) {
		if (info_ptr->valid & PNG_INFO_gAMA) {
		    png_set_gamma(png_ptr, screen_gamma,
				  (double)info_ptr->gamma);
		} else {
		    png_set_gamma(png_ptr, screen_gamma, (double)0.45455);
		}
	    }
	}
    
	png_read_update_info(png_ptr, info_ptr);

	alpha_pixels = (png_byte *)malloc(info_ptr->rowbytes * h
			* sizeof(png_byte));
    
	row_pointers = (png_byte **) malloc(h * sizeof(png_byte *));
	for (i = 0; i < h; i++) {
	    row_pointers[i] = alpha_pixels + (info_ptr->rowbytes * i);
	}
	png_read_image(png_ptr, row_pointers);

#ifndef DISABLE_TRACE
	if (srcTrace) {
	    fprintf(stderr, "\nAFTER Alpha \n");
	    fprintf(stderr, "bit depth = %d\n", info_ptr->bit_depth);
	    fprintf(stderr, "color type = %d\n", info_ptr->color_type);
	    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
		 fprintf(stderr, "num colors = %d\n", info_ptr->num_palette);
	    fprintf(stderr, "rowbytes = %d\n", (int)info_ptr->rowbytes);
	    if (*bg == -2) {
		fprintf(stderr, "bg_index = %d\n",
			(int)info_ptr->background.index);
		if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) {
		    fprintf(stderr, "gray_bg = %d\n",
			    (int)info_ptr->background.gray);
		}
	    }
	}
#endif
    
	png_read_end(png_ptr, info_ptr);
	free((char *)row_pointers);

	num = h * w;
	*alpha = a = malloc(num);
	for (i = 0, j = 3; i < num; i++, j += 4) {
	    *a++ = alpha_pixels[j];
	}
	free((char *)alpha_pixels);

	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    }
    
    return png_pixels;
}
#endif
