Skip to content

Commit

Permalink
Mattias Engdeg?rd - Tue Feb 27 12:44:43 PST 2001
Browse files Browse the repository at this point in the history
 * Improved the PCX loading code
 * Modified showimage to set hardware palette for 8-bit displays
  • Loading branch information
Sam Lantinga committed Feb 27, 2001
1 parent 52dc13a commit d658fa6
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 70 deletions.
3 changes: 3 additions & 0 deletions 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
Expand Down
175 changes: 105 additions & 70 deletions IMG_pcx.c
Expand Up @@ -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 <stdio.h>
#include <stdlib.h>

#include "SDL_endian.h"

Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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; y<surface->h; ++y ) {
for ( i=0; i<pcxh.NPlanes; ++i ) {
row = (Uint8 *)surface->pixels + y*surface->pitch;
index = i;
for ( x=0; x<pcxh.BytesPerLine; ) {
if ( ! SDL_RWread(src, &ch, 1, 1) ) {
read_error = 1;
/* decode a scan line to a temporary buffer first */
int i, count = 0;
Uint8 ch;
Uint8 *dst = (src_bits == 8) ? row : buf;
for(i = 0; i < bpl; i++) {
if(!count) {
if(!SDL_RWread(src, &ch, 1, 1)) {
error = "file truncated";
goto done;
}
if ( (ch & 0xC0) == 0xC0 ) {
count = ch & 0x3F;
SDL_RWread(src, &ch, 1, 1);
} else {
if( (ch & 0xc0) == 0xc0) {
count = ch & 0x3f;
if(!SDL_RWread(src, &ch, 1, 1)) {
error = "file truncated";
goto done;
}
} else
count = 1;
}
dst[i] = ch;
count--;
}

if(src_bits <= 4) {
/* expand planes to 1 byte/pixel */
Uint8 *src = buf;
int plane;
for(plane = 0; plane < pcxh.NPlanes; plane++) {
int i, j, x = 0;
for(i = 0; i < pcxh.BytesPerLine; i++) {
Uint8 byte = *src++;
for(j = 7; j >= 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);
Expand Down
2 changes: 2 additions & 0 deletions showimage.c
Expand Up @@ -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",
Expand Down

0 comments on commit d658fa6

Please sign in to comment.