Skip to content

Latest commit

 

History

History
258 lines (230 loc) · 7.09 KB

IMG_pnm.c

File metadata and controls

258 lines (230 loc) · 7.09 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
Feb 15, 2013
Feb 15, 2013
3
Copyright (C) 1997-2013 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
#include <stdio.h>
Mar 7, 2001
Mar 7, 2001
31
#include <stdlib.h>
Aug 10, 2000
Aug 10, 2000
32
33
34
35
36
#include <ctype.h>
#include <string.h>
#include "SDL_image.h"
Mar 7, 2001
Mar 7, 2001
37
#ifdef LOAD_PNM
Aug 10, 2000
Aug 10, 2000
38
39
/* See if an image is contained in a data source */
Mar 7, 2001
Mar 7, 2001
40
int IMG_isPNM(SDL_RWops *src)
Aug 10, 2000
Aug 10, 2000
41
{
May 22, 2013
May 22, 2013
42
43
44
Sint64 start;
int is_PNM;
char magic[2];
Aug 10, 2000
Aug 10, 2000
45
May 22, 2013
May 22, 2013
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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
67
68
}
Mar 4, 2001
Mar 4, 2001
69
/* read a non-negative integer from the source. return -1 upon error */
Aug 10, 2000
Aug 10, 2000
70
71
static int ReadNumber(SDL_RWops *src)
{
May 22, 2013
May 22, 2013
72
73
int number;
unsigned char ch;
Aug 10, 2000
Aug 10, 2000
74
May 22, 2013
May 22, 2013
75
76
/* Initialize return value */
number = 0;
Aug 10, 2000
Aug 10, 2000
77
May 22, 2013
May 22, 2013
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/* 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) );
Aug 10, 2000
Aug 10, 2000
92
May 22, 2013
May 22, 2013
93
94
95
96
/* Add up the number */
do {
number *= 10;
number += ch-'0';
Aug 10, 2000
Aug 10, 2000
97
May 22, 2013
May 22, 2013
98
99
100
101
if ( !SDL_RWread(src, &ch, 1, 1) ) {
return -1;
}
} while ( isdigit(ch) );
Aug 10, 2000
Aug 10, 2000
102
May 22, 2013
May 22, 2013
103
return(number);
Aug 10, 2000
Aug 10, 2000
104
}
Nov 29, 2000
Nov 29, 2000
105
Mar 7, 2001
Mar 7, 2001
106
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
Aug 10, 2000
Aug 10, 2000
107
{
May 22, 2013
May 22, 2013
108
109
110
111
112
113
114
115
116
117
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
118
Mar 7, 2001
Mar 7, 2001
119
120
#define ERROR(s) do { error = (s); goto done; } while(0)
May 22, 2013
May 22, 2013
121
122
123
124
125
if ( !src ) {
/* The error message has been set in SDL_RWFromFile */
return NULL;
}
start = SDL_RWtell(src);
Jan 4, 2004
Jan 4, 2004
126
May 22, 2013
May 22, 2013
127
128
129
130
131
132
133
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
134
May 22, 2013
May 22, 2013
135
136
137
138
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
139
May 22, 2013
May 22, 2013
140
141
142
143
144
145
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
146
May 22, 2013
May 22, 2013
147
148
/* 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
149
May 22, 2013
May 22, 2013
150
151
152
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
153
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
May 22, 2013
May 22, 2013
154
0x000000ff, 0x0000ff00, 0x00ff0000,
Mar 4, 2001
Mar 4, 2001
155
#else
May 22, 2013
May 22, 2013
156
0x00ff0000, 0x0000ff00, 0x000000ff,
Mar 4, 2001
Mar 4, 2001
157
#endif
May 22, 2013
May 22, 2013
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
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
184
May 22, 2013
May 22, 2013
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
226
227
228
229
230
/* 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
231
done:
May 22, 2013
May 22, 2013
232
233
234
235
236
237
238
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
239
IMG_SetError("%s", error);
May 22, 2013
May 22, 2013
240
241
}
return(surface);
Aug 10, 2000
Aug 10, 2000
242
243
244
245
246
}
#else
/* See if an image is contained in a data source */
Mar 7, 2001
Mar 7, 2001
247
int IMG_isPNM(SDL_RWops *src)
Aug 10, 2000
Aug 10, 2000
248
{
May 22, 2013
May 22, 2013
249
return(0);
Aug 10, 2000
Aug 10, 2000
250
251
}
Mar 7, 2001
Mar 7, 2001
252
253
/* Load a PNM type image from an SDL datasource */
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
Aug 10, 2000
Aug 10, 2000
254
{
May 22, 2013
May 22, 2013
255
return(NULL);
Aug 10, 2000
Aug 10, 2000
256
257
}
Mar 7, 2001
Mar 7, 2001
258
#endif /* LOAD_PNM */