Skip to content

Latest commit

 

History

History
471 lines (393 loc) · 11 KB

IMG_lbm.c

File metadata and controls

471 lines (393 loc) · 11 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
Written by Daniel Morais ( Daniel@Morais.com ) in September 2001.
Jan 4, 2004
Jan 4, 2004
28
29
30
31
24 bits ILBM files support added by Marc Le Douarain (mavati AT club-internet
POINT fr) in December 2002.
EHB and HAM (specific Amiga graphic chip modes) support added by Marc Le Douarain
(mavati AT club-internet POINT fr) in December 2003.
32
33
34
35
*/
#include <stdio.h>
#include <stdlib.h>
Dec 17, 2001
Dec 17, 2001
36
#include <string.h>
37
38
39
40
41
42
43
44
45
#include "SDL_endian.h"
#include "SDL_image.h"
#ifdef LOAD_LBM
#define MAXCOLORS 256
Nov 20, 2001
Nov 20, 2001
46
/* Structure for an IFF picture ( BMHD = Bitmap Header ) */
47
48
49
typedef struct
{
Nov 20, 2001
Nov 20, 2001
50
51
52
53
54
55
56
57
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 */
58
yAspect;
Nov 20, 2001
Nov 20, 2001
59
60
Sint16 Lpage; /* width of the screen in pixels */
Sint16 Hpage; /* height of the screen in pixels */
61
62
63
64
65
66
67
68
} BMHD;
int IMG_isLBM( SDL_RWops *src )
{
int is_LBM;
Uint8 magic[4+4+4];
is_LBM = 0;
Jan 20, 2003
Jan 20, 2003
69
if ( SDL_RWread( src, magic, 4+4+4, 1 ) )
Jan 20, 2003
Jan 20, 2003
71
72
73
if ( !memcmp( magic, "FORM", 4 ) &&
( !memcmp( magic + 8, "PBM ", 4 ) ||
!memcmp( magic + 8, "ILBM", 4 ) ) )
74
75
76
77
78
79
80
81
82
83
84
{
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
85
Uint32 size, bytesloaded, nbcolors;
86
87
Uint32 i, j, bytesperline, nbplanes, plane, h;
Uint32 remainingbytes;
Feb 26, 2003
Feb 26, 2003
88
Uint32 width;
89
90
BMHD bmhd;
char *error;
Jan 4, 2004
Jan 4, 2004
91
Uint8 flagHAM,flagEHB;
92
93
94
95
96
Image = NULL;
error = NULL;
MiniBuf = NULL;
Jan 4, 2004
Jan 4, 2004
97
if ( !SDL_RWread( src, id, 4, 1 ) )
Jan 20, 2003
Jan 20, 2003
99
error="error reading IFF chunk";
100
101
102
goto done;
}
Nov 20, 2001
Nov 20, 2001
103
104
/* 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
106
error="error reading IFF chunk size";
107
108
109
goto done;
}
Nov 20, 2001
Nov 20, 2001
110
/* As size is not used here, no need to swap it */
Jan 20, 2003
Jan 20, 2003
111
112
if ( memcmp( id, "FORM", 4 ) != 0 )
Jan 20, 2003
Jan 20, 2003
114
error="not a IFF file";
115
116
117
goto done;
}
Jan 20, 2003
Jan 20, 2003
118
if ( !SDL_RWread( src, id, 4, 1 ) )
Jan 20, 2003
Jan 20, 2003
120
error="error reading IFF chunk";
121
122
123
124
125
goto done;
}
pbm = 0;
Nov 20, 2001
Nov 20, 2001
126
127
/* File format : PBM=Packed Bitmap, ILBM=Interleaved Bitmap */
if ( !memcmp( id, "PBM ", 4 ) ) pbm = 1;
128
129
else if ( memcmp( id, "ILBM", 4 ) )
{
Jan 20, 2003
Jan 20, 2003
130
error="not a IFF picture";
131
132
133
134
135
136
goto done;
}
nbcolors = 0;
memset( &bmhd, 0, sizeof( BMHD ) );
Jan 4, 2004
Jan 4, 2004
137
138
flagHAM = 0;
flagEHB = 0;
Jan 20, 2003
Jan 20, 2003
140
while ( memcmp( id, "BODY", 4 ) != 0 )
141
142
143
{
if ( !SDL_RWread( src, id, 4, 1 ) )
{
Jan 20, 2003
Jan 20, 2003
144
error="error reading IFF chunk";
145
146
147
goto done;
}
Jan 20, 2003
Jan 20, 2003
148
if ( !SDL_RWread( src, &size, 4, 1 ) )
Jan 20, 2003
Jan 20, 2003
150
error="error reading IFF chunk size";
151
152
153
154
155
156
goto done;
}
bytesloaded = 0;
size = SDL_SwapBE32( size );
Jan 20, 2003
Jan 20, 2003
157
Nov 20, 2001
Nov 20, 2001
158
if ( !memcmp( id, "BMHD", 4 ) ) /* Bitmap header */
159
160
161
{
if ( !SDL_RWread( src, &bmhd, sizeof( BMHD ), 1 ) )
{
Jan 20, 2003
Jan 20, 2003
162
error="error reading BMHD chunk";
163
164
165
166
167
168
169
170
171
172
173
174
175
176
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
177
if ( !memcmp( id, "CMAP", 4 ) ) /* palette ( Color Map ) */
178
179
180
{
if ( !SDL_RWread( src, &colormap, size, 1 ) )
{
Jan 20, 2003
Jan 20, 2003
181
error="error reading CMAP chunk";
182
183
184
185
186
187
188
goto done;
}
bytesloaded = size;
nbcolors = size / 3;
}
Jan 4, 2004
Jan 4, 2004
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
if ( !memcmp( id, "CAMG", 4 ) ) /* Amiga ViewMode */
{
Uint32 viewmodes;
if ( !SDL_RWread( src, &viewmodes, sizeof(viewmodes), 1 ) )
{
error="error reading CAMG chunk";
goto done;
}
bytesloaded = size;
viewmodes = SDL_SwapBE32( viewmodes );
if ( viewmodes & 0x0800 )
flagHAM = 1;
if ( viewmodes & 0x0080 )
flagEHB = 1;
}
206
207
if ( memcmp( id, "BODY", 4 ) )
{
Jan 20, 2003
Jan 20, 2003
208
if ( size & 1 ) ++size; /* padding ! */
209
size -= bytesloaded;
Nov 20, 2001
Nov 20, 2001
210
211
/* skip the remaining bytes of this chunk */
if ( size ) SDL_RWseek( src, size, SEEK_CUR );
212
213
214
}
}
Nov 20, 2001
Nov 20, 2001
215
/* compute some usefull values, based on the bitmap header */
Nov 20, 2001
Nov 20, 2001
217
width = ( bmhd.w + 15 ) & 0xFFFFFFF0; /* Width in pixels modulo 16 */
Nov 20, 2001
Nov 20, 2001
219
bytesperline = ( ( bmhd.w + 15 ) / 16 ) * 2;
Nov 20, 2001
Nov 20, 2001
221
nbplanes = bmhd.planes;
Nov 20, 2001
Nov 20, 2001
223
if ( pbm ) /* File format : 'Packed Bitmap' */
Jan 20, 2003
Jan 20, 2003
225
bytesperline *= 8;
226
227
228
nbplanes = 1;
}
Nov 20, 2001
Nov 20, 2001
229
if ( bmhd.mask ) ++nbplanes; /* There is a mask ( 'stencil' ) */
Nov 20, 2001
Nov 20, 2001
231
232
/* Allocate memory for a temporary buffer ( used for
decompression/deinterleaving ) */
233
234
235
if ( ( MiniBuf = (void *)malloc( bytesperline * nbplanes ) ) == NULL )
{
Jan 20, 2003
Jan 20, 2003
236
error="no enough memory for temporary buffer";
237
238
239
goto done;
}
Jan 4, 2004
Jan 4, 2004
240
if ( ( Image = SDL_CreateRGBSurface( SDL_SWSURFACE, width, bmhd.h, (bmhd.planes==24 || flagHAM==1)?24:8, 0, 0, 0, 0 ) ) == NULL )
241
242
goto done;
Nov 20, 2001
Nov 20, 2001
243
/* Update palette informations */
Jan 20, 2003
Jan 20, 2003
245
/* There is no palette in 24 bits ILBM file */
Jan 4, 2004
Jan 4, 2004
246
if ( nbcolors>0 && flagHAM==0 )
Jan 20, 2003
Jan 20, 2003
247
248
{
Image->format->palette->ncolors = nbcolors;
Jan 20, 2003
Jan 20, 2003
250
ptr = &colormap[0];
Jan 20, 2003
Jan 20, 2003
252
253
254
255
256
257
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++;
}
Jan 4, 2004
Jan 4, 2004
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
/* Amiga EHB mode (Extra-Half-Bright) */
/* 6 bitplanes mode with a 32 colors palette */
/* The 32 last colors are the same but divided by 2 */
/* Some Amiga pictures save 64 colors with 32 last wrong colors,
/* they shouldn't !, and here we overwrite these 32 bad colors. */
if ( (nbcolors==32 || flagEHB ) && (1<<bmhd.planes)==64 )
{
Image->format->palette->ncolors = 64;
ptr = &colormap[0];
for ( i=32; i<64; i++ )
{
Image->format->palette->colors[i].r = (*ptr++)/2;
Image->format->palette->colors[i].g = (*ptr++)/2;
Image->format->palette->colors[i].b = (*ptr++)/2;
}
}
275
276
}
Nov 20, 2001
Nov 20, 2001
277
/* Get the bitmap */
278
279
280
for ( h=0; h < bmhd.h; h++ )
{
Jan 20, 2003
Jan 20, 2003
281
282
283
/* uncompress the datas of each planes */
for ( plane=0; plane < nbplanes; plane++ )
Jan 20, 2003
Jan 20, 2003
285
286
ptr = MiniBuf + ( plane * bytesperline );
287
remainingbytes = bytesperline;
Jan 20, 2003
Jan 20, 2003
288
Nov 20, 2001
Nov 20, 2001
289
if ( bmhd.tcomp == 1 ) /* Datas are compressed */
Jan 20, 2003
Jan 20, 2003
291
do
Jan 20, 2003
Jan 20, 2003
293
if ( !SDL_RWread( src, &count, 1, 1 ) )
Jan 20, 2003
Jan 20, 2003
295
error="error reading BODY chunk";
296
297
goto done;
}
Jan 20, 2003
Jan 20, 2003
298
299
300
if ( count & 0x80 )
{
Jan 20, 2003
Jan 20, 2003
301
302
303
count ^= 0xFF;
count += 2; /* now it */
304
305
306
307
308
309
310
311
312
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
313
++count;
314
315
316
317
318
319
320
if ( !SDL_RWread( src, ptr, count, 1 ) )
{
error="error reading BODY chunk";
goto done;
}
}
Jan 20, 2003
Jan 20, 2003
321
322
323
ptr += count;
remainingbytes -= count;
Jan 20, 2003
Jan 20, 2003
324
325
326
} while ( remainingbytes > 0 );
}
Jan 20, 2003
Jan 20, 2003
327
else
Jan 20, 2003
Jan 20, 2003
329
if ( !SDL_RWread( src, ptr, bytesperline, 1 ) )
Jan 20, 2003
Jan 20, 2003
331
error="error reading BODY chunk";
332
333
334
335
goto done;
}
}
}
Jan 20, 2003
Jan 20, 2003
336
337
/* One line has been read, store it ! */
338
339
ptr = Image->pixels;
Jan 4, 2004
Jan 4, 2004
340
if ( nbplanes==24 || flagHAM==1 )
Jan 20, 2003
Jan 20, 2003
341
342
343
344
ptr += h * width * 3;
else
ptr += h * width;
Nov 20, 2001
Nov 20, 2001
345
if ( pbm ) /* File format : 'Packed Bitmap' */
346
347
348
{
memcpy( ptr, MiniBuf, width );
}
Nov 20, 2001
Nov 20, 2001
349
else /* We have to un-interlace the bits ! */
Jan 4, 2004
Jan 4, 2004
351
if ( nbplanes!=24 && flagHAM==0 )
Jan 20, 2003
Jan 20, 2003
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
{
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 4, 2004
Jan 4, 2004
377
Uint32 finalcolor = 0;
Jan 20, 2003
Jan 20, 2003
378
379
size = ( width + 7 ) / 8;
/* 24 bitplanes ILBM : R0...R7,G0...G7,B0...B7 */
Jan 4, 2004
Jan 4, 2004
380
/* or HAM (6 bitplanes) or HAM8 (8 bitplanes) modes */
Jan 20, 2003
Jan 20, 2003
381
for ( i=0; i<width; i=i+8 )
Jan 20, 2003
Jan 20, 2003
383
Uint8 maskBit = 0x80;
384
385
for ( j=0; j<8; j++ )
{
Jan 4, 2004
Jan 4, 2004
386
387
Uint32 pixelcolor = 0;
Uint32 maskColor = 1;
Jan 20, 2003
Jan 20, 2003
388
389
390
391
392
Uint8 dataBody;
for ( plane=0; plane < nbplanes; plane++ )
{
dataBody = MiniBuf[ plane*size+i/8 ];
if ( dataBody&maskBit )
Jan 4, 2004
Jan 4, 2004
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
pixelcolor = pixelcolor | maskColor;
maskColor = maskColor<<1;
}
/* HAM : 12 bits RGB image (4 bits per color component) */
/* HAM8 : 18 bits RGB image (6 bits per color component) */
if ( flagHAM )
{
switch( pixelcolor>>(nbplanes-2) )
{
case 0: /* take direct color from palette */
finalcolor = colormap[ pixelcolor*3 ] + (colormap[ pixelcolor*3+1 ]<<8) + (colormap[ pixelcolor*3+2 ]<<16);
break;
case 1: /* modify only blue component */
finalcolor = finalcolor&0x00FFFF;
finalcolor = finalcolor | (pixelcolor<<(16+(10-nbplanes)));
break;
case 2: /* modify only red component */
finalcolor = finalcolor&0xFFFF00;
finalcolor = finalcolor | pixelcolor<<(10-nbplanes);
break;
case 3: /* modify only green component */
finalcolor = finalcolor&0xFF00FF;
finalcolor = finalcolor | (pixelcolor<<(8+(10-nbplanes)));
break;
}
}
else
{
finalcolor = pixelcolor;
Jan 20, 2003
Jan 20, 2003
422
423
424
}
if ( SDL_BYTEORDER == SDL_LIL_ENDIAN )
{
Jan 4, 2004
Jan 4, 2004
425
426
427
*ptr++ = finalcolor>>16;
*ptr++ = finalcolor>>8;
*ptr++ = finalcolor;
Jan 20, 2003
Jan 20, 2003
428
429
430
}
else
{
Jan 4, 2004
Jan 4, 2004
431
432
433
*ptr++ = finalcolor;
*ptr++ = finalcolor>>8;
*ptr++ = finalcolor>>16;
Jan 20, 2003
Jan 20, 2003
434
435
436
}
maskBit = maskBit>>1;
437
438
439
440
441
442
443
444
445
446
}
}
}
}
}
done:
if ( MiniBuf ) free( MiniBuf );
Jan 20, 2003
Jan 20, 2003
447
if ( error )
448
449
{
IMG_SetError( error );
Jan 20, 2003
Jan 20, 2003
450
SDL_FreeSurface( Image );
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
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 */