Coverage Report

Created: 2025-11-11 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeimage-svn/FreeImage/trunk/Source/FreeImage/PluginWBMP.cpp
Line
Count
Source
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
56
typedef 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
88
static DWORD
89
0
multiByteRead(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
0
  DWORD Out = 0;
98
0
  BYTE In = 0;
99
100
0
  while (io->read_proc(&In, 1, 1, handle)) {
101
0
    Out += (In & 0x7F);
102
103
0
    if ((In & 0x80) == 0x00)
104
0
      break;
105
106
0
    Out <<= 7;
107
0
  }
108
109
0
  return Out;
110
0
}
111
112
static void
113
0
multiByteWrite(FreeImageIO *io, fi_handle handle, DWORD In) {
114
0
  BYTE Out, k = 1;
115
  
116
0
  while (In & (0x7F << 7*k))
117
0
    k++;
118
  
119
0
  while (k > 1) {
120
0
    k--;
121
122
0
    Out = (BYTE)(0x80 | (In >> 7*k) & 0xFF);
123
124
0
    io->write_proc(&Out, 1, 1, handle);
125
0
  }
126
127
0
  Out = (BYTE)(In & 0x7F);
128
129
0
  io->write_proc(&Out, 1, 1, handle);
130
0
}
131
132
static void
133
0
readExtHeader(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
0
  switch (b & 0x60) {
140
    // Type 00: read multi-byte bitfield
141
142
0
    case 0x00:
143
0
    {
144
0
      DWORD info = multiByteRead(io, handle);
145
0
      break;
146
0
    }   
147
148
    // Type 11: read a sequence of parameter/value pairs.
149
150
0
    case 0x60:
151
0
    {
152
0
      BYTE sizeParamIdent = (b & 0x70) >> 4;  // Size of Parameter Identifier (in bytes)
153
0
      BYTE sizeParamValue = (b & 0x0F);   // Size of Parameter Value (in bytes)
154
      
155
0
      BYTE *Ident = (BYTE*)malloc(sizeParamIdent * sizeof(BYTE));
156
0
      BYTE *Value = (BYTE*)malloc(sizeParamValue * sizeof(BYTE));
157
    
158
0
      io->read_proc(Ident, sizeParamIdent, 1, handle);
159
0
      io->read_proc(Value, sizeParamValue, 1, handle);
160
      
161
0
      free(Ident);
162
0
      free(Value);
163
0
      break;
164
0
    }   
165
166
    // reserved for future use
167
168
0
    case 0x20:  // Type 01
169
0
    case 0x40:  // Type 10
170
0
      break;
171
0
  }
172
0
}
173
174
// ==========================================================
175
// Plugin Interface
176
// ==========================================================
177
178
static int s_format_id;
179
180
// ==========================================================
181
// Plugin Implementation
182
// ==========================================================
183
184
static const char * DLL_CALLCONV
185
2
Format() {
186
2
  return "WBMP";
187
2
}
188
189
static const char * DLL_CALLCONV
190
0
Description() {
191
0
  return "Wireless Bitmap";
192
0
}
193
194
static const char * DLL_CALLCONV
195
0
Extension() {
196
0
  return "wap,wbmp,wbm";
197
0
}
198
199
static const char * DLL_CALLCONV
200
0
RegExpr() {
201
0
  return NULL;
202
0
}
203
204
static const char * DLL_CALLCONV
205
0
MimeType() {
206
0
  return "image/vnd.wap.wbmp";
207
0
}
208
209
static BOOL DLL_CALLCONV
210
0
SupportsExportDepth(int depth) {
211
0
  return (
212
0
    (depth == 1)
213
0
    );
214
0
}
215
216
static BOOL DLL_CALLCONV 
217
0
SupportsExportType(FREE_IMAGE_TYPE type) {
218
0
  return (type == FIT_BITMAP) ? TRUE : FALSE;
219
0
}
220
221
// ----------------------------------------------------------
222
223
static FIBITMAP * DLL_CALLCONV
224
0
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
225
0
  WORD x, y, width, height;
226
0
  FIBITMAP *dib;
227
0
    BYTE *bits;   // pointer to dib data
228
0
  RGBQUAD *pal; // pointer to dib palette
229
230
0
  WBMPHEADER header;
