Skip to content

Latest commit

 

History

History
405 lines (329 loc) · 8.73 KB

IMG_lbm.c

File metadata and controls

405 lines (329 loc) · 8.73 KB
 
Dec 14, 2001
Dec 14, 2001
2
3
SDL_image: An example image loading library for use with SDL
Copyright (C) 1999, 2000, 2001 Sam Lantinga
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Sam Lantinga
Dec 14, 2001
Dec 14, 2001
20
slouken@libsdl.org
Dec 14, 2001
Dec 14, 2001
22
23
/* $Id$ */
Jan 20, 2003
Jan 20, 2003
24
25
26
/* This is a ILBM image file loading framework
Load IFF pictures, PBM & ILBM packing methods, with or without stencil
Jan 20, 2003
Jan 20, 2003
27
28
29
Written by Daniel Morais ( Daniel@Morais.com ) in September 2001.
24 bits ILBM files support added by Marc Le Douarain (mavati@club-internet.fr)
in December 2002.
30
31
32
33
*/
#include <stdio.h>
#include <stdlib.h>
Dec 17, 2001
Dec 17, 2001
34
#include <string.h>
35
36
37
38
39
40
41
42
43
#include "SDL_endian.h"
#include "SDL_image.h"
#ifdef LOAD_LBM
#define MAXCOLORS 256
Nov 20, 2001
Nov 20, 2001
44
/* Structure for an IFF picture ( BMHD = Bitmap Header ) */
45
46
47
typedef struct
{
Nov 20, 2001
Nov 20, 2001
48
49
50
51
52
53
54
55
Uint16 w, h; /* width & height of the bitmap in pixels */
Sint16 x, y; /* screen coordinates of the bitmap */
Uint8 planes; /* number of planes of the bitmap */
Uint8 mask; /* mask type ( 0 => no mask ) */
Uint8 tcomp; /* compression type */
Uint8 pad1; /* dummy value, for padding */
Uint16 tcolor; /* transparent color */
Uint8 xAspect, /* pixel aspect ratio */
56
yAspect;
Nov 20, 2001
Nov 20, 2001
57
58
Sint16 Lpage; /* width of the screen in pixels */
Sint16 Hpage; /* height of the screen in pixels */
59
60
61
62
63
64
65
66
} BMHD;
int IMG_isLBM( SDL_RWops *src )
{
int is_LBM;
Uint8 magic[4+4+4];
is_LBM = 0;
Jan 20, 2003
Jan 20, 2003
67
if ( SDL_RWread( src, magic, 4+4+4, 1 ) )
Jan 20, 2003
Jan 20, 2003
69
70
71
if ( !memcmp( magic, "FORM", 4 ) &&
( !memcmp( magic + 8, "PBM ", 4 ) ||
!memcmp( magic + 8, "ILBM", 4 ) ) )
72
73
74
75
76
77
78
79
80
81
82
{
is_LBM = 1;
}
}
return( is_LBM );
}
SDL_Surface *IMG_LoadLBM_RW( SDL_RWops *src )
{
SDL_Surface *Image;
Uint8 id[4], pbm, colormap[MAXCOLORS*3], *MiniBuf, *ptr, count, color, msk;
Jan 20, 2003
Jan 20, 2003
83
Uint32 size, bytesloaded, nbcolors;
84
85
86
87
88
89
90
91
92
93
94
95
96
97
Uint32 i, j, bytesperline, nbplanes, plane, h;
Uint32 remainingbytes;
int width;
BMHD bmhd;
char *error;
Image = NULL;
error = NULL;
MiniBuf = NULL;
if ( src == NULL ) goto done;
if ( !SDL_RWread( src, id, 4, 1 ) )
{
Jan 20, 2003
Jan 20, 2003
98
error="error reading IFF chunk";
99
100
101
goto done;
}
Nov 20, 2001
Nov 20, 2001
102
103
/* Should be the size of the file minus 4+4 ( 'FORM'+size ) */
if ( !SDL_RWread( src, &size, 4, 1 ) )
Jan 20, 2003
Jan 20, 2003
105
error="error reading IFF chunk size";
106
107
108
goto done;
}
Nov 20, 2001
Nov 20, 2001
109
/* As size is not used here, no need to swap it */
Jan 20, 2003
Jan 20, 2003
110
111
if ( memcmp( id, "FORM", 4 ) != 0 )
Jan 20, 2003
Jan 20, 2003
113
error="not a IFF file";
114
115
116
goto done;
}
Jan 20, 2003
Jan 20, 2003
117
if ( !SDL_RWread( src, id, 4, 1 ) )
Jan 20, 2003
Jan 20, 2003
119
error="error reading IFF chunk";
120
121
122
123
124
goto done;
}
pbm = 0;
Nov 20, 2001
Nov 20, 2001
125
126
/* File format : PBM=Packed Bitmap, ILBM=Interleaved Bitmap */
if ( !memcmp( id, "PBM ", 4 ) ) pbm = 1;
127
128
else if ( memcmp( id, "ILBM", 4 ) )
{
Jan 20, 2003
Jan 20, 2003
129
error="not a IFF picture";
130
131
132
133
134
135
136
goto done;
}
nbcolors = 0;
memset( &bmhd, 0, sizeof( BMHD ) );
Jan 20, 2003
Jan 20, 2003
137
while ( memcmp( id, "BODY", 4 ) != 0 )
138
139
140
{
if ( !SDL_RWread( src, id, 4, 1 ) )
{
Jan 20, 2003
Jan 20, 2003
141
error="error reading IFF chunk";
142
143
144
goto done;
}
Jan 20, 2003
Jan 20, 2003
145
if ( !SDL_RWread( src, &size, 4, 1 ) )
Jan 20, 2003
Jan 20, 2003
147
error="error reading IFF chunk size";
148
149
150
151
152
153
goto done;
}
bytesloaded = 0;
size = SDL_SwapBE32( size );
Jan 20, 2003
Jan 20, 2003
154
Nov 20, 2001
Nov 20, 2001
155
if ( !memcmp( id, "BMHD", 4 ) ) /* Bitmap header */
156
157
158
{
if ( !SDL_RWread( src, &bmhd, sizeof( BMHD ), 1 ) )
{
Jan 20, 2003
Jan 20, 2003
159
error="error reading BMHD chunk";
160
161
162
163
164
165
166
167
168
169
170
171
172
173
goto done;
}
bytesloaded = sizeof( BMHD );
bmhd.w = SDL_SwapBE16( bmhd.w );
bmhd.h = SDL_SwapBE16( bmhd.h );
bmhd.x = SDL_SwapBE16( bmhd.x );
bmhd.y = SDL_SwapBE16( bmhd.y );
bmhd.tcolor = SDL_SwapBE16( bmhd.tcolor );
bmhd.Lpage = SDL_SwapBE16( bmhd.Lpage );
bmhd.Hpage = SDL_SwapBE16( bmhd.Hpage );
}
Nov 20, 2001
Nov 20, 2001
174
if ( !memcmp( id, "CMAP", 4 ) ) /* palette ( Color Map ) */
175
176
177
{
if ( !SDL_RWread( src, &colormap, size, 1 ) )
{
Jan 20, 2003
Jan 20, 2003
178
error="error reading CMAP chunk";
179
180
181
182
183
184
185
186
187
goto done;
}
bytesloaded = size;
nbcolors = size / 3;
}
if ( memcmp( id, "BODY", 4 ) )
{
Jan 20, 2003
Jan 20, 2003
188
if ( size & 1 ) ++size; /* padding ! */
189
size -= bytesloaded;
Nov 20, 2001
Nov 20, 2001
190
191
/* skip the remaining bytes of this chunk */
if ( size ) SDL_RWseek( src, size, SEEK_CUR );
192
193
194
}
}
Nov 20, 2001
Nov 20, 2001
195
/* compute some usefull values, based on the bitmap header */
Nov 20, 2001
Nov 20, 2001
197
width = ( bmhd.w + 15 ) & 0xFFFFFFF0; /* Width in pixels modulo 16 */
Nov 20, 2001
Nov 20, 2001
199
bytesperline = ( ( bmhd.w + 15 ) / 16 ) * 2;
Nov 20, 2001
Nov 20, 2001
201
nbplanes = bmhd.planes;
Nov 20, 2001
Nov 20, 2001
203
if ( pbm ) /* File format : 'Packed Bitmap' */
Jan 20, 2003
Jan 20, 2003
205
bytesperline *= 8;
206
207
208
nbplanes = 1;
}
Nov 20, 2001
Nov 20, 2001
209
if ( bmhd.mask ) ++nbplanes; /* There is a mask ( 'stencil' ) */
Nov 20, 2001
Nov 20, 2001
211
212
/* Allocate memory for a temporary buffer ( used for
decompression/deinterleaving ) */
213
214
215
if ( ( MiniBuf = (void *)malloc( bytesperline * nbplanes ) ) == NULL )
{
Jan 20, 2003
Jan 20, 2003
216
error="no enough memory for temporary buffer";
217
218
219
goto done;
}
Jan 20, 2003
Jan 20, 2003
220
if ( ( Image = SDL_CreateRGBSurface( SDL_SWSURFACE, width, bmhd.h, bmhd.planes==24?24:8, 0, 0, 0, 0 ) ) == NULL )
221
222
goto done;
Nov 20, 2001
Nov 20, 2001
223
/* Update palette informations */
Jan 20, 2003
Jan 20, 2003
225
226
227
228
/* There is no palette in 24 bits ILBM file */
if ( nbcolors>0 )
{
Image->format->palette->ncolors = nbcolors;
Jan 20, 2003
Jan 20, 2003
230
ptr = &colormap[0];
Jan 20, 2003
Jan 20, 2003
232
233
234
235
236
237
for ( i=0; i<nbcolors; i++ )
{
Image->format->palette->colors[i].r = *ptr++;
Image->format->palette->colors[i].g = *ptr++;
Image->format->palette->colors[i].b = *ptr++;
}
238
239
}
Nov 20, 2001
Nov 20, 2001
240
/* Get the bitmap */
241
242
243
for ( h=0; h < bmhd.h; h++ )
{
Jan 20, 2003
Jan 20, 2003
244
245
246
/* uncompress the datas of each planes */
for ( plane=0; plane < nbplanes; plane++ )
Jan 20, 2003
Jan 20, 2003
248
249
ptr = MiniBuf + ( plane * bytesperline );
250
remainingbytes = bytesperline;
Jan 20, 2003
Jan 20, 2003
251
Nov 20, 2001
Nov 20, 2001
252
if ( bmhd.tcomp == 1 ) /* Datas are compressed */
Jan 20, 2003
Jan 20, 2003
254
do
Jan 20, 2003
Jan 20, 2003
256
if ( !SDL_RWread( src, &count, 1, 1 ) )
Jan 20, 2003
Jan 20, 2003
258
error="error reading BODY chunk";
259
260
goto done;
}
Jan 20, 2003
Jan 20, 2003
261
262
263
if ( count & 0x80 )
{
Jan 20, 2003
Jan 20, 2003
264
265
266
count ^= 0xFF;
count += 2; /* now it */
267
268
269
270
271
272
273
274
275
if ( !SDL_RWread( src, &color, 1, 1 ) )
{
error="error reading BODY chunk";
goto done;
}
memset( ptr, color, count );
}
else
{
Jan 20, 2003
Jan 20, 2003
276
++count;
277
278
279
280
281
282
283
if ( !SDL_RWread( src, ptr, count, 1 ) )
{
error="error reading BODY chunk";
goto done;
}
}
Jan 20, 2003
Jan 20, 2003
284
285
286
ptr += count;
remainingbytes -= count;
Jan 20, 2003
Jan 20, 2003
287
288
289
} while ( remainingbytes > 0 );
}
Jan 20, 2003
Jan 20, 2003
290
else
Jan 20, 2003
Jan 20, 2003
292
if ( !SDL_RWread( src, ptr, bytesperline, 1 ) )
Jan 20, 2003
Jan 20, 2003
294
error="error reading BODY chunk";
295
296
297
298
goto done;
}
}
}
Jan 20, 2003
Jan 20, 2003
299
300
/* One line has been read, store it ! */
301
302
ptr = Image->pixels;
Jan 20, 2003
Jan 20, 2003
303
304
305
306
307
if ( nbplanes==24 )
ptr += h * width * 3;
else
ptr += h * width;
Nov 20, 2001
Nov 20, 2001
308
if ( pbm ) /* File format : 'Packed Bitmap' */
309
310
311
{
memcpy( ptr, MiniBuf, width );
}
Nov 20, 2001
Nov 20, 2001
312
else /* We have to un-interlace the bits ! */
Jan 20, 2003
Jan 20, 2003
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
if ( nbplanes!=24 )
{
size = ( width + 7 ) / 8;
for ( i=0; i < size; i++ )
{
memset( ptr, 0, 8 );
for ( plane=0; plane < nbplanes; plane++ )
{
color = *( MiniBuf + i + ( plane * bytesperline ) );
msk = 0x80;
for ( j=0; j<8; j++ )
{
if ( ( plane + j ) <= 7 ) ptr[j] |= (Uint8)( color & msk ) >> ( 7 - plane - j );
else ptr[j] |= (Uint8)( color & msk ) << ( plane + j - 7 );
msk >>= 1;
}
}
ptr += 8;
}
}
else
Jan 20, 2003
Jan 20, 2003
340
341
342
size = ( width + 7 ) / 8;
/* 24 bitplanes ILBM : R0...R7,G0...G7,B0...B7 */
for ( i=0; i<width; i=i+8 )
Jan 20, 2003
Jan 20, 2003
344
Uint8 maskBit = 0x80;
345
346
for ( j=0; j<8; j++ )
{
Jan 20, 2003
Jan 20, 2003
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
Uint32 color24 = 0;
Uint32 maskColor24 = 1;
Uint8 dataBody;
for ( plane=0; plane < nbplanes; plane++ )
{
dataBody = MiniBuf[ plane*size+i/8 ];
if ( dataBody&maskBit )
color24 = color24 | maskColor24;
maskColor24 = maskColor24<<1;
}
if ( SDL_BYTEORDER == SDL_LIL_ENDIAN )
{
*ptr++ = color24>>16;
*ptr++ = color24>>8;
*ptr++ = color24;
}
else
{
*ptr++ = color24;
*ptr++ = color24>>8;
*ptr++ = color24>>16;
}
maskBit = maskBit>>1;
371
372
373
374
375
376
377
378
379
380
}
}
}
}
}
done:
if ( MiniBuf ) free( MiniBuf );
Jan 20, 2003
Jan 20, 2003
381
if ( error )
382
383
{
IMG_SetError( error );
Jan 20, 2003
Jan 20, 2003
384
SDL_FreeSurface( Image );
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
Image = NULL;
}
return( Image );
}
#else /* LOAD_LBM */
/* See if an image is contained in a data source */
int IMG_isLBM(SDL_RWops *src)
{
return(0);
}
/* Load an IFF type image from an SDL datasource */
SDL_Surface *IMG_LoadLBM_RW(SDL_RWops *src)
{
return(NULL);
}
#endif /* LOAD_LBM */