Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 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
/*
26
 * PNM (portable anymap) image loader:
27
 *
28
 * Supports: PBM, PGM and PPM, ASCII and binary formats
29
 * (PBM and PGM are loaded as 8bpp surfaces)
30
 * Does not support: maximum component value > 255
31
 */
32
 
33
#include 
34
#include 
35
#include 
36
#include 
37
 
38
#include "SDL_image.h"
39
 
40
#ifdef LOAD_PNM
41
 
42
/* See if an image is contained in a data source */
43
int IMG_isPNM(SDL_RWops *src)
44
{
45
	char magic[2];
46
 
47
	/*
48
	 * PNM magic signatures:
49
	 * P1	PBM, ascii format
50
	 * P2	PGM, ascii format
51
	 * P3	PPM, ascii format
52
	 * P4	PBM, binary format
53
	 * P5	PGM, binary format
54
	 * P6	PPM, binary format
55
	 */
56
	return (SDL_RWread(src, magic, 2, 1)
57
		&& magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6');
58
}
59
 
60
/* read a non-negative integer from the source. return -1 upon error */
61
static int ReadNumber(SDL_RWops *src)
62
{
63
	int number;
64
	unsigned char ch;
65
 
66
	/* Initialize return value */
67
	number = 0;
68
 
69
	/* Skip leading whitespace */
70
	do {
71
		if ( ! SDL_RWread(src, &ch, 1, 1) ) {
72
			return(0);
73
		}
74
		/* Eat comments as whitespace */
75
		if ( ch == '#' ) {  /* Comment is '#' to end of line */
76
			do {
77
				if ( ! SDL_RWread(src, &ch, 1, 1) ) {
78
					return -1;
79
				}
80
			} while ( (ch != '\r') && (ch != '\n') );
81
		}
82
	} while ( isspace(ch) );
83
 
84
	/* Add up the number */
85
	do {
86
		number *= 10;
87
		number += ch-'0';
88
 
89
		if ( !SDL_RWread(src, &ch, 1, 1) ) {
90
			return -1;
91
		}
92
	} while ( isdigit(ch) );
93
 
94
	return(number);
95
}
96
 
97
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
98
{
99
	SDL_Surface *surface = NULL;
100
	int width, height;
101
	int maxval, y, bpl;
102
	Uint8 *row;
103
	Uint8 *buf = NULL;
104
	char *error = NULL;
105
	Uint8 magic[2];
106
	int ascii;
107
	enum { PBM, PGM, PPM } kind;
108
 
109
#define ERROR(s) do { error = (s); goto done; } while(0)
110
 
111
	if(!src)
112
		return NULL;
113
 
114
	SDL_RWread(src, magic, 2, 1);
115
	kind = magic[1] - '1';
116
	ascii = 1;
117
	if(kind >= 3) {
118
		ascii = 0;
119
		kind -= 3;
120
	}
121
 
122
	width = ReadNumber(src);
123
	height = ReadNumber(src);
124
	if(width <= 0 || height <= 0)
125
		ERROR("Unable to read image width and height");
126
 
127
	if(kind != PBM) {
128
		maxval = ReadNumber(src);
129
		if(maxval <= 0 || maxval > 255)
130
			ERROR("unsupported PNM format");
131
	} else
132
		maxval = 255;	/* never scale PBMs */
133
 
134
	/* binary PNM allows just a single character of whitespace after
135
	   the last parameter, and we've already consumed it */
136
 
137
	if(kind == PPM) {
138
		/* 24-bit surface in R,G,B byte order */
139
		surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, 24,
140
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
141
					   0x000000ff, 0x0000ff00, 0x00ff0000,
142
#else
143
					   0x00ff0000, 0x0000ff00, 0x000000ff,
144
#endif
145
					   0);
146
	} else {
147
		/* load PBM/PGM as 8-bit indexed images */
148
		surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, 8,
149
					   0, 0, 0, 0);
150
	}
151
	if ( surface == NULL )
152
		ERROR("Out of memory");
153
	bpl = width * surface->format->BytesPerPixel;
154
	if(kind == PGM) {
155
		SDL_Color *c = surface->format->palette->colors;
156
		int i;
157
		for(i = 0; i < 256; i++)
158
			c[i].r = c[i].g = c[i].b = i;
159
		surface->format->palette->ncolors = 256;
160
	} else if(kind == PBM) {
161
		/* for some reason PBM has 1=black, 0=white */
162
		SDL_Color *c = surface->format->palette->colors;
163
		c[0].r = c[0].g = c[0].b = 255;
164
		c[1].r = c[1].g = c[1].b = 0;
165
		surface->format->palette->ncolors = 2;
166
		bpl = (width + 7) >> 3;
167
		buf = malloc(bpl);
168
		if(buf == NULL)
169
			ERROR("Out of memory");
170
	}
171
 
172
	/* Read the image into the surface */
173
	row = surface->pixels;
174
	for(y = 0; y < height; y++) {
175
		if(ascii) {
176
			int i;
177
			if(kind == PBM) {
178
				for(i = 0; i < width; i++) {
179
					Uint8 ch;
180
					do {
181
						if(!SDL_RWread(src, &ch,
182
							       1, 1))
183
						       ERROR("file truncated");
184
						ch -= '0';
185
					} while(ch > 1);
186
					row[i] = ch;
187
				}
188
			} else {
189
				for(i = 0; i < bpl; i++) {
190
					int c;
191
					c = ReadNumber(src);
192
					if(c < 0)
193
						ERROR("file truncated");
194
					row[i] = c;
195
				}
196
			}
197
		} else {
198
			Uint8 *dst = (kind == PBM) ? buf : row;
199
			if(!SDL_RWread(src, dst, bpl, 1))
200
				ERROR("file truncated");
201
			if(kind == PBM) {
202
				/* expand bitmap to 8bpp */
203
				int i;
204
				for(i = 0; i < width; i++) {
205
					int bit = 7 - (i & 7);
206
					row[i] = (buf[i >> 3] >> bit) & 1;
207
				}
208
			}
209
		}
210
		if(maxval < 255) {
211
			/* scale up to full dynamic range (slow) */
212
			int i;
213
			for(i = 0; i < bpl; i++)
214
				row[i] = row[i] * 255 / maxval;
215
		}
216
		row += surface->pitch;
217
	}
218
done:
219
	free(buf);
220
	if(error) {
221
		SDL_FreeSurface(surface);
222
		IMG_SetError(error);
223
		surface = NULL;
224
	}
225
	return(surface);
226
}
227
 
228
#else
229
 
230
/* See if an image is contained in a data source */
231
int IMG_isPNM(SDL_RWops *src)
232
{
233
	return(0);
234
}
235
 
236
/* Load a PNM type image from an SDL datasource */
237
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
238
{
239
	return(NULL);
240
}
241
 
242
#endif /* LOAD_PNM */