IMG_lbm.c
changeset 45 45736a3044c0
child 50 754bff7e03aa
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/IMG_lbm.c	Sun Sep 23 23:33:06 2001 +0000
     1.3 @@ -0,0 +1,369 @@
     1.4 +/*
     1.5 +    IMGLIB:  An example image loading library for use with SDL
     1.6 +    Copyright (C) 1999  Sam Lantinga
     1.7 +
     1.8 +    This library is free software; you can redistribute it and/or
     1.9 +    modify it under the terms of the GNU Library General Public
    1.10 +    License as published by the Free Software Foundation; either
    1.11 +    version 2 of the License, or (at your option) any later version.
    1.12 +
    1.13 +    This library is distributed in the hope that it will be useful,
    1.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +    Library General Public License for more details.
    1.17 +
    1.18 +    You should have received a copy of the GNU Library General Public
    1.19 +    License along with this library; if not, write to the Free
    1.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    1.21 +
    1.22 +    Sam Lantinga
    1.23 +    5635-34 Springhouse Dr.
    1.24 +    Pleasanton, CA 94588 (USA)
    1.25 +    slouken@devolution.com
    1.26 +*/
    1.27 + 
    1.28 +/* This is a ILBM image file loading framework
    1.29 +   Load IFF pictures, PBM & ILBM packing methods, with or without stencil
    1.30 +   Written by Daniel Morais ( Daniel@Morais.com ) in September 2001
    1.31 +*/
    1.32 +
    1.33 +#include <stdio.h>
    1.34 +#include <stdlib.h>
    1.35 +
    1.36 +#include "SDL_endian.h"
    1.37 +#include "SDL_image.h"
    1.38 +
    1.39 +#ifdef LOAD_LBM
    1.40 +
    1.41 +
    1.42 +//===========================================================================
    1.43 +// DEFINES
    1.44 +//===========================================================================
    1.45 +
    1.46 +#define MAXCOLORS 256
    1.47 +
    1.48 +//===========================================================================
    1.49 +// STRUCTURES
    1.50 +//===========================================================================
    1.51 +
    1.52 +// Structure for an IFF picture ( BMHD = Bitmap Header )
    1.53 +
    1.54 +typedef struct
    1.55 +{
    1.56 +   Uint16 w, h;		// width & height of the bitmap in pixels
    1.57 +   Sint16 x, y;      // screen coordinates of the bitmap
    1.58 +   Uint8 planes;     // number of planes of the bitmap
    1.59 +   Uint8 mask;       // mask type ( 0 => no mask )
    1.60 +   Uint8 tcomp;      // compression type
    1.61 +   Uint8 pad1;       // dummy value, for padding
    1.62 +   Uint16 tcolor;    // transparent color
    1.63 +   Uint8 xAspect,    // pixel aspect ratio
    1.64 +         yAspect;
    1.65 +   Sint16  Lpage;		// width of the screen in pixels
    1.66 +   Sint16  Hpage;		// height of the screen in pixels
    1.67 +
    1.68 +} BMHD;
    1.69 +
    1.70 +//===========================================================================
    1.71 +// See if an image is contained in a data source
    1.72 +
    1.73 +int IMG_isLBM( SDL_RWops *src )
    1.74 +{
    1.75 +	int   is_LBM;
    1.76 +	Uint8 magic[4+4+4];
    1.77 +
    1.78 +	is_LBM = 0;
    1.79 +	if ( SDL_RWread( src, magic, 4+4+4, 1 ) ) 
    1.80 +	{
    1.81 +		if ( !memcmp( magic, "FORM", 4 ) && 
    1.82 +			( !memcmp( magic + 8, "PBM ", 4 ) || 
    1.83 +			  !memcmp( magic + 8, "ILBM", 4 ) ) ) 
    1.84 +		{
    1.85 +			is_LBM = 1;
    1.86 +		}
    1.87 +	}
    1.88 +	return( is_LBM );
    1.89 +}
    1.90 +
    1.91 +//===========================================================================
    1.92 +// Load a IFF type image from an SDL datasource
    1.93 +
    1.94 +SDL_Surface *IMG_LoadLBM_RW( SDL_RWops *src )
    1.95 +{
    1.96 +	SDL_Surface *Image;
    1.97 +	Uint8       id[4], pbm, colormap[MAXCOLORS*3], *MiniBuf, *ptr, count, color, msk;
    1.98 +   Uint32      size, bytesloaded, nbcolors;
    1.99 +	Uint32      i, j, bytesperline, nbplanes, plane, h;
   1.100 +	Uint32      remainingbytes;
   1.101 +	int         width;
   1.102 +	BMHD	      bmhd;
   1.103 +	char        *error;
   1.104 +
   1.105 +	Image   = NULL;
   1.106 +	error   = NULL;
   1.107 +	MiniBuf = NULL;
   1.108 +
   1.109 +	if ( src == NULL ) goto done;
   1.110 +
   1.111 +	if ( !SDL_RWread( src, id, 4, 1 ) ) 
   1.112 +	{
   1.113 +	   error="error reading IFF chunk";
   1.114 +		goto done;
   1.115 +	}
   1.116 +
   1.117 +	if ( !SDL_RWread( src, &size, 4, 1 ) ) // Should be the size of the file minus 4+4 ( 'FORM'+size )
   1.118 +	{
   1.119 +	   error="error reading IFF chunk size";
   1.120 +		goto done;
   1.121 +	}
   1.122 +
   1.123 +	// As size is not used here, no need to swap it
   1.124 +	
   1.125 +	if ( memcmp( id, "FORM", 4 ) != 0 ) 
   1.126 +	{
   1.127 +	   error="not a IFF file";
   1.128 +		goto done;
   1.129 +	}
   1.130 +
   1.131 +	if ( !SDL_RWread( src, id, 4, 1 ) ) 
   1.132 +	{
   1.133 +	   error="error reading IFF chunk";
   1.134 +		goto done;
   1.135 +	}
   1.136 +
   1.137 +	pbm = 0;
   1.138 +
   1.139 +	if ( !memcmp( id, "PBM ", 4 ) ) pbm = 1; // File format : PBM=Packed Bitmap, ILBM=Interleaved Bitmap
   1.140 +	else if ( memcmp( id, "ILBM", 4 ) )
   1.141 +	{
   1.142 +	   error="not a IFF picture";
   1.143 +		goto done;
   1.144 +	}
   1.145 +
   1.146 +	nbcolors = 0;
   1.147 +
   1.148 +	memset( &bmhd, 0, sizeof( BMHD ) );
   1.149 +
   1.150 +	while ( memcmp( id, "BODY", 4 ) != 0 ) 
   1.151 +	{
   1.152 +		if ( !SDL_RWread( src, id, 4, 1 ) ) 
   1.153 +		{
   1.154 +	      error="error reading IFF chunk";
   1.155 +			goto done;
   1.156 +		}
   1.157 +
   1.158 +		if ( !SDL_RWread( src, &size, 4, 1 ) ) 
   1.159 +		{
   1.160 +	      error="error reading IFF chunk size";
   1.161 +			goto done;
   1.162 +		}
   1.163 +
   1.164 +		bytesloaded = 0;
   1.165 +
   1.166 +		size = SDL_SwapBE32( size );
   1.167 +		
   1.168 +		if ( !memcmp( id, "BMHD", 4 ) ) // Bitmap header
   1.169 +		{
   1.170 +			if ( !SDL_RWread( src, &bmhd, sizeof( BMHD ), 1 ) )
   1.171 +			{
   1.172 +			   error="error reading BMHD chunk";
   1.173 +				goto done;
   1.174 +			}
   1.175 +
   1.176 +			bytesloaded = sizeof( BMHD );
   1.177 +
   1.178 +			bmhd.w 		= SDL_SwapBE16( bmhd.w );
   1.179 +			bmhd.h 		= SDL_SwapBE16( bmhd.h );
   1.180 +			bmhd.x 		= SDL_SwapBE16( bmhd.x );
   1.181 +			bmhd.y 		= SDL_SwapBE16( bmhd.y );
   1.182 +			bmhd.tcolor = SDL_SwapBE16( bmhd.tcolor );
   1.183 +			bmhd.Lpage 	= SDL_SwapBE16( bmhd.Lpage );
   1.184 +			bmhd.Hpage 	= SDL_SwapBE16( bmhd.Hpage );
   1.185 +		}
   1.186 +
   1.187 +		if ( !memcmp( id, "CMAP", 4 ) ) // palette ( Color Map )
   1.188 +		{
   1.189 +			if ( !SDL_RWread( src, &colormap, size, 1 ) )
   1.190 +			{
   1.191 +			   error="error reading CMAP chunk";
   1.192 +				goto done;
   1.193 +			}
   1.194 +
   1.195 +			bytesloaded = size;
   1.196 +			nbcolors = size / 3;
   1.197 +		}
   1.198 +
   1.199 +		if ( memcmp( id, "BODY", 4 ) )
   1.200 +		{
   1.201 +		   if ( size & 1 )	++size;  	// padding !
   1.202 +			size -= bytesloaded;
   1.203 +			if ( size )	SDL_RWseek( src, size, SEEK_CUR ); // skip the remaining bytes of this chunk
   1.204 +		}
   1.205 +	}
   1.206 +
   1.207 +	// compute some usefull values, based on the bitmap header
   1.208 +
   1.209 +	width = ( bmhd.w + 15 ) & 0xFFFFFFF0;        // Width in pixels modulo 16
   1.210 +
   1.211 +	bytesperline = ( ( bmhd.w + 15 ) / 16 ) * 2;	// Number of bytes per line
   1.212 +
   1.213 +	nbplanes = bmhd.planes;                      // Number of planes
   1.214 +
   1.215 +	if ( pbm )                                   // File format : 'Packed Bitmap'
   1.216 +	{
   1.217 +	   bytesperline *= 8;
   1.218 +		nbplanes = 1;
   1.219 +	}
   1.220 +
   1.221 +	if ( bmhd.mask ) ++nbplanes;                 // There is a mask ( 'stencil' )
   1.222 +
   1.223 +	// Allocate memory for a temporary buffer ( used for decompression/deinterleaving )
   1.224 +
   1.225 +	if ( ( MiniBuf = (void *)malloc( bytesperline * nbplanes ) ) == NULL )
   1.226 +	{
   1.227 +	   error="no enough memory for temporary buffer";
   1.228 +		goto done;
   1.229 +	}
   1.230 +
   1.231 +	// Create the surface
   1.232 +
   1.233 +	if ( ( Image = SDL_CreateRGBSurface( SDL_SWSURFACE, width, bmhd.h, 8, 0, 0, 0, 0 ) ) == NULL )
   1.234 +	   goto done;
   1.235 +
   1.236 +	// Update palette informations
   1.237 +
   1.238 +	Image->format->palette->ncolors = nbcolors;
   1.239 +
   1.240 +	ptr = &colormap[0];
   1.241 +
   1.242 +	for ( i=0; i<nbcolors; i++ )
   1.243 +	{
   1.244 +	   Image->format->palette->colors[i].r = *ptr++;
   1.245 +	   Image->format->palette->colors[i].g = *ptr++;
   1.246 +	   Image->format->palette->colors[i].b = *ptr++;
   1.247 +	}
   1.248 +
   1.249 +	// Get the bitmap
   1.250 +
   1.251 +	for ( h=0; h < bmhd.h; h++ )
   1.252 +	{
   1.253 +		// uncompress the datas of each planes
   1.254 +			  
   1.255 +	   for ( plane=0; plane < nbplanes; plane++ )
   1.256 +		{
   1.257 +		   ptr = MiniBuf + ( plane * bytesperline );
   1.258 +	
   1.259 +			remainingbytes = bytesperline;
   1.260 +	
   1.261 +			if ( bmhd.tcomp == 1 )			// Datas are compressed
   1.262 +			{
   1.263 +			   do
   1.264 +				{
   1.265 +				   if ( !SDL_RWread( src, &count, 1, 1 ) )
   1.266 +					{
   1.267 +					   error="error reading BODY chunk";
   1.268 +						goto done;
   1.269 +					}
   1.270 +	
   1.271 +					if ( count & 0x80 )
   1.272 +					{
   1.273 +					   count ^= 0xFF;
   1.274 +						count += 2; // now it
   1.275 +						
   1.276 +						if ( !SDL_RWread( src, &color, 1, 1 ) )
   1.277 +						{
   1.278 +						   error="error reading BODY chunk";
   1.279 +							goto done;
   1.280 +						}
   1.281 +						memset( ptr, color, count );
   1.282 +					}
   1.283 +					else
   1.284 +					{
   1.285 +					   ++count;
   1.286 +
   1.287 +						if ( !SDL_RWread( src, ptr, count, 1 ) )
   1.288 +						{
   1.289 +						   error="error reading BODY chunk";
   1.290 +							goto done;
   1.291 +						}
   1.292 +					}
   1.293 +	
   1.294 +					ptr += count;
   1.295 +					remainingbytes -= count;
   1.296 +	
   1.297 +				} while ( remainingbytes > 0 );
   1.298 +			}
   1.299 +			else	
   1.300 +			{
   1.301 +			   if ( !SDL_RWread( src, ptr, bytesperline, 1 ) )
   1.302 +				{
   1.303 +				   error="error reading BODY chunk";
   1.304 +					goto done;
   1.305 +				}
   1.306 +			}
   1.307 +		}
   1.308 +	
   1.309 +		// One line has been read, store it !
   1.310 +
   1.311 +		ptr = Image->pixels;
   1.312 +		ptr += h * width;
   1.313 +	
   1.314 +		if ( pbm )                 // File format : 'Packed Bitmap'
   1.315 +		{
   1.316 +		   memcpy( ptr, MiniBuf, width );
   1.317 +		}
   1.318 +		else							   // We have to un-interlace the bits !
   1.319 +		{
   1.320 +		   size = ( width + 7 ) / 8;
   1.321 +	
   1.322 +			for ( i=0; i < size; i++ )
   1.323 +			{
   1.324 +			   memset( ptr, 0, 8 );
   1.325 +	
   1.326 +				for ( plane=0; plane < nbplanes; plane++ )
   1.327 +				{
   1.328 +				   color = *( MiniBuf + i + ( plane * bytesperline ) );
   1.329 +					msk = 0x80;
   1.330 +	
   1.331 +					for ( j=0; j<8; j++ )
   1.332 +					{
   1.333 +					   if ( ( plane + j ) <= 7 ) ptr[j] |= (Uint8)( color & msk ) >> ( 7 - plane - j );
   1.334 +						else 	                    ptr[j] |= (Uint8)( color & msk ) << ( plane + j - 7 );
   1.335 +	
   1.336 +						msk >>= 1;
   1.337 +					}
   1.338 +				}
   1.339 +				ptr += 8;
   1.340 +			}
   1.341 +		}
   1.342 +	}
   1.343 +
   1.344 +done:
   1.345 +
   1.346 +	if ( MiniBuf ) free( MiniBuf );
   1.347 +
   1.348 +	if ( error ) 
   1.349 +	{
   1.350 +		IMG_SetError( error );
   1.351 +	   SDL_FreeSurface( Image );
   1.352 +		Image = NULL;
   1.353 +	}
   1.354 +
   1.355 +	return( Image );
   1.356 +}
   1.357 +
   1.358 +#else /* LOAD_LBM */
   1.359 +
   1.360 +/* See if an image is contained in a data source */
   1.361 +int IMG_isLBM(SDL_RWops *src)
   1.362 +{
   1.363 +	return(0);
   1.364 +}
   1.365 +
   1.366 +/* Load an IFF type image from an SDL datasource */
   1.367 +SDL_Surface *IMG_LoadLBM_RW(SDL_RWops *src)
   1.368 +{
   1.369 +	return(NULL);
   1.370 +}
   1.371 +
   1.372 +#endif /* LOAD_LBM */