Skip to content

Latest commit

 

History

History
260 lines (233 loc) · 7.2 KB

IMG_pnm.c

File metadata and controls

260 lines (233 loc) · 7.2 KB
 
Aug 10, 2000
Aug 10, 2000
1
/*
Dec 31, 2011
Dec 31, 2011
2
SDL_image: An example image loading library for use with SDL
Mar 1, 2018
Mar 1, 2018
3
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
Aug 10, 2000
Aug 10, 2000
4
Dec 31, 2011
Dec 31, 2011
5
6
7
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Aug 10, 2000
Aug 10, 2000
8
Dec 31, 2011
Dec 31, 2011
9
10
11
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
Aug 10, 2000
Aug 10, 2000
12
Dec 31, 2011
Dec 31, 2011
13
14
15
16
17
18
19
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Aug 10, 2000
Aug 10, 2000
20
21
*/
Mar 4, 2001
Mar 4, 2001
22
/*
Mar 7, 2001
Mar 7, 2001
23
* PNM (portable anymap) image loader:
Mar 4, 2001
Mar 4, 2001
24
*
Mar 7, 2001
Mar 7, 2001
25
26
* Supports: PBM, PGM and PPM, ASCII and binary formats
* (PBM and PGM are loaded as 8bpp surfaces)
Mar 4, 2001
Mar 4, 2001
27
28
* Does not support: maximum component value > 255
*/
Aug 10, 2000
Aug 10, 2000
29
30
31
#include "SDL_image.h"
Mar 7, 2001
Mar 7, 2001
32
#ifdef LOAD_PNM
Aug 10, 2000
Aug 10, 2000
33
34
/* See if an image is contained in a data source */
Mar 7, 2001
Mar 7, 2001
35
int IMG_isPNM(SDL_RWops *src)
Aug 10, 2000
Aug 10, 2000
36
{
May 22, 2013
May 22, 2013
37
38
39
Sint64 start;
int is_PNM;
char magic[2];
Aug 10, 2000
Aug 10, 2000
40
May 22, 2013
May 22, 2013
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
if ( !src )
return 0;
start = SDL_RWtell(src);
is_PNM = 0;
if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
/*
* 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
* P7 PAM, a general wrapper for PNM data
*/
if ( magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6' ) {
is_PNM = 1;
}
}
SDL_RWseek(src, start, RW_SEEK_SET);
return(is_PNM);
Aug 10, 2000
Aug 10, 2000
62
63
}
Mar 4, 2001
Mar 4, 2001
64
/* read a non-negative integer from the source. return -1 upon error */
Aug 10, 2000
Aug 10, 2000
65
66
static int ReadNumber(SDL_RWops *src)
{
May 22, 2013
May 22, 2013
67
68
int number;
unsigned char ch;
Aug 10, 2000
Aug 10, 2000
69
May 22, 2013
May 22, 2013
70
71
/* Initialize return value */
number = 0;
Aug 10, 2000
Aug 10, 2000
72
May 22, 2013
May 22, 2013
73
74
75
/* Skip leading whitespace */
do {
if ( ! SDL_RWread(src, &ch, 1, 1) ) {
Sep 26, 2018
Sep 26, 2018
76
return(-1);
May 22, 2013
May 22, 2013
77
78
79
80
81
82
83
84
85
}
/* 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') );
}
Jun 15, 2015
Jun 15, 2015
86
} while ( SDL_isspace(ch) );
Aug 10, 2000
Aug 10, 2000
87
May 22, 2013
May 22, 2013
88
/* Add up the number */
Sep 29, 2018
Sep 29, 2018
89
90
91
if (!SDL_isdigit(ch)) {
return -1;
}
May 22, 2013
May 22, 2013
92
do {
Sep 29, 2018
Sep 29, 2018
93
/* Protect from possible overflow */
Oct 26, 2018
Oct 26, 2018
94
if (number >= (SDL_MAX_SINT32 / 10)) {
Sep 29, 2018
Sep 29, 2018
95
96
return -1;
}
May 22, 2013
May 22, 2013
97
98
number *= 10;
number += ch-'0';
Aug 10, 2000
Aug 10, 2000
99
May 22, 2013
May 22, 2013
100
101
102
if ( !SDL_RWread(src, &ch, 1, 1) ) {
return -1;
}
Jun 15, 2015
Jun 15, 2015
103
} while ( SDL_isdigit(ch) );
Aug 10, 2000
Aug 10, 2000
104
May 22, 2013
May 22, 2013
105
return(number);
Aug 10, 2000
Aug 10, 2000
106
}
Nov 29, 2000
Nov 29, 2000
107
Mar 7, 2001
Mar 7, 2001
108
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
Aug 10, 2000
Aug 10, 2000
109
{
May 22, 2013
May 22, 2013
110
111
112
113
114
115
116
117
118
119
Sint64 start;
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, PAM } kind;
Aug 10, 2000
Aug 10, 2000
120
Mar 7, 2001
Mar 7, 2001
121
122
#define ERROR(s) do { error = (s); goto done; } while(0)
May 22, 2013
May 22, 2013
123
124
125
126
127
if ( !src ) {
/* The error message has been set in SDL_RWFromFile */
return NULL;
}
start = SDL_RWtell(src);
Jan 4, 2004
Jan 4, 2004
128
May 22, 2013
May 22, 2013
129
130
131
132
133
134
135
SDL_RWread(src, magic, 2, 1);
kind = magic[1] - '1';
ascii = 1;
if(kind >= 3) {
ascii = 0;
kind -= 3;
}
Aug 10, 2000
Aug 10, 2000
136
May 22, 2013
May 22, 2013
137
138
139
140
width = ReadNumber(src);
height = ReadNumber(src);
if(width <= 0 || height <= 0)
ERROR("Unable to read image width and height");
Mar 7, 2001
Mar 7, 2001
141
May 22, 2013
May 22, 2013
142
143
144
145
146
147
if(kind != PBM) {
maxval = ReadNumber(src);
if(maxval <= 0 || maxval > 255)
ERROR("unsupported PNM format");
} else
maxval = 255; /* never scale PBMs */
Mar 7, 2001
Mar 7, 2001
148
May 22, 2013
May 22, 2013
149
150
/* binary PNM allows just a single character of whitespace after
the last parameter, and we've already consumed it */
Mar 7, 2001
Mar 7, 2001
151
May 22, 2013
May 22, 2013
152
153
154
if(kind == PPM) {
/* 24-bit surface in R,G,B byte order */
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24,
Mar 4, 2001
Mar 4, 2001
155
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
May 22, 2013
May 22, 2013
156
0x000000ff, 0x0000ff00, 0x00ff0000,
Mar 4, 2001
Mar 4, 2001
157
#else
May 22, 2013
May 22, 2013
158
0x00ff0000, 0x0000ff00, 0x000000ff,
Mar 4, 2001
Mar 4, 2001
159
#endif
May 22, 2013
May 22, 2013
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
0);
} else {
/* load PBM/PGM as 8-bit indexed images */
surface = SDL_CreateRGBSurface(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 = (Uint8 *)SDL_malloc(bpl);
if(buf == NULL)
ERROR("Out of memory");
}
Aug 10, 2000
Aug 10, 2000
186
May 22, 2013
May 22, 2013
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/* Read the image into the surface */
row = (Uint8 *)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;
}
Mar 4, 2001
Mar 4, 2001
233
done:
May 22, 2013
May 22, 2013
234
235
236
237
238
239
240
SDL_free(buf);
if(error) {
SDL_RWseek(src, start, RW_SEEK_SET);
if ( surface ) {
SDL_FreeSurface(surface);
surface = NULL;
}
Jun 15, 2014
Jun 15, 2014
241
IMG_SetError("%s", error);
May 22, 2013
May 22, 2013
242
243
}
return(surface);
Aug 10, 2000
Aug 10, 2000
244
245
246
247
248
}
#else
/* See if an image is contained in a data source */
Mar 7, 2001
Mar 7, 2001
249
int IMG_isPNM(SDL_RWops *src)
Aug 10, 2000
Aug 10, 2000
250
{
May 22, 2013
May 22, 2013
251
return(0);
Aug 10, 2000
Aug 10, 2000
252
253
}
Mar 7, 2001
Mar 7, 2001
254
255
/* Load a PNM type image from an SDL datasource */
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
Aug 10, 2000
Aug 10, 2000
256
{
May 22, 2013
May 22, 2013
257
return(NULL);
Aug 10, 2000
Aug 10, 2000
258
259
}
Mar 7, 2001
Mar 7, 2001
260
#endif /* LOAD_PNM */