IMG_png.c
author Thomas Bernard <miniupnp@free.fr>
Fri, 30 Nov 2018 11:04:15 +0100
branchSDL-1.2
changeset 634 68f958f43339
parent 613 89225c8816d6
permissions -rw-r--r--
IMG_xcf.c: Avoid infinite loop in read_xcf_header()
     1 /*
     2   SDL_image:  An example image loading library for use with SDL
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 #if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
    23 
    24 /* This is a PNG image file loading framework */
    25 
    26 #include <stdlib.h>
    27 #include <stdio.h>
    28 
    29 #include "SDL_image.h"
    30 
    31 #ifdef LOAD_PNG
    32 
    33 /*=============================================================================
    34         File: SDL_png.c
    35      Purpose: A PNG loader and saver for the SDL library      
    36     Revision: 
    37   Created by: Philippe Lavoie          (2 November 1998)
    38               lavoie@zeus.genie.uottawa.ca
    39  Modified by: 
    40 
    41  Copyright notice:
    42           Copyright (C) 1998 Philippe Lavoie
    43  
    44           This library is free software; you can redistribute it and/or
    45           modify it under the terms of the GNU Library General Public
    46           License as published by the Free Software Foundation; either
    47           version 2 of the License, or (at your option) any later version.
    48  
    49           This library is distributed in the hope that it will be useful,
    50           but WITHOUT ANY WARRANTY; without even the implied warranty of
    51           MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    52           Library General Public License for more details.
    53  
    54           You should have received a copy of the GNU Library General Public
    55           License along with this library; if not, write to the Free
    56           Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    57 
    58     Comments: The load and save routine are basically the ones you can find
    59              in the example.c file from the libpng distribution.
    60 
    61   Changes:
    62     5/17/99 - Modified to use the new SDL data sources - Sam Lantinga
    63 
    64 =============================================================================*/
    65 
    66 #include "SDL_endian.h"
    67 
    68 #ifdef macintosh
    69 #define MACOS
    70 #endif
    71 #include <png.h>
    72 
    73 /* Check for the older version of libpng */
    74 #if (PNG_LIBPNG_VER_MAJOR == 1)
    75 #if (PNG_LIBPNG_VER_MINOR < 5)
    76 #define LIBPNG_VERSION_12
    77 typedef png_bytep png_const_bytep;
    78 #endif
    79 #if (PNG_LIBPNG_VER_MINOR < 4)
    80 typedef png_structp png_const_structp;
    81 typedef png_infop png_const_infop;
    82 #endif
    83 #if (PNG_LIBPNG_VER_MINOR < 6)
    84 typedef png_structp png_structrp;
    85 typedef png_infop png_inforp;
    86 typedef png_const_structp png_const_structrp;
    87 typedef png_const_infop png_const_inforp;
    88 /* noconst15: version < 1.6 doesn't have const, >= 1.6 adds it */
    89 /* noconst16: version < 1.6 does have const, >= 1.6 removes it */
    90 typedef png_structp png_noconst15_structrp;
    91 typedef png_inforp png_noconst15_inforp;
    92 typedef png_const_inforp png_noconst16_inforp;
    93 #else
    94 typedef png_const_structp png_noconst15_structrp;
    95 typedef png_const_inforp png_noconst15_inforp;
    96 typedef png_inforp png_noconst16_inforp;
    97 #endif
    98 #else
    99 typedef png_const_structp png_noconst15_structrp;
   100 typedef png_const_inforp png_noconst15_inforp;
   101 typedef png_inforp png_noconst16_inforp;
   102 #endif
   103 
   104 static struct {
   105 	int loaded;
   106 	void *handle;
   107 	png_infop (*png_create_info_struct) (png_noconst15_structrp png_ptr);
   108 	png_structp (*png_create_read_struct) (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn);
   109 	void (*png_destroy_read_struct) (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr);
   110 	png_uint_32 (*png_get_IHDR) (png_noconst15_structrp png_ptr, png_noconst15_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, int *interlace_method, int *compression_method, int *filter_method);
   111 	png_voidp (*png_get_io_ptr) (png_noconst15_structrp png_ptr);
   112 	png_byte (*png_get_channels) (png_const_structrp png_ptr, png_const_inforp info_ptr);
   113 	png_uint_32 (*png_get_PLTE) (png_const_structrp png_ptr, png_noconst16_inforp info_ptr, png_colorp *palette, int *num_palette);
   114 	png_uint_32 (*png_get_tRNS) (png_const_structrp png_ptr, png_inforp info_ptr, png_bytep *trans, int *num_trans, png_color_16p *trans_values);
   115 	png_uint_32 (*png_get_valid) (png_const_structrp png_ptr, png_const_inforp info_ptr, png_uint_32 flag);
   116 	void (*png_read_image) (png_structrp png_ptr, png_bytepp image);
   117 	void (*png_read_info) (png_structrp png_ptr, png_inforp info_ptr);
   118 	void (*png_read_update_info) (png_structrp png_ptr, png_inforp info_ptr);
   119 	void (*png_set_expand) (png_structrp png_ptr);
   120 	void (*png_set_gray_to_rgb) (png_structrp png_ptr);
   121 	void (*png_set_packing) (png_structrp png_ptr);
   122 	void (*png_set_read_fn) (png_structrp png_ptr, png_voidp io_ptr, png_rw_ptr read_data_fn);
   123 	void (*png_set_strip_16) (png_structrp png_ptr);
   124 	int (*png_set_interlace_handling) (png_structp png_ptr);
   125 	int (*png_sig_cmp) (png_const_bytep sig, png_size_t start, png_size_t num_to_check);
   126 #ifndef LIBPNG_VERSION_12
   127 	jmp_buf* (*png_set_longjmp_fn) (png_structrp, png_longjmp_ptr, size_t);
   128 #endif
   129 } lib;
   130 
   131 #ifdef LOAD_PNG_DYNAMIC
   132 int IMG_InitPNG()
   133 {
   134 	if ( lib.loaded == 0 ) {
   135 		lib.handle = SDL_LoadObject(LOAD_PNG_DYNAMIC);
   136 		if ( lib.handle == NULL ) {
   137 			return -1;
   138 		}
   139 		lib.png_create_info_struct =
   140 			(png_infop (*) (png_noconst15_structrp))
   141 			SDL_LoadFunction(lib.handle, "png_create_info_struct");
   142 		if ( lib.png_create_info_struct == NULL ) {
   143 			SDL_UnloadObject(lib.handle);
   144 			return -1;
   145 		}
   146 		lib.png_create_read_struct =
   147 			(png_structrp (*) (png_const_charp, png_voidp, png_error_ptr, png_error_ptr))
   148 			SDL_LoadFunction(lib.handle, "png_create_read_struct");
   149 		if ( lib.png_create_read_struct == NULL ) {
   150 			SDL_UnloadObject(lib.handle);
   151 			return -1;
   152 		}
   153 		lib.png_destroy_read_struct =
   154 			(void (*) (png_structpp, png_infopp, png_infopp))
   155 			SDL_LoadFunction(lib.handle, "png_destroy_read_struct");
   156 		if ( lib.png_destroy_read_struct == NULL ) {
   157 			SDL_UnloadObject(lib.handle);
   158 			return -1;
   159 		}
   160 		lib.png_get_IHDR =
   161 			(png_uint_32 (*) (png_noconst15_structrp, png_noconst15_inforp, png_uint_32 *, png_uint_32 *, int *, int *, int *, int *, int *))
   162 			SDL_LoadFunction(lib.handle, "png_get_IHDR");
   163 		if ( lib.png_get_IHDR == NULL ) {
   164 			SDL_UnloadObject(lib.handle);
   165 			return -1;
   166 		}
   167 		lib.png_get_channels =
   168 			(png_byte (*) (png_const_structrp, png_const_inforp))
   169 			SDL_LoadFunction(lib.handle, "png_get_channels");
   170 		if ( lib.png_get_channels == NULL ) {
   171 			SDL_UnloadObject(lib.handle);
   172 			return -1;
   173 		}
   174 		lib.png_get_io_ptr =
   175 			(png_voidp (*) (png_noconst15_structrp))
   176 			SDL_LoadFunction(lib.handle, "png_get_io_ptr");
   177 		if ( lib.png_get_io_ptr == NULL ) {
   178 			SDL_UnloadObject(lib.handle);
   179 			return -1;
   180 		}
   181 		lib.png_get_PLTE =
   182 			(png_uint_32 (*) (png_const_structrp, png_noconst16_inforp, png_colorp *, int *))
   183 			SDL_LoadFunction(lib.handle, "png_get_PLTE");
   184 		if ( lib.png_get_PLTE == NULL ) {
   185 			SDL_UnloadObject(lib.handle);
   186 			return -1;
   187 		}
   188 		lib.png_get_tRNS =
   189 			(png_uint_32 (*) (png_const_structrp, png_inforp, png_bytep *, int *, png_color_16p *))
   190 			SDL_LoadFunction(lib.handle, "png_get_tRNS");
   191 		if ( lib.png_get_tRNS == NULL ) {
   192 			SDL_UnloadObject(lib.handle);
   193 			return -1;
   194 		}
   195 		lib.png_get_valid =
   196 			(png_uint_32 (*) (png_const_structrp, png_const_inforp, png_uint_32))
   197 			SDL_LoadFunction(lib.handle, "png_get_valid");
   198 		if ( lib.png_get_valid == NULL ) {
   199 			SDL_UnloadObject(lib.handle);
   200 			return -1;
   201 		}
   202 		lib.png_read_image =
   203 			(void (*) (png_structrp, png_bytepp))
   204 			SDL_LoadFunction(lib.handle, "png_read_image");
   205 		if ( lib.png_read_image == NULL ) {
   206 			SDL_UnloadObject(lib.handle);
   207 			return -1;
   208 		}
   209 		lib.png_read_info =
   210 			(void (*) (png_structrp, png_inforp))
   211 			SDL_LoadFunction(lib.handle, "png_read_info");
   212 		if ( lib.png_read_info == NULL ) {
   213 			SDL_UnloadObject(lib.handle);
   214 			return -1;
   215 		}
   216 		lib.png_read_update_info =
   217 			(void (*) (png_structrp, png_inforp))
   218 			SDL_LoadFunction(lib.handle, "png_read_update_info");
   219 		if ( lib.png_read_update_info == NULL ) {
   220 			SDL_UnloadObject(lib.handle);
   221 			return -1;
   222 		}
   223 		lib.png_set_expand =
   224 			(void (*) (png_structrp))
   225 			SDL_LoadFunction(lib.handle, "png_set_expand");
   226 		if ( lib.png_set_expand == NULL ) {
   227 			SDL_UnloadObject(lib.handle);
   228 			return -1;
   229 		}
   230 		lib.png_set_gray_to_rgb =
   231 			(void (*) (png_structrp))
   232 			SDL_LoadFunction(lib.handle, "png_set_gray_to_rgb");
   233 		if ( lib.png_set_gray_to_rgb == NULL ) {
   234 			SDL_UnloadObject(lib.handle);
   235 			return -1;
   236 		}
   237 		lib.png_set_packing =
   238 			(void (*) (png_structrp))
   239 			SDL_LoadFunction(lib.handle, "png_set_packing");
   240 		if ( lib.png_set_packing == NULL ) {
   241 			SDL_UnloadObject(lib.handle);
   242 			return -1;
   243 		}
   244 		lib.png_set_read_fn =
   245 			(void (*) (png_structrp, png_voidp, png_rw_ptr))
   246 			SDL_LoadFunction(lib.handle, "png_set_read_fn");
   247 		if ( lib.png_set_read_fn == NULL ) {
   248 			SDL_UnloadObject(lib.handle);
   249 			return -1;
   250 		}
   251 		lib.png_set_strip_16 =
   252 			(void (*) (png_structrp))
   253 			SDL_LoadFunction(lib.handle, "png_set_strip_16");
   254 		if ( lib.png_set_strip_16 == NULL ) {
   255 			SDL_UnloadObject(lib.handle);
   256 			return -1;
   257 		}
   258 		lib.png_set_interlace_handling =
   259 			(int (*) (png_structp))
   260 			SDL_LoadFunction(lib.handle, "png_set_interlace_handling");
   261 		if ( lib.png_set_interlace_handling == NULL ) {
   262 			SDL_UnloadObject(lib.handle);
   263 			return -1;
   264 		}
   265 		lib.png_sig_cmp =
   266 			(int (*) (png_const_bytep, png_size_t, png_size_t))
   267 			SDL_LoadFunction(lib.handle, "png_sig_cmp");
   268 		if ( lib.png_sig_cmp == NULL ) {
   269 			SDL_UnloadObject(lib.handle);
   270 			return -1;
   271 		}
   272 #ifndef LIBPNG_VERSION_12
   273 		lib.png_set_longjmp_fn =
   274 			(jmp_buf * (*) (png_structrp, png_longjmp_ptr, size_t))
   275 			SDL_LoadFunction(lib.handle, "png_set_longjmp_fn");
   276 		if ( lib.png_set_longjmp_fn == NULL ) {
   277 			SDL_UnloadObject(lib.handle);
   278 			return -1;
   279 		}
   280 #endif
   281 	}
   282 	++lib.loaded;
   283 
   284 	return 0;
   285 }
   286 void IMG_QuitPNG()
   287 {
   288 	if ( lib.loaded == 0 ) {
   289 		return;
   290 	}
   291 	if ( lib.loaded == 1 ) {
   292 		SDL_UnloadObject(lib.handle);
   293 	}
   294 	--lib.loaded;
   295 }
   296 #else
   297 int IMG_InitPNG()
   298 {
   299 	if ( lib.loaded == 0 ) {
   300 		lib.png_create_info_struct = png_create_info_struct;
   301 		lib.png_create_read_struct = png_create_read_struct;
   302 		lib.png_destroy_read_struct = png_destroy_read_struct;
   303 		lib.png_get_IHDR = png_get_IHDR;
   304 		lib.png_get_channels = png_get_channels;
   305 		lib.png_get_io_ptr = png_get_io_ptr;
   306 		lib.png_get_PLTE = png_get_PLTE;
   307 		lib.png_get_tRNS = png_get_tRNS;
   308 		lib.png_get_valid = png_get_valid;
   309 		lib.png_read_image = png_read_image;
   310 		lib.png_read_info = png_read_info;
   311 		lib.png_read_update_info = png_read_update_info;
   312 		lib.png_set_expand = png_set_expand;
   313 		lib.png_set_gray_to_rgb = png_set_gray_to_rgb;
   314 		lib.png_set_packing = png_set_packing;
   315 		lib.png_set_read_fn = png_set_read_fn;
   316 		lib.png_set_strip_16 = png_set_strip_16;
   317 		lib.png_set_interlace_handling = png_set_interlace_handling;
   318 		lib.png_sig_cmp = png_sig_cmp;
   319 #ifndef LIBPNG_VERSION_12
   320 		lib.png_set_longjmp_fn = png_set_longjmp_fn;
   321 #endif
   322 	}
   323 	++lib.loaded;
   324 
   325 	return 0;
   326 }
   327 void IMG_QuitPNG()
   328 {
   329 	if ( lib.loaded == 0 ) {
   330 		return;
   331 	}
   332 	if ( lib.loaded == 1 ) {
   333 	}
   334 	--lib.loaded;
   335 }
   336 #endif /* LOAD_PNG_DYNAMIC */
   337 
   338 /* See if an image is contained in a data source */
   339 int IMG_isPNG(SDL_RWops *src)
   340 {
   341 	int start;
   342 	int is_PNG;
   343 	Uint8 magic[4];
   344 
   345 	if ( !src )
   346 		return 0;
   347 	start = SDL_RWtell(src);
   348 	is_PNG = 0;
   349 	if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
   350                 if ( magic[0] == 0x89 &&
   351                      magic[1] == 'P' &&
   352                      magic[2] == 'N' &&
   353                      magic[3] == 'G' ) {
   354 			is_PNG = 1;
   355 		}
   356 	}
   357 	SDL_RWseek(src, start, RW_SEEK_SET);
   358 	return(is_PNG);
   359 }
   360 
   361 /* Load a PNG type image from an SDL datasource */
   362 static void png_read_data(png_structp ctx, png_bytep area, png_size_t size)
   363 {
   364 	SDL_RWops *src;
   365 
   366 	src = (SDL_RWops *)lib.png_get_io_ptr(ctx);
   367 	SDL_RWread(src, area, size, 1);
   368 }
   369 SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
   370 {
   371 	int start;
   372 	const char *error;
   373 	SDL_Surface *volatile surface;
   374 	png_structp png_ptr;
   375 	png_infop info_ptr;
   376 	png_uint_32 width, height;
   377 	int bit_depth, color_type, interlace_type, num_channels;
   378 	Uint32 Rmask;
   379 	Uint32 Gmask;
   380 	Uint32 Bmask;
   381 	Uint32 Amask;
   382 	SDL_Palette *palette;
   383 	png_bytep *volatile row_pointers;
   384 	int row, i;
   385 	volatile int ckey = -1;
   386 	png_color_16 *transv;
   387 
   388 	if ( !src ) {
   389 		/* The error message has been set in SDL_RWFromFile */
   390 		return NULL;
   391 	}
   392 	start = SDL_RWtell(src);
   393 
   394 	if ( (IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) == 0 ) {
   395 		return NULL;
   396 	}
   397 
   398 	/* Initialize the data we will clean up when we're done */
   399 	error = NULL;
   400 	png_ptr = NULL; info_ptr = NULL; row_pointers = NULL; surface = NULL;
   401 
   402 	/* Create the PNG loading context structure */
   403 	png_ptr = lib.png_create_read_struct(PNG_LIBPNG_VER_STRING,
   404 					  NULL,NULL,NULL);
   405 	if (png_ptr == NULL){
   406 		error = "Couldn't allocate memory for PNG file or incompatible PNG dll";
   407 		goto done;
   408 	}
   409 
   410 	 /* Allocate/initialize the memory for image information.  REQUIRED. */
   411 	info_ptr = lib.png_create_info_struct(png_ptr);
   412 	if (info_ptr == NULL) {
   413 		error = "Couldn't create image information for PNG file";
   414 		goto done;
   415 	}
   416 
   417 	/* Set error handling if you are using setjmp/longjmp method (this is
   418 	 * the normal method of doing things with libpng).  REQUIRED unless you
   419 	 * set up your own error handlers in png_create_read_struct() earlier.
   420 	 */
   421 #ifndef LIBPNG_VERSION_12
   422 	if ( setjmp(*lib.png_set_longjmp_fn(png_ptr, longjmp, sizeof (jmp_buf))) )
   423 #else
   424 	if ( setjmp(png_ptr->jmpbuf) )
   425 #endif
   426 	{
   427 		error = "Error reading the PNG file.";
   428 		goto done;
   429 	}
   430 
   431 	/* Set up the input control */
   432 	lib.png_set_read_fn(png_ptr, src, png_read_data);
   433 
   434 	/* Read PNG header info */
   435 	lib.png_read_info(png_ptr, info_ptr);
   436 	lib.png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
   437 			&color_type, &interlace_type, NULL, NULL);
   438 
   439 	/* tell libpng to strip 16 bit/color files down to 8 bits/color */
   440 	lib.png_set_strip_16(png_ptr) ;
   441 
   442 	/* tell libpng to de-interlace (if the image is interlaced) */
   443 	lib.png_set_interlace_handling(png_ptr) ;
   444 
   445 	/* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
   446 	 * byte into separate bytes (useful for paletted and grayscale images).
   447 	 */
   448 	lib.png_set_packing(png_ptr);
   449 
   450 	/* scale greyscale values to the range 0..255 */
   451 	if(color_type == PNG_COLOR_TYPE_GRAY)
   452 		lib.png_set_expand(png_ptr);
   453 
   454 	/* For images with a single "transparent colour", set colour key;
   455 	   if more than one index has transparency, or if partially transparent
   456 	   entries exist, use full alpha channel */
   457 	if (lib.png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
   458 	        int num_trans;
   459 		Uint8 *trans;
   460 		lib.png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans,
   461 			     &transv);
   462 		if(color_type == PNG_COLOR_TYPE_PALETTE) {
   463 		    /* Check if all tRNS entries are opaque except one */
   464 		    int j, t = -1;
   465 		    for(j = 0; j < num_trans; j++) {
   466 			if(trans[j] == 0) {
   467 			    if (t >= 0) {
   468 				break;
   469 			    }
   470 			    t = j;
   471 			} else if(trans[j] != 255) {
   472 			    break;
   473 			}
   474 		    }
   475 		    if(j == num_trans) {
   476 			/* exactly one transparent index */
   477 			ckey = t;
   478 		    } else {
   479 			/* more than one transparent index, or translucency */
   480 			lib.png_set_expand(png_ptr);
   481 		    }
   482 		} else
   483 		    ckey = 0; /* actual value will be set later */
   484 	}
   485 
   486 	if ( color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
   487 		lib.png_set_gray_to_rgb(png_ptr);
   488 
   489 	lib.png_read_update_info(png_ptr, info_ptr);
   490 
   491 	lib.png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
   492 			&color_type, &interlace_type, NULL, NULL);
   493 
   494 	/* Allocate the SDL surface to hold the image */
   495 	Rmask = Gmask = Bmask = Amask = 0 ;
   496 	num_channels = lib.png_get_channels(png_ptr, info_ptr);
   497 	if ( color_type != PNG_COLOR_TYPE_PALETTE ) {
   498 		if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
   499 			Rmask = 0x000000FF;
   500 			Gmask = 0x0000FF00;
   501 			Bmask = 0x00FF0000;
   502 			Amask = (num_channels == 4) ? 0xFF000000 : 0;
   503 		} else {
   504 			int s = (num_channels == 4) ? 0 : 8;
   505 			Rmask = 0xFF000000 >> s;
   506 			Gmask = 0x00FF0000 >> s;
   507 			Bmask = 0x0000FF00 >> s;
   508 			Amask = 0x000000FF >> s;
   509 		}
   510 	}
   511 	surface = SDL_AllocSurface(SDL_SWSURFACE, width, height,
   512 			bit_depth*num_channels, Rmask,Gmask,Bmask,Amask);
   513 	if ( surface == NULL ) {
   514 		error = "Out of memory";
   515 		goto done;
   516 	}
   517 
   518 	if(ckey != -1) {
   519 	        if(color_type != PNG_COLOR_TYPE_PALETTE)
   520 			/* FIXME: Should these be truncated or shifted down? */
   521 		        ckey = SDL_MapRGB(surface->format,
   522 			                 (Uint8)transv->red,
   523 			                 (Uint8)transv->green,
   524 			                 (Uint8)transv->blue);
   525 	        SDL_SetColorKey(surface, SDL_SRCCOLORKEY, ckey);
   526 	}
   527 
   528 	/* Create the array of pointers to image data */
   529 	row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*height);
   530 	if (row_pointers == NULL) {
   531 		error = "Out of memory";
   532 		goto done;
   533 	}
   534 	for (row = 0; row < (int)height; row++) {
   535 		row_pointers[row] = (png_bytep)
   536 				(Uint8 *)surface->pixels + row*surface->pitch;
   537 	}
   538 
   539 	/* Read the entire image in one go */
   540 	lib.png_read_image(png_ptr, row_pointers);
   541 
   542 	/* and we're done!  (png_read_end() can be omitted if no processing of
   543 	 * post-IDAT text/time/etc. is desired)
   544 	 * In some cases it can't read PNG's created by some popular programs (ACDSEE),
   545 	 * we do not want to process comments, so we omit png_read_end
   546 
   547 	lib.png_read_end(png_ptr, info_ptr);
   548 	*/
   549 
   550 	/* Load the palette, if any */
   551 	palette = surface->format->palette;
   552 	if ( palette ) {
   553 	    int png_num_palette;
   554 	    png_colorp png_palette;
   555 	    lib.png_get_PLTE(png_ptr, info_ptr, &png_palette, &png_num_palette);
   556 	    if(color_type == PNG_COLOR_TYPE_GRAY) {
   557 		palette->ncolors = 256;
   558 		for(i = 0; i < 256; i++) {
   559 		    palette->colors[i].r = (Uint8)i;
   560 		    palette->colors[i].g = (Uint8)i;
   561 		    palette->colors[i].b = (Uint8)i;
   562 		}
   563 	    } else if (png_num_palette > 0 ) {
   564 		palette->ncolors = png_num_palette;
   565 		for( i=0; i<png_num_palette; ++i ) {
   566 		    palette->colors[i].b = png_palette[i].blue;
   567 		    palette->colors[i].g = png_palette[i].green;
   568 		    palette->colors[i].r = png_palette[i].red;
   569 		}
   570 	    }
   571 	}
   572 
   573 done:	/* Clean up and return */
   574 	if ( png_ptr ) {
   575 		lib.png_destroy_read_struct(&png_ptr,
   576 		                        info_ptr ? &info_ptr : (png_infopp)0,
   577 								(png_infopp)0);
   578 	}
   579 	if ( row_pointers ) {
   580 		free(row_pointers);
   581 	}
   582 	if ( error ) {
   583 		SDL_RWseek(src, start, RW_SEEK_SET);
   584 		if ( surface ) {
   585 			SDL_FreeSurface(surface);
   586 			surface = NULL;
   587 		}
   588 		IMG_SetError(error);
   589 	}
   590 	return(surface); 
   591 }
   592 
   593 #else
   594 
   595 int IMG_InitPNG()
   596 {
   597 	IMG_SetError("PNG images are not supported");
   598 	return(-1);
   599 }
   600 
   601 void IMG_QuitPNG()
   602 {
   603 }
   604 
   605 /* See if an image is contained in a data source */
   606 int IMG_isPNG(SDL_RWops *src)
   607 {
   608 	return(0);
   609 }
   610 
   611 /* Load a PNG type image from an SDL datasource */
   612 SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
   613 {
   614 	return(NULL);
   615 }
   616 
   617 #endif /* LOAD_PNG */
   618 
   619 #endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */