Line No. | Rev | Author | Line |
---|---|---|---|
1 | 32 | kaklik | #define __BMPDECODER_C__ |
2 | /****************************************************************************** |
||
3 | |||
4 | * FileName: BmpDecoder.c |
||
5 | * Dependencies: Image decoding library; project requires File System library |
||
6 | * Processor: PIC24/dsPIC30/dsPIC33/PIC32MX |
||
7 | * Compiler: C30 v2.01/C32 v0.00.18 |
||
8 | * Company: Microchip Technology, Inc. |
||
9 | |||
10 | * Software License Agreement |
||
11 | * |
||
12 | * Copyright © 2008 Microchip Technology Inc. All rights reserved. |
||
13 | * Microchip licenses to you the right to use, modify, copy and distribute |
||
14 | * Software only when embedded on a Microchip microcontroller or digital |
||
15 | * signal controller, which is integrated into your product or third party |
||
16 | * product (pursuant to the sublicense terms in the accompanying license |
||
17 | * agreement). |
||
18 | * |
||
19 | * You should refer to the license agreement accompanying this Software |
||
20 | * for additional information regarding your rights and obligations. |
||
21 | * |
||
22 | * SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY |
||
23 | * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY |
||
24 | * OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR |
||
25 | * PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR |
||
26 | * OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, |
||
27 | * BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT |
||
28 | * DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, |
||
29 | * INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, |
||
30 | * COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY |
||
31 | * CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), |
||
32 | * OR OTHER SIMILAR COSTS. |
||
33 | |||
34 | Author Date Comments |
||
35 | -------------------------------------------------------------------------------- |
||
36 | Pradeep Budagutta 03-Mar-2008 First release |
||
37 | *******************************************************************************/ |
||
38 | |||
39 | #include "Image Decoders\ImageDecoder.h" |
||
40 | |||
41 | #ifdef IMG_SUPPORT_BMP |
||
42 | |||
43 | /*************************/ |
||
44 | /**** DATA STRUCTURES ****/ |
||
45 | /*************************/ |
||
46 | typedef struct _BMPDECODER |
||
47 | { |
||
48 | IMG_FILE *pImageFile; /* Image file pointer */ |
||
49 | LONG lWidth; |
||
50 | LONG lHeight; |
||
51 | LONG lImageOffset; |
||
52 | WORD wPaletteEntries; |
||
53 | BYTE bBitsPerPixel; |
||
54 | BYTE bHeaderType; |
||
55 | BYTE blBmMarkerFlag : 1; |
||
56 | BYTE blCompressionType : 3; |
||
57 | BYTE bNumOfPlanes : 3; |
||
58 | BYTE b16bit565flag : 1; |
||
59 | BYTE aPalette[256][3]; /* Each palette entry has RGB */ |
||
60 | } BMPDECODER; |
||
61 | |||
62 | /**************************/ |
||
63 | /******* FUNCTIONS *******/ |
||
64 | /**************************/ |
||
65 | |||
66 | /******************************************************************************* |
||
67 | Function: void BDEC_vResetData(BMPDECODER *pBmpDec) |
||
68 | |||
69 | Precondition: None |
||
70 | |||
71 | Overview: This function resets the variables so that new Bitmap image |
||
72 | can be decoded |
||
73 | |||
74 | Input: Bitmap decoder's data structure |
||
75 | |||
76 | Output: None |
||
77 | *******************************************************************************/ |
||
78 | void BDEC_vResetData(BMPDECODER *pBmpDec) |
||
79 | { |
||
80 | pBmpDec->pImageFile = NULL; |
||
81 | pBmpDec->lWidth = 0; |
||
82 | pBmpDec->lHeight = 0; |
||
83 | pBmpDec->lImageOffset = 0; |
||
84 | pBmpDec->wPaletteEntries = 0; |
||
85 | pBmpDec->bBitsPerPixel = 0; |
||
86 | pBmpDec->bHeaderType = 0; |
||
87 | pBmpDec->blBmMarkerFlag = 0; |
||
88 | pBmpDec->blCompressionType = 0; |
||
89 | pBmpDec->bNumOfPlanes = 0; |
||
90 | pBmpDec->b16bit565flag = 0; |
||
91 | } |
||
92 | |||
93 | /******************************************************************************* |
||
94 | Function: BYTE BDEC_bReadHeader(BMPDECODER *pBmpDec) |
||
95 | |||
96 | Precondition: None |
||
97 | |||
98 | Overview: This function reads the Bitmap file header and |
||
99 | fills the data structure |
||
100 | |||
101 | Input: Bitmap decoder's data structure |
||
102 | |||
103 | Output: Error code - '0' means no error |
||
104 | *******************************************************************************/ |
||
105 | BYTE BDEC_bReadHeader(BMPDECODER *pBmpDec) |
||
106 | { |
||
107 | BYTE bByte1, bByte2; |
||
108 | WORD wWord; |
||
109 | LONG lLong; |
||
110 | |||
111 | IMG_FREAD(&bByte1, sizeof(bByte1), 1, pBmpDec->pImageFile); /* Marker */ |
||
112 | IMG_FREAD(&bByte2, sizeof(bByte2), 1, pBmpDec->pImageFile); /* Marker */ |
||
113 | |||
114 | if(bByte1 == 'B' && bByte2 == 'M') |
||
115 | { |
||
116 | pBmpDec->blBmMarkerFlag = 1; |
||
117 | } |
||
118 | else |
||
119 | { |
||
120 | return(100); |
||
121 | } |
||
122 | |||
123 | IMG_FREAD(&lLong, sizeof(lLong), 1, pBmpDec->pImageFile); /* File length */ |
||
124 | IMG_FREAD(&wWord, sizeof(wWord), 1, pBmpDec->pImageFile); /* Reserved */ |
||
125 | IMG_FREAD(&wWord, sizeof(wWord), 1, pBmpDec->pImageFile); /* Reserved */ |
||
126 | |||
127 | IMG_FREAD(&lLong, sizeof(lLong), 1, pBmpDec->pImageFile); /* Image offset */ |
||
128 | pBmpDec->lImageOffset = lLong; |
||
129 | |||
130 | IMG_FREAD(&lLong, sizeof(lLong), 1, pBmpDec->pImageFile); /* Header length */ |
||
131 | pBmpDec->bHeaderType = (BYTE)lLong; |
||
132 | |||
133 | if(pBmpDec->bHeaderType >= 40) |
||
134 | { |
||
135 | IMG_FREAD(&lLong, sizeof(lLong), 1, pBmpDec->pImageFile); /* Image Width */ |
||
136 | pBmpDec->lWidth = lLong; |
||
137 | |||
138 | IMG_FREAD(&lLong, sizeof(lLong), 1, pBmpDec->pImageFile); /* Image Height */ |
||
139 | pBmpDec->lHeight = lLong; |
||
140 | |||
141 | IMG_FREAD(&wWord, sizeof(wWord), 1, pBmpDec->pImageFile); /* Number of Planes */ |
||
142 | pBmpDec->bNumOfPlanes = (BYTE)wWord; |
||
143 | |||
144 | IMG_FREAD(&wWord, sizeof(wWord), 1, pBmpDec->pImageFile); /* Bits per Pixel */ |
||
145 | pBmpDec->bBitsPerPixel = (BYTE)wWord; |
||
146 | |||
147 | IMG_FREAD(&lLong, sizeof(lLong), 1, pBmpDec->pImageFile); /* Compression info */ |
||
148 | pBmpDec->blCompressionType = (BYTE)lLong; |
||
149 | |||
150 | IMG_FREAD(&lLong, sizeof(lLong), 1, pBmpDec->pImageFile); /* Image length */ |
||
151 | IMG_FREAD(&lLong, sizeof(lLong), 1, pBmpDec->pImageFile); /* xPixels per metre */ |
||
152 | IMG_FREAD(&lLong, sizeof(lLong), 1, pBmpDec->pImageFile); /* yPixels per metre */ |
||
153 | |||
154 | IMG_FREAD(&lLong, sizeof(lLong), 1, pBmpDec->pImageFile); /* Palette entries */ |
||
155 | pBmpDec->wPaletteEntries = (WORD)lLong; |
||
156 | |||
157 | if(pBmpDec->wPaletteEntries == 0) |
||
158 | { |
||
159 | WORD wTemp = (WORD)(pBmpDec->lImageOffset - 14 - 40)/4; |
||
160 | if(wTemp > 0) |
||
161 | { |
||
162 | pBmpDec->wPaletteEntries = wTemp; /* This is because of a bug in MSPAINT */ |
||
163 | } |
||
164 | } |
||
165 | |||
166 | IMG_FREAD(&lLong, sizeof(lLong), 1, pBmpDec->pImageFile); /* Important colors */ |
||
167 | if(pBmpDec->bBitsPerPixel == 16 && pBmpDec->bHeaderType > 40) |
||
168 | { |
||
169 | IMG_FREAD(&lLong, sizeof(lLong), 1, pBmpDec->pImageFile); /* Red mask */ |
||
170 | if((WORD)lLong == 0xF800) |
||
171 | { |
||
172 | pBmpDec->b16bit565flag = 1; |
||
173 | } |
||
174 | } |
||
175 | |||
176 | IMG_FSEEK(pBmpDec->pImageFile, pBmpDec->bHeaderType + 14, 0); |
||
177 | |||
178 | if(pBmpDec->wPaletteEntries <= 256) |
||
179 | { |
||
180 | WORD wCounter; |
||
181 | for(wCounter = 0; wCounter < pBmpDec->wPaletteEntries; wCounter++) |
||
182 | { |
||
183 | IMG_FREAD(&pBmpDec->aPalette[wCounter][2], sizeof(BYTE), 1, pBmpDec->pImageFile); /* R */ |
||
184 | IMG_FREAD(&pBmpDec->aPalette[wCounter][1], sizeof(BYTE), 1, pBmpDec->pImageFile); /* G */ |
||
185 | IMG_FREAD(&pBmpDec->aPalette[wCounter][0], sizeof(BYTE), 1, pBmpDec->pImageFile); /* B */ |
||
186 | IMG_FREAD(&wWord, sizeof(BYTE), 1, pBmpDec->pImageFile); /* Dummy */ |
||
187 | } |
||
188 | } |
||
189 | } |
||
190 | return(0); |
||
191 | } |
||
192 | |||
193 | /******************************************************************************* |
||
194 | Function: BYTE BMP_bDecode(IMG_FILE *pFile) |
||
195 | |||
196 | Precondition: None |
||
197 | |||
198 | Overview: This function decodes and displays a Bitmap image |
||
199 | |||
200 | Input: Image file |
||
201 | |||
202 | Output: Error code - '0' means no error |
||
203 | *******************************************************************************/ |
||
204 | BYTE BMP_bDecode(IMG_FILE *pFile) |
||
205 | { |
||
206 | BMPDECODER BmpDec; |
||
207 | WORD wX, wY; |
||
208 | BYTE bPadding; |
||
209 | |||
210 | BDEC_vResetData(&BmpDec); |
||
211 | BmpDec.pImageFile = pFile; |
||
212 | BDEC_bReadHeader(&BmpDec); |
||
213 | if(BmpDec.blBmMarkerFlag == 0 || BmpDec.bHeaderType < 40 || (BmpDec.blCompressionType != 0 && BmpDec.blCompressionType != 3)) |
||
214 | { |
||
215 | return 100; |
||
216 | } |
||
217 | IMG_wImageWidth = (WORD)BmpDec.lWidth; |
||
218 | IMG_wImageHeight = (WORD)BmpDec.lHeight; |
||
219 | IMG_vSetboundaries(); |
||
220 | |||
221 | IMG_FSEEK(pFile, BmpDec.lImageOffset, 0); |
||
222 | if(BmpDec.wPaletteEntries == 0 && BmpDec.bBitsPerPixel == 8) /* Grayscale Image */ |
||
223 | { |
||
224 | bPadding = (4 - (BmpDec.lWidth % 4))%4; |
||
225 | for(wY = 0; wY < BmpDec.lHeight; wY++) |
||
226 | { |
||
227 | IMG_vLoopCallback(); |
||
228 | IMG_vCheckAndAbort(); |
||
229 | for(wX = 0; wX < BmpDec.lWidth; wX++) |
||
230 | { |
||
231 | BYTE bY; |
||
232 | IMG_FREAD(&bY, sizeof(bY), 1, BmpDec.pImageFile); /* Y */ |
||
233 | IMG_vSetColor(bY, bY, bY); |
||
234 | IMG_vPutPixel(wX, BmpDec.lHeight - wY - 1); |
||
235 | } |
||
236 | for(wX = 0; wX < bPadding; wX++) |
||
237 | { |
||
238 | BYTE bValue; |
||
239 | IMG_FREAD(&bValue, sizeof(bValue), 1, BmpDec.pImageFile); |
||
240 | } |
||
241 | } |
||
242 | } |
||
243 | else if(BmpDec.bBitsPerPixel == 16) /* 16-bit Color Image */ |
||
244 | { |
||
245 | bPadding = (4 - ((BmpDec.lWidth*2) % 4))%4; |
||
246 | for(wY = 0; wY < BmpDec.lHeight; wY++) |
||
247 | { |
||
248 | IMG_vLoopCallback(); |
||
249 | IMG_vCheckAndAbort(); |
||
250 | for(wX = 0; wX < BmpDec.lWidth; wX++) |
||
251 | { |
||
252 | WORD wColor; |
||
253 | BYTE bR, bG, bB; |
||
254 | IMG_FREAD(&wColor, sizeof(wColor), 1, BmpDec.pImageFile); /* RGB */ |
||
255 | if(BmpDec.b16bit565flag == 1) |
||
256 | { |
||
257 | bR = (wColor >> 11) << 3; |
||
258 | bG = ((wColor & 0x07E0) >> 5) << 2; |
||
259 | bB = (wColor & 0x001F) << 3; |
||
260 | } |
||
261 | else |
||
262 | { |
||
263 | bR = ((wColor & 0x7FFF) >> 10) << 3; |
||
264 | bG = ((wColor & 0x03E0) >> 5) << 3; |
||
265 | bB = (wColor & 0x001F) << 3; |
||
266 | } |
||
267 | IMG_vSetColor(bR, bG, bB); |
||
268 | IMG_vPutPixel(wX, BmpDec.lHeight - wY - 1); |
||
269 | } |
||
270 | for(wX = 0; wX < bPadding; wX++) |
||
271 | { |
||
272 | BYTE bValue; |
||
273 | IMG_FREAD(&bValue, sizeof(bValue), 1, BmpDec.pImageFile); |
||
274 | } |
||
275 | } |
||
276 | } |
||
277 | else if(BmpDec.bBitsPerPixel == 24) /* True color Image */ |
||
278 | { |
||
279 | bPadding = (4 - ((BmpDec.lWidth*3) % 4))%4; |
||
280 | for(wY = 0; wY < BmpDec.lHeight; wY++) |
||
281 | { |
||
282 | IMG_vLoopCallback(); |
||
283 | IMG_vCheckAndAbort(); |
||
284 | for(wX = 0; wX < BmpDec.lWidth; wX++) |
||
285 | { |
||
286 | BYTE bR, bG, bB; |
||
287 | IMG_FREAD(&bB, sizeof(bB), 1, BmpDec.pImageFile); /* B */ |
||
288 | IMG_FREAD(&bG, sizeof(bG), 1, BmpDec.pImageFile); /* G */ |
||
289 | IMG_FREAD(&bR, sizeof(bR), 1, BmpDec.pImageFile); /* R */ |
||
290 | IMG_vSetColor(bR, bG, bB); |
||
291 | IMG_vPutPixel(wX, BmpDec.lHeight - wY - 1); |
||
292 | } |
||
293 | for(wX = 0; wX < bPadding; wX++) |
||
294 | { |
||
295 | BYTE bValue; |
||
296 | IMG_FREAD(&bValue, sizeof(bValue), 1, BmpDec.pImageFile); |
||
297 | } |
||
298 | } |
||
299 | } |
||
300 | else if(BmpDec.wPaletteEntries != 0 && BmpDec.bBitsPerPixel == 1) /* B/W Image */ |
||
301 | { |
||
302 | WORD wBytesPerRow = BmpDec.lWidth/8; |
||
303 | BYTE bAdditionalBitsPerRow = BmpDec.lWidth % 8; |
||
304 | bPadding = (4 - ((wBytesPerRow + (bAdditionalBitsPerRow?1:0)) % 4))%4; |
||
305 | for(wY = 0; wY < BmpDec.lHeight; wY++) |
||
306 | { |
||
307 | BYTE bBits, bValue; |
||
308 | IMG_vLoopCallback(); |
||
309 | IMG_vCheckAndAbort(); |
||
310 | for(wX = 0; wX < wBytesPerRow; wX++) |
||
311 | { |
||
312 | IMG_FREAD(&bValue, sizeof(bValue), 1, BmpDec.pImageFile); |
||
313 | |||
314 | for(bBits = 0; bBits < 8; bBits++) |
||
315 | { |
||
316 | BYTE bIndex = (bValue & (0x80 >> bBits))?1:0; |
||
317 | IMG_vSetColor(BmpDec.aPalette[bIndex][0], BmpDec.aPalette[bIndex][1], BmpDec.aPalette[bIndex][2]); |
||
318 | IMG_vPutPixel(wX*8+bBits, BmpDec.lHeight - wY - 1); |
||
319 | } |
||
320 | } |
||
321 | if(bAdditionalBitsPerRow > 0) |
||
322 | { |
||
323 | IMG_FREAD(&bValue, sizeof(bValue), 1, BmpDec.pImageFile); |
||
324 | |||
325 | for(bBits = 0; bBits < bAdditionalBitsPerRow; bBits++) |
||
326 | { |
||
327 | BYTE bIndex = (bValue & (0x80 >> bBits))?1:0; |
||
328 | IMG_vSetColor(BmpDec.aPalette[bIndex][0], BmpDec.aPalette[bIndex][1], BmpDec.aPalette[bIndex][2]); |
||
329 | IMG_vPutPixel(wX*8+bBits, BmpDec.lHeight - wY - 1); |
||
330 | } |
||
331 | } |
||
332 | for(wX = 0; wX < bPadding; wX++) |
||
333 | { |
||
334 | BYTE bValue; |
||
335 | IMG_FREAD(&bValue, sizeof(bValue), 1, BmpDec.pImageFile); |
||
336 | } |
||
337 | } |
||
338 | } |
||
339 | else if(BmpDec.wPaletteEntries != 0 && BmpDec.bBitsPerPixel == 4) /* 16 colors Image */ |
||
340 | { |
||
341 | WORD wBytesPerRow = BmpDec.lWidth/2; |
||
342 | BYTE bAdditionalNibblePerRow = BmpDec.lWidth % 2; |
||
343 | bPadding = (4 - ((wBytesPerRow + bAdditionalNibblePerRow) % 4))%4; |
||
344 | for(wY = 0; wY < BmpDec.lHeight; wY++) |
||
345 | { |
||
346 | IMG_vLoopCallback(); |
||
347 | IMG_vCheckAndAbort(); |
||
348 | for(wX = 0; wX < wBytesPerRow; wX++) |
||
349 | { |
||
350 | BYTE bIndex, bValue; |
||
351 | IMG_FREAD(&bValue, sizeof(bValue), 1, BmpDec.pImageFile); |
||
352 | bIndex = bValue >> 4; |
||
353 | IMG_vSetColor(BmpDec.aPalette[bIndex][0], BmpDec.aPalette[bIndex][1], BmpDec.aPalette[bIndex][2]); |
||
354 | IMG_vPutPixel(wX*2, BmpDec.lHeight - wY - 1); |
||
355 | bIndex = bValue & 0x0F; |
||
356 | IMG_vSetColor(BmpDec.aPalette[bIndex][0], BmpDec.aPalette[bIndex][1], BmpDec.aPalette[bIndex][2]); |
||
357 | IMG_vPutPixel(wX*2+1, BmpDec.lHeight - wY - 1); |
||
358 | } |
||
359 | if(bAdditionalNibblePerRow) |
||
360 | { |
||
361 | BYTE bIndex, bValue; |
||
362 | IMG_FREAD(&bValue, sizeof(bValue), 1, BmpDec.pImageFile); /* Bits8 */ |
||
363 | bIndex = bValue >> 4; |
||
364 | IMG_vSetColor(BmpDec.aPalette[bIndex][0], BmpDec.aPalette[bIndex][1], BmpDec.aPalette[bIndex][2]); |
||
365 | IMG_vPutPixel(wX*2, BmpDec.lHeight - wY - 1); |
||
366 | } |
||
367 | for(wX = 0; wX < bPadding; wX++) |
||
368 | { |
||
369 | BYTE bValue; |
||
370 | IMG_FREAD(&bValue, sizeof(bValue), 1, BmpDec.pImageFile); |
||
371 | } |
||
372 | } |
||
373 | } |
||
374 | else if(BmpDec.wPaletteEntries != 0 && BmpDec.bBitsPerPixel == 8) /* 256 colors Image */ |
||
375 | { |
||
376 | bPadding = (4 - (BmpDec.lWidth % 4))%4; |
||
377 | for(wY = 0; wY < BmpDec.lHeight; wY++) |
||
378 | { |
||
379 | IMG_vLoopCallback(); |
||
380 | IMG_vCheckAndAbort(); |
||
381 | for(wX = 0; wX < BmpDec.lWidth; wX++) |
||
382 | { |
||
383 | BYTE bIndex; |
||
384 | IMG_FREAD(&bIndex, sizeof(bIndex), 1, BmpDec.pImageFile); |
||
385 | IMG_vSetColor(BmpDec.aPalette[bIndex][0], BmpDec.aPalette[bIndex][1], BmpDec.aPalette[bIndex][2]); |
||
386 | IMG_vPutPixel(wX, BmpDec.lHeight - wY - 1); |
||
387 | } |
||
388 | for(wX = 0; wX < bPadding; wX++) |
||
389 | { |
||
390 | BYTE bValue; |
||
391 | IMG_FREAD(&bValue, sizeof(bValue), 1, BmpDec.pImageFile); |
||
392 | } |
||
393 | } |
||
394 | } |
||
395 | |||
396 | return 0; |
||
397 | } |
||
398 | |||
399 | #endif /* #ifdef IMG_SUPPORT_BMP */ |
||
400 | |||
401 | #undef __BMPDECODER_C__ |
Powered by WebSVN v2.8.3