Skip to content

Latest commit

 

History

History
253 lines (226 loc) · 7.03 KB

IMG_pnm.c

File metadata and controls

253 lines (226 loc) · 7.03 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
76
77
78
79
80
81
82
83
84
85
/* 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') );
}
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
89
90
91
/* Add up the number */
do {
number *= 10;
number += ch-'0';
Aug 10, 2000
Aug 10, 2000
92
May 22, 2013
May 22, 2013
93
94
95
if ( !SDL_RWread(src, &ch, 1, 1) ) {
return -1;
}
Jun 15, 2015
Jun 15, 2015
96
} while ( SDL_isdigit(ch) );
Aug 10, 2000
Aug 10, 2000
97
May 22, 2013
May 22, 2013
98
return(number);
Aug 10, 2000
Aug 10, 2000
99
}
Nov 29, 2000
Nov 29, 2000
100
Mar 7, 2001
Mar 7, 2001
101
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
Aug 10, 2000
Aug 10, 2000
102
{
May 22, 2013
May 22, 2013
103
104
105
106
107
108
109
110
111
112
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
113
Mar 7, 2001
Mar 7, 2001
114
115
#define ERROR(s) do { error = (s); goto done; } while(0)
May 22, 2013
May 22, 2013
116
117
118
119
120
if ( !src ) {
/* The error message has been set in SDL_RWFromFile */
return NULL;
}
start = SDL_RWtell(src);
Jan 4, 2004
Jan 4, 2004
121
May 22, 2013
May 22, 2013
122
123
124
125
126
127
128
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
129
May 22, 2013
May 22, 2013
130
131
132
133
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
134
May 22, 2013
May 22, 2013
135
136
137
138
139
140
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
141
May 22, 2013
May 22, 2013
142
143
/* 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
144
May 22, 2013
May 22, 2013
145
146
147
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
148
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
May 22, 2013
May 22, 2013
149
0x000000ff, 0x0000ff00, 0x00ff0000,
Mar 4, 2001
Mar 4, 2001
150
#else
May 22, 2013
May 22, 2013
151
0x00ff0000, 0x0000ff00, 0x000000ff,
Mar 4, 2001
Mar 4, 2001
152
#endif
May 22, 2013
May 22, 2013
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
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
179
May 22, 2013
May 22, 2013
180
181
182
183
184
185
186
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
/* 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
226
done:
May 22, 2013
May 22, 2013
227
228
229
230
231
232
233
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
234
IMG_SetError("%s", error);
May 22, 2013
May 22, 2013
235
236
}
return(surface);
Aug 10, 2000
Aug 10, 2000
237
238
239
240
241
}
#else
/* See if an image is contained in a data source */
Mar 7, 2001
Mar 7, 2001
242
int IMG_isPNM(SDL_RWops *src)
Aug 10, 2000
Aug 10, 2000
243
{
May 22, 2013
May 22, 2013
244
return(0);
Aug 10, 2000
Aug 10, 2000
245
246
}
Mar 7, 2001
Mar 7, 2001
247
248
/* Load a PNM type image from an SDL datasource */
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
Aug 10, 2000
Aug 10, 2000
249
{
May 22, 2013
May 22, 2013
250
return(NULL);
Aug 10, 2000
Aug 10, 2000
251
252
}
Mar 7, 2001
Mar 7, 2001
253
#endif /* LOAD_PNM */