PageRenderTime 67ms CodeModel.GetById 13ms app.highlight 48ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/cabalistic/ogredeps/
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}