Line No. | Rev | Author | Line |
---|---|---|---|
1 | 32 | kaklik | #define __GIFDECODER_C__ |
2 | /****************************************************************************** |
||
3 | |||
4 | * FileName: GifDecoder.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_GIF |
||
42 | |||
43 | /*************************/ |
||
44 | /**** DATA STRUCTURES ****/ |
||
45 | /*************************/ |
||
46 | typedef struct _GIFDECODER |
||
47 | { |
||
48 | IMG_FILE *pImageFile; /* Image file pointer */ |
||
49 | WORD wImageWidth; |
||
50 | WORD wImageHeight; |
||
51 | WORD wImageX; |
||
52 | WORD wImageY; |
||
53 | WORD wScreenWidth; |
||
54 | WORD wScreenHeight; |
||
55 | WORD wGlobalPaletteEntries; |
||
56 | WORD wLocalPaletteEntries; |
||
57 | BYTE bBgColorIndex; |
||
58 | BYTE bPixelAspectRatio; |
||
59 | BYTE blGifMarkerFlag : 1; |
||
60 | BYTE blGloabalColorTableFlag : 1; |
||
61 | BYTE blLocalColorTableFlag : 1; |
||
62 | BYTE blInterlacedFlag : 1; |
||
63 | BYTE blFirstcodeFlag : 1; |
||
64 | BYTE bInterlacePass : 3; |
||
65 | #if GIF_USE_16_BITS_PER_PIXEL == 0 |
||
66 | BYTE aPalette[256][3]; /* Each palette entry has RGB */ |
||
67 | #else |
||
68 | WORD awPalette[256]; /* Each palette entry has RGB */ |
||
69 | #endif |
||
70 | /* For decoding */ |
||
71 | BYTE abSymbol[4096]; |
||
72 | |||
73 | #if GIF_CRUSH_PREV_SYMBOL_PTR_TABLE == 0 |
||
74 | WORD awPrevSymbolPtr[4096]; |
||
75 | #else |
||
76 | WORD awPrevSymbolPtr[(4096 * 3)/4]; |
||
77 | #endif |
||
78 | |||
79 | WORD wInitialSymbols; |
||
80 | WORD wMaxSymbol; |
||
81 | BYTE bInitialSymbolBits; |
||
82 | BYTE bMaxSymbolBits; |
||
83 | LONG lGlobalColorTablePos; |
||
84 | /* Work memory */ |
||
85 | BYTE bWorkBits; |
||
86 | BYTE bRemainingDataInBlock; |
||
87 | BYTE bRemainingBits; |
||
88 | WORD wCurrentX; |
||
89 | WORD wCurrentY; |
||
90 | } GIFDECODER; |
||
91 | |||
92 | |||
93 | /**************************/ |
||
94 | /****** LOOKUP TABLE ******/ |
||
95 | /**************************/ |
||
96 | static const WORD GIF_awMask[] = { 0x000, 0x001, 0x003, 0x007, 0x00F, 0x01F, 0x03F, 0x07F, 0x0FF, 0x1FF, 0x3FF, 0x7FF, 0xFFF }; |
||
97 | |||
98 | /**************************/ |
||
99 | /******* FUNCTIONS *******/ |
||
100 | /**************************/ |
||
101 | /******************************************************************************* |
||
102 | Function: void GIF_vResetData(GIFDECODER *pGifDec) |
||
103 | |||
104 | Precondition: None |
||
105 | |||
106 | Overview: This function resets the variables so that new GIF image |
||
107 | can be decoded |
||
108 | |||
109 | Input: GIF decoder's data structure |
||
110 | |||
111 | Output: None |
||
112 | *******************************************************************************/ |
||
113 | static void GIF_vResetData(GIFDECODER *pGifDec) |
||
114 | { |
||
115 | pGifDec->pImageFile = NULL; |
||
116 | pGifDec->wImageWidth = 0; |
||
117 | pGifDec->wImageHeight = 0; |
||
118 | pGifDec->wImageX = 0; |
||
119 | pGifDec->wImageY = 0; |
||
120 | pGifDec->wScreenWidth = 0; |
||
121 | pGifDec->wScreenHeight = 0; |
||
122 | pGifDec->wGlobalPaletteEntries = 0; |
||
123 | pGifDec->wLocalPaletteEntries = 0; |
||
124 | pGifDec->bBgColorIndex = 0; |
||
125 | pGifDec->bPixelAspectRatio = 0; |
||
126 | pGifDec->blGifMarkerFlag = 0; |
||
127 | pGifDec->blGloabalColorTableFlag = 0; |
||
128 | pGifDec->blLocalColorTableFlag = 0; |
||
129 | pGifDec->blInterlacedFlag = 0; |
||
130 | pGifDec->blFirstcodeFlag = 1; |
||
131 | pGifDec->bInterlacePass = 0; |
||
132 | pGifDec->wMaxSymbol = 0; |
||
133 | pGifDec->bMaxSymbolBits = 0; |
||
134 | pGifDec->wInitialSymbols = 0; |
||
135 | pGifDec->bInitialSymbolBits = 0; |
||
136 | pGifDec->bWorkBits = 0; |
||
137 | pGifDec->bRemainingDataInBlock = 0; |
||
138 | pGifDec->bRemainingBits = 0; |
||
139 | pGifDec->wCurrentX = 0; |
||
140 | pGifDec->wCurrentY = 0; |
||
141 | pGifDec->lGlobalColorTablePos = 0; |
||
142 | } |
||
143 | |||
144 | /******************************************************************************* |
||
145 | Function: void GIF_vPutPrevCode(GIFDECODER *pGifDec, WORD wAddress, WORD wCode) |
||
146 | |||
147 | Precondition: None |
||
148 | |||
149 | Overview: This function puts the data(code) to the provided address |
||
150 | |||
151 | Input: GIF decoder's data structure, Address, Data(Code) |
||
152 | |||
153 | Output: None |
||
154 | *******************************************************************************/ |
||
155 | static void GIF_vPutPrevCode(GIFDECODER *pGifDec, WORD wAddress, WORD wCode) |
||
156 | { |
||
157 | #if GIF_CRUSH_PREV_SYMBOL_PTR_TABLE == 0 |
||
158 | pGifDec->awPrevSymbolPtr[wAddress] = wCode; |
||
159 | #else |
||
160 | WORD wCrushedAddress = (wAddress * 3) / 4; |
||
161 | if((wAddress & 0x03) == 0) |
||
162 | { |
||
163 | pGifDec->awPrevSymbolPtr[wCrushedAddress] &= 0xF000; |
||
164 | pGifDec->awPrevSymbolPtr[wCrushedAddress] |= (wCode & 0x0FFF); |
||
165 | } |
||
166 | else if((wAddress & 0x03) == 1) |
||
167 | { |
||
168 | pGifDec->awPrevSymbolPtr[wCrushedAddress] &= 0x0FFF; |
||
169 | pGifDec->awPrevSymbolPtr[wCrushedAddress + 1] &= 0xFF00; |
||
170 | pGifDec->awPrevSymbolPtr[wCrushedAddress] |= (wCode << 12); |
||
171 | pGifDec->awPrevSymbolPtr[wCrushedAddress + 1] |= ((wCode >> 4) & 0x00FF); |
||
172 | } |
||
173 | else if((wAddress & 0x03) == 2) |
||
174 | { |
||
175 | pGifDec->awPrevSymbolPtr[wCrushedAddress] &= 0x00FF; |
||
176 | pGifDec->awPrevSymbolPtr[wCrushedAddress + 1] &= 0xFFF0; |
||
177 | pGifDec->awPrevSymbolPtr[wCrushedAddress] |= (wCode << 8); |
||
178 | pGifDec->awPrevSymbolPtr[wCrushedAddress + 1] |= ((wCode >> 8) & 0x000F); |
||
179 | } |
||
180 | else |
||
181 | { |
||
182 | pGifDec->awPrevSymbolPtr[wCrushedAddress] &= 0x000F; |
||
183 | pGifDec->awPrevSymbolPtr[wCrushedAddress] |= (wCode << 4); |
||
184 | } |
||
185 | #endif |
||
186 | } |
||
187 | |||
188 | /******************************************************************************* |
||
189 | Function: WORD GIF_wGetPrevCode(GIFDECODER *pGifDec, WORD wAddress) |
||
190 | |||
191 | Precondition: None |
||
192 | |||
193 | Overview: This function gets the data(code) from the provided address |
||
194 | |||
195 | Input: GIF decoder's data structure, Address |
||
196 | |||
197 | Output: Data(Code) |
||
198 | *******************************************************************************/ |
||
199 | static WORD GIF_wGetPrevCode(GIFDECODER *pGifDec, WORD wAddress) |
||
200 | { |
||
201 | WORD wCode; |
||
202 | #if GIF_CRUSH_PREV_SYMBOL_PTR_TABLE == 0 |
||
203 | wCode = pGifDec->awPrevSymbolPtr[wAddress]; |
||
204 | #else |
||
205 | WORD wCrushedAddress = (wAddress * 3) / 4; |
||
206 | if((wAddress & 0x03) == 0) |
||
207 | { |
||
208 | wCode = (pGifDec->awPrevSymbolPtr[wCrushedAddress] & 0x0FFF); |
||
209 | } |
||
210 | else if((wAddress & 0x03) == 1) |
||
211 | { |
||
212 | wCode = (pGifDec->awPrevSymbolPtr[wCrushedAddress] >> 12); |
||
213 | wCode |= ((pGifDec->awPrevSymbolPtr[wCrushedAddress + 1] & 0x00FF) << 4); |
||
214 | } |
||
215 | else if((wAddress & 0x03) == 2) |
||
216 | { |
||
217 | wCode = (pGifDec->awPrevSymbolPtr[wCrushedAddress] >> 8); |
||
218 | wCode |= ((pGifDec->awPrevSymbolPtr[wCrushedAddress + 1] & 0x000F) << 8); |
||
219 | } |
||
220 | else |
||
221 | { |
||
222 | wCode = (pGifDec->awPrevSymbolPtr[wCrushedAddress] >> 4); |
||
223 | } |
||
224 | #endif |
||
225 | return wCode; |
||
226 | } |
||
227 | |||
228 | /******************************************************************************* |
||
229 | Function: void GIF_vInitializeTable(GIFDECODER *pGifDec) |
||
230 | |||
231 | Precondition: pGifDec->wInitialSymbols must be set to a proper value by |
||
232 | reading the Header |
||
233 | |||
234 | Overview: This function initializes the code table to the initial number |
||
235 | of symbols |
||
236 | |||
237 | Input: GIF decoder's data structure |
||
238 | |||
239 | Output: None |
||
240 | *******************************************************************************/ |
||
241 | static void GIF_vInitializeTable(GIFDECODER *pGifDec) |
||
242 | { |
||
243 | WORD wCounter; |
||
244 | for(wCounter = 0; wCounter < pGifDec->wInitialSymbols; wCounter++) |
||
245 | { |
||
246 | pGifDec->abSymbol[wCounter] = wCounter; |
||
247 | GIF_vPutPrevCode(pGifDec, wCounter, pGifDec->wInitialSymbols); |
||
248 | } |
||
249 | } |
||
250 | |||
251 | /******************************************************************************* |
||
252 | Function: void GIF_vReadColorTable(GIFDECODER *pGifDec, WORD wNumberOfEntries) |
||
253 | |||
254 | Precondition: None |
||
255 | |||
256 | Overview: This function initializes the code table to the initial number |
||
257 | of symbols |
||
258 | |||
259 | Input: GIF decoder's data structure |
||
260 | |||
261 | Output: None |
||
262 | *******************************************************************************/ |
||
263 | static void GIF_vReadColorTable(GIFDECODER *pGifDec, WORD wNumberOfEntries) |
||
264 | { |
||
265 | BYTE r, g, b; |
||
266 | WORD wCounter; |
||
267 | for(wCounter = 0; wCounter < wNumberOfEntries; wCounter++) |
||
268 | { |
||
269 | IMG_FREAD(&r, sizeof(BYTE), 1, pGifDec->pImageFile); /* R */ |
||
270 | IMG_FREAD(&g, sizeof(BYTE), 1, pGifDec->pImageFile); /* G */ |
||
271 | IMG_FREAD(&b, sizeof(BYTE), 1, pGifDec->pImageFile); /* B */ |
||
272 | #if GIF_USE_16_BITS_PER_PIXEL == 0 |
||
273 | pGifDec->aPalette[wCounter][0] = r; |
||
274 | pGifDec->aPalette[wCounter][1] = g; |
||
275 | pGifDec->aPalette[wCounter][2] = b; |
||
276 | #else |
||
277 | pGifDec->awPalette[wCounter] = RGB565CONVERT(r, g, b); |
||
278 | #endif |
||
279 | } |
||
280 | } |
||
281 | |||
282 | /******************************************************************************* |
||
283 | Function: BYTE GIF_bReadHeader(GIFDECODER *pGifDec) |
||
284 | |||
285 | Precondition: None |
||
286 | |||
287 | Overview: This function reads the GIF file's header information |
||
288 | |||
289 | Input: GIF decoder's data structure |
||
290 | |||
291 | Output: Error code - '0' means no error |
||
292 | *******************************************************************************/ |
||
293 | static BYTE GIF_bReadHeader(GIFDECODER *pGifDec) |
||
294 | { |
||
295 | BYTE abByte[6]; |
||
296 | BYTE bFlags; |
||
297 | |||
298 | IMG_FREAD(abByte, sizeof(BYTE), 6, pGifDec->pImageFile); /* Marker */ |
||
299 | if(abByte[0] == 'G' && abByte[1] == 'I' && abByte[2] == 'F' && |
||
300 | abByte[3] == '8' && (abByte[4] == '7' || abByte[4] == '9') && |
||
301 | abByte[5] == 'a') |
||
302 | { |
||
303 | pGifDec->blGifMarkerFlag = 1; |
||
304 | } |
||
305 | else |
||
306 | { |
||
307 | return(100); |
||
308 | } |
||
309 | |||
310 | IMG_FREAD(&pGifDec->wScreenWidth, sizeof(WORD), 1, pGifDec->pImageFile); |
||
311 | IMG_FREAD(&pGifDec->wScreenHeight, sizeof(WORD), 1, pGifDec->pImageFile); |
||
312 | IMG_FREAD(&bFlags, sizeof(BYTE), 1, pGifDec->pImageFile); /* Packed fields */ |
||
313 | IMG_FREAD(&pGifDec->bBgColorIndex, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
314 | IMG_FREAD(&pGifDec->bPixelAspectRatio, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
315 | if(bFlags & 0x80) |
||
316 | { |
||
317 | pGifDec->blGloabalColorTableFlag = 1; |
||
318 | } |
||
319 | pGifDec->wGlobalPaletteEntries = 0x01 << ((bFlags & 0x07) + 1); |
||
320 | |||
321 | if(pGifDec->blGloabalColorTableFlag == 1) |
||
322 | { |
||
323 | pGifDec->lGlobalColorTablePos = IMG_FTELL(pGifDec->pImageFile); |
||
324 | GIF_vReadColorTable(pGifDec, pGifDec->wGlobalPaletteEntries); |
||
325 | } |
||
326 | return(0); |
||
327 | } |
||
328 | |||
329 | /******************************************************************************* |
||
330 | Function: BYTE GIF_bReadNextImageDescriptor(GIFDECODER *pGifDec) |
||
331 | |||
332 | Precondition: File pointer must be pointing to proper location (Like start of |
||
333 | extension) |
||
334 | |||
335 | Overview: This function reads the next image descriptor |
||
336 | |||
337 | Input: GIF decoder's data structure |
||
338 | |||
339 | Output: Error code - '0' means no error |
||
340 | *******************************************************************************/ |
||
341 | static BYTE GIF_bReadNextImageDescriptor(GIFDECODER *pGifDec) |
||
342 | { |
||
343 | BYTE bSection, bSectionDetails, bBlockSize, bTemp; |
||
344 | BYTE bFlags; |
||
345 | BYTE bCounter; |
||
346 | do |
||
347 | { |
||
348 | IMG_FREAD(&bSection, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
349 | if(bSection == 0x21) /* Extension block */ |
||
350 | { |
||
351 | IMG_FREAD(&bSectionDetails, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
352 | switch(bSectionDetails) |
||
353 | { |
||
354 | /* GRAPHICS EXTENSION */ case 0xF9: IMG_FREAD(&bBlockSize, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
355 | IMG_FSEEK(pGifDec->pImageFile, bBlockSize, 1); |
||
356 | break; |
||
357 | /* PLAIN TEXT EXTENSION */ case 0x01: |
||
358 | /* APPLICATION EXTENSION */ case 0xFF: IMG_FREAD(&bBlockSize, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
359 | IMG_FSEEK(pGifDec->pImageFile, bBlockSize, 1); |
||
360 | /* COMMENT EXTENSION */ case 0xFE: IMG_FREAD(&bBlockSize, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
361 | for(bCounter = 0; bCounter < bBlockSize; bCounter++) |
||
362 | { |
||
363 | IMG_FREAD(&bTemp, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
364 | } |
||
365 | break; |
||
366 | |||
367 | default: return(100); |
||
368 | } |
||
369 | /* BLOCK TERMINATOR */ IMG_FREAD(&bTemp, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
370 | if(bTemp != 0) |
||
371 | { |
||
372 | return(100); |
||
373 | } |
||
374 | } |
||
375 | else if(bSection != 0x2C) |
||
376 | { |
||
377 | return(100); |
||
378 | } |
||
379 | } |
||
380 | while(bSection != 0x2C); |
||
381 | |||
382 | pGifDec->blFirstcodeFlag = 1; |
||
383 | pGifDec->bInterlacePass = 0; |
||
384 | pGifDec->bWorkBits = 0; |
||
385 | pGifDec->bRemainingDataInBlock = 0; |
||
386 | pGifDec->bRemainingBits = 0; |
||
387 | IMG_FREAD(&pGifDec->wImageX, sizeof(WORD), 1, pGifDec->pImageFile); |
||
388 | IMG_FREAD(&pGifDec->wImageY, sizeof(WORD), 1, pGifDec->pImageFile); |
||
389 | IMG_FREAD(&pGifDec->wImageWidth, sizeof(WORD), 1, pGifDec->pImageFile); |
||
390 | IMG_FREAD(&pGifDec->wImageHeight, sizeof(WORD), 1, pGifDec->pImageFile); |
||
391 | IMG_FREAD(&bFlags, sizeof(BYTE), 1, pGifDec->pImageFile); /* Packed fields */ |
||
392 | if(bFlags & 0x40) |
||
393 | { |
||
394 | pGifDec->blInterlacedFlag = 1; |
||
395 | } |
||
396 | if(bFlags & 0x80) |
||
397 | { |
||
398 | pGifDec->blLocalColorTableFlag = 1; |
||
399 | } |
||
400 | pGifDec->wLocalPaletteEntries = 0x01 << ((bFlags & 0x07) + 1); |
||
401 | if(pGifDec->blLocalColorTableFlag == 1) |
||
402 | { |
||
403 | GIF_vReadColorTable(pGifDec, pGifDec->wLocalPaletteEntries); |
||
404 | } |
||
405 | pGifDec->wCurrentX = pGifDec->wImageX; |
||
406 | pGifDec->wCurrentY = pGifDec->wImageY; |
||
407 | return 0; |
||
408 | } |
||
409 | |||
410 | /******************************************************************************* |
||
411 | Function: WORD GIF_wGetNextByte(GIFDECODER *pGifDec) |
||
412 | |||
413 | Precondition: None |
||
414 | |||
415 | Overview: This function reads the next data byte. It also handles the |
||
416 | data block intra-boundaries |
||
417 | |||
418 | Input: GIF decoder's data structure |
||
419 | |||
420 | Output: Data byte, 0xFFFF means error |
||
421 | *******************************************************************************/ |
||
422 | static WORD GIF_wGetNextByte(GIFDECODER *pGifDec) |
||
423 | { |
||
424 | BYTE bByte; |
||
425 | if(pGifDec->bRemainingDataInBlock == 0) |
||
426 | { |
||
427 | IMG_FREAD(&pGifDec->bRemainingDataInBlock, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
428 | if(pGifDec->bRemainingDataInBlock == 0) |
||
429 | { |
||
430 | return 0xFFFF; /* End of data */ |
||
431 | } |
||
432 | } |
||
433 | IMG_FREAD(&bByte, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
434 | pGifDec->bRemainingDataInBlock--; |
||
435 | return (WORD)bByte; |
||
436 | } |
||
437 | |||
438 | /******************************************************************************* |
||
439 | Function: WORD GIF_wGetNextSymbol(GIFDECODER *pGifDec) |
||
440 | |||
441 | Precondition: pGifDec->bMaxSymbolBits must be properly updated |
||
442 | |||
443 | Overview: This function reads the next code symbol brom the data stream |
||
444 | |||
445 | Input: GIF decoder's data structure |
||
446 | |||
447 | Output: Next Code, 0xFFFF means error |
||
448 | *******************************************************************************/ |
||
449 | static WORD GIF_wGetNextSymbol(GIFDECODER *pGifDec) |
||
450 | { |
||
451 | WORD wDataBits = 0xFFFF; |
||
452 | if(pGifDec->bRemainingBits < pGifDec->bMaxSymbolBits) |
||
453 | { |
||
454 | WORD wTemp1, wTemp2; |
||
455 | BYTE bBitsRequired; |
||
456 | |||
457 | bBitsRequired = pGifDec->bMaxSymbolBits - pGifDec->bRemainingBits; |
||
458 | wDataBits = pGifDec->bWorkBits & GIF_awMask[pGifDec->bRemainingBits]; |
||
459 | wTemp1 = GIF_wGetNextByte(pGifDec); |
||
460 | if(wTemp1 == 0xFFFF) |
||
461 | { |
||
462 | return 0xFFFF; |
||
463 | } |
||
464 | pGifDec->bWorkBits = (BYTE)wTemp1; |
||
465 | if(bBitsRequired > 8) |
||
466 | { |
||
467 | wTemp2 = GIF_wGetNextByte(pGifDec); |
||
468 | if(wTemp2 == 0xFFFF) |
||
469 | { |
||
470 | return 0xFFFF; |
||
471 | } |
||
472 | pGifDec->bWorkBits = (BYTE)wTemp2; |
||
473 | wTemp1 |= wTemp2 << 8; |
||
474 | } |
||
475 | wDataBits |= wTemp1 << pGifDec->bRemainingBits; |
||
476 | pGifDec->bRemainingBits = 8 - (bBitsRequired % 8); |
||
477 | if(bBitsRequired == 8) |
||
478 | { |
||
479 | pGifDec->bRemainingBits = 0; |
||
480 | } |
||
481 | pGifDec->bWorkBits >>= 8 - pGifDec->bRemainingBits; |
||
482 | } |
||
483 | else |
||
484 | { |
||
485 | wDataBits = pGifDec->bWorkBits; |
||
486 | pGifDec->bRemainingBits -= pGifDec->bMaxSymbolBits; |
||
487 | pGifDec->bWorkBits >>= pGifDec->bMaxSymbolBits; |
||
488 | } |
||
489 | wDataBits &= GIF_awMask[pGifDec->bMaxSymbolBits]; |
||
490 | return wDataBits; |
||
491 | } |
||
492 | |||
493 | /******************************************************************************* |
||
494 | Function: void GIF_vPaintData(GIFDECODER *pGifDec, BYTE bData) |
||
495 | |||
496 | Precondition: pGifDec->blInterlacedFlag must be properly set |
||
497 | |||
498 | Overview: This function puts the actual pixel on the display. It also |
||
499 | takes care of the interlaced pixel arrangement. |
||
500 | |||
501 | Input: GIF decoder's data structure, palette index |
||
502 | |||
503 | Output: None |
||
504 | *******************************************************************************/ |
||
505 | static void GIF_vPaintData(GIFDECODER *pGifDec, BYTE bData) |
||
506 | { |
||
507 | #if GIF_USE_16_BITS_PER_PIXEL == 0 |
||
508 | IMG_vSetColor(pGifDec->aPalette[bData][0], pGifDec->aPalette[bData][1], pGifDec->aPalette[bData][2]); |
||
509 | #else |
||
510 | IMG_vSetColor565(pGifDec->awPalette[bData]); |
||
511 | #endif |
||
512 | IMG_vPutPixel(pGifDec->wCurrentX, pGifDec->wCurrentY); |
||
513 | pGifDec->wCurrentX++; |
||
514 | if(pGifDec->wCurrentX >= pGifDec->wImageWidth) |
||
515 | { |
||
516 | IMG_vLoopCallback(); |
||
517 | pGifDec->wCurrentX = pGifDec->wImageX; |
||
518 | if(pGifDec->blInterlacedFlag == 0) |
||
519 | { |
||
520 | pGifDec->wCurrentY++; |
||
521 | } |
||
522 | else |
||
523 | { |
||
524 | switch(pGifDec->bInterlacePass) |
||
525 | { |
||
526 | case 0: pGifDec->wCurrentY += 8; |
||
527 | break; |
||
528 | case 1: pGifDec->wCurrentY += 8; |
||
529 | break; |
||
530 | case 2: pGifDec->wCurrentY += 4; |
||
531 | break; |
||
532 | case 3: pGifDec->wCurrentY += 2; |
||
533 | break; |
||
534 | } |
||
535 | if(pGifDec->wCurrentY - pGifDec->wImageY >= pGifDec->wImageHeight) |
||
536 | { |
||
537 | switch(pGifDec->bInterlacePass) |
||
538 | { |
||
539 | case 0: pGifDec->wCurrentY = pGifDec->wImageY + 4; |
||
540 | break; |
||
541 | case 1: pGifDec->wCurrentY = pGifDec->wImageY + 2; |
||
542 | break; |
||
543 | case 2: pGifDec->wCurrentY = pGifDec->wImageY + 1; |
||
544 | break; |
||
545 | case 3: pGifDec->wCurrentY = pGifDec->wImageY + 0; |
||
546 | break; |
||
547 | } |
||
548 | pGifDec->bInterlacePass++; |
||
549 | } |
||
550 | } |
||
551 | } |
||
552 | } |
||
553 | |||
554 | /******************************************************************************* |
||
555 | Function: void GIF_vDisplayCode(GIFDECODER *pGifDec, WORD wCode) |
||
556 | |||
557 | Precondition: None |
||
558 | |||
559 | Overview: This function puts the stream of pixels corresponding to the |
||
560 | code. This uses recursion. |
||
561 | |||
562 | Input: GIF decoder's data structure, code |
||
563 | |||
564 | Output: None |
||
565 | *******************************************************************************/ |
||
566 | static void GIF_vDisplayCode(GIFDECODER *pGifDec, WORD wCode) |
||
567 | { |
||
568 | WORD wPrevCode = GIF_wGetPrevCode(pGifDec, wCode); |
||
569 | if(wPrevCode != pGifDec->wInitialSymbols) |
||
570 | { |
||
571 | GIF_vDisplayCode(pGifDec, wPrevCode); |
||
572 | } |
||
573 | GIF_vPaintData(pGifDec, pGifDec->abSymbol[wCode]); |
||
574 | } |
||
575 | |||
576 | /******************************************************************************* |
||
577 | Function: BYTE GIF_bTraceFirstData(GIFDECODER *pGifDec, WORD wCode) |
||
578 | |||
579 | Precondition: None |
||
580 | |||
581 | Overview: This function gets the first symbol of the code |
||
582 | |||
583 | Input: GIF decoder's data structure, code |
||
584 | |||
585 | Output: First symbol of the code |
||
586 | *******************************************************************************/ |
||
587 | static BYTE GIF_bTraceFirstData(GIFDECODER *pGifDec, WORD wCode) |
||
588 | { |
||
589 | while(GIF_wGetPrevCode(pGifDec, wCode) != pGifDec->wInitialSymbols) |
||
590 | { |
||
591 | wCode = GIF_wGetPrevCode(pGifDec, wCode); |
||
592 | } |
||
593 | return pGifDec->abSymbol[wCode]; |
||
594 | } |
||
595 | |||
596 | /******************************************************************************* |
||
597 | Function: GIF_vExecuteClearCode(GIFDECODER *pGifDec) |
||
598 | |||
599 | Precondition: None |
||
600 | |||
601 | Overview: This function sets the code table to the initial condition |
||
602 | |||
603 | Input: GIF decoder's data structure |
||
604 | |||
605 | Output: None |
||
606 | *******************************************************************************/ |
||
607 | static void GIF_vExecuteClearCode(GIFDECODER *pGifDec) |
||
608 | { |
||
609 | pGifDec->wMaxSymbol = pGifDec->wInitialSymbols; |
||
610 | pGifDec->bMaxSymbolBits = pGifDec->bInitialSymbolBits; |
||
611 | pGifDec->blFirstcodeFlag = 1; |
||
612 | } |
||
613 | |||
614 | /******************************************************************************* |
||
615 | Function: BYTE GIF_bDecodeNextImage(GIFDECODER *pGifDec) |
||
616 | |||
617 | Precondition: Header must be read and file pointer should point to the end |
||
618 | of the previous image |
||
619 | |||
620 | Overview: This function sets the code table to the initial condition |
||
621 | |||
622 | Input: GIF decoder's data structure |
||
623 | |||
624 | Output: Error code - '0' means no error |
||
625 | *******************************************************************************/ |
||
626 | static BYTE GIF_bDecodeNextImage(GIFDECODER *pGifDec) |
||
627 | { |
||
628 | BYTE bBlockTerminator; |
||
629 | WORD wCode; |
||
630 | if(GIF_bReadNextImageDescriptor(pGifDec) != 0) |
||
631 | { |
||
632 | return(100); |
||
633 | } |
||
634 | |||
635 | IMG_FREAD(&pGifDec->bMaxSymbolBits, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
636 | if(pGifDec->bMaxSymbolBits > 11) |
||
637 | { |
||
638 | return(100); |
||
639 | } |
||
640 | pGifDec->wMaxSymbol = (0x01 << pGifDec->bMaxSymbolBits) + 1; |
||
641 | pGifDec->bMaxSymbolBits++; |
||
642 | pGifDec->wInitialSymbols = pGifDec->wMaxSymbol; |
||
643 | pGifDec->bInitialSymbolBits = pGifDec->bMaxSymbolBits; |
||
644 | GIF_vInitializeTable(pGifDec); |
||
645 | |||
646 | /* Actual decoding starts here */ |
||
647 | while(!IMG_FEOF(pGifDec->pImageFile)) |
||
648 | { |
||
649 | IMG_vCheckAndAbort(); |
||
650 | wCode = GIF_wGetNextSymbol(pGifDec); |
||
651 | if(wCode >= 4096) |
||
652 | { |
||
653 | return(100); |
||
654 | } |
||
655 | if(wCode == pGifDec->wInitialSymbols) /* End code */ |
||
656 | { |
||
657 | break; |
||
658 | } |
||
659 | if(wCode == pGifDec->wInitialSymbols - 1) /* Clear code */ |
||
660 | { |
||
661 | GIF_vExecuteClearCode(pGifDec); |
||
662 | continue; |
||
663 | } |
||
664 | if(wCode <= pGifDec->wMaxSymbol) /* Code exists */ |
||
665 | { |
||
666 | GIF_vDisplayCode(pGifDec, wCode); |
||
667 | if(pGifDec->blFirstcodeFlag == 0 && pGifDec->wMaxSymbol < 4095) |
||
668 | { |
||
669 | pGifDec->wMaxSymbol++; |
||
670 | pGifDec->abSymbol[pGifDec->wMaxSymbol] = GIF_bTraceFirstData(pGifDec, wCode); |
||
671 | } |
||
672 | if(pGifDec->wMaxSymbol < 4095) |
||
673 | { |
||
674 | GIF_vPutPrevCode(pGifDec, pGifDec->wMaxSymbol + 1, wCode); |
||
675 | } |
||
676 | pGifDec->blFirstcodeFlag = 0; |
||
677 | } |
||
678 | else if(wCode == pGifDec->wMaxSymbol + 1 && wCode <= 4095) |
||
679 | { |
||
680 | if(pGifDec->blFirstcodeFlag == 1) |
||
681 | { |
||
682 | return(100); |
||
683 | } |
||
684 | pGifDec->wMaxSymbol++; |
||
685 | pGifDec->abSymbol[pGifDec->wMaxSymbol] = GIF_bTraceFirstData(pGifDec, GIF_wGetPrevCode(pGifDec, pGifDec->wMaxSymbol)); |
||
686 | GIF_vDisplayCode(pGifDec, wCode); |
||
687 | if(pGifDec->wMaxSymbol < 4095) |
||
688 | { |
||
689 | GIF_vPutPrevCode(pGifDec, pGifDec->wMaxSymbol + 1, wCode); |
||
690 | } |
||
691 | } |
||
692 | else |
||
693 | { |
||
694 | return(100); |
||
695 | } |
||
696 | |||
697 | if((pGifDec->bMaxSymbolBits < 12) && (pGifDec->wMaxSymbol >= (0x01 << pGifDec->bMaxSymbolBits) - 1)) |
||
698 | { |
||
699 | pGifDec->bMaxSymbolBits++; |
||
700 | } |
||
701 | } |
||
702 | if(pGifDec->blLocalColorTableFlag == 1) /* Restore Global color table */ |
||
703 | { |
||
704 | if(pGifDec->lGlobalColorTablePos > 0) |
||
705 | { |
||
706 | LONG lFilePos = IMG_FTELL(pGifDec->pImageFile); |
||
707 | IMG_FSEEK(pGifDec->pImageFile, pGifDec->lGlobalColorTablePos, 0); |
||
708 | GIF_vReadColorTable(pGifDec, pGifDec->wGlobalPaletteEntries); |
||
709 | IMG_FSEEK(pGifDec->pImageFile, lFilePos, 0); |
||
710 | } |
||
711 | } |
||
712 | IMG_FREAD(&bBlockTerminator, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
713 | if(bBlockTerminator == 0) |
||
714 | { |
||
715 | BYTE bTemp; |
||
716 | IMG_FREAD(&bTemp, sizeof(BYTE), 1, pGifDec->pImageFile); |
||
717 | if(bTemp == 0x3B) /* End of GIF stream */ |
||
718 | { |
||
719 | return 0x3B; |
||
720 | } |
||
721 | IMG_FSEEK(pGifDec->pImageFile, -1, 1); |
||
722 | } |
||
723 | return bBlockTerminator; |
||
724 | } |
||
725 | |||
726 | /******************************************************************************* |
||
727 | Function: BYTE GIF_bDecode(IMG_FILE *pFile) |
||
728 | |||
729 | Precondition: None |
||
730 | |||
731 | Overview: This function decodes and displays a GIF image |
||
732 | |||
733 | Input: Image file |
||
734 | |||
735 | Output: Error code - '0' means no error |
||
736 | *******************************************************************************/ |
||
737 | BYTE GIF_bDecode(IMG_FILE *pFile) |
||
738 | { |
||
739 | GIFDECODER GifDec; |
||
740 | |||
741 | GIF_vResetData(&GifDec); |
||
742 | GifDec.pImageFile = pFile; |
||
743 | GIF_bReadHeader(&GifDec); |
||
744 | if(GifDec.blGifMarkerFlag == 0) |
||
745 | { |
||
746 | return(100); |
||
747 | } |
||
748 | IMG_wImageWidth = GifDec.wScreenWidth; |
||
749 | IMG_wImageHeight = GifDec.wScreenHeight; |
||
750 | IMG_vSetboundaries(); |
||
751 | return GIF_bDecodeNextImage(&GifDec); |
||
752 | } |
||
753 | |||
754 | #endif |
||
755 | #undef __GIFDECODER_C__ |
Powered by WebSVN v2.8.3