IMG_pcx.c
author Sam Lantinga <slouken@lokigames.com>
Fri, 01 Sep 2000 00:45:57 +0000
changeset 4 b1bb33e907f8
parent 0 76be7dab668c
child 7 e1b6443ffb6b
permissions -rw-r--r--
Mattias Engdeg�rd - Wed Aug 9 20:32:22 MET DST 2000
* Removed the alpha flipping, made IMG_InvertAlpha() a noop
* Fixed nonexisting PCX alpha support
* Some TIFF bugfixes
* PNG greyscale images are loaded as 8bpp with a greyscale palette
     1 /*
     2     IMGLIB:  An example image loading library for use with SDL
     3     Copyright (C) 1999  Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     5635-34 Springhouse Dr.
    21     Pleasanton, CA 94588 (USA)
    22     slouken@devolution.com
    23 */
    24 
    25 /* This is a PCX image file loading framework */
    26 
    27 #include <stdio.h>
    28 
    29 #include "SDL_endian.h"
    30 
    31 #include "SDL_image.h"
    32 
    33 #ifdef LOAD_PCX
    34 
    35 struct PCXheader {
    36 	Uint8 Manufacturer;
    37 	Uint8 Version;
    38 	Uint8 Encoding;
    39 	Uint8 BitsPerPixel;
    40 	Sint16 Xmin, Ymin, Xmax, Ymax;
    41 	Sint16 HDpi, VDpi;
    42 	Uint8 Colormap[48];
    43 	Uint8 Reserved;
    44 	Uint8 NPlanes;
    45 	Sint16 BytesPerLine;
    46 	Sint16 PaletteInfo;
    47 	Sint16 HscreenSize;
    48 	Sint16 VscreenSize;
    49 	Uint8 Filler[54];
    50 };
    51 
    52 /* See if an image is contained in a data source */
    53 int IMG_isPCX(SDL_RWops *src)
    54 {
    55 	int is_PCX;
    56 	const int ZSoft_Manufacturer = 10;
    57 	const int PC_Paintbrush_Version = 5;
    58 	const int PCX_RunLength_Encoding = 1;
    59 	struct PCXheader pcxh;
    60 
    61 	is_PCX = 0;
    62 	if ( SDL_RWread(src, &pcxh, sizeof(pcxh), 1) == 1 ) {
    63 		if ( (pcxh.Manufacturer == ZSoft_Manufacturer) &&
    64 		     (pcxh.Version == PC_Paintbrush_Version) &&
    65 		     (pcxh.Encoding == PCX_RunLength_Encoding) ) {
    66 			is_PCX = 1;
    67 		}
    68 	}
    69 	return(is_PCX);
    70 }
    71 
    72 /* Load a PCX type image from an SDL datasource */
    73 SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
    74 {
    75 	struct PCXheader pcxh;
    76 	Uint32 Rmask;
    77 	Uint32 Gmask;
    78 	Uint32 Bmask;
    79 	Uint32 Amask;
    80 	SDL_Surface *surface;
    81 	int width, height;
    82 	int i, index, x, y;
    83 	int count;
    84 	Uint8 *row, ch;
    85 	int read_error;
    86 
    87 	/* Initialize the data we will clean up when we're done */
    88 	surface = NULL;
    89 	read_error = 0;
    90 
    91 	/* Check to make sure we have something to do */
    92 	if ( ! src ) {
    93 		goto done;
    94 	}
    95 
    96 	/* Read and convert the header */
    97 	if ( ! SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) {
    98 		goto done;
    99 	}
   100 	pcxh.Xmin = SDL_SwapLE16(pcxh.Xmin);
   101 	pcxh.Ymin = SDL_SwapLE16(pcxh.Ymin);
   102 	pcxh.Xmax = SDL_SwapLE16(pcxh.Xmax);
   103 	pcxh.Ymax = SDL_SwapLE16(pcxh.Ymax);
   104 	pcxh.BytesPerLine = SDL_SwapLE16(pcxh.BytesPerLine);
   105 
   106 	/* Create the surface of the appropriate type */
   107 	width = (pcxh.Xmax - pcxh.Xmin) + 1;
   108 	height = (pcxh.Ymax - pcxh.Ymin) + 1;
   109 	Rmask = Gmask = Bmask = Amask = 0 ; 
   110 	if ( pcxh.BitsPerPixel * pcxh.NPlanes > 16 ) {
   111 		if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) {
   112 			Rmask = 0x000000FF;
   113 			Gmask = 0x0000FF00;
   114 			Bmask = 0x00FF0000;
   115 		} else {
   116 		        int s = (pcxh.NPlanes == 4) ? 0 : 8;
   117 			Rmask = 0xFF0000;
   118 			Gmask = 0x00FF00;
   119 			Bmask = 0x0000FF;
   120 		}
   121 	}
   122 	surface = SDL_AllocSurface(SDL_SWSURFACE, width, height,
   123 			pcxh.BitsPerPixel*pcxh.NPlanes,Rmask,Gmask,Bmask,Amask);
   124 	if ( surface == NULL ) {
   125 		IMG_SetError("Out of memory");
   126 		goto done;
   127 	}
   128 
   129 	/* Decode the image to the surface */
   130 	for ( y=0; y<surface->h; ++y ) {
   131 		for ( i=0; i<pcxh.NPlanes; ++i ) {
   132 			row = (Uint8 *)surface->pixels + y*surface->pitch;
   133 			index = i;
   134 			for ( x=0; x<pcxh.BytesPerLine; ) {
   135 				if ( ! SDL_RWread(src, &ch, 1, 1) ) {
   136 					read_error = 1;
   137 					goto done;
   138 				}
   139 				if ( (ch & 0xC0) == 0xC0 ) {
   140 					count = ch & 0x3F;
   141 					SDL_RWread(src, &ch, 1, 1);
   142 				} else {
   143 					count = 1;
   144 				}
   145 				while ( count-- ) {
   146 					row[index] = ch;
   147 					++x;
   148 					index += pcxh.NPlanes;
   149 				}
   150 			}
   151 		}
   152 	}
   153 
   154 	/* Look for the palette, if necessary */
   155 	switch (surface->format->BitsPerPixel) {
   156 	    case 1: {
   157 		SDL_Color *colors = surface->format->palette->colors;
   158 
   159 		colors[0].r = 0x00;
   160 		colors[0].g = 0x00;
   161 		colors[0].b = 0x00;
   162 		colors[1].r = 0xFF;
   163 		colors[1].g = 0xFF;
   164 		colors[1].b = 0xFF;
   165 	    }
   166 	    break;
   167 
   168 	    case 8: {
   169 		SDL_Color *colors = surface->format->palette->colors;
   170 
   171 		/* Look for the palette */
   172 		do {
   173 			if ( ! SDL_RWread(src, &ch, 1, 1) ) {
   174 				read_error = 1;
   175 				goto done;
   176 			}
   177 		} while ( ch != 12 );
   178 
   179 		/* Set the image surface palette */
   180 		for ( i=0; i<256; ++i ) {
   181 			SDL_RWread(src, &colors[i].r, 1, 1);
   182 			SDL_RWread(src, &colors[i].g, 1, 1);
   183 			SDL_RWread(src, &colors[i].b, 1, 1);
   184 		}
   185 	    }
   186 	    break;
   187 
   188 	    default: {
   189 		/* Don't do anything... */;
   190 	    }
   191 	    break;
   192 	}
   193 
   194 done:
   195 	if ( read_error ) {
   196 		SDL_FreeSurface(surface);
   197 		IMG_SetError("Error reading PCX data");
   198 		surface = NULL;
   199 	}
   200 	return(surface);
   201 }
   202 
   203 #else
   204 
   205 /* See if an image is contained in a data source */
   206 int IMG_isPCX(SDL_RWops *src)
   207 {
   208 	return(0);
   209 }
   210 
   211 /* Load a PCX type image from an SDL datasource */
   212 SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
   213 {
   214 	return(NULL);
   215 }
   216 
   217 #endif /* LOAD_PCX */