diff options
author | Kirill Volinsky <mataes2007@gmail.com> | 2012-12-22 16:38:58 +0000 |
---|---|---|
committer | Kirill Volinsky <mataes2007@gmail.com> | 2012-12-22 16:38:58 +0000 |
commit | 87d155ba9f4e699293adc65954c89f20fc65b36d (patch) | |
tree | d79d69145cc6ef4e97d2ad2912b4d645c7b27158 /plugins/AdvaImg/src/FreeImage/PluginXBM.cpp | |
parent | a8bd33017b1959588d60c9a8a5ae3a744cb75e4d (diff) |
AdvaImg plugin folder renaming
git-svn-id: http://svn.miranda-ng.org/main/trunk@2801 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/AdvaImg/src/FreeImage/PluginXBM.cpp')
-rw-r--r-- | plugins/AdvaImg/src/FreeImage/PluginXBM.cpp | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/plugins/AdvaImg/src/FreeImage/PluginXBM.cpp b/plugins/AdvaImg/src/FreeImage/PluginXBM.cpp new file mode 100644 index 0000000000..140029e862 --- /dev/null +++ b/plugins/AdvaImg/src/FreeImage/PluginXBM.cpp @@ -0,0 +1,399 @@ +// ========================================================== +// XBM Loader +// +// Design and implementation by +// - Hervé Drolon <drolon@infonie.fr> +// part of the code adapted from the netPBM package (xbmtopbm.c) +// +// This file is part of FreeImage 3 +// +// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY +// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES +// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE +// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED +// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT +// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY +// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL +// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER +// THIS DISCLAIMER. +// +// Use at your own risk! +// +// +// ========================================================== + +#include "FreeImage.h" +#include "Utilities.h" + +// ========================================================== +// Internal functions +// ========================================================== + +#define MAX_LINE 512 + +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() { + return "xbm"; +} + +static const char * DLL_CALLCONV +RegExpr() { + return NULL; +} + +static const char * DLL_CALLCONV +MimeType() { + return "image/x-xbitmap"; +} + +static BOOL DLL_CALLCONV +Validate(FreeImageIO *io, fi_handle handle) { + char magic[8]; + if(readLine(magic, 7, io, handle)) { + if(strcmp(magic, "#define") == 0) + return TRUE; + } + return FALSE; +} + +static BOOL DLL_CALLCONV +SupportsExportDepth(int depth) { + return FALSE; +} + +static BOOL DLL_CALLCONV +SupportsExportType(FREE_IMAGE_TYPE type) { + return FALSE; +} + +// ---------------------------------------------------------- + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + char *buffer = NULL; + int width, height; + FIBITMAP *dib = NULL; + + try { + + // load the bitmap data + const char* error = readXBMFile(io, handle, &width, &height, &buffer); + // Microsoft doesn't implement throw between functions :( + if(error) throw (char*)error; + + + // allocate a new dib + dib = FreeImage_Allocate(width, height, 1); + if (!dib) throw (char*)ERR_XBM_MEMORY; + + // write the palette data + RGBQUAD *pal = FreeImage_GetPalette(dib); + pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; + pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; + + // copy the bitmap + BYTE *bP = (BYTE*)buffer; + for(int y = 0; y < height; y++) { + BYTE count = 0; + BYTE mask = 1; + BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y); + + for(int x = 0; x < width; x++) { + if(count >= 8) { + bP++; + count = 0; + mask = 1; + } + if (*bP & mask) { + // Set bit(x, y) to 0 + bits[x >> 3] &= (0xFF7F >> (x & 0x7)); + } else { + // Set bit(x, y) to 1 + bits[x >> 3] |= (0x80 >> (x & 0x7)); + } + count++; + mask <<= 1; + } + bP++; + } + + free(buffer); + return dib; + + } catch(const char *text) { + if(buffer) free(buffer); + if(dib) FreeImage_Unload(dib); + FreeImage_OutputMessageProc(s_format_id, text); + return NULL; + } +} + + +// ========================================================== +// Init +// ========================================================== + +void DLL_CALLCONV +InitXBM(Plugin *plugin, int format_id) { + s_format_id = format_id; + + plugin->format_proc = Format; + plugin->description_proc = Description; + plugin->extension_proc = Extension; + plugin->regexpr_proc = RegExpr; + plugin->open_proc = NULL; + plugin->close_proc = NULL; + plugin->pagecount_proc = NULL; + plugin->pagecapability_proc = NULL; + plugin->load_proc = Load; + plugin->save_proc = NULL; + plugin->validate_proc = Validate; + plugin->mime_proc = MimeType; + plugin->supports_export_bpp_proc = SupportsExportDepth; + plugin->supports_export_type_proc = SupportsExportType; + plugin->supports_icc_profiles_proc = NULL; +} + |