231
232
0
  if (handle) {
233
0
    try {
234
      // Read header information
235
      // -----------------------
236
237
      // Type
238
239
0
      header.TypeField = (WORD)multiByteRead(io, handle);
240
241
0
      if (header.TypeField != 0) {
242
0
        throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
243
0
      }
244
245
      // FixHeaderField
246
247
0
      io->read_proc(&header.FixHeaderField, 1, 1, handle);
248
249
      // ExtHeaderFields
250
      // 1 = more will follow, 0 = last octet
251
252
0
      if (header.FixHeaderField & 0x80) {
253
0
        header.ExtHeaderFields = 0x80;
254
255
0
        while(header.ExtHeaderFields & 0x80) {
256
0
          io->read_proc(&header.ExtHeaderFields, 1, 1, handle);
257
258
0
          readExtHeader(io, handle, header.ExtHeaderFields);
259
0
        }
260
0
      }
261
262
      // width & height
263
264
0
      width  = (WORD)multiByteRead(io, handle);
265
0
      height = (WORD)multiByteRead(io, handle);
266
267
      // Allocate a new dib
268
269
0
      dib = FreeImage_Allocate(width, height, 1);
270
0
      if (!dib) {
271
0
        throw FI_MSG_ERROR_DIB_MEMORY;
272
0
      }
273
274
      // write the palette data
275
276
0
      pal = FreeImage_GetPalette(dib);
277
0
      pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
278
0
      pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
279
280
      // read the bitmap data
281
      
282
0
      int line = FreeImage_GetLine(dib);
283
284
0
      for (y = 0; y < height; y++) {
285
0
        bits = FreeImage_GetScanLine(dib, height - 1 - y);
286
287
0
        for (x = 0; x < line; x++) {
288
0
          io->read_proc(&bits[x], 1, 1, handle);
289
0
        }
290
0
      }
291
292
0
      return dib;
293
294
0
    } catch(const char *text)  {
295
0
      FreeImage_OutputMessageProc(s_format_id, text);
296
297
0
      return NULL;
298
0
    }
299
300
0
  }
301
302
0
  return NULL;
303
0
}
304
305
static BOOL DLL_CALLCONV
306
0
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
307
0
    BYTE *bits; // pointer to dib data
308
309
0
  if ((dib) && (handle)) {
310
0
    try {
311
0
      if (FreeImage_GetBPP(dib) != 1)
312
0
        throw "Only 1-bit depth bitmaps can be saved as WBMP";
313
314
      // write the header
315
316
0
      WBMPHEADER header;
317
0
      header.TypeField = 0;               // Type 0: B/W, no compression
318
0
      header.FixHeaderField = 0;              // No ExtHeaderField
319
0
      header.Width = (WORD)FreeImage_GetWidth(dib);   // Image width
320
0
      header.Height = (WORD)FreeImage_GetHeight(dib);   // Image height
321
322
0
      multiByteWrite(io, handle, header.TypeField);
323
      
324
0
      io->write_proc(&header.FixHeaderField, 1, 1, handle);
325
326
0
      multiByteWrite(io, handle, header.Width);
327
0
      multiByteWrite(io, handle, header.Height);
328
329
      // write the bitmap data
330
331
0
      WORD linelength = (WORD)FreeImage_GetLine(dib);
332
333
0
      for (WORD y = 0; y < header.Height; y++) {
334
0
        bits = FreeImage_GetScanLine(dib, header.Height - 1 - y);
335
336
0
        io->write_proc(&bits[0], linelength, 1, handle);
337
0
      }
338
339
0
      return TRUE;
340
341
0
    } catch (const char* text) {
342
0
      FreeImage_OutputMessageProc(s_format_id, text);
343
0
    }
344
0
  }
345
346
0
  return FALSE;
347
0
}
348
349
// ==========================================================
350
//   Init
351
// ==========================================================
352
353
void DLL_CALLCONV
354
2
InitWBMP(Plugin *plugin, int format_id) {
355
2
  s_format_id = format_id;
356
357
2
  plugin->format_proc = Format;
358
2
  plugin->description_proc = Description;
359
2
  plugin->extension_proc = Extension;
360
2
  plugin->regexpr_proc = RegExpr;
361
2
  plugin->open_proc = NULL;
362
2
  plugin->close_proc = NULL;
363
2
  plugin->pagecount_proc = NULL;
364
2
  plugin->pagecapability_proc = NULL;
365
2
  plugin->load_proc = Load;
366
2
  plugin->save_proc = Save;
367
2
  plugin->validate_proc = NULL;
368
2
  plugin->mime_proc = MimeType;
369
2
  plugin->supports_export_bpp_proc = SupportsExportDepth;
370
2
  plugin->supports_export_type_proc = SupportsExportType;
371
  plugin->supports_icc_profiles_proc = NULL;
372
2
}