0,0 → 1,242 |
/* |
IMGLIB: An example image loading library for use with SDL |
Copyright (C) 1999 Sam Lantinga |
|
This library is free software; you can redistribute it and/or |
modify it under the terms of the GNU Library General Public |
License as published by the Free Software Foundation; either |
version 2 of the License, or (at your option) any later version. |
|
This library is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
Library General Public License for more details. |
|
You should have received a copy of the GNU Library General Public |
License along with this library; if not, write to the Free |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
Sam Lantinga |
5635-34 Springhouse Dr. |
Pleasanton, CA 94588 (USA) |
slouken@devolution.com |
*/ |
|
/* |
* PNM (portable anymap) image loader: |
* |
* Supports: PBM, PGM and PPM, ASCII and binary formats |
* (PBM and PGM are loaded as 8bpp surfaces) |
* Does not support: maximum component value > 255 |
*/ |
|
#include <stdio.h> |
#include <stdlib.h> |
#include <ctype.h> |
#include <string.h> |
|
#include "SDL_image.h" |
|
#ifdef LOAD_PNM |
|
/* See if an image is contained in a data source */ |
int IMG_isPNM(SDL_RWops *src) |
{ |
char magic[2]; |
|
/* |
* PNM magic signatures: |
* P1 PBM, ascii format |
* P2 PGM, ascii format |
* P3 PPM, ascii format |
* P4 PBM, binary format |
* P5 PGM, binary format |
* P6 PPM, binary format |
*/ |
return (SDL_RWread(src, magic, 2, 1) |
&& magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6'); |
} |
|
/* read a non-negative integer from the source. return -1 upon error */ |
static int ReadNumber(SDL_RWops *src) |
{ |
int number; |
unsigned char ch; |
|
/* Initialize return value */ |
number = 0; |
|
/* Skip leading whitespace */ |
do { |
if ( ! SDL_RWread(src, &ch, 1, 1) ) { |
return(0); |
} |
/* Eat comments as whitespace */ |
if ( ch == '#' ) { /* Comment is '#' to end of line */ |
do { |
if ( ! SDL_RWread(src, &ch, 1, 1) ) { |
return -1; |
} |
} while ( (ch != '\r') && (ch != '\n') ); |
} |
} while ( isspace(ch) ); |
|
/* Add up the number */ |
do { |
number *= 10; |
number += ch-'0'; |
|
if ( !SDL_RWread(src, &ch, 1, 1) ) { |
return -1; |
} |
} while ( isdigit(ch) ); |
|
return(number); |
} |
|
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src) |
{ |
SDL_Surface *surface = NULL; |
int width, height; |
int maxval, y, bpl; |
Uint8 *row; |
Uint8 *buf = NULL; |
char *error = NULL; |
Uint8 magic[2]; |
int ascii; |
enum { PBM, PGM, PPM } kind; |
|
#define ERROR(s) do { error = (s); goto done; } while(0) |
|
if(!src) |
return NULL; |
|
SDL_RWread(src, magic, 2, 1); |
kind = magic[1] - '1'; |
ascii = 1; |
if(kind >= 3) { |
ascii = 0; |
kind -= 3; |
} |
|
width = ReadNumber(src); |
height = ReadNumber(src); |
if(width <= 0 || height <= 0) |
ERROR("Unable to read image width and height"); |
|
if(kind != PBM) { |
maxval = ReadNumber(src); |
if(maxval <= 0 || maxval > 255) |
ERROR("unsupported PNM format"); |
} else |
maxval = 255; /* never scale PBMs */ |
|
/* binary PNM allows just a single character of whitespace after |
the last parameter, and we've already consumed it */ |
|
if(kind == PPM) { |
/* 24-bit surface in R,G,B byte order */ |
surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, 24, |
#if SDL_BYTEORDER == SDL_LIL_ENDIAN |
0x000000ff, 0x0000ff00, 0x00ff0000, |
#else |
0x00ff0000, 0x0000ff00, 0x000000ff, |
#endif |
0); |
} else { |
/* load PBM/PGM as 8-bit indexed images */ |
surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, 8, |
0, 0, 0, 0); |
} |
if ( surface == NULL ) |
ERROR("Out of memory"); |
bpl = width * surface->format->BytesPerPixel; |
if(kind == PGM) { |
SDL_Color *c = surface->format->palette->colors; |
int i; |
for(i = 0; i < 256; i++) |
c[i].r = c[i].g = c[i].b = i; |
surface->format->palette->ncolors = 256; |
} else if(kind == PBM) { |
/* for some reason PBM has 1=black, 0=white */ |
SDL_Color *c = surface->format->palette->colors; |
c[0].r = c[0].g = c[0].b = 255; |
c[1].r = c[1].g = c[1].b = 0; |
surface->format->palette->ncolors = 2; |
bpl = (width + 7) >> 3; |
buf = malloc(bpl); |
if(buf == NULL) |
ERROR("Out of memory"); |
} |
|
/* Read the image into the surface */ |
row = surface->pixels; |
for(y = 0; y < height; y++) { |
if(ascii) { |
int i; |
if(kind == PBM) { |
for(i = 0; i < width; i++) { |
Uint8 ch; |
do { |
if(!SDL_RWread(src, &ch, |
1, 1)) |
ERROR("file truncated"); |
ch -= '0'; |
} while(ch > 1); |
row[i] = ch; |
} |
} else { |
for(i = 0; i < bpl; i++) { |
int c; |
c = ReadNumber(src); |
if(c < 0) |
ERROR("file truncated"); |
row[i] = c; |
} |
} |
} else { |
Uint8 *dst = (kind == PBM) ? buf : row; |
if(!SDL_RWread(src, dst, bpl, 1)) |
ERROR("file truncated"); |
if(kind == PBM) { |
/* expand bitmap to 8bpp */ |
int i; |
for(i = 0; i < width; i++) { |
int bit = 7 - (i & 7); |
row[i] = (buf[i >> 3] >> bit) & 1; |
} |
} |
} |
if(maxval < 255) { |
/* scale up to full dynamic range (slow) */ |
int i; |
for(i = 0; i < bpl; i++) |
row[i] = row[i] * 255 / maxval; |
} |
row += surface->pitch; |
} |
done: |
free(buf); |
if(error) { |
SDL_FreeSurface(surface); |
IMG_SetError(error); |
surface = NULL; |
} |
return(surface); |
} |
|
#else |
|
/* See if an image is contained in a data source */ |
int IMG_isPNM(SDL_RWops *src) |
{ |
return(0); |
} |
|
/* Load a PNM type image from an SDL datasource */ |
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src) |
{ |
return(NULL); |
} |
|
#endif /* LOAD_PNM */ |