Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/FreeImage/PluginXBM.cpp  view on Meta::CPAN

static const char *ERR_XBM_SYNTAX	= "Syntax error";
static const char *ERR_XBM_LINE		= "Line too long";
static const char *ERR_XBM_DECL		= "Unable to find a line in the file containing the start of C array declaration (\"static char\" or whatever)";
static const char *ERR_XBM_EOFREAD	= "EOF / read error";
static const char *ERR_XBM_WIDTH	= "Invalid width";
static const char *ERR_XBM_HEIGHT	= "Invalid height";
static const char *ERR_XBM_MEMORY	= "Out of memory";

/**
Get a string from a stream. 
Read the string from the current stream to the first newline character. 
The result stored in str is appended with a null character.
@param str Storage location for data 
@param n Maximum number of characters to read 
@param io Pointer to the FreeImageIO structure
@param handle Handle to the stream
@return Returns str. NULL is returned to indicate an error or an end-of-file condition.
*/
static char* 
readLine(char *str, int n, FreeImageIO *io, fi_handle handle) {
	char c;
	int count, i = 0;
	do {
		count = io->read_proc(&c, 1, 1, handle);
		str[i++] = c;
	} while((c != '\n') && (i < n));
	if(count <= 0)
		return NULL;
	str[i] = '\0';
	return str;
}

/**
Get a char from the stream
@param io Pointer to the FreeImageIO structure
@param handle Handle to the stream
@return Returns the next character in the stream
*/
static int 
readChar(FreeImageIO *io, fi_handle handle) {
	BYTE c;
	io->read_proc(&c, 1, 1, handle);
	return c;
}

