2 SDL_image: An example image loading library for use with SDL
3 Copyright (C) 1997-2009 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 * PNM (portable anymap) image loader:
26 * Supports: PBM, PGM and PPM, ASCII and binary formats
27 * (PBM and PGM are loaded as 8bpp surfaces)
28 * Does not support: maximum component value > 255
36 #include "SDL_image.h"
40 /* See if an image is contained in a data source */
41 int IMG_isPNM(SDL_RWops *src)
49 start = SDL_RWtell(src);
51 if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
53 * PNM magic signatures:
54 * P1 PBM, ascii format
55 * P2 PGM, ascii format
56 * P3 PPM, ascii format
57 * P4 PBM, binary format
58 * P5 PGM, binary format
59 * P6 PPM, binary format
60 * P7 PAM, a general wrapper for PNM data
62 if ( magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6' ) {
66 SDL_RWseek(src, start, RW_SEEK_SET);
70 /* read a non-negative integer from the source. return -1 upon error */
71 static int ReadNumber(SDL_RWops *src)
76 /* Initialize return value */
79 /* Skip leading whitespace */
81 if ( ! SDL_RWread(src, &ch, 1, 1) ) {
84 /* Eat comments as whitespace */
85 if ( ch == '#' ) { /* Comment is '#' to end of line */
87 if ( ! SDL_RWread(src, &ch, 1, 1) ) {
90 } while ( (ch != '\r') && (ch != '\n') );
92 } while ( isspace(ch) );
94 /* Add up the number */
99 if ( !SDL_RWread(src, &ch, 1, 1) ) {
102 } while ( isdigit(ch) );
107 SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
110 SDL_Surface *surface = NULL;
118 enum { PBM, PGM, PPM, PAM } kind;
120 #define ERROR(s) do { error = (s); goto done; } while(0)
123 /* The error message has been set in SDL_RWFromFile */
126 start = SDL_RWtell(src);
128 SDL_RWread(src, magic, 2, 1);
129 kind = magic[1] - '1';
136 width = ReadNumber(src);
137 height = ReadNumber(src);
138 if(width <= 0 || height <= 0)
139 ERROR("Unable to read image width and height");
142 maxval = ReadNumber(src);
143 if(maxval <= 0 || maxval > 255)
144 ERROR("unsupported PNM format");
146 maxval = 255; /* never scale PBMs */
148 /* binary PNM allows just a single character of whitespace after
149 the last parameter, and we've already consumed it */
152 /* 24-bit surface in R,G,B byte order */
153 surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, 24,
154 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
155 0x000000ff, 0x0000ff00, 0x00ff0000,
157 0x00ff0000, 0x0000ff00, 0x000000ff,
161 /* load PBM/PGM as 8-bit indexed images */
162 surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, 8,
165 if ( surface == NULL )
166 ERROR("Out of memory");
167 bpl = width * surface->format->BytesPerPixel;
169 SDL_Color *c = surface->format->palette->colors;
171 for(i = 0; i < 256; i++)
172 c[i].r = c[i].g = c[i].b = i;
173 surface->format->palette->ncolors = 256;
174 } else if(kind == PBM) {
175 /* for some reason PBM has 1=black, 0=white */
176 SDL_Color *c = surface->format->palette->colors;
177 c[0].r = c[0].g = c[0].b = 255;
178 c[1].r = c[1].g = c[1].b = 0;
179 surface->format->palette->ncolors = 2;
180 bpl = (width + 7) >> 3;
183 ERROR("Out of memory");
186 /* Read the image into the surface */
187 row = surface->pixels;
188 for(y = 0; y < height; y++) {
192 for(i = 0; i < width; i++) {
195 if(!SDL_RWread(src, &ch,
197 ERROR("file truncated");
203 for(i = 0; i < bpl; i++) {
207 ERROR("file truncated");
212 Uint8 *dst = (kind == PBM) ? buf : row;
213 if(!SDL_RWread(src, dst, bpl, 1))
214 ERROR("file truncated");
216 /* expand bitmap to 8bpp */
218 for(i = 0; i < width; i++) {
219 int bit = 7 - (i & 7);
220 row[i] = (buf[i >> 3] >> bit) & 1;
225 /* scale up to full dynamic range (slow) */
227 for(i = 0; i < bpl; i++)
228 row[i] = row[i] * 255 / maxval;
230 row += surface->pitch;
235 SDL_RWseek(src, start, RW_SEEK_SET);
237 SDL_FreeSurface(surface);
247 /* See if an image is contained in a data source */
248 int IMG_isPNM(SDL_RWops *src)
253 /* Load a PNM type image from an SDL datasource */
254 SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
259 #endif /* LOAD_PNM */