From: Robert K. <may...@us...> - 2001-06-06 21:22:53
|
Update of /cvsroot/bitcollider/bitcollider/image In directory usw-pr-cvs1:/tmp/cvs-serv16801/image Modified Files: image.c Log Message: Checked in the new image plugin from delirium Index: image.c =================================================================== RCS file: /cvsroot/bitcollider/bitcollider/image/image.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -r1.1 -r1.2 *** image.c 2001/05/31 21:57:38 1.1 --- image.c 2001/06/06 21:22:50 1.2 *************** *** 4,7 **** --- 4,9 ---- * * v0.1.0 - 30 May 2001 - Initial version, supports BMP (Bitmaps) + * v0.1.1 - 01 Jun 2001 - Added endian-safe portable input functions + * v0.2.0 - 04 Jun 2001 - Added support for GIF (CompuServe Graphics Interchange Format) */ *************** *** 14,19 **** #include "plugin.h" - /*-------------------------------------------------------------------------*/ PluginMethods *init_plugin(void); static void image_shutdown_plugin(void); --- 16,29 ---- #include "plugin.h" + /*--32-bit Specific Definitions of Portable Data Types---------------------*/ + + typedef unsigned char uint8; + typedef unsigned short uint16; + typedef unsigned uint32; + + /*--Prototypes-------------------------------------------------------------*/ + + /* external plugin functions */ PluginMethods *init_plugin(void); static void image_shutdown_plugin(void); *************** *** 23,48 **** static const char *image_get_version(void); static char *image_get_error(void); ! static Attribute *image_file_analyze(const char *fileName); ! /*-------------------------------------------------------------------------*/ ! #define PLUGIN_VERSION "0.1.0" ! #define PLUGIN_NAME "Image metadata (supports: BMP)" #define NUM_ATTRS 4 ! /*-------------------------------------------------------------------------*/ ! typedef int int32; ! typedef unsigned uint32; ! typedef short int16; ! typedef unsigned short uint16; ! /*-------------------------------------------------------------------------*/ static SupportedFormat formats[] = { ! { ".bmp", "BMP (Bitmap) format" }, ! { NULL, NULL } }; static char *errorString = NULL; --- 33,73 ---- static const char *image_get_version(void); static char *image_get_error(void); ! static Attribute *image_file_analyze(const char *fileName); ! /* datafile parsing functions */ ! int parse_bmp(FILE *file, uint32 *width, uint32 *height, uint16 *bpp); ! int parse_gif(FILE *file, uint32 *width, uint32 *height, uint16 *bpp); ! ! /* endian-safe input functions */ ! uint8 read_8(FILE *file); ! uint16 read_16_big_endian(FILE *file); ! uint16 read_16_little_endian(FILE *file); ! uint32 read_32_big_endian(FILE *file); ! uint32 read_32_little_endian(FILE *file); ! /*--Plugin Parameters------------------------------------------------------*/ ! ! #define PLUGIN_VERSION "0.2.0" ! #define PLUGIN_NAME "Image metadata (BMP, GIF)" #define NUM_ATTRS 4 ! /*--Cross Platform Foo-----------------------------------------------------*/ ! #ifdef _WIN32 ! #define strcasecmp stricmp ! #undef WORDS_BIGENDIAN ! #else ! #include "../config.h" ! #endif ! /*--Plugin Info------------------------------------------------------------*/ static SupportedFormat formats[] = { ! { ".bmp", "BMP (Windows Bitmap) image" }, ! { ".gif", "GIF (CompuServe Graphics Interchange Format) image" }, ! { NULL , NULL } }; + static char *errorString = NULL; *************** *** 61,65 **** }; ! /*-------------------------------------------------------------------------*/ PluginMethods *init_plugin(void) --- 86,90 ---- }; ! /*--Externally-called Plugin Functions-------------------------------------*/ PluginMethods *init_plugin(void) *************** *** 94,101 **** Attribute *attrList; char temp[100]; ! uint16 type; ! int32 width; ! int32 height; uint16 bpp; --- 119,127 ---- Attribute *attrList; char temp[100]; + char *ext; + int errorcode = 1; ! uint32 width; ! uint32 height; uint16 bpp; *************** *** 104,141 **** return NULL; ! attrList = malloc(sizeof(Attribute) * NUM_ATTRS); ! memset(attrList, 0, sizeof(Attribute) * NUM_ATTRS); ! /* read in the type header and check if it's a valid BMP */ ! if(fread(&type, sizeof(uint16), 1, file) < 1) ! { ! fclose(file); ! return NULL; ! } ! /* type header must be "MB" ("BM" stored big-endian) */ ! if(type != 0x4D42) ! { ! fclose(file); ! return NULL; ! } ! fseek(file, 16L, SEEK_CUR); /* seek to width info */ ! if(fread(&width, sizeof(int32), 1, file) < 1) ! { ! fclose(file); ! return NULL; ! } ! if(fread(&height, sizeof(int32), 1, file) < 1) /* height immediately follows */ ! { ! fclose(file); ! return NULL; ! } ! fseek(file, 2L, SEEK_CUR); /* seek to color depth (bpp) info */ ! if(fread(&bpp, sizeof(uint16), 1, file) < 1) ! { ! fclose(file); return NULL; - } sprintf(temp, "%d", width); attrList[0].key = strdup("tag.image.width"); --- 130,149 ---- return NULL; ! ext = strrchr(fileName, '.'); ! if(strcasecmp(ext,".bmp") == 0) ! errorcode = parse_bmp(file, &width, &height, &bpp); ! else if(strcasecmp(ext, ".gif") == 0) ! errorcode = parse_gif(file, &width, &height, &bpp); ! fclose(file); ! ! if(errorcode || width==0 || height==0 || bpp==0) return NULL; + /* by this point we should have valid info, so return it */ + attrList = malloc(sizeof(Attribute) * NUM_ATTRS); + memset(attrList, 0, sizeof(Attribute) * NUM_ATTRS); + sprintf(temp, "%d", width); attrList[0].key = strdup("tag.image.width"); *************** *** 150,155 **** attrList[2].value = strdup(temp); - fclose(file); - return attrList; } --- 158,161 ---- *************** *** 175,176 **** --- 181,290 ---- } + /*--Functions to Parse Files for Width/Height/BPP info---------------------*/ + + /* All functions return 0 on success and 1 if file is not a valid file of that type */ + + int parse_bmp(FILE *file, uint32 *width, uint32 *height, uint16 *bpp) + { + /* File must start with "BM" */ + if(read_8(file) != 'B' || read_8(file) != 'M') + return 1; + + fseek(file, 16L, SEEK_CUR); + *width = read_32_little_endian(file); + + *height = read_32_little_endian(file); + + fseek(file, 2L, SEEK_CUR); + *bpp = read_16_little_endian(file); + + return 0; + } + + int parse_gif(FILE *file, uint32 *width, uint32 *height, uint16 *bpp) + { + unsigned char packed; + uint16 bpp1, bpp2; + + /* File must start with "GIF" */ + if(read_8(file) != 'G' || read_8(file) != 'I' || read_8(file) != 'F') + return 1; + + fseek(file, 3L, SEEK_CUR); + *width = (uint32) read_16_little_endian(file); + + *height = (uint32) read_16_little_endian(file); + + /* packed byte: + Bits 8 and 5 are flags we don't need to worry about; + bits 6-8 and 1-3 are 3-bit descriptions of the number of bits, + minus 1, of "color resolution" and "bits per pixel" respectively. + Usually these values are the same, but if they're not, take the + larger of the two to be "bpp," since this is what standard + image editing programs seem to do. I don't know why. + */ + packed = read_8(file); + bpp1 = ((packed & 0x70) >> 4) + 1; + bpp2 = (packed & 0x07) + 1; + + if(bpp1 > bpp2) + *bpp = bpp1; + else + *bpp = bpp2; + + return 0; + } + + /*--Endian-Safe Input Functions--------------------------------------------*/ + + uint8 read_8(FILE *file) + { + uint8 a; + + if((a=getc(file))==(uint8)EOF) + return 0; + + return a; + } + + uint16 read_16_big_endian(FILE *file) + { + uint16 a,b; + + if((a=getc(file))==(uint16)EOF || (b=getc(file))==(uint16)EOF) + return 0; + + return ((a<<8) + b); + } + + uint16 read_16_little_endian(FILE *file) + { + uint16 a,b; + + if((a=getc(file))==(uint16)EOF || (b=getc(file))==(uint16)EOF) + return 0; + + return ((b<<8) + a); + } + + uint32 read_32_big_endian(FILE *file) + { + uint32 a,b,c,d; + + if((a=getc(file))==(uint32)EOF || (b=getc(file))==(uint32)EOF || + (c=getc(file))==(uint32)EOF || (d=getc(file))==(uint32)EOF) + return 0; + + return ((a<<24) + (b<<16) + (c<<8) + d); + } + + uint32 read_32_little_endian(FILE *file) + { + uint32 a,b,c,d; + + if((a=getc(file))==(uint32)EOF || (b=getc(file))==(uint32)EOF || + (c=getc(file))==(uint32)EOF || (d=getc(file))==(uint32)EOF) + return 0; + + return ((d<<24) + (c<<16) + (b<<8) + a); + } |