123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- /*
- SDL_image: An example image loading library for use with SDL
- Copyright (C) 1999, 2000, 2001 Sam Lantinga
- 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
- slouken@libsdl.org
- */
- /* $Id: IMG_lbm.c,v 1.1 2004/07/21 16:24:11 paigoddess Exp $ */
- /* This is a ILBM image file loading framework
- Load IFF pictures, PBM & ILBM packing methods, with or without stencil
- 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.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "SDL_endian.h"
- #include "SDL_image.h"
- #define MAXCOLORS 256
- /* Structure for an IFF picture ( BMHD = Bitmap Header ) */
- typedef struct
- {
- 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 */
- yAspect;
- Sint16 Lpage; /* width of the screen in pixels */
- Sint16 Hpage; /* height of the screen in pixels */
- } BMHD;
- int IMG_isLBM( SDL_RWops *src )
- {
- int is_LBM;
- Uint8 magic[4+4+4];
- is_LBM = 0;
- if ( SDL_RWread( src, magic, 4+4+4, 1 ) )
- {
- if ( !memcmp( magic, "FORM", 4 ) &&
- ( !memcmp( magic + 8, "PBM ", 4 ) ||
- !memcmp( magic + 8, "ILBM", 4 ) ) )
- {
- 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;
- Uint32 size, bytesloaded, nbcolors;
- Uint32 i, j, bytesperline, nbplanes, plane, h;
- Uint32 remainingbytes;
- Uint32 width;
- BMHD bmhd;
- char *error;
- Image = NULL;
- error = NULL;
- MiniBuf = NULL;
- if ( src == NULL ) goto done;
- if ( !SDL_RWread( src, id, 4, 1 ) )
- {
- error="error reading IFF chunk";
- goto done;
- }
- /* Should be the size of the file minus 4+4 ( 'FORM'+size ) */
- if ( !SDL_RWread( src, &size, 4, 1 ) )
- {
- error="error reading IFF chunk size";
- goto done;
- }
- /* As size is not used here, no need to swap it */
- if ( memcmp( id, "FORM", 4 ) != 0 )
- {
- error="not a IFF file";
- goto done;
- }
- if ( !SDL_RWread( src, id, 4, 1 ) )
- {
- error="error reading IFF chunk";
- goto done;
- }
- pbm = 0;
- /* File format : PBM=Packed Bitmap, ILBM=Interleaved Bitmap */
- if ( !memcmp( id, "PBM ", 4 ) ) pbm = 1;
- else if ( memcmp( id, "ILBM", 4 ) )
- {
- error="not a IFF picture";
- goto done;
- }
- nbcolors = 0;
- memset( &bmhd, 0, sizeof( BMHD ) );
- while ( memcmp( id, "BODY", 4 ) != 0 )
- {
- if ( !SDL_RWread( src, id, 4, 1 ) )
- {
- error="error reading IFF chunk";
- goto done;
- }
- if ( !SDL_RWread( src, &size, 4, 1 ) )
- {
- error="error reading IFF chunk size";
- goto done;
- }
- bytesloaded = 0;
- size = SDL_SwapBE32( size );
- if ( !memcmp( id, "BMHD", 4 ) ) /* Bitmap header */
- {
- if ( !SDL_RWread( src, &bmhd, sizeof( BMHD ), 1 ) )
- {
- error="error reading BMHD chunk";
- 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 );
- }
- if ( !memcmp( id, "CMAP", 4 ) ) /* palette ( Color Map ) */
- {
- if ( !SDL_RWread( src, &colormap, size, 1 ) )
- {
- error="error reading CMAP chunk";
- goto done;
- }
- bytesloaded = size;
- nbcolors = size / 3;
- }
- if ( memcmp( id, "BODY", 4 ) )
- {
- if ( size & 1 ) ++size; /* padding ! */
- size -= bytesloaded;
- /* skip the remaining bytes of this chunk */
- if ( size ) SDL_RWseek( src, size, SEEK_CUR );
- }
- }
- /* compute some usefull values, based on the bitmap header */
- width = ( bmhd.w + 15 ) & 0xFFFFFFF0; /* Width in pixels modulo 16 */
- bytesperline = ( ( bmhd.w + 15 ) / 16 ) * 2;
- nbplanes = bmhd.planes;
- if ( pbm ) /* File format : 'Packed Bitmap' */
- {
- bytesperline *= 8;
- nbplanes = 1;
- }
- if ( bmhd.mask ) ++nbplanes; /* There is a mask ( 'stencil' ) */
- /* Allocate memory for a temporary buffer ( used for
- decompression/deinterleaving ) */
- if ( ( MiniBuf = (Uint8 *)malloc( bytesperline * nbplanes ) ) == NULL )
- {
- error="no enough memory for temporary buffer";
- goto done;
- }
- if ( ( Image = SDL_CreateRGBSurface( SDL_SWSURFACE, width, bmhd.h, bmhd.planes==24?24:8, 0, 0, 0, 0 ) ) == NULL )
- goto done;
- /* Update palette informations */
- /* There is no palette in 24 bits ILBM file */
- if ( nbcolors>0 )
- {
- Image->format->palette->ncolors = nbcolors;
- ptr = &colormap[0];
- 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++;
- }
- }
- /* Get the bitmap */
- for ( h=0; h < bmhd.h; h++ )
- {
- /* uncompress the datas of each planes */
- for ( plane=0; plane < nbplanes; plane++ )
- {
- ptr = MiniBuf + ( plane * bytesperline );
- remainingbytes = bytesperline;
- if ( bmhd.tcomp == 1 ) /* Datas are compressed */
- {
- do
- {
- if ( !SDL_RWread( src, &count, 1, 1 ) )
- {
- error="error reading BODY chunk";
- goto done;
- }
- if ( count & 0x80 )
- {
- count ^= 0xFF;
- count += 2; /* now it */
- if ( !SDL_RWread( src, &color, 1, 1 ) )
- {
- error="error reading BODY chunk";
- goto done;
- }
- memset( ptr, color, count );
- }
- else
- {
- ++count;
- if ( !SDL_RWread( src, ptr, count, 1 ) )
- {
- error="error reading BODY chunk";
- goto done;
- }
- }
- ptr += count;
- remainingbytes -= count;
- } while ( remainingbytes > 0 );
- }
- else
- {
- if ( !SDL_RWread( src, ptr, bytesperline, 1 ) )
- {
- error="error reading BODY chunk";
- goto done;
- }
- }
- }
- /* One line has been read, store it ! */
- ptr = (Uint8*)Image->pixels;
- if ( nbplanes==24 )
- ptr += h * width * 3;
- else
- ptr += h * width;
- if ( pbm ) /* File format : 'Packed Bitmap' */
- {
- memcpy( ptr, MiniBuf, width );
- }
- else /* We have to un-interlace the bits ! */
- {
- 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
- {
- size = ( width + 7 ) / 8;
- /* 24 bitplanes ILBM : R0...R7,G0...G7,B0...B7 */
- for ( i=0; i<width; i=i+8 )
- {
- Uint8 maskBit = 0x80;
- for ( j=0; j<8; j++ )
- {
- 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;
- }
- }
- }
- }
- }
- done:
- if ( MiniBuf ) free( MiniBuf );
- if ( error )
- {
- IMG_SetError( error );
- SDL_FreeSurface( Image );
- Image = NULL;
- }
- return( Image );
- }
|