Mattias Engdeg�rd - Tue Feb 27 12:44:43 PST 2001
authorSam Lantinga <slouken@lokigames.com>
Tue, 27 Feb 2001 20:45:58 +0000
changeset 20463951886af1
parent 19 346fbadf38a3
child 21 fcbcd2324998
Mattias Engdeg�rd - Tue Feb 27 12:44:43 PST 2001
* Improved the PCX loading code
* Modified showimage to set hardware palette for 8-bit displays
CHANGES
IMG_pcx.c
showimage.c
     1.1 --- a/CHANGES	Sat Feb 17 01:46:37 2001 +0000
     1.2 +++ b/CHANGES	Tue Feb 27 20:45:58 2001 +0000
     1.3 @@ -1,5 +1,8 @@
     1.4  
     1.5  1.1.1:
     1.6 +Mattias Engdegrd - Tue Feb 27 12:44:43 PST 2001
     1.7 + * Improved the PCX loading code
     1.8 + * Modified showimage to set hardware palette for 8-bit displays
     1.9  Sam Lantinga - Tue Jan 30 14:24:06 PST 2001
    1.10   * Modified showimage to accept multiple images on the command line
    1.11  Sam Lantinga - Mon Dec 18 02:49:29 PST 2000
     2.1 --- a/IMG_pcx.c	Sat Feb 17 01:46:37 2001 +0000
     2.2 +++ b/IMG_pcx.c	Tue Feb 27 20:45:58 2001 +0000
     2.3 @@ -22,9 +22,19 @@
     2.4      slouken@devolution.com
     2.5  */
     2.6  
     2.7 -/* This is a PCX image file loading framework */
     2.8 -
     2.9 +/*
    2.10 + * PCX file reader:
    2.11 + * Supports:
    2.12 + *  1..4 bits/pixel in multiplanar format (1 bit/plane/pixel)
    2.13 + *  8 bits/pixel in single-planar format (8 bits/plane/pixel)
    2.14 + *  24 bits/pixel in 3-plane format (8 bits/plane/pixel)
    2.15 + *
    2.16 + * Doesn't support:
    2.17 + *  single-planar packed-pixel formats other than 8bpp
    2.18 + *  4-plane 32bpp format with a fourth "intensity" plane
    2.19 + */
    2.20  #include <stdio.h>
    2.21 +#include <stdlib.h>
    2.22  
    2.23  #include "SDL_endian.h"
    2.24  
    2.25 @@ -77,24 +87,19 @@
    2.26  	Uint32 Gmask;
    2.27  	Uint32 Bmask;
    2.28  	Uint32 Amask;
    2.29 -	SDL_Surface *surface;
    2.30 +	SDL_Surface *surface = NULL;
    2.31  	int width, height;
    2.32 -	int i, index, x, y;
    2.33 -	int count;
    2.34 -	Uint8 *row, ch;
    2.35 -	int read_error;
    2.36 +	int y, bpl;
    2.37 +	Uint8 *row, *buf = NULL;
    2.38 +	char *error = NULL;
    2.39 +	int bits, src_bits;
    2.40  
    2.41 -	/* Initialize the data we will clean up when we're done */
    2.42 -	surface = NULL;
    2.43 -	read_error = 0;
    2.44 -
    2.45 -	/* Check to make sure we have something to do */
    2.46  	if ( ! src ) {
    2.47  		goto done;
    2.48  	}
    2.49  
    2.50 -	/* Read and convert the header */
    2.51  	if ( ! SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) {
    2.52 +		error = "file truncated";
    2.53  		goto done;
    2.54  	}
    2.55  	pcxh.Xmin = SDL_SwapLE16(pcxh.Xmin);
    2.56 @@ -106,8 +111,13 @@
    2.57  	/* Create the surface of the appropriate type */
    2.58  	width = (pcxh.Xmax - pcxh.Xmin) + 1;
    2.59  	height = (pcxh.Ymax - pcxh.Ymin) + 1;
    2.60 -	Rmask = Gmask = Bmask = Amask = 0 ; 
    2.61 -	if ( pcxh.BitsPerPixel * pcxh.NPlanes > 16 ) {
    2.62 +	Rmask = Gmask = Bmask = Amask = 0;
    2.63 +	src_bits = pcxh.BitsPerPixel * pcxh.NPlanes;
    2.64 +	if((pcxh.BitsPerPixel == 1 && pcxh.NPlanes >= 1 && pcxh.NPlanes <= 4)
    2.65 +	   || (pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 1)) {
    2.66 +		bits = 8;
    2.67 +	} else if(pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 3) {
    2.68 +		bits = 24;
    2.69  		if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
    2.70  			Rmask = 0x000000FF;
    2.71  			Gmask = 0x0000FF00;
    2.72 @@ -117,83 +127,108 @@
    2.73  			Gmask = 0x00FF00;
    2.74  			Bmask = 0x0000FF;
    2.75  		}
    2.76 +	} else {
    2.77 +		error = "unsupported PCX format";
    2.78 +		goto done;
    2.79  	}
    2.80  	surface = SDL_AllocSurface(SDL_SWSURFACE, width, height,
    2.81 -			pcxh.BitsPerPixel*pcxh.NPlanes,Rmask,Gmask,Bmask,Amask);
    2.82 -	if ( surface == NULL ) {
    2.83 -		IMG_SetError("Out of memory");
    2.84 +				   bits, Rmask, Gmask, Bmask, Amask);
    2.85 +	if ( surface == NULL )
    2.86  		goto done;
    2.87 +
    2.88 +	bpl = pcxh.NPlanes * pcxh.BytesPerLine;
    2.89 +	buf = malloc(bpl);
    2.90 +	row = surface->pixels;
    2.91 +	for ( y=0; y<surface->h; ++y ) {
    2.92 +		/* decode a scan line to a temporary buffer first */
    2.93 +		int i, count = 0;
    2.94 +		Uint8 ch;
    2.95 +		Uint8 *dst = (src_bits == 8) ? row : buf;
    2.96 +		for(i = 0; i < bpl; i++) {
    2.97 +			if(!count) {
    2.98 +				if(!SDL_RWread(src, &ch, 1, 1)) {
    2.99 +					error = "file truncated";
   2.100 +					goto done;
   2.101 +				}
   2.102 +				if( (ch & 0xc0) == 0xc0) {
   2.103 +					count = ch & 0x3f;
   2.104 +					if(!SDL_RWread(src, &ch, 1, 1)) {
   2.105 +						error = "file truncated";
   2.106 +						goto done;
   2.107 +					}
   2.108 +				} else
   2.109 +					count = 1;
   2.110 +			}
   2.111 +			dst[i] = ch;
   2.112 +			count--;
   2.113 +		}
   2.114 +
   2.115 +		if(src_bits <= 4) {
   2.116 +			/* expand planes to 1 byte/pixel */
   2.117 +			Uint8 *src = buf;
   2.118 +			int plane;
   2.119 +			for(plane = 0; plane < pcxh.NPlanes; plane++) {
   2.120 +				int i, j, x = 0;
   2.121 +				for(i = 0; i < pcxh.BytesPerLine; i++) {
   2.122 +					Uint8 byte = *src++;
   2.123 +					for(j = 7; j >= 0; j--) {
   2.124 +						unsigned bit = (byte >> j) & 1;
   2.125 +						row[x++] |= bit << plane;
   2.126 +					}
   2.127 +				}
   2.128 +			}
   2.129 + 		} else if(src_bits == 24) {
   2.130 +			/* de-interlace planes */
   2.131 +			Uint8 *src = buf;
   2.132 +			int plane;
   2.133 +			for(plane = 0; plane < pcxh.NPlanes; plane++) {
   2.134 +				int x;
   2.135 +				dst = row + plane;
   2.136 +				for(x = 0; x < width; x++) {
   2.137 +					*dst = *src++;
   2.138 +					dst += pcxh.NPlanes;
   2.139 +				}
   2.140 +			}
   2.141 +		}
   2.142 +
   2.143 +		row += surface->pitch;
   2.144  	}
   2.145  
   2.146 -	/* Decode the image to the surface */
   2.147 -	for ( y=0; y<surface->h; ++y ) {
   2.148 -		for ( i=0; i<pcxh.NPlanes; ++i ) {
   2.149 -			row = (Uint8 *)surface->pixels + y*surface->pitch;
   2.150 -			index = i;
   2.151 -			for ( x=0; x<pcxh.BytesPerLine; ) {
   2.152 -				if ( ! SDL_RWread(src, &ch, 1, 1) ) {
   2.153 -					read_error = 1;
   2.154 +	if(bits == 8) {
   2.155 +		SDL_Color *colors = surface->format->palette->colors;
   2.156 +		int nc = 1 << src_bits;
   2.157 +		int i;
   2.158 +
   2.159 +		surface->format->palette->ncolors = nc;
   2.160 +		if(src_bits == 8) {
   2.161 +			Uint8 ch;
   2.162 +			/* look for a 256-colour palette */
   2.163 +			do {
   2.164 +				if ( !SDL_RWread(src, &ch, 1, 1)) {
   2.165 +					error = "file truncated";
   2.166  					goto done;
   2.167  				}
   2.168 -				if ( (ch & 0xC0) == 0xC0 ) {
   2.169 -					count = ch & 0x3F;
   2.170 -					SDL_RWread(src, &ch, 1, 1);
   2.171 -				} else {
   2.172 -					count = 1;
   2.173 -				}
   2.174 -				while ( count-- ) {
   2.175 -					row[index] = ch;
   2.176 -					++x;
   2.177 -					index += pcxh.NPlanes;
   2.178 -				}
   2.179 +			} while ( ch != 12 );
   2.180 +
   2.181 +			for(i = 0; i < 256; i++) {
   2.182 +				SDL_RWread(src, &colors[i].r, 1, 1);
   2.183 +				SDL_RWread(src, &colors[i].g, 1, 1);
   2.184 +				SDL_RWread(src, &colors[i].b, 1, 1);
   2.185 +			}
   2.186 +		} else {
   2.187 +			for(i = 0; i < nc; i++) {
   2.188 +				colors[i].r = pcxh.Colormap[i * 3];
   2.189 +				colors[i].g = pcxh.Colormap[i * 3 + 1];
   2.190 +				colors[i].b = pcxh.Colormap[i * 3 + 2];
   2.191  			}
   2.192  		}
   2.193  	}
   2.194  
   2.195 -	/* Look for the palette, if necessary */
   2.196 -	switch (surface->format->BitsPerPixel) {
   2.197 -	    case 1: {
   2.198 -		SDL_Color *colors = surface->format->palette->colors;
   2.199 -
   2.200 -		colors[0].r = 0x00;
   2.201 -		colors[0].g = 0x00;
   2.202 -		colors[0].b = 0x00;
   2.203 -		colors[1].r = 0xFF;
   2.204 -		colors[1].g = 0xFF;
   2.205 -		colors[1].b = 0xFF;
   2.206 -	    }
   2.207 -	    break;
   2.208 -
   2.209 -	    case 8: {
   2.210 -		SDL_Color *colors = surface->format->palette->colors;
   2.211 -
   2.212 -		/* Look for the palette */
   2.213 -		do {
   2.214 -			if ( ! SDL_RWread(src, &ch, 1, 1) ) {
   2.215 -				read_error = 1;
   2.216 -				goto done;
   2.217 -			}
   2.218 -		} while ( ch != 12 );
   2.219 -
   2.220 -		/* Set the image surface palette */
   2.221 -		for ( i=0; i<256; ++i ) {
   2.222 -			SDL_RWread(src, &colors[i].r, 1, 1);
   2.223 -			SDL_RWread(src, &colors[i].g, 1, 1);
   2.224 -			SDL_RWread(src, &colors[i].b, 1, 1);
   2.225 -		}
   2.226 -	    }
   2.227 -	    break;
   2.228 -
   2.229 -	    default: {
   2.230 -		/* Don't do anything... */;
   2.231 -	    }
   2.232 -	    break;
   2.233 -	}
   2.234 -
   2.235  done:
   2.236 -	if ( read_error ) {
   2.237 +	free(buf);
   2.238 +	if ( error ) {
   2.239  		SDL_FreeSurface(surface);
   2.240 -		IMG_SetError("Error reading PCX data");
   2.241 +		IMG_SetError(error);
   2.242  		surface = NULL;
   2.243  	}
   2.244  	return(surface);
     3.1 --- a/showimage.c	Sat Feb 17 01:46:37 2001 +0000
     3.2 +++ b/showimage.c	Tue Feb 27 20:45:58 2001 +0000
     3.3 @@ -118,6 +118,8 @@
     3.4  		if ( (image->format->BytesPerPixel > 1) && (depth == 8) ) {
     3.5  	    		depth = 32;
     3.6  		}
     3.7 +		if(depth == 8)
     3.8 +			flags |= SDL_HWPALETTE;
     3.9  		screen = SDL_SetVideoMode(image->w, image->h, depth, flags);
    3.10  		if ( screen == NULL ) {
    3.11  			fprintf(stderr,"Couldn't set %dx%dx%d video mode: %s\n",