/src/FreeImage/Source/FreeImage/PluginWBMP.cpp

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 372 lines · 192 code · 88 blank · 92 comment · 21 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. #include "FreeImage.h"
  22. #include "Utilities.h"
  23. // ----------------------------------------------------------
  24. // Wireless Bitmap Format
  25. // ----------------------
  26. // The WBMP format enables graphical information to be sent to a variety of handsets.
  27. // The WBMP format is terminal independent and describes only graphical information.
  28. // IMPLEMENTATION NOTES:
  29. // ------------------------
  30. // The WBMP format is configured according to a type field value (TypeField below),
  31. // which maps to all relevant image encoding information, such as:
  32. // · Pixel organisation and encoding
  33. // · Palette organisation and encoding
  34. // · Compression characteristics
  35. // · Animation encoding
  36. // For each TypeField value, all relevant image characteristics are
  37. // fully specified as part of the WAP documentation.
  38. // Currently, a simple compact, monochrome image format is defined
  39. // within the WBMP type space :
  40. //
  41. // Image Type Identifier, multi-byte integer 0
  42. // Image Format description 0 B/W, no compression
  43. // -------------------------------------------------------------------------------
  44. // WBMP Header
  45. #ifdef _WIN32
  46. #pragma pack(push, 1)
  47. #else
  48. #pragma pack(1)
  49. #endif
  50. typedef struct tagWBMPHEADER {
  51. WORD TypeField; // Image type identifier of multi-byte length
  52. BYTE FixHeaderField; // Octet of general header information
  53. BYTE ExtHeaderFields; // Zero or more extension header fields
  54. WORD Width; // Multi-byte width field
  55. WORD Height; // Multi-byte height field
  56. } WBMPHEADER;
  57. #ifdef _WIN32
  58. #pragma pack(pop)
  59. #else
  60. #pragma pack()
  61. #endif
  62. // The extension headers may be of type binary 00 through binary 11, defined as follows.
  63. // - Type 00 indicates a multi-byte bitfield used to specify additional header information.
  64. // The first bit is set if a type 00, extension header is set if more data follows.
  65. // The other bits are reserved for future use.
  66. // - Type 01 - reserved for future use.
  67. // - Type 10 - reserved for future use.
  68. // - Type 11 indicates a sequence of parameter/value pairs. These can be used for
  69. // optimisations and special purpose extensions, eg, animation image formats.
  70. // The parameter size tells the length (1-8 bytes) of the following parameter name.
  71. // The value size gives the length (1-16 bytes) of the following parameter value.
  72. // The concatenation flag indicates whether another parameter/value pair will follow
  73. // after reading the specified bytes of data.
  74. // ==========================================================
  75. // Internal functions
  76. // ==========================================================
  77. static DWORD
  78. multiByteRead(FreeImageIO *io, fi_handle handle) {
  79. // Multi-byte encoding / decoding
  80. // -------------------------------
  81. // A multi-byte integer consists of a series of octets, where the most significant bit
  82. // is the continuation flag, and the remaining seven bits are a scalar value.
  83. // The continuation flag is used to indicate that an octet is not the end of the multi-byte
  84. // sequence.
  85. DWORD Out = 0;
  86. BYTE In = 0;
  87. while (io->read_proc(&In, 1, 1, handle)) {
  88. Out += (In & 0x7F);
  89. if ((In & 0x80) == 0x00)
  90. break;
  91. Out <<= 7;
  92. }
  93. return Out;
  94. }
  95. static void
  96. multiByteWrite(FreeImageIO *io, fi_handle handle, DWORD In) {
  97. BYTE Out, k = 1;
  98. while (In & (0x7F << 7*k))
  99. k++;
  100. while (k > 1) {
  101. k--;
  102. Out = (BYTE)(0x80 | (In >> 7*k) & 0xFF);
  103. io->write_proc(&Out, 1, 1, handle);
  104. }
  105. Out = (BYTE)(In & 0x7F);
  106. io->write_proc(&Out, 1, 1, handle);
  107. }
  108. static void
  109. readExtHeader(FreeImageIO *io, fi_handle handle, BYTE b) {
  110. // Extension header fields
  111. // ------------------------
  112. // Read the extension header fields
  113. // (since we don't use them for the moment, we skip them).
  114. switch (b & 0x60) {
  115. // Type 00: read multi-byte bitfield
  116. case 0x00:
  117. {
  118. DWORD info = multiByteRead(io, handle);
  119. break;
  120. }
  121. // Type 11: read a sequence of parameter/value pairs.
  122. case 0x60:
  123. {
  124. BYTE sizeParamIdent = (b & 0x70) >> 4; // Size of Parameter Identifier (in bytes)
  125. BYTE sizeParamValue = (b & 0x0F); // Size of Parameter Value (in bytes)
  126. BYTE *Ident = (BYTE*)malloc(sizeParamIdent * sizeof(BYTE));
  127. BYTE *Value = (BYTE*)malloc(sizeParamValue * sizeof(BYTE));
  128. io->read_proc(Ident, sizeParamIdent, 1, handle);
  129. io->read_proc(Value, sizeParamValue, 1, handle);
  130. free(Ident);
  131. free(Value);
  132. break;
  133. }
  134. // reserved for future use
  135. case 0x20: // Type 01
  136. case 0x40: // Type 10
  137. break;
  138. }
  139. }
  140. // ==========================================================
  141. // Plugin Interface
  142. // ==========================================================
  143. static int s_format_id;
  144. // ==========================================================
  145. // Plugin Implementation
  146. // ==========================================================
  147. static const char * DLL_CALLCONV
  148. Format() {
  149. return "WBMP";
  150. }
  151. static const char * DLL_CALLCONV
  152. Description() {
  153. return "Wireless Bitmap";
  154. }
  155. static const char * DLL_CALLCONV
  156. Extension() {
  157. return "wap,wbmp,wbm";
  158. }
  159. static const char * DLL_CALLCONV
  160. RegExpr() {
  161. return NULL;
  162. }
  163. static const char * DLL_CALLCONV
  164. MimeType() {
  165. return "image/vnd.wap.wbmp";
  166. }
  167. static BOOL DLL_CALLCONV
  168. SupportsExportDepth(int depth) {
  169. return (
  170. (depth == 1)
  171. );
  172. }
  173. static BOOL DLL_CALLCONV
  174. SupportsExportType(FREE_IMAGE_TYPE type) {
  175. return (type == FIT_BITMAP) ? TRUE : FALSE;
  176. }
  177. // ----------------------------------------------------------
  178. static FIBITMAP * DLL_CALLCONV
  179. Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
  180. WORD x, y, width, height;
  181. FIBITMAP *dib;
  182. BYTE *bits; // pointer to dib data
  183. RGBQUAD *pal; // pointer to dib palette
  184. WBMPHEADER header;
  185. if (handle) {
  186. try {
  187. // Read header information
  188. // -----------------------
  189. // Type
  190. header.TypeField = (WORD)multiByteRead(io, handle);
  191. if (header.TypeField != 0) {
  192. throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
  193. }
  194. // FixHeaderField
  195. io->read_proc(&header.FixHeaderField, 1, 1, handle);
  196. // ExtHeaderFields
  197. // 1 = more will follow, 0 = last octet
  198. if (header.FixHeaderField & 0x80) {
  199. header.ExtHeaderFields = 0x80;
  200. while(header.ExtHeaderFields & 0x80) {
  201. io->read_proc(&header.ExtHeaderFields, 1, 1, handle);
  202. readExtHeader(io, handle, header.ExtHeaderFields);
  203. }
  204. }
  205. // width & height
  206. width = (WORD)multiByteRead(io, handle);
  207. height = (WORD)multiByteRead(io, handle);
  208. // Allocate a new dib
  209. dib = FreeImage_Allocate(width, height, 1);
  210. if (!dib) {
  211. throw FI_MSG_ERROR_DIB_MEMORY;
  212. }
  213. // write the palette data
  214. pal = FreeImage_GetPalette(dib);
  215. pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
  216. pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
  217. // read the bitmap data
  218. int line = FreeImage_GetLine(dib);
  219. for (y = 0; y < height; y++) {
  220. bits = FreeImage_GetScanLine(dib, height - 1 - y);
  221. for (x = 0; x < line; x++) {
  222. io->read_proc(&bits[x], 1, 1, handle);
  223. }
  224. }
  225. return dib;
  226. } catch(const char *text) {
  227. FreeImage_OutputMessageProc(s_format_id, text);
  228. return NULL;
  229. }
  230. }
  231. return NULL;
  232. }
  233. static BOOL DLL_CALLCONV
  234. Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
  235. BYTE *bits; // pointer to dib data
  236. if ((dib) && (handle)) {
  237. try {
  238. if (FreeImage_GetBPP(dib) != 1)
  239. throw "Only 1-bit depth bitmaps can be saved as WBMP";
  240. // write the header
  241. WBMPHEADER header;
  242. header.TypeField = 0; // Type 0: B/W, no compression
  243. header.FixHeaderField = 0; // No ExtHeaderField
  244. header.Width = (WORD)FreeImage_GetWidth(dib); // Image width
  245. header.Height = (WORD)FreeImage_GetHeight(dib); // Image height
  246. multiByteWrite(io, handle, header.TypeField);
  247. io->write_proc(&header.FixHeaderField, 1, 1, handle);
  248. multiByteWrite(io, handle, header.Width);
  249. multiByteWrite(io, handle, header.Height);
  250. // write the bitmap data
  251. WORD linelength = (WORD)FreeImage_GetLine(dib);
  252. for (WORD y = 0; y < header.Height; y++) {
  253. bits = FreeImage_GetScanLine(dib, header.Height - 1 - y);
  254. io->write_proc(&bits[0], linelength, 1, handle);
  255. }
  256. return TRUE;
  257. } catch (const char* text) {
  258. FreeImage_OutputMessageProc(s_format_id, text);
  259. }
  260. }
  261. return FALSE;
  262. }
  263. // ==========================================================
  264. // Init
  265. // ==========================================================
  266. void DLL_CALLCONV
  267. InitWBMP(Plugin *plugin, int format_id) {
  268. s_format_id = format_id;
  269. plugin->format_proc = Format;
  270. plugin->description_proc = Description;
  271. plugin->extension_proc = Extension;
  272. plugin->regexpr_proc = RegExpr;
  273. plugin->open_proc = NULL;
  274. plugin->close_proc = NULL;
  275. plugin->pagecount_proc = NULL;
  276. plugin->pagecapability_proc = NULL;
  277. plugin->load_proc = Load;
  278. plugin->save_proc = Save;
  279. plugin->validate_proc = NULL;
  280. plugin->mime_proc = MimeType;
  281. plugin->supports_export_bpp_proc = SupportsExportDepth;
  282. plugin->supports_export_type_proc = SupportsExportType;
  283. plugin->supports_icc_profiles_proc = NULL;
  284. }