/src/FreeImage/Source/FreeImage/PluginWBMP.cpp
C++ | 372 lines | 192 code | 88 blank | 92 comment | 20 complexity | 30a55ab511a4838e746092097fb6eeed MD5 | raw file
1// ========================================================== 2// Wireless Bitmap Format Loader and Writer 3// 4// Design and implementation by 5// - Hervé Drolon <drolon@infonie.fr> 6// 7// This file is part of FreeImage 3 8// 9// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY 10// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES 11// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE 12// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED 13// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT 14// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY 15// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL 16// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER 17// THIS DISCLAIMER. 18// 19// Use at your own risk! 20// ========================================================== 21 22#include "FreeImage.h" 23#include "Utilities.h" 24 25// ---------------------------------------------------------- 26// Wireless Bitmap Format 27// ---------------------- 28// The WBMP format enables graphical information to be sent to a variety of handsets. 29// The WBMP format is terminal independent and describes only graphical information. 30 31// IMPLEMENTATION NOTES: 32// ------------------------ 33// The WBMP format is configured according to a type field value (TypeField below), 34// which maps to all relevant image encoding information, such as: 35// · Pixel organisation and encoding 36// · Palette organisation and encoding 37// · Compression characteristics 38// · Animation encoding 39// For each TypeField value, all relevant image characteristics are 40// fully specified as part of the WAP documentation. 41// Currently, a simple compact, monochrome image format is defined 42// within the WBMP type space : 43// 44// Image Type Identifier, multi-byte integer 0 45// Image Format description 0 B/W, no compression 46// ------------------------------------------------------------------------------- 47 48// WBMP Header 49 50#ifdef _WIN32 51#pragma pack(push, 1) 52#else 53#pragma pack(1) 54#endif 55 56typedef struct tagWBMPHEADER { 57 WORD TypeField; // Image type identifier of multi-byte length 58 BYTE FixHeaderField; // Octet of general header information 59 BYTE ExtHeaderFields; // Zero or more extension header fields 60 WORD Width; // Multi-byte width field 61 WORD Height; // Multi-byte height field 62} WBMPHEADER; 63 64#ifdef _WIN32 65#pragma pack(pop) 66#else 67#pragma pack() 68#endif 69 70// The extension headers may be of type binary 00 through binary 11, defined as follows. 71 72// - Type 00 indicates a multi-byte bitfield used to specify additional header information. 73// The first bit is set if a type 00, extension header is set if more data follows. 74// The other bits are reserved for future use. 75// - Type 01 - reserved for future use. 76// - Type 10 - reserved for future use. 77// - Type 11 indicates a sequence of parameter/value pairs. These can be used for 78// optimisations and special purpose extensions, eg, animation image formats. 79// The parameter size tells the length (1-8 bytes) of the following parameter name. 80// The value size gives the length (1-16 bytes) of the following parameter value. 81// The concatenation flag indicates whether another parameter/value pair will follow 82// after reading the specified bytes of data. 83 84// ========================================================== 85// Internal functions 86// ========================================================== 87 88static DWORD 89multiByteRead(FreeImageIO *io, fi_handle handle) { 90 // Multi-byte encoding / decoding 91 // ------------------------------- 92 // A multi-byte integer consists of a series of octets, where the most significant bit 93 // is the continuation flag, and the remaining seven bits are a scalar value. 94 // The continuation flag is used to indicate that an octet is not the end of the multi-byte 95 // sequence. 96 97 DWORD Out = 0; 98 BYTE In = 0; 99 100 while (io->read_proc(&In, 1, 1, handle)) { 101 Out += (In & 0x7F); 102 103 if ((In & 0x80) == 0x00) 104 break; 105 106 Out <<= 7; 107 } 108 109 return Out; 110} 111 112static void 113multiByteWrite(FreeImageIO *io, fi_handle handle, DWORD In) { 114 BYTE Out, k = 1; 115 116 while (In & (0x7F << 7*k)) 117 k++; 118 119 while (k > 1) { 120 k--; 121 122 Out = (BYTE)(0x80 | (In >> 7*k) & 0xFF); 123 124 io->write_proc(&Out, 1, 1, handle); 125 } 126 127 Out = (BYTE)(In & 0x7F); 128 129 io->write_proc(&Out, 1, 1, handle); 130} 131 132static void 133readExtHeader(FreeImageIO *io, fi_handle handle, BYTE b) { 134 // Extension header fields 135 // ------------------------ 136 // Read the extension header fields 137 // (since we don't use them for the moment, we skip them). 138 139 switch (b & 0x60) { 140 // Type 00: read multi-byte bitfield 141 142 case 0x00: 143 { 144 DWORD info = multiByteRead(io, handle); 145 break; 146 } 147 148 // Type 11: read a sequence of parameter/value pairs. 149 150 case 0x60: 151 { 152 BYTE sizeParamIdent = (b & 0x70) >> 4; // Size of Parameter Identifier (in bytes) 153 BYTE sizeParamValue = (b & 0x0F); // Size of Parameter Value (in bytes) 154 155 BYTE *Ident = (BYTE*)malloc(sizeParamIdent * sizeof(BYTE)); 156 BYTE *Value = (BYTE*)malloc(sizeParamValue * sizeof(BYTE)); 157 158 io->read_proc(Ident, sizeParamIdent, 1, handle); 159 io->read_proc(Value, sizeParamValue, 1, handle); 160 161 free(Ident); 162 free(Value); 163 break; 164 } 165 166 // reserved for future use 167 168 case 0x20: // Type 01 169 case 0x40: // Type 10 170 break; 171 } 172} 173 174// ========================================================== 175// Plugin Interface 176// ========================================================== 177 178static int s_format_id; 179 180// ========================================================== 181// Plugin Implementation 182// ========================================================== 183 184static const char * DLL_CALLCONV 185Format() { 186 return "WBMP"; 187} 188 189static const char * DLL_CALLCONV 190Description() { 191 return "Wireless Bitmap"; 192} 193 194static const char * DLL_CALLCONV 195Extension() { 196 return "wap,wbmp,wbm"; 197} 198 199static const char * DLL_CALLCONV 200RegExpr() { 201 return NULL; 202} 203 204static const char * DLL_CALLCONV 205MimeType() { 206 return "image/vnd.wap.wbmp"; 207} 208 209static BOOL DLL_CALLCONV 210SupportsExportDepth(int depth) { 211 return ( 212 (depth == 1) 213 ); 214} 215 216static BOOL DLL_CALLCONV 217SupportsExportType(FREE_IMAGE_TYPE type) { 218 return (type == FIT_BITMAP) ? TRUE : FALSE; 219} 220 221// ---------------------------------------------------------- 222 223static FIBITMAP * DLL_CALLCONV 224Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { 225 WORD x, y, width, height; 226 FIBITMAP *dib; 227 BYTE *bits; // pointer to dib data 228 RGBQUAD *pal; // pointer to dib palette 229 230 WBMPHEADER header; 231 232 if (handle) { 233 try { 234 // Read header information 235 // ----------------------- 236 237 // Type 238 239 header.TypeField = (WORD)multiByteRead(io, handle); 240 241 if (header.TypeField != 0) { 242 throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; 243 } 244 245 // FixHeaderField 246 247 io->read_proc(&header.FixHeaderField, 1, 1, handle); 248 249 // ExtHeaderFields 250 // 1 = more will follow, 0 = last octet 251 252 if (header.FixHeaderField & 0x80) { 253 header.ExtHeaderFields = 0x80; 254 255 while(header.ExtHeaderFields & 0x80) { 256 io->read_proc(&header.ExtHeaderFields, 1, 1, handle); 257 258 readExtHeader(io, handle, header.ExtHeaderFields); 259 } 260 } 261 262 // width & height 263 264 width = (WORD)multiByteRead(io, handle); 265 height = (WORD)multiByteRead(io, handle); 266 267 // Allocate a new dib 268 269 dib = FreeImage_Allocate(width, height, 1); 270 if (!dib) { 271 throw FI_MSG_ERROR_DIB_MEMORY; 272 } 273 274 // write the palette data 275 276 pal = FreeImage_GetPalette(dib); 277 pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0; 278 pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255; 279 280 // read the bitmap data 281 282 int line = FreeImage_GetLine(dib); 283 284 for (y = 0; y < height; y++) { 285 bits = FreeImage_GetScanLine(dib, height - 1 - y); 286 287 for (x = 0; x < line; x++) { 288 io->read_proc(&bits[x], 1, 1, handle); 289 } 290 } 291 292 return dib; 293 294 } catch(const char *text) { 295 FreeImage_OutputMessageProc(s_format_id, text); 296 297 return NULL; 298 } 299 300 } 301 302 return NULL; 303} 304 305static BOOL DLL_CALLCONV 306Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { 307 BYTE *bits; // pointer to dib data 308 309 if ((dib) && (handle)) { 310 try { 311 if (FreeImage_GetBPP(dib) != 1) 312 throw "Only 1-bit depth bitmaps can be saved as WBMP"; 313 314 // write the header 315 316 WBMPHEADER header; 317 header.TypeField = 0; // Type 0: B/W, no compression 318 header.FixHeaderField = 0; // No ExtHeaderField 319 header.Width = (WORD)FreeImage_GetWidth(dib); // Image width 320 header.Height = (WORD)FreeImage_GetHeight(dib); // Image height 321 322 multiByteWrite(io, handle, header.TypeField); 323 324 io->write_proc(&header.FixHeaderField, 1, 1, handle); 325 326 multiByteWrite(io, handle, header.Width); 327 multiByteWrite(io, handle, header.Height); 328 329 // write the bitmap data 330 331 WORD linelength = (WORD)FreeImage_GetLine(dib); 332 333 for (WORD y = 0; y < header.Height; y++) { 334 bits = FreeImage_GetScanLine(dib, header.Height - 1 - y); 335 336 io->write_proc(&bits[0], linelength, 1, handle); 337 } 338 339 return TRUE; 340 341 } catch (const char* text) { 342 FreeImage_OutputMessageProc(s_format_id, text); 343 } 344 } 345 346 return FALSE; 347} 348 349// ========================================================== 350// Init 351// ========================================================== 352 353void DLL_CALLCONV 354InitWBMP(Plugin *plugin, int format_id) { 355 s_format_id = format_id; 356 357 plugin->format_proc = Format; 358 plugin->description_proc = Description; 359 plugin->extension_proc = Extension; 360 plugin->regexpr_proc = RegExpr; 361 plugin->open_proc = NULL; 362 plugin->close_proc = NULL; 363 plugin->pagecount_proc = NULL; 364 plugin->pagecapability_proc = NULL; 365 plugin->load_proc = Load; 366 plugin->save_proc = Save; 367 plugin->validate_proc = NULL; 368 plugin->mime_proc = MimeType; 369 plugin->supports_export_bpp_proc = SupportsExportDepth; 370 plugin->supports_export_type_proc = SupportsExportType; 371 plugin->supports_icc_profiles_proc = NULL; 372}