1 //-----------------------------------------------------------------------------
2 //
3 // ImageLib Sources
4 // Copyright (C) 2000-2009 by Denton Woods
5 // Last modified: 03/07/2009
6 //
7 // Filename: src-IL/src/il_wbmp.c
8 //
9 // Description: Reads from a Wireless Bitmap (.wbmp) file. Specs available from
10 // http://www.ibm.com/developerworks/wireless/library/wi-wbmp/
11 //
12 //-----------------------------------------------------------------------------
13
14
15 #include "il_internal.h"
16 #ifndef IL_NO_WBMP
17 #include "il_bits.h"
18
19
20 ILboolean iLoadWbmpInternal(void);
21 ILuint WbmpGetMultibyte(void);
22 ILboolean iSaveWbmpInternal(void);
23
24 // Reads a .wbmp file
ilLoadWbmp(ILconst_string FileName)25 ILboolean ilLoadWbmp(ILconst_string FileName)
26 {
27 ILHANDLE WbmpFile;
28 ILboolean bWbmp = IL_FALSE;
29
30 WbmpFile = iopenr(FileName);
31 if (WbmpFile == NULL) {
32 ilSetError(IL_COULD_NOT_OPEN_FILE);
33 return bWbmp;
34 }
35
36 iSetInputFile(WbmpFile);
37
38 bWbmp = ilLoadWbmpF(WbmpFile);
39
40 icloser(WbmpFile);
41
42 return bWbmp;
43 }
44
45
46 //! Reads an already-opened .wbmp file
ilLoadWbmpF(ILHANDLE File)47 ILboolean ilLoadWbmpF(ILHANDLE File)
48 {
49 ILuint FirstPos;
50 ILboolean bRet;
51
52 iSetInputFile(File);
53 FirstPos = itell();
54 bRet = iLoadWbmpInternal();
55 iseek(FirstPos, IL_SEEK_SET);
56
57 return bRet;
58 }
59
60
61 //! Reads from a memory "lump" that contains a .wbmp
ilLoadWbmpL(const void * Lump,ILuint Size)62 ILboolean ilLoadWbmpL(const void *Lump, ILuint Size)
63 {
64 iSetInputLump(Lump, Size);
65 return iLoadWbmpInternal();
66 }
67
68
iLoadWbmpInternal(void)69 ILboolean iLoadWbmpInternal(void)
70 {
71 ILuint Width, Height, BitPadding, i;
72 BITFILE *File;
73 ILubyte Padding[8];
74
75 if (iCurImage == NULL) {
76 ilSetError(IL_ILLEGAL_OPERATION);
77 return IL_FALSE;
78 }
79
80 if (igetc() != 0 || igetc() != 0) { // The first two bytes have to be 0 (the "header")
81 ilSetError(IL_INVALID_FILE_HEADER);
82 return IL_FALSE;
83 }
84
85 Width = WbmpGetMultibyte(); // Next follows the width and height.
86 Height = WbmpGetMultibyte();
87
88 if (Width == 0 || Height == 0) { // Must have at least some height and width.
89 ilSetError(IL_INVALID_FILE_HEADER);
90 return IL_FALSE;
91 }
92
93 if (!ilTexImage(Width, Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL))
94 return IL_FALSE;
95 iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; // Always has origin in the upper left.
96
97 BitPadding = (8 - (Width % 8)) % 8; // Has to be aligned on a byte boundary. The rest is padding.
98 File = bfile(iGetFile());
99 if (File == NULL)
100 return IL_FALSE; //@TODO: Error?
101
102 //@TODO: Do this without bread? Would be faster, since we would not have to do
103 // the second loop.
104
105 // Reads the bits
106 for (i = 0; i < iCurImage->Height; i++) {
107 bread(&iCurImage->Data[iCurImage->Width * i], 1, iCurImage->Width, File);
108 //bseek(File, BitPadding, IL_SEEK_CUR); //@TODO: This function does not work correctly.
109 bread(Padding, 1, BitPadding, File); // Skip padding bits.
110 }
111 // Converts bit value of 1 to white and leaves 0 at 0 (2-colour images only).
112 for (i = 0; i < iCurImage->SizeOfData; i++) {
113 if (iCurImage->Data[i] == 1)
114 iCurImage->Data[i] = 0xFF; // White
115 }
116
117 bclose(File);
118
119 return IL_TRUE;
120 }
121
122
WbmpGetMultibyte()123 ILuint WbmpGetMultibyte()
124 {
125 ILuint Val = 0, i;
126 ILubyte Cur;
127
128 for (i = 0; i < 5; i++) { // Should not be more than 5 bytes.
129 Cur = igetc();
130 Val = (Val << 7) | (Cur & 0x7F); // Drop the MSB of Cur.
131 if (!(Cur & 0x80)) { // Check the MSB and break if 0.
132 break;
133 }
134 }
135
136 return Val;
137 }
138
139
WbmpPutMultibyte(ILuint Val)140 ILboolean WbmpPutMultibyte(ILuint Val)
141 {
142 ILint i, NumBytes = 0;
143 ILuint MultiVal = Val;
144
145 do {
146 MultiVal >>= 7;
147 NumBytes++;
148 } while (MultiVal != 0);
149
150 for (i = NumBytes - 1; i >= 0; i--) {
151 MultiVal = (Val >> (i * 7)) & 0x7F;
152 if (i != 0)
153 MultiVal |= 0x80;
154 iputc(MultiVal);
155 }
156
157 return IL_TRUE;
158 }
159
160
161 //! Writes a Wbmp file
ilSaveWbmp(const ILstring FileName)162 ILboolean ilSaveWbmp(const ILstring FileName)
163 {
164 ILHANDLE WbmpFile;
165 ILuint WbmpSize;
166
167 if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
168 if (iFileExists(FileName)) {
169 ilSetError(IL_FILE_ALREADY_EXISTS);
170 return IL_FALSE;
171 }
172 }
173
174 WbmpFile = iopenw(FileName);
175 if (WbmpFile == NULL) {
176 ilSetError(IL_COULD_NOT_OPEN_FILE);
177 return IL_FALSE;
178 }
179
180 WbmpSize = ilSaveWbmpF(WbmpFile);
181 iclosew(WbmpFile);
182
183 if (WbmpSize == 0)
184 return IL_FALSE;
185 return IL_TRUE;
186 }
187
188
189 //! Writes a .wbmp to an already-opened file
ilSaveWbmpF(ILHANDLE File)190 ILuint ilSaveWbmpF(ILHANDLE File)
191 {
192 ILuint Pos;
193 iSetOutputFile(File);
194 Pos = itellw();
195 if (iSaveWbmpInternal() == IL_FALSE)
196 return 0; // Error occurred
197 return itellw() - Pos; // Return the number of bytes written.
198 }
199
200
201 //! Writes a .wbmp to a memory "lump"
ilSaveWbmpL(void * Lump,ILuint Size)202 ILuint ilSaveWbmpL(void *Lump, ILuint Size)
203 {
204 ILuint Pos;
205 iSetOutputLump(Lump, Size);
206 Pos = itellw();
207 if (iSaveWbmpInternal() == IL_FALSE)
208 return 0; // Error occurred
209 return itellw() - Pos; // Return the number of bytes written.
210 }
211
212
213 // In il_quantizer.c
214 ILimage *iQuantizeImage(ILimage *Image, ILuint NumCols);
215 // In il_neuquant.c
216 ILimage *iNeuQuant(ILimage *Image, ILuint NumCols);
217
218
219 // Internal function used to save the Wbmp.
iSaveWbmpInternal()220 ILboolean iSaveWbmpInternal()
221 {
222 ILimage *TempImage = NULL;
223 ILuint i, j;
224 ILint k;
225 ILubyte Val;
226 ILubyte *TempData;
227
228 iputc(0); // First two header values
229 iputc(0); // must be 0.
230
231 WbmpPutMultibyte(iCurImage->Width); // Write the width
232 WbmpPutMultibyte(iCurImage->Height); // and the height.
233
234 //TempImage = iConvertImage(iCurImage, IL_LUMINANCE, IL_UNSIGNED_BYTE);
235 if (iGetInt(IL_QUANTIZATION_MODE) == IL_NEU_QUANT)
236 TempImage = iNeuQuant(iCurImage, 2);
237 else // Assume IL_WU_QUANT otherwise.
238 TempImage = iQuantizeImage(iCurImage, 2);
239
240 if (TempImage == NULL)
241 return IL_FALSE;
242
243 if (TempImage->Origin != IL_ORIGIN_UPPER_LEFT) {
244 TempData = iGetFlipped(TempImage);
245 if (TempData == NULL) {
246 ilCloseImage(TempImage);
247 return IL_FALSE;
248 }
249 } else {
250 TempData = TempImage->Data;
251 }
252
253 for (i = 0; i < TempImage->Height; i++) {
254 for (j = 0; j < TempImage->Width; j += 8) {
255 Val = 0;
256 for (k = 0; k < 8; k++) {
257 if (j + k < TempImage->Width) {
258 //Val |= ((TempData[TempImage->Width * i + j + k] > 0x7F) ? (0x80 >> k) : 0x00);
259 Val |= ((TempData[TempImage->Width * i + j + k] == 1) ? (0x80 >> k) : 0x00);
260 }
261 }
262 iputc(Val);
263 }
264 }
265
266 if (TempData != TempImage->Data)
267 ifree(TempData);
268 ilCloseImage(TempImage);
269
270 return IL_TRUE;
271 }
272
273 #endif//IL_NO_WBMP
274
275