/**
Read an XBM file into a buffer
@param io Pointer to the FreeImageIO structure
@param handle Handle to the stream
@param widthP (return value) Pointer to the bitmap width
@param heightP (return value) Pointer to the bitmap height
@param dataP (return value) Pointer to the bitmap buffer
@return Returns NULL if OK, returns an error message otherwise
*/
static const char* 
readXBMFile(FreeImageIO *io, fi_handle handle, int *widthP, int *heightP, char **dataP) {
	char line[MAX_LINE], name_and_type[MAX_LINE];
	char* ptr;
	char* t;
	int version = 0;
	int raster_length, v;
	int bytes, bytes_per_line, padding;
	int c1, c2, value1, value2;
	int hex_table[256];
	BOOL found_declaration;
	/* in scanning through the bitmap file, we have found the first
	 line of the C declaration of the array (the "static char ..."
	 or whatever line)
	 */
	BOOL eof;	// we've encountered end of file while searching file

	*widthP = *heightP = -1;

	found_declaration = FALSE;    // haven't found it yet; haven't even looked
	eof = FALSE;                  // haven't encountered end of file yet 
	
	while(!found_declaration && !eof) {

		if( readLine(line, MAX_LINE, io, handle) == NULL) {
			eof = TRUE;
		}
		else {
			if( strlen( line ) == MAX_LINE - 1 )
				return( ERR_XBM_LINE );
			if( sscanf(line, "#define %s %d", name_and_type, &v) == 2 ) {
				if( ( t = strrchr( name_and_type, '_' ) ) == NULL )
					t = name_and_type;
				else
					t++;
				if ( ! strcmp( "width", t ) )
					*widthP = v;
				else if ( ! strcmp( "height", t ) )
					*heightP = v;
				continue;
			}

			if( sscanf( line, "static short %s = {", name_and_type ) == 1 ) {
				version = 10;
				found_declaration = TRUE;
			}
			else if( sscanf( line, "static char %s = {", name_and_type ) == 1 ) {
				version = 11;
				found_declaration = TRUE;
			}
			else if(sscanf(line, "static unsigned char %s = {", name_and_type ) == 1 ) {
				version = 11;
				found_declaration = TRUE;
			}
		}
	}

	if(!found_declaration) 
		return( ERR_XBM_DECL );

	if(*widthP == -1 )
		return( ERR_XBM_WIDTH );
	if( *heightP == -1 )
		return( ERR_XBM_HEIGHT );

	padding = 0;
	if ( ((*widthP % 16) >= 1) && ((*widthP % 16) <= 8) && (version == 10) )
		padding = 1;

	bytes_per_line = (*widthP + 7) / 8 + padding;

	raster_length =  bytes_per_line * *heightP;
	*dataP = (char*) malloc( raster_length );
	if ( *dataP == (char*) 0 )
		return( ERR_XBM_MEMORY );

	// initialize hex_table
	for ( c1 = 0; c1 < 256; c1++ ) {
		hex_table[c1] = 256;
	}
	hex_table['0'] = 0;
	hex_table['1'] = 1;
	hex_table['2'] = 2;
	hex_table['3'] = 3;
	hex_table['4'] = 4;
	hex_table['5'] = 5;
	hex_table['6'] = 6;
	hex_table['7'] = 7;
	hex_table['8'] = 8;
	hex_table['9'] = 9;
	hex_table['A'] = 10;
	hex_table['B'] = 11;
	hex_table['C'] = 12;
	hex_table['D'] = 13;
	hex_table['E'] = 14;
	hex_table['F'] = 15;
	hex_table['a'] = 10;
	hex_table['b'] = 11;
	hex_table['c'] = 12;
	hex_table['d'] = 13;
	hex_table['e'] = 14;
	hex_table['f'] = 15;

	if(version == 10) {
		for( bytes = 0, ptr = *dataP; bytes < raster_length; bytes += 2 ) {
			while( ( c1 = readChar(io, handle) ) != 'x' ) {
				if ( c1 == EOF )
					return( ERR_XBM_EOFREAD );
			}

			c1 = readChar(io, handle);
			c2 = readChar(io, handle);
			if( c1 == EOF || c2 == EOF )
				return( ERR_XBM_EOFREAD );
			value1 = ( hex_table[c1] << 4 ) + hex_table[c2];
			if ( value1 >= 256 )
				return( ERR_XBM_SYNTAX );
			c1 = readChar(io, handle);
			c2 = readChar(io, handle);
			if( c1 == EOF || c2 == EOF )
				return( ERR_XBM_EOFREAD );
			value2 = ( hex_table[c1] << 4 ) + hex_table[c2];
			if ( value2 >= 256 )
				return( ERR_XBM_SYNTAX );
			*ptr++ = (char)value2;
			if ( ( ! padding ) || ( ( bytes + 2 ) % bytes_per_line ) )
				*ptr++ = (char)value1;
		}
	}
	else {
		for(bytes = 0, ptr = *dataP; bytes < raster_length; bytes++ ) {
			/*
			** skip until digit is found
			*/
			for( ; ; ) {
				c1 = readChar(io, handle);
				if ( c1 == EOF )
					return( ERR_XBM_EOFREAD );
				value1 = hex_table[c1];
				if ( value1 != 256 )
					break;
			}
			/*
			** loop on digits
			*/
			for( ; ; ) {
				c2 = readChar(io, handle);
				if ( c2 == EOF )
					return( ERR_XBM_EOFREAD );
				value2 = hex_table[c2];
				if ( value2 != 256 ) {
					value1 = (value1 << 4) | value2;
					if ( value1 >= 256 )
						return( ERR_XBM_SYNTAX );
				}
				else if ( c2 == 'x' || c2 == 'X' ) {
					if ( value1 == 0 )
						continue;
					else return( ERR_XBM_SYNTAX );
				}
				else break;
			}
			*ptr++ = (char)value1;
		}
	}

	return NULL;
}

// ==========================================================
// Plugin Interface
// ==========================================================

static int s_format_id;

// ==========================================================
// Plugin Implementation
// ==========================================================

static const char * DLL_CALLCONV
Format() {
	return "XBM";
}

static const char * DLL_CALLCONV
Description() {
	return "X11 Bitmap Format";
}

static const char * DLL_CALLCONV
Extension() {



( run in 1.488 second using v1.01-cache-2.11-cpan-119454b85a5 )