From d658fa62b780a920b55cb2d6602c1adc58e1c059 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 27 Feb 2001 20:45:58 +0000 Subject: [PATCH] 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 | 3 + IMG_pcx.c | 175 +++++++++++++++++++++++++++++++--------------------- showimage.c | 2 + 3 files changed, 110 insertions(+), 70 deletions(-) diff --git a/CHANGES b/CHANGES index 265ec89f..6e0b0785 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,8 @@ 1.1.1: +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 Sam Lantinga - Tue Jan 30 14:24:06 PST 2001 * Modified showimage to accept multiple images on the command line Sam Lantinga - Mon Dec 18 02:49:29 PST 2000 diff --git a/IMG_pcx.c b/IMG_pcx.c index eb132cb2..f33a0547 100644 --- a/IMG_pcx.c +++ b/IMG_pcx.c @@ -22,9 +22,19 @@ slouken@devolution.com */ -/* This is a PCX image file loading framework */ - +/* + * PCX file reader: + * Supports: + * 1..4 bits/pixel in multiplanar format (1 bit/plane/pixel) + * 8 bits/pixel in single-planar format (8 bits/plane/pixel) + * 24 bits/pixel in 3-plane format (8 bits/plane/pixel) + * + * Doesn't support: + * single-planar packed-pixel formats other than 8bpp + * 4-plane 32bpp format with a fourth "intensity" plane + */ #include +#include #include "SDL_endian.h" @@ -77,24 +87,19 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src) Uint32 Gmask; Uint32 Bmask; Uint32 Amask; - SDL_Surface *surface; + SDL_Surface *surface = NULL; int width, height; - int i, index, x, y; - int count; - Uint8 *row, ch; - int read_error; - - /* Initialize the data we will clean up when we're done */ - surface = NULL; - read_error = 0; + int y, bpl; + Uint8 *row, *buf = NULL; + char *error = NULL; + int bits, src_bits; - /* Check to make sure we have something to do */ if ( ! src ) { goto done; } - /* Read and convert the header */ if ( ! SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) { + error = "file truncated"; goto done; } pcxh.Xmin = SDL_SwapLE16(pcxh.Xmin); @@ -106,8 +111,13 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src) /* Create the surface of the appropriate type */ width = (pcxh.Xmax - pcxh.Xmin) + 1; height = (pcxh.Ymax - pcxh.Ymin) + 1; - Rmask = Gmask = Bmask = Amask = 0 ; - if ( pcxh.BitsPerPixel * pcxh.NPlanes > 16 ) { + Rmask = Gmask = Bmask = Amask = 0; + src_bits = pcxh.BitsPerPixel * pcxh.NPlanes; + if((pcxh.BitsPerPixel == 1 && pcxh.NPlanes >= 1 && pcxh.NPlanes <= 4) + || (pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 1)) { + bits = 8; + } else if(pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 3) { + bits = 24; if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) { Rmask = 0x000000FF; Gmask = 0x0000FF00; @@ -117,83 +127,108 @@ SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src) Gmask = 0x00FF00; Bmask = 0x0000FF; } + } else { + error = "unsupported PCX format"; + goto done; } surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, - pcxh.BitsPerPixel*pcxh.NPlanes,Rmask,Gmask,Bmask,Amask); - if ( surface == NULL ) { - IMG_SetError("Out of memory"); + bits, Rmask, Gmask, Bmask, Amask); + if ( surface == NULL ) goto done; - } - /* Decode the image to the surface */ + bpl = pcxh.NPlanes * pcxh.BytesPerLine; + buf = malloc(bpl); + row = surface->pixels; for ( y=0; yh; ++y ) { - for ( i=0; ipixels + y*surface->pitch; - index = i; - for ( x=0; x= 0; j--) { + unsigned bit = (byte >> j) & 1; + row[x++] |= bit << plane; + } } - while ( count-- ) { - row[index] = ch; - ++x; - index += pcxh.NPlanes; + } + } else if(src_bits == 24) { + /* de-interlace planes */ + Uint8 *src = buf; + int plane; + for(plane = 0; plane < pcxh.NPlanes; plane++) { + int x; + dst = row + plane; + for(x = 0; x < width; x++) { + *dst = *src++; + dst += pcxh.NPlanes; } } } - } - /* Look for the palette, if necessary */ - switch (surface->format->BitsPerPixel) { - case 1: { - SDL_Color *colors = surface->format->palette->colors; - - colors[0].r = 0x00; - colors[0].g = 0x00; - colors[0].b = 0x00; - colors[1].r = 0xFF; - colors[1].g = 0xFF; - colors[1].b = 0xFF; - } - break; + row += surface->pitch; + } - case 8: { + if(bits == 8) { SDL_Color *colors = surface->format->palette->colors; + int nc = 1 << src_bits; + int i; + + surface->format->palette->ncolors = nc; + if(src_bits == 8) { + Uint8 ch; + /* look for a 256-colour palette */ + do { + if ( !SDL_RWread(src, &ch, 1, 1)) { + error = "file truncated"; + goto done; + } + } while ( ch != 12 ); - /* Look for the palette */ - do { - if ( ! SDL_RWread(src, &ch, 1, 1) ) { - read_error = 1; - goto done; + for(i = 0; i < 256; i++) { + SDL_RWread(src, &colors[i].r, 1, 1); + SDL_RWread(src, &colors[i].g, 1, 1); + SDL_RWread(src, &colors[i].b, 1, 1); + } + } else { + for(i = 0; i < nc; i++) { + colors[i].r = pcxh.Colormap[i * 3]; + colors[i].g = pcxh.Colormap[i * 3 + 1]; + colors[i].b = pcxh.Colormap[i * 3 + 2]; } - } while ( ch != 12 ); - - /* Set the image surface palette */ - for ( i=0; i<256; ++i ) { - SDL_RWread(src, &colors[i].r, 1, 1); - SDL_RWread(src, &colors[i].g, 1, 1); - SDL_RWread(src, &colors[i].b, 1, 1); } - } - break; - - default: { - /* Don't do anything... */; - } - break; } done: - if ( read_error ) { + free(buf); + if ( error ) { SDL_FreeSurface(surface); - IMG_SetError("Error reading PCX data"); + IMG_SetError(error); surface = NULL; } return(surface); diff --git a/showimage.c b/showimage.c index 0c7ddc24..34e02205 100644 --- a/showimage.c +++ b/showimage.c @@ -118,6 +118,8 @@ int main(int argc, char *argv[]) if ( (image->format->BytesPerPixel > 1) && (depth == 8) ) { depth = 32; } + if(depth == 8) + flags |= SDL_HWPALETTE; screen = SDL_SetVideoMode(image->w, image->h, depth, flags); if ( screen == NULL ) { fprintf(stderr,"Couldn't set %dx%dx%d video mode: %s\n",