⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 img_lbm.c

📁 It is extension program for SDL to display images other than bmp, but all the other formats.
💻 C
字号:
/*    SDL_image:  An example image loading library for use with SDL    Copyright (C) 1997-2006 Sam Lantinga    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Lesser General Public    License as published by the Free Software Foundation; either    version 2.1 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    Lesser General Public License for more details.    You should have received a copy of the GNU Lesser General Public    License along with this library; if not, write to the Free Software    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA    Sam Lantinga    slouken@libsdl.org*//* This is a ILBM image file loading framework   Load IFF pictures, PBM & ILBM packing methods, with or without stencil   Written by Daniel Morais ( Daniel AT Morais DOT com ) in September 2001.   24 bits ILBM files support added by Marc Le Douarain (http://www.multimania.com/mavati)   in December 2002.   EHB and HAM (specific Amiga graphic chip modes) support added by Marc Le Douarain   (http://www.multimania.com/mavati) in December 2003.   Stencil and colorkey fixes by David Raulo (david.raulo AT free DOT fr) in February 2004.   Buffer overflow fix in RLE decompression by David Raulo in January 2008.*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "SDL_endian.h"#include "SDL_image.h"#ifdef LOAD_LBM#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 start;	int   is_LBM;	Uint8 magic[4+4+4];	if ( !src ) 		return 0;	start = SDL_RWtell(src);	is_LBM = 0;	if ( SDL_RWread( src, magic, sizeof(magic), 1 ) )	{		if ( !memcmp( magic, "FORM", 4 ) &&			( !memcmp( magic + 8, "PBM ", 4 ) ||			  !memcmp( magic + 8, "ILBM", 4 ) ) )		{			is_LBM = 1;		}	}	SDL_RWseek(src, start, SEEK_SET);	return( is_LBM );}SDL_Surface *IMG_LoadLBM_RW( SDL_RWops *src ){	int start;	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;	Uint8       flagHAM,flagEHB;	Image   = NULL;	error   = NULL;	MiniBuf = NULL;	if ( !src ) {		/* The error message has been set in SDL_RWFromFile */		return NULL;	}	start = SDL_RWtell(src);	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 ) );	flagHAM = 0;	flagEHB = 0;	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, "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;		}		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 & 1 ) ++nbplanes;   /* There is a mask ( 'stencil' ) */	/* Allocate memory for a temporary buffer ( used for           decompression/deinterleaving ) */	if ( ( MiniBuf = (void *)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 || flagHAM==1)?24:8, 0, 0, 0, 0 ) ) == NULL )	   goto done;	if ( bmhd.mask & 2 )               /* There is a transparent color */		SDL_SetColorKey( Image, SDL_SRCCOLORKEY, bmhd.tcolor );	/* Update palette informations */	/* There is no palette in 24 bits ILBM file */	if ( nbcolors>0 && flagHAM==0 )	{		int nbrcolorsfinal = 1 << nbplanes;		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++;		}		/* 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 )		{			nbcolors = 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;			}		}		/* If nbcolors < 2^nbplanes, repeat the colormap */		/* This happens when pictures have a stencil mask */		if ( nbrcolorsfinal > (1<<bmhd.planes) ) {			nbrcolorsfinal = (1<<bmhd.planes);		}		for ( i=nbcolors; i < (Uint32)nbrcolorsfinal; i++ )		{			Image->format->palette->colors[i].r = Image->format->palette->colors[i%nbcolors].r;			Image->format->palette->colors[i].g = Image->format->palette->colors[i%nbcolors].g;			Image->format->palette->colors[i].b = Image->format->palette->colors[i%nbcolors].b;		}		if ( !pbm )			Image->format->palette->ncolors = nbrcolorsfinal;	}	/* 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 ( ( count > remainingbytes ) || !SDL_RWread( src, &color, 1, 1 ) )						{						   error="error reading BODY chunk";							goto done;						}						memset( ptr, color, count );					}					else					{						++count;						if ( ( count > remainingbytes ) || !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 = Image->pixels;		if ( nbplanes==24 || flagHAM==1 )			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 && flagHAM==0 )			{				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			{				Uint32 finalcolor = 0;				size = ( width + 7 ) / 8;				/* 24 bitplanes ILBM : R0...R7,G0...G7,B0...B7 */				/* or HAM (6 bitplanes) or HAM8 (8 bitplanes) modes */				for ( i=0; i<width; i=i+8 )				{					Uint8 maskBit = 0x80;					for ( j=0; j<8; j++ )					{						Uint32 pixelcolor = 0;						Uint32 maskColor = 1;						Uint8 dataBody;						for ( plane=0; plane < nbplanes; plane++ )						{							dataBody = MiniBuf[ plane*size+i/8 ];							if ( dataBody&maskBit )								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;						}						if ( SDL_BYTEORDER == SDL_LIL_ENDIAN )						{							*ptr++ = (Uint8)(finalcolor>>16);							*ptr++ = (Uint8)(finalcolor>>8);							*ptr++ = (Uint8)(finalcolor);						}						else						{							*ptr++ = (Uint8)(finalcolor);							*ptr++ = (Uint8)(finalcolor>>8);							*ptr++ = (Uint8)(finalcolor>>16);						}						maskBit = maskBit>>1;					}				}			}		}	}done:	if ( MiniBuf ) free( MiniBuf );	if ( error )	{		SDL_RWseek(src, start, SEEK_SET);		if ( Image ) {			SDL_FreeSurface( Image );			Image = NULL;		}		IMG_SetError( error );	}	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 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -