1 //<MStar Software>
2 //******************************************************************************
3 // MStar Software
4 // Copyright (c) 2010 - 2012 MStar Semiconductor, Inc. All rights reserved.
5 // All software, firmware and related documentation herein ("MStar Software") are
6 // intellectual property of MStar Semiconductor, Inc. ("MStar") and protected by
7 // law, including, but not limited to, copyright law and international treaties.
8 // Any use, modification, reproduction, retransmission, or republication of all
9 // or part of MStar Software is expressly prohibited, unless prior written
10 // permission has been granted by MStar.
11 //
12 // By accessing, browsing and/or using MStar Software, you acknowledge that you
13 // have read, understood, and agree, to be bound by below terms ("Terms") and to
14 // comply with all applicable laws and regulations:
15 //
16 // 1. MStar shall retain any and all right, ownership and interest to MStar
17 // Software and any modification/derivatives thereof.
18 // No right, ownership, or interest to MStar Software and any
19 // modification/derivatives thereof is transferred to you under Terms.
20 //
21 // 2. You understand that MStar Software might include, incorporate or be
22 // supplied together with third party`s software and the use of MStar
23 // Software may require additional licenses from third parties.
24 // Therefore, you hereby agree it is your sole responsibility to separately
25 // obtain any and all third party right and license necessary for your use of
26 // such third party`s software.
27 //
28 // 3. MStar Software and any modification/derivatives thereof shall be deemed as
29 // MStar`s confidential information and you agree to keep MStar`s
30 // confidential information in strictest confidence and not disclose to any
31 // third party.
32 //
33 // 4. MStar Software is provided on an "AS IS" basis without warranties of any
34 // kind. Any warranties are hereby expressly disclaimed by MStar, including
35 // without limitation, any warranties of merchantability, non-infringement of
36 // intellectual property rights, fitness for a particular purpose, error free
37 // and in conformity with any international standard. You agree to waive any
38 // claim against MStar for any loss, damage, cost or expense that you may
39 // incur related to your use of MStar Software.
40 // In no event shall MStar be liable for any direct, indirect, incidental or
41 // consequential damages, including without limitation, lost of profit or
42 // revenues, lost or damage of data, and unauthorized system use.
43 // You agree that this Section 4 shall still apply without being affected
44 // even if MStar Software has been modified by MStar in accordance with your
45 // request or instruction for your use, except otherwise agreed by both
46 // parties in writing.
47 //
48 // 5. If requested, MStar may from time to time provide technical supports or
49 // services in relation with MStar Software to you for your use of
50 // MStar Software in conjunction with your or your customer`s product
51 // ("Services").
52 // You understand and agree that, except otherwise agreed by both parties in
53 // writing, Services are provided on an "AS IS" basis and the warranty
54 // disclaimer set forth in Section 4 above shall apply.
55 //
56 // 6. Nothing contained herein shall be construed as by implication, estoppels
57 // or otherwise:
58 // (a) conferring any license or right to use MStar name, trademark, service
59 // mark, symbol or any other identification;
60 // (b) obligating MStar or any of its affiliates to furnish any person,
61 // including without limitation, you and your customers, any assistance
62 // of any kind whatsoever, or any information; or
63 // (c) conferring any license or right under any intellectual property right.
64 //
65 // 7. These terms shall be governed by and construed in accordance with the laws
66 // of Taiwan, R.O.C., excluding its conflict of law rules.
67 // Any and all dispute arising out hereof or related hereto shall be finally
68 // settled by arbitration referred to the Chinese Arbitration Association,
69 // Taipei in accordance with the ROC Arbitration Law and the Arbitration
70 // Rules of the Association by three (3) arbitrators appointed in accordance
71 // with the said Rules.
72 // The place of arbitration shall be in Taipei, Taiwan and the language shall
73 // be English.
74 // The arbitration award shall be final and binding to both parties.
75 //
76 //******************************************************************************
77 //<MStar Software>
78 /******************************************************************************
79 * "Gif-Lib" - Yet another gif library. *
80 * *
81 * Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990 *
82 *******************************************************************************
83 * The kernel of the GIF Decoding process can be found here. *
84 *******************************************************************************
85 * History: *
86 * 16 Jun 89 - Version 1.0 by Gershon Elber. *
87 * 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
88 ******************************************************************************/
89 #ifdef MSOS_TYPE_LINUX_KERNEL
90 #include <linux/string.h>
91 #include <linux/module.h>
92 #include <linux/kernel.h>
93 #include <linux/time.h>
94 #else
95 #include <string.h>
96 #include <stdio.h>
97 #include <stdlib.h>
98 #endif
99 #include "MsCommon.h"
100 #include "gif_lib.h"
101 #include "gif_lib_private.h"
102 #include "gpd_reg.h"
103 #include "drvgpd.h"
104 #include "mdrvgpd.h"
105 #include "MsOS.h"
106
107
108
109 #define READ(_gif,_buf,_len) \
110 (((GifFilePrivateType*)_gif->Private)->Read ? \
111 ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \
112 read_byte(_gif,_buf,_len))
113
114
115
116 static MS_U32 DGifGetWord(GifFileType *GifFile, MS_U32 *Word);
117 //static MS_U32 DGifSetupDecompress(GifFileType *GifFile);
118
119 #ifdef SW_DEC
120 static MS_U32 DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
121 MS_U32 LineLen);
122 static MS_U32 DGifGetPrefixChar(MS_U32 *Prefix, MS_U32 Code, MS_U32 ClearCode);
123 static MS_U32 DGifDecompressInput(GifFileType *GifFile, MS_U32 *Code);
124 static MS_U32 DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
125 GifByteType *NextByte);
126 #endif
127 //----------------------------------------------------------------------------------
128 // Local Variable
129 //----------------------------------------------------------------------------------
130
131 static GifFileType g_GifFile;
132 static GifFilePrivateType g_Private;
133 static ColorMapObject CMObject[20];
134 static ColorMapObject LoObject;
135 static GifColorType ColorTyp[20];
136
137 //static struct SavedImage g_SavedImages[20];
138 static MS_U32 obj_idx = 0;
139 static GifFileType *GifFile = &g_GifFile;
140 static MS_U32 FileHandle = 0;
141 static gpd_roi_info frame_roi;
142 static MS_U32 GIFmode = NO_SUPPORT_MGIF;
143
MstDGifGetDuration(void)144 MS_U32 MstDGifGetDuration(void)
145 {
146 return GifFile->GraphicCtrl.time;
147 }
148
MstDGifSetMode(MS_U32 mode)149 void MstDGifSetMode (MS_U32 mode)
150 {
151 GIFmode = mode;
152 }
153
154
read_byte(GifFileType * gif,GifByteType * buf,MS_U32 len)155 MS_U32 read_byte(GifFileType* gif,GifByteType* buf,MS_U32 len)
156 {
157 MS_U32 i=0,cnt=len;
158 MS_U16 tmp;
159
160 while (cnt>=2)
161 {
162 //tmp = show_bits(16);
163 //console_printf("0show bit=%x\n",tmp);
164 tmp = read_bits(16);
165 #if 1
166 buf[i] = (MS_U8)(tmp&0xff);
167 buf[i+1] = (MS_U8)(tmp>>8);
168 #else
169 memcpy((void*)(buf+i),(void*)&tmp,2);
170 #endif
171 i+=2;
172 cnt-=2;
173 }
174 if(cnt>0)
175 {
176 //tmp = show_bits(8);
177 //console_printf("1show bit=%x\n",tmp);
178 buf[i] = (GifByteType)read_bits(8);
179 }
180 gif->UserData+=len;
181 return len;
182 }
183
READ_ram(GifFileType * gif,GifByteType * buf,MS_U32 len)184 MS_U32 READ_ram(GifFileType* gif,GifByteType* buf,MS_U32 len)
185 {
186 #if 1
187 MS_U32 u32i;
188 for(u32i=0; u32i<len; u32i++)
189 {
190 buf[u32i] = *((MS_U8*)gif->UserData +u32i);
191 }
192 #else
193 memcpy((void*)buf,(void*)(gif->UserData),len);
194 #endif
195 gif->UserData+=len;
196 return len;
197 }
198
rgb2yuv(MS_U8 r_in,MS_U8 g_in,MS_U8 b_in,MS_U8 * y_out_ptr,MS_U8 * cb_out_ptr,MS_U8 * cr_out_ptr)199 void rgb2yuv(MS_U8 r_in, MS_U8 g_in, MS_U8 b_in,
200 MS_U8 *y_out_ptr, MS_U8 *cb_out_ptr, MS_U8 *cr_out_ptr)
201 {
202 MS_U32 y_term_r;
203 MS_U32 y_term_g;
204 MS_U32 y_term_b;
205
206 MS_U32 cb_term_r;
207 MS_U32 cb_term_g;
208 MS_U32 cb_term_b;
209
210 MS_U32 cr_term_r;
211 MS_U32 cr_term_g;
212 MS_U32 cr_term_b;
213
214 MS_U32 y_term_r_g_b;
215 MS_U32 y_out_temp;
216
217 MS_U32 cb_term_r_g;
218 MS_U32 cb_term_b_e;
219 MS_U32 cb_out_temp;
220
221 MS_U32 cr_term_g_b;
222 MS_U32 cr_term_r_e;
223 MS_U32 cr_out_temp;
224
225
226 y_term_r = r_in * 263;
227 y_term_g = g_in * 129;
228 y_term_b = b_in * 25;
229 y_term_r_g_b = (y_term_r >> 2) + y_term_g + y_term_b;
230 y_out_temp = (y_term_r_g_b >> 7) + 33;
231 *y_out_ptr = (y_out_temp >> 1) & 0xFF;
232
233 cb_term_r = r_in * 19;
234 cb_term_g = g_in * 37;
235 cb_term_b = b_in * 7;
236 cb_term_r_g = cb_term_r + cb_term_g;
237 cb_term_b_e = cb_term_b + 2056;
238 cb_out_temp = (cb_term_b_e << 3) - cb_term_r_g;
239 *cb_out_ptr = (cb_out_temp >> 7) & 0xFF;
240
241 cr_term_r = r_in * 7;
242 cr_term_g = g_in * 47;
243 cr_term_b = b_in * 9;
244 cr_term_g_b = cr_term_g + cr_term_b;
245 cr_term_r_e = cr_term_r + 2056;
246 cr_out_temp = (cr_term_r_e << 3) - cr_term_g_b;
247 *cr_out_ptr = (cr_out_temp >> 7) & 0xFF;
248 }
249
250
251
FillBkColor(GifFileType * GifFile,GifByteType * framebuff,MS_U32 ocolor,MS_U32 width,MS_U32 height,MS_U32 pitch)252 void FillBkColor(GifFileType *GifFile, GifByteType* framebuff, MS_U32 ocolor,
253 MS_U32 width, MS_U32 height, MS_U32 pitch)
254 {
255 GifByteType red = 0;
256 GifByteType green = 0;
257 GifByteType blue = 0;
258 GifByteType alpha = 0xFF;
259 GifByteType y, cb, cr;
260 MS_U32 u32color;
261 MS_U16 u16color;
262 MS_U8 u8color;
263 MS_U8 colorbuff[4];
264 MS_U32 i, pixelbytes;
265
266 if (GifFile->SColorMap && GifFile->SBackGroundColor < GifFile->SColorMap->ColorCount)
267 {
268 GifColorType *palette = GifFile->SColorMap->Colors;
269 red = palette[GifFile->SBackGroundColor].Red;
270 green = palette[GifFile->SBackGroundColor].Green;
271 blue = palette[GifFile->SBackGroundColor].Blue;
272 }
273
274
275 switch (ocolor)
276 {
277 case ARGB8888:
278 u32color = (alpha << 24) | (red << 16) | (green << 8) | (blue);
279 memcpy(colorbuff, &u32color, 4);
280 pixelbytes = 4;
281 break;
282 case RGB565:
283 u16color = ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | ((blue & 0xF8) >> 3);
284 memcpy(colorbuff, &u16color, 2);
285 pixelbytes = 2;
286 break;
287 case YUV422:
288
289 case YVYU422:
290 rgb2yuv(red, green, blue, &y, &cb, &cr);
291 u32color = (cr << 24) | (y << 16) | (cb << 8) | (y);
292 memcpy(colorbuff, &u32color, 4);
293 pixelbytes = 2;
294 break;
295 case GRAY_ALPHA:
296 rgb2yuv(red, green, blue, &y, &cb, &cr);
297 u16color = (alpha << 8) | (y);
298 memcpy(colorbuff, &u16color, 2);
299 pixelbytes = 2;
300 break;
301 case GRAY:
302 rgb2yuv(red, green, blue, &y, &cb, &cr);
303 u8color = y;
304 memcpy(colorbuff, &u8color, 1);
305 pixelbytes = 1;
306 break;
307 default:
308 return;
309 }
310
311 if(ocolor == YUV422)
312 {
313 for (i = 0; i < width * pixelbytes; i += pixelbytes)
314 {
315 if(i % 4)
316 memcpy(framebuff + i, colorbuff + 2, pixelbytes);
317 else
318 memcpy(framebuff + i, colorbuff, pixelbytes);
319
320 }
321
322 }
323 else if(ocolor == YVYU422)
324 {
325 for (i = 0; i < width * pixelbytes; i += pixelbytes)
326 {
327 if(i % 4)
328 memcpy(framebuff + i, colorbuff, pixelbytes);
329 else
330 memcpy(framebuff + i, colorbuff + 2, pixelbytes);
331
332 }
333
334 }
335 else
336 {
337 for (i = 0; i < width * pixelbytes; i += pixelbytes)
338 memcpy(framebuff + i, colorbuff, pixelbytes);
339 }
340
341
342 for (i = 1; i < height; i++)
343 memcpy(framebuff + pitch * i, framebuff, width * pixelbytes);
344 }
345
GetFrameROI(GifFileType * GifFile,gpd_roi_info image_roi)346 gpd_roi_info GetFrameROI(GifFileType *GifFile, gpd_roi_info image_roi)
347 {
348 MS_U32 left = GifFile->Image.Left;
349 MS_U32 right = GifFile->Image.Left + GifFile->Image.Width;
350 MS_U32 top = GifFile->Image.Top;
351 MS_U32 bottom = GifFile->Image.Top + GifFile->Image.Height;
352 gpd_roi_info frame_roi;
353
354 if (left < image_roi.hstart)
355 left = image_roi.hstart;
356 if (left > image_roi.hstart + image_roi.width)
357 left = image_roi.hstart + image_roi.width;
358
359 if (right < image_roi.hstart)
360 right = image_roi.hstart;
361 if (right > image_roi.hstart + image_roi.width)
362 right = image_roi.hstart + image_roi.width;
363
364 if (top < image_roi.vstart)
365 top = image_roi.vstart;
366 if (top > image_roi.vstart + image_roi.height)
367 top = image_roi.vstart + image_roi.height;
368
369 if (bottom < image_roi.vstart)
370 bottom = image_roi.vstart;
371 if (bottom > image_roi.vstart + image_roi.height)
372 bottom = image_roi.vstart + image_roi.height;
373
374 frame_roi.hstart = left - GifFile->Image.Left;
375 frame_roi.vstart = top - GifFile->Image.Top;
376 frame_roi.width = right - left;
377 frame_roi.height = bottom - top;
378
379 //console_printf("image roi: %d, %d, %d, %d\n", image_roi.hstart, image_roi.vstart, image_roi.width, image_roi.height);
380 console_printf("frame roi: %td, %td, %td, %td\n", (ptrdiff_t)frame_roi.hstart, (ptrdiff_t)frame_roi.vstart, (ptrdiff_t)frame_roi.width, (ptrdiff_t)frame_roi.height);
381 //console_printf("frame area: %d, %d, %d, %d\n", GifFile->Image.Left, GifFile->Image.Top, GifFile->Image.Width, GifFile->Image.Height);
382
383 return frame_roi;
384 }
385
386 /******************************************************************************
387 * Open a new gif file for read, given by its name. *
388 * Returns GifFileType pointer dynamically allocated which serves as the gif *
389 * info record. _MstGifError is cleared if succesfull. *
390 ******************************************************************************/
MstDGifProcess(void * ptr,MS_U32 ocolor_typ,MS_U32 mode,void * roi)391 GifFileType *MstDGifProcess(void *ptr, MS_U32 ocolor_typ, MS_U32 mode, void *roi)
392 {
393 gpd_addr_info *buf_addr = (gpd_addr_info *)ptr;
394 gpd_roi_info *roi_ptr = (gpd_roi_info *)roi;
395 gpd_roi_info image_roi = {0};
396 //gpd_roi_info frame_roi;
397 //GifFileType *GifFile;
398 //MS_U32 FileHandle = 0;
399 GifRecordType RecordType;
400 GifByteType *Extension;
401 MS_U32 vdata, image_pitch, frame_pitch, pixelbytes;
402 MS_VIRT FrameBuffAddr, TempBuffOffset, StreamBuffAddr;
403 MS_U32 vstart_shift = 0;
404 MS_U32 frame_cnt = 0;
405 MS_U32 frame_size = 0;
406 MS_U32 i, j, ExtCode;
407
408 MS_U32 roi_mode = 0;
409 MS_U32 dummy_pass = 0;
410 MS_U32 bstart_set = 0;
411 MS_U32 trans_idx = -1;
412
413 obj_idx = 0;
414
415 switch (ocolor_typ)
416 {
417 case ARGB8888:
418 pixelbytes = 4; break;
419 case RGB565:
420 case YUV422:
421 case YVYU422:
422 pixelbytes = 2; break;
423 case GRAY_ALPHA:
424 //pixelbytes = 2; break;
425 case GRAY:
426 //pixelbytes = 1; break;
427 default:
428 console_printf("Unsupported output color %td\n", (ptrdiff_t)ocolor_typ);
429 return NULL;
430 }
431
432 StreamBuffAddr = buf_addr->u32VA_ReadBufferAddr;
433 FrameBuffAddr = buf_addr->u32VA_WriteBufferAddr;
434 TempBuffOffset = (buf_addr->u32WriteBufferSize / 2) & ~(64-1);
435
436 //add new mode 3 as motion GIF mode
437 if(mode != 3)
438 {
439 drv_gpd_gif_en();
440 drv_gpd_Init();
441 drv_gpd_set_ocolor(ocolor_typ);
442 drv_gpd_set_default_alpha(DEFAULT_ALPHA);
443 //drv_gpd_eng_active(0x3f);
444 /*Get Screen Descriptor*/
445 GifFile = MstDGifOpenFileHandle(FileHandle, (InputFunc)READ_ram, (GifByteType*)(StreamBuffAddr));
446 console_printf("width = %td, height = %td\n", (ptrdiff_t)GifFile->SWidth, (ptrdiff_t)GifFile->SHeight);
447 }
448
449 /*Calculate image ROI and frame buffer size*/
450 if (mode == 2)
451 {
452 roi_mode = 1;
453 image_roi = *roi_ptr;
454 frame_size = ((roi_ptr->width * pixelbytes + 7) & ~7) * (roi_ptr->height + 7);
455 }
456 else if((mode == 0) || (mode == 3)) // add mode 3 motion GIF
457 {
458 roi_mode = 0;
459 image_roi.hstart = 0;
460 image_roi.vstart = 0;
461 image_roi.height = GifFile->SHeight;
462 image_roi.width = GifFile->SWidth;
463 frame_size = ((GifFile->SWidth * pixelbytes + 7) & ~7) * GifFile->SHeight;
464 }
465 image_pitch = (image_roi.width * pixelbytes + 7) >> 3;
466
467 if((drv_gpd_get_scaling_mode() & 0x1) && mode==0)
468 {
469 switch(drv_gpd_get_scaling_mode() >> 1)
470 {
471 case 0:
472 frame_size/=4;
473 break;
474 case 1:
475 frame_size/=16;
476 break;
477 case 2:
478 frame_size/=64;
479 break;
480 case 3:
481 frame_size/=256;
482 break;
483 default:
484 break;
485 }
486 }
487
488 /* Check buffer size */
489 if (frame_size > TempBuffOffset)
490 {
491 console_printf("Frame buffer is too small\n");
492 return NULL;
493 }
494
495 /*Fill background color*/
496 if((mode != 1) && (mode != 3))
497 {
498 FillBkColor(GifFile, (GifByteType*)(FrameBuffAddr), ocolor_typ,
499 image_roi.width, image_roi.height, image_pitch << 3);
500 if(MsOS_Dcache_Flush(FrameBuffAddr, buf_addr->u32WriteBufferSize))
501 {
502 console_printf("Invalidate cache\n");
503 }
504 MsOS_FlushMemory();
505 }
506 do
507 {
508 if (MstDGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
509 {
510 PrintGifError();
511 return NULL;
512 }
513
514 switch (RecordType)
515 {
516 case IMAGE_DESC_RECORD_TYPE:
517 if (MstDGifGetImageDesc(GifFile) == GIF_ERROR)
518 {
519 PrintGifError();
520 return NULL;
521 }
522
523 /*Check frame boundary*/
524 if (GifFile->Image.Left + GifFile->Image.Width > GifFile->SWidth ||
525 GifFile->Image.Top + GifFile->Image.Height > GifFile->SHeight)
526 return NULL;
527
528 /*Get info only*/
529 if (mode == 1)
530 {
531 return GifFile;
532 }
533
534 /*Calculate frame ROI*/
535 frame_roi = GetFrameROI(GifFile, image_roi);
536 dummy_pass = 0;
537 if (frame_roi.width == 0 || frame_roi.height == 0)
538 {
539 dummy_pass = 1;
540 frame_roi.hstart = 0;
541 frame_roi.vstart = 0;
542 frame_roi.width = 1;
543 frame_roi.height = 1;
544 }
545
546 /*Check ROI alignment for interlace frame*/
547 vstart_shift = 0;
548 if (GifFile->Image.Interlace)
549 {
550 vstart_shift = frame_roi.vstart & 7UL;
551 frame_roi.vstart -= vstart_shift;
552 frame_roi.height += vstart_shift;
553 }
554
555 /*Set ROI*/
556 drv_gpd_set_ROI(roi_mode, frame_roi.hstart, frame_roi.vstart, frame_roi.width, frame_roi.height);
557
558 /*Set pitch*/
559 frame_pitch = (frame_roi.width * pixelbytes + 7) >> 3;
560 drv_gpd_set_pitch(frame_pitch);
561
562 /*Set istart*/
563 vdata = buf_addr->u32PA_WriteBufferAddr + TempBuffOffset;
564 drv_gpd_set_istart(vdata);
565
566 /*Fill background color when disposal method is 2*/
567 if (GifFile->GraphicCtrl.enable && GifFile->GraphicCtrl.disposal_method == 2)
568 {
569 FillBkColor(GifFile, (GifByteType*)(FrameBuffAddr), ocolor_typ,
570 image_roi.width, image_roi.height, image_pitch << 3);
571 }
572
573 /*Set iwidth and iheight*/
574 drv_gpd_set_iwidth_height(GifFile->Image.Width, GifFile->Image.Height);
575
576 /*Set interlace*/
577 drv_gpd_set_interlace(GifFile->Image.Interlace);
578
579 /*Set bstart and bend*/
580 if ((!bstart_set) && (mode != 3))
581 {
582 bstart_set = 1;
583 ((GifFilePrivateType*)(GifFile->Private))->Read = NULL;
584 vdata = GifFile->UserData - buf_addr->u32VA_ReadBufferAddr;
585 drv_gpd_set_bstart_end((vdata + buf_addr->u32PA_ReadBufferAddr), 0);
586
587 /*Flush fifo data*/
588 for (i = 0; i < 4; i++)
589 read_bits(16);
590 }
591
592 console_printf("flush done\n");
593
594 /*Set color map*/
595 if (GifFile->GraphicCtrl.enable && GifFile->GraphicCtrl.trans_bit)
596 trans_idx = GifFile->GraphicCtrl.trans_idx;
597 else
598 trans_idx = -1;
599 drv_gpd_set_gif_local_map_size(0);
600 if (GifFile->Image.ColorMap)
601 drv_gpd_write_cmap(GifFile->Image.ColorMap->ColorCount, 0, trans_idx);
602 else
603 drv_gpd_write_cmap(GifFile->SColorMap->ColorCount, (MS_U8 *)GifFile->SColorMap->Colors, trans_idx);
604
605 /*Start decoding*/
606 drv_gpd_set_gif_go();
607
608 console_printf("gif go\n");
609
610 while (!drv_gpd_gif_done())
611 {
612 if (drv_gpd_ofifo_done())
613 {
614 console_printf("Ofifo done but gif done.\n");
615 }
616 }
617 #if 0
618 drv_gpd_script_wait_gif_done(1);
619 {
620 SCRIPT_DUMP("#Dump frame %d\n", frame_cnt);
621 SCRIPT_DUMP("setchannel XD2MIU-32\n");
622 SCRIPT_DUMP("save (filename).frame%d.%dx%d.argb8888 0x%X 0x%X\n",
623 frame_cnt, frame_pitch * 2, frame_roi.height,
624 FrameBuffAddr + TempBuffOffset, frame_roi.height * frame_pitch * 8);
625 SCRIPT_DUMP("setchannel TOP_RIU-16b\n\n");
626 }
627 #endif
628 frame_cnt++;
629 console_printf("gif done\n");
630
631 if (MsOS_Dcache_Flush(FrameBuffAddr, buf_addr->u32WriteBufferSize))
632 {
633 console_printf("Invalidate cache\n");
634 }
635 MsOS_FlushMemory();
636
637 /*Blending*/
638 if (!dummy_pass)
639 {
640 console_printf("blending...\n");
641 GifByteType *image_ptr = (GifByteType *)(FrameBuffAddr);
642 GifByteType *frame_ptr = (GifByteType *)((FrameBuffAddr + TempBuffOffset));
643
644 #if 0
645 console_printf("image_ptr = %x\n", image_ptr);
646 console_printf("frame_roi.vstart = %d\n", frame_roi.vstart);
647 console_printf("GifFile->Image.Top = %d\n", GifFile->Image.Top);
648 console_printf("roi_ptr->vstart = %d\n", roi_ptr->vstart);
649 console_printf("vstart_shift = %d\n", vstart_shift);
650 console_printf("image_pitch = %d\n", image_pitch);
651 console_printf("frame_roi.hstart = %d\n", frame_roi.hstart);
652 console_printf("GifFile->Image.Left = %d\n", GifFile->Image.Left);
653 console_printf("roi_ptr->hstart = %d\n", roi_ptr->hstart);
654 console_printf("pixelbytes; = %d\n", pixelbytes);
655 #endif
656
657 image_ptr += (frame_roi.vstart + GifFile->Image.Top - roi_ptr->vstart + vstart_shift) * (image_pitch << 3) +
658 (frame_roi.hstart + GifFile->Image.Left - roi_ptr->hstart) * pixelbytes;
659
660 //console_printf("image_ptr = %x\n", image_ptr);
661 frame_ptr += vstart_shift * (frame_pitch << 3);
662 //console_printf("frame_ptr = %x\n", frame_ptr);
663 //console_printf("frame_roi_height = %d vstart_shift = %d\n", frame_roi.height, vstart_shift);
664 //MsOS_ReadMemory();
665 //console_printf("Read Memory!!\n");
666
667 for (j = 0; j < frame_roi.height - vstart_shift; j++)
668 {
669 /*Only support ARGB8888*/
670
671 if(ocolor_typ == ARGB8888)
672 {
673 for (i = 0; i < frame_roi.width * 4; i += 4)
674 {
675 if (frame_ptr[i+3])
676 {
677 image_ptr[i+0] = frame_ptr[i+0];
678 image_ptr[i+1] = frame_ptr[i+1];
679 image_ptr[i+2] = frame_ptr[i+2];
680 image_ptr[i+3] = 0xFF;
681 }
682 }
683 }
684 else if(ocolor_typ == GRAY)
685 {
686 for (i = 0; i < frame_roi.width * 1; i += 1)
687 image_ptr[i+0] = frame_ptr[i+0];
688 }
689 else if(ocolor_typ == GRAY_ALPHA)
690 {
691 for (i = 0; i < frame_roi.width * 2; i += 2)
692 {
693 if (frame_ptr[i+1])
694 {
695 image_ptr[i+0] = frame_ptr[i+0];
696 image_ptr[i+1] = 0xFF;
697 }
698 }
699 }
700 else
701 {
702 for (i = 0; i < frame_roi.width * 2; i += 2)
703 {
704 //console_printf("data:%x\n", frame_ptr[i+1]);
705 //console_printf("data:%x\n", frame_ptr[i+0]);
706
707 image_ptr[i+0] = frame_ptr[i+0];
708 image_ptr[i+1] = frame_ptr[i+1];
709
710 //console_printf("data 0:%x\n", image_ptr[i+0]);
711 //image_ptr[i+0] = 0x77;
712 //console_printf("data 1:%x\n", image_ptr[i+0]);
713 //image_ptr[i+0] = frame_ptr[i+0];
714 //console_printf("data 2:%x\n", image_ptr[i+0]);
715 }
716 }
717 image_ptr += image_pitch << 3;
718 frame_ptr += frame_pitch << 3;
719 }
720 }
721
722 if(MsOS_Dcache_Flush(FrameBuffAddr, buf_addr->u32WriteBufferSize))
723 {
724 console_printf("Invalidate cache\n");
725 }
726 MsOS_FlushMemory();
727
728 GifFile->GraphicCtrl.enable = 0;
729
730 if(GifFile->isMGIF && GIFmode)
731 {
732 GifFile->GifState = STATE_MGIF_WAIT_BUFFFER;
733 return GifFile;
734 }
735 break;
736
737 case EXTENSION_RECORD_TYPE:
738 /* Skip any extension blocks in file: */
739 if (MstDGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR)
740 {
741 PrintGifError();
742 return NULL;
743 }
744 while (Extension != NULL)
745 {
746 if (MstDGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR)
747 {
748 PrintGifError();
749 return NULL;
750 }
751 }
752 break;
753
754 case TERMINATE_RECORD_TYPE:
755 break;
756
757 default:
758 /* Should be traps by MstDGifGetRecordType. */
759 break;
760 }
761 } while (RecordType != TERMINATE_RECORD_TYPE);
762
763
764 GifFile->GifState = STATE_MGIF_TERMINATE;
765 return GifFile;
766 }
767
768 /******************************************************************************
769 * Update a new gif file, given its file handle. *
770 * Returns GifFileType pointer dynamically allocated which serves as the gif *
771 * info record. _MstGifError is cleared if succesfull. *
772 ******************************************************************************/
MstDGifOpenFileHandle(MS_U32 FileHandle,InputFunc read_fun,GifByteType * bitstream)773 GifFileType *MstDGifOpenFileHandle(MS_U32 FileHandle, InputFunc read_fun, GifByteType* bitstream)
774 {
775 GifByteType Buf[GIF_STAMP_LEN+1];
776 GifFileType *GifFile;
777 GifFilePrivateType *Private;
778
779 #if 1
780 GifFile = (GifFileType *)&g_GifFile;
781 memset(GifFile, 0, sizeof(GifFileType));
782 Private = (GifFilePrivateType *)&g_Private;
783 #else
784 if ((GifFile = (GifFileType *)&g_GifFile) == NULL) {
785 _MstGifError = D_GIF_ERR_NOT_ENOUGH_MEM;
786 return NULL;
787 }
788 memset(GifFile, 0, sizeof(GifFileType));
789
790 if ((Private = (GifFilePrivateType *)&g_Private) == NULL)
791 {
792 _MstGifError = D_GIF_ERR_NOT_ENOUGH_MEM;
793 return NULL;
794 }
795 #endif
796
797 GifFile->Private = (VoidPtr) Private;
798 Private->FileHandle = FileHandle;
799 Private->FileState = FILE_STATE_READ;
800 Private->Read = read_fun;//0; /* don't use alternate input method (TVT) */
801 GifFile->UserData = (MS_VIRT)(bitstream);//0; /* TVT */
802 /* Lets see if this is a GIF file: */
803
804 //if (read_byte(GifFile,Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
805 if (READ(GifFile,Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
806 _MstGifError = D_GIF_ERR_READ_FAILED;
807 return NULL;
808 }
809
810
811 /* The GIF Version number is ignored at this time. Maybe we should do */
812 /* something more useful with it. */
813 Buf[GIF_STAMP_LEN] = 0;
814 if (strncmp(GIF_STAMP, (void*)Buf, GIF_VERSION_POS) != 0)
815 {
816 _MstGifError = D_GIF_ERR_NOT_GIF_FILE;
817 return NULL;
818 }
819 if (MstDGifGetScreenDesc(GifFile) == GIF_ERROR) {
820 return NULL;
821 }
822
823 _MstGifError = 0;
824
825 return GifFile;
826 }
827 /******************************************************************************
828 * Miscellaneous utility functions *
829 ******************************************************************************/
830
MstBitSize(MS_U32 n)831 MS_U32 MstBitSize(MS_U32 n)
832 /* return smallest bitfield size n will fit in */
833 {
834 MS_U32 i;
835
836 for (i = 1; i <= 8; i++)
837 if ((1 << i) >= n)
838 break;
839 return(i);
840 }
841
MstMakeMapObject(MS_U32 ColorCount,const GifColorType * ColorMap)842 ColorMapObject *MstMakeMapObject(MS_U32 ColorCount, const GifColorType *ColorMap)
843 /*
844 * Allocate a color map of given size; initialize with contents of
845 * ColorMap if that pointer is non-NULL.
846 */
847 {
848 ColorMapObject *Object;
849
850 if (ColorCount != (1 << MstBitSize(ColorCount)))
851 return((ColorMapObject *)NULL);
852 //console_printf("MstMakeMapObject=%d\n",ColorCount);
853 Object = &CMObject[obj_idx];//(ColorMapObject *)malloc(sizeof(ColorMapObject));
854 //Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
855
856 //if (Object == (ColorMapObject *)NULL)
857 // return((ColorMapObject *)NULL);
858 //console_printf("Object=%x\n",Object);
859
860 Object->Colors = &ColorTyp[obj_idx];//(GifColorType *)calloc(ColorCount, sizeof(GifColorType));
861 //Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
862 //console_printf("Object->Colors=%x\n",Object->Colors);
863 if (Object->Colors == (GifColorType *)NULL)
864 return((ColorMapObject *)NULL);
865 Object->ColorCount = ColorCount;
866 Object->BitsPerPixel = MstBitSize(ColorCount);
867
868 if (ColorMap)
869 memcpy((char *)Object->Colors,
870 (char *)ColorMap, ColorCount * sizeof(GifColorType));
871 obj_idx++;
872 return(Object);
873 }
MstFreeMapObject(ColorMapObject * Object)874 void MstFreeMapObject(ColorMapObject *Object)
875 /*
876 * Free a color map object
877 */
878 {
879 obj_idx--;
880 //free(Object->Colors);
881 //free(Object);
882 }
883
884 /******************************************************************************
885 * This routine should be called before any other DGif calls. Note that *
886 * this routine is called automatically from DGif file open routines. *
887 ******************************************************************************/
MstDGifGetScreenDesc(GifFileType * GifFile)888 MS_U32 MstDGifGetScreenDesc(GifFileType *GifFile)
889 {
890 MS_U32 BitsPerPixel;
891 GifByteType Buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
892
893 /* Put the screen descriptor into the file: */
894 if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
895 DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
896 return GIF_ERROR;
897
898 if (READ( GifFile, Buf, 3) != 3) {
899 _MstGifError = D_GIF_ERR_READ_FAILED;
900 return GIF_ERROR;
901 }
902
903 GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
904 BitsPerPixel = (Buf[0] & 0x07) + 1;
905 GifFile->SBackGroundColor = Buf[1];
906 GifFile->AspectRatio = Buf[2];
907 GifFile->SColorMap = NULL;
908
909 if (Buf[0] & 0x80)
910 {/* Do we have global color map? */
911
912 GifFile->SColorMap = MstMakeMapObject(1 << BitsPerPixel, NULL);
913 if(GifFile->SColorMap)
914 {
915 GifFile->SColorMap->Colors = (GifColorType *)(GifFile->UserData);
916 GifFile->UserData += 3 * GifFile->SColorMap->ColorCount;
917 }
918 }
919
920 return GIF_OK;
921 }
922 /******************************************************************************
923 * Get 2 bytes (word) from the given file: *
924 ******************************************************************************/
DGifGetWord(GifFileType * GifFile,MS_U32 * Word)925 static MS_U32 DGifGetWord(GifFileType *GifFile, MS_U32 *Word)
926 {
927 MS_U8 c[2] = {0, 0};
928
929 if (READ(GifFile,c, 2) != 2) {
930 _MstGifError = D_GIF_ERR_READ_FAILED;
931 return GIF_ERROR;
932 }
933
934 *Word = (((MS_U32) c[1]) << 8) + c[0];
935 return GIF_OK;
936 }
937
938 /******************************************************************************
939 * This routine should be called before any attemp to read an image. *
940 ******************************************************************************/
MstDGifGetRecordType(GifFileType * GifFile,GifRecordType * Type)941 MS_U32 MstDGifGetRecordType(GifFileType *GifFile, GifRecordType *Type)
942 {
943 GifByteType Buf = 0;
944 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
945
946 if (!IS_READABLE(Private)) {
947 /* This file was NOT open for reading: */
948 _MstGifError = D_GIF_ERR_NOT_READABLE;
949 return GIF_ERROR;
950 }
951
952 if (READ( GifFile, &Buf, 1) != 1) {
953 _MstGifError = D_GIF_ERR_READ_FAILED;
954 return GIF_ERROR;
955 }
956
957 switch (Buf) {
958 case ',':
959 *Type = IMAGE_DESC_RECORD_TYPE;
960 break;
961 case '!':
962 *Type = EXTENSION_RECORD_TYPE;
963 break;
964 case ';':
965 *Type = TERMINATE_RECORD_TYPE;
966 break;
967 default:
968 *Type = UNDEFINED_RECORD_TYPE;
969 _MstGifError = D_GIF_ERR_WRONG_RECORD;
970 return GIF_ERROR;
971 }
972
973 return GIF_OK;
974 }
975
976 /******************************************************************************
977 * This routine should be called before any attemp to read an image. *
978 * Note it is assumed the Image desc. header (',') has been read. *
979 ******************************************************************************/
MstDGifGetImageDesc(GifFileType * GifFile)980 MS_U32 MstDGifGetImageDesc(GifFileType *GifFile)
981 {
982 MS_U32 BitsPerPixel;
983 GifByteType Buf[3] = {0, 0, 0};
984 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
985
986 if (!IS_READABLE(Private))
987 {
988 /* This file was NOT open for reading: */
989 _MstGifError = D_GIF_ERR_NOT_READABLE;
990 return GIF_ERROR;
991 }
992
993 if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
994 DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
995 DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
996 DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
997 return GIF_ERROR;
998
999 if (READ(GifFile,Buf, 1) != 1)
1000 {
1001 _MstGifError = D_GIF_ERR_READ_FAILED;
1002 return GIF_ERROR;
1003 }
1004
1005 BitsPerPixel = (Buf[0] & 0x07) + 1;
1006 GifFile->Image.Interlace = (Buf[0] & 0x40)>>6;
1007
1008 if (Buf[0] & 0x80)
1009 {
1010 /* Does this image have local color map? */
1011 GifFile->Image.ColorMap = &LoObject;
1012 GifFile->Image.ColorMap->ColorCount = (1 << BitsPerPixel);
1013 GifFile->Image.ColorMap->BitsPerPixel = BitsPerPixel;
1014 }
1015 else
1016 {
1017 GifFile->Image.ColorMap = NULL;
1018 }
1019 return GIF_OK;
1020 }
1021 /******************************************************************************
1022 * Get an extension block (see GIF manual) from gif file. This routine only *
1023 * returns the first data block, and MstDGifGetExtensionNext shouldbe called *
1024 * after this one until NULL extension is returned. *
1025 * The Extension should NOT be freed by the user (not dynamically allocated).*
1026 * Note it is assumed the Extension desc. header ('!') has been read. *
1027 ******************************************************************************/
MstDGifGetExtension(GifFileType * GifFile,MS_U32 * ExtCode,GifByteType ** Extension)1028 MS_U32 MstDGifGetExtension(GifFileType *GifFile, MS_U32 *ExtCode,
1029 GifByteType **Extension)
1030 {
1031 GifByteType Buf = 0;
1032 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1033 MS_U32 ret;
1034
1035 if (!IS_READABLE(Private))
1036 {
1037 /* This file was NOT open for reading: */
1038 _MstGifError = D_GIF_ERR_NOT_READABLE;
1039 return GIF_ERROR;
1040 }
1041
1042 if (READ(GifFile,&Buf, 1) != 1)
1043 {
1044 _MstGifError = D_GIF_ERR_READ_FAILED;
1045 return GIF_ERROR;
1046 }
1047 *ExtCode = Buf;
1048
1049 ret = MstDGifGetExtensionNext(GifFile, Extension);
1050
1051 if (ret == GIF_OK && Buf == 0xF9)
1052 {
1053 GifFile->GraphicCtrl.enable = 1;
1054 GifFile->GraphicCtrl.disposal_method = ((*Extension)[1] >> 2) & 0x7;
1055 GifFile->GraphicCtrl.trans_bit = ((*Extension)[1]) & 0x1;
1056 GifFile->GraphicCtrl.time = (*Extension)[2] + ((*Extension)[3] << 8);
1057 GifFile->GraphicCtrl.trans_idx = (*Extension)[4];
1058 }
1059 else if(ret == GIF_OK && Buf == 0xFF) // for MGIF testing
1060 {
1061 #if 0
1062 MS_U32 i = 0;
1063 //dump extension block data
1064 console_printf("##################EXTENSION BLOCK######################################\n");
1065 for(i = 1;i < ((*Extension)[0]-1);i++)
1066 {
1067 console_printf("%x,",(*Extension)[i]);
1068 }
1069 console_printf("\n#######################################################################\n");
1070 #endif
1071 GifFile->isMGIF = 1;
1072 }
1073
1074 return ret;
1075 }
1076
1077 /******************************************************************************
1078 * Get a following extension block (see GIF manual) from gif file. This *
1079 * routine should be called until NULL Extension is returned. *
1080 * The Extension should NOT be freed by the user (not dynamically allocated).*
1081 ******************************************************************************/
MstDGifGetExtensionNext(GifFileType * GifFile,GifByteType ** Extension)1082 MS_U32 MstDGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension)
1083 {
1084 GifByteType Buf = 0;
1085 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1086
1087
1088 if (READ(GifFile,&Buf, 1) != 1)
1089 {
1090 _MstGifError = D_GIF_ERR_READ_FAILED;
1091 return GIF_ERROR;
1092 }
1093 if (Buf > 0)
1094 {
1095 *Extension = Private->Buf; /* Use private unused buffer. */
1096 (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
1097 if (READ(GifFile,&((*Extension)[1]), Buf) != Buf)
1098 {
1099 _MstGifError = D_GIF_ERR_READ_FAILED;
1100 return GIF_ERROR;
1101 }
1102 }
1103 else
1104 *Extension = NULL;
1105
1106 return GIF_OK;
1107 }
1108 /******************************************************************************
1109 * Setup the LZ decompression for this image: *
1110 ******************************************************************************/
1111 #if 0
1112 static MS_U32 DGifSetupDecompress(GifFileType *GifFile)
1113 {
1114 MS_U32 i, BitsPerPixel;
1115 GifByteType CodeSize;
1116 MS_U32 *Prefix;
1117 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1118
1119 READ(GifFile,&CodeSize, 1); /* Read Code size from file. */
1120 BitsPerPixel = CodeSize;
1121
1122 Private->Buf[0] = 0; /* Input Buffer empty. */
1123 Private->BitsPerPixel = BitsPerPixel;
1124 Private->ClearCode = (1 << BitsPerPixel);
1125 Private->EOFCode = Private->ClearCode + 1;
1126 Private->RunningCode = Private->EOFCode + 1;
1127 Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
1128 Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
1129 Private->StackPtr = 0; /* No pixels on the pixel stack. */
1130 Private->LastCode = NO_SUCH_CODE;
1131 Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
1132 Private->CrntShiftDWord = 0;
1133
1134 Prefix = Private->Prefix;
1135 for (i = 0; i <= LZ_MAX_CODE; i++)
1136 Prefix[i] = NO_SUCH_CODE;
1137
1138 return GIF_OK;
1139 }
1140 #endif
1141
1142 /******************************************************************************
1143 * Get one full scanned line (Line) of length LineLen from GIF file. *
1144 ******************************************************************************/
1145 #ifdef SW_DEC
MstDGifGetLine(GifFileType * GifFile,GifPixelType * Line,MS_U32 LineLen)1146 MS_U32 MstDGifGetLine(GifFileType *GifFile, GifPixelType *Line, MS_U32 LineLen)
1147 {
1148 GifByteType *Dummy;
1149 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1150
1151 if (!IS_READABLE(Private))
1152 {
1153 /* This file was NOT open for reading: */
1154 _MstGifError = D_GIF_ERR_NOT_READABLE;
1155 return GIF_ERROR;
1156 }
1157
1158 if (!LineLen) LineLen = GifFile->Image.Width;
1159
1160 #if defined(__MSDOS__) || defined(__GNUC__)
1161 if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
1162 #else
1163 if ((Private->PixelCount -= LineLen) > 0xffff0000) {
1164 #endif /* __MSDOS__ */
1165 _MstGifError = D_GIF_ERR_DATA_TOO_BIG;
1166 return GIF_ERROR;
1167 }
1168
1169 if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
1170 if (Private->PixelCount == 0) {
1171 /* We probably would not be called any more, so lets clean */
1172 /* everything before we return: need to flush out all rest of */
1173 /* image until empty block (size 0) detected. We use GetCodeNext.*/
1174 do if (MstDGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
1175 return GIF_ERROR;
1176 while (Dummy != NULL);
1177 }
1178 return GIF_OK;
1179 }
1180 else
1181 return GIF_ERROR;
1182 }
1183
1184 /******************************************************************************
1185 * Put one pixel (Pixel) into GIF file. *
1186 ******************************************************************************/
1187 MS_U32 MstDGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
1188 {
1189 GifByteType *Dummy;
1190 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1191
1192 if (!IS_READABLE(Private)) {
1193 /* This file was NOT open for reading: */
1194 _MstGifError = D_GIF_ERR_NOT_READABLE;
1195 return GIF_ERROR;
1196 }
1197
1198 #if defined(__MSDOS__) || defined(__GNUC__)
1199 if (--Private->PixelCount > 0xffff0000UL)
1200 #else
1201 if (--Private->PixelCount > 0xffff0000)
1202 #endif /* __MSDOS__ */
1203 {
1204 _MstGifError = D_GIF_ERR_DATA_TOO_BIG;
1205 return GIF_ERROR;
1206 }
1207
1208 if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
1209 if (Private->PixelCount == 0) {
1210 /* We probably would not be called any more, so lets clean */
1211 /* everything before we return: need to flush out all rest of */
1212 /* image until empty block (size 0) detected. We use GetCodeNext.*/
1213 do if (MstDGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
1214 return GIF_ERROR;
1215 while (Dummy != NULL);
1216 }
1217 return GIF_OK;
1218 }
1219 else
1220 return GIF_ERROR;
1221 }
1222
1223
1224
1225 /******************************************************************************
1226 * Get the image code in compressed form. his routine can be called if the *
1227 * information needed to be piped out as is. Obviously this is much faster *
1228 * than decoding and encoding again. This routine should be followed by calls *
1229 * to MstDGifGetCodeNext, until NULL block is returned. *
1230 * The block should NOT be freed by the user (not dynamically allocated). *
1231 ******************************************************************************/
1232 MS_U32 MstDGifGetCode(GifFileType *GifFile, MS_U32 *CodeSize, GifByteType **CodeBlock)
1233 {
1234 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1235
1236 if (!IS_READABLE(Private)) {
1237 /* This file was NOT open for reading: */
1238 _MstGifError = D_GIF_ERR_NOT_READABLE;
1239 return GIF_ERROR;
1240 }
1241
1242 *CodeSize = Private->BitsPerPixel;
1243
1244 return MstDGifGetCodeNext(GifFile, CodeBlock);
1245 }
1246
1247 /******************************************************************************
1248 * Continue to get the image code in compressed form. This routine should be *
1249 * called until NULL block is returned. *
1250 * The block should NOT be freed by the user (not dynamically allocated). *
1251 ******************************************************************************/
1252 MS_U32 MstDGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
1253 {
1254 GifByteType Buf;
1255 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1256
1257 if (READ(GifFile,&Buf, 1) != 1) {
1258 _MstGifError = D_GIF_ERR_READ_FAILED;
1259 return GIF_ERROR;
1260 }
1261
1262 if (Buf > 0) {
1263 *CodeBlock = Private->Buf; /* Use private unused buffer. */
1264 (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
1265 if (READ(GifFile,&((*CodeBlock)[1]), Buf) != Buf) {
1266 _MstGifError = D_GIF_ERR_READ_FAILED;
1267 return GIF_ERROR;
1268 }
1269 }
1270 else {
1271 *CodeBlock = NULL;
1272 Private->Buf[0] = 0; /* Make sure the buffer is empty! */
1273 Private->PixelCount = 0; /* And local info. indicate image read. */
1274 }
1275
1276 return GIF_OK;
1277 }
1278
1279 /******************************************************************************
1280 * The LZ decompression routine: *
1281 * This version decompress the given gif file into Line of length LineLen. *
1282 * This routine can be called few times (one per scan line, for example), in *
1283 * order the complete the whole image. *
1284 ******************************************************************************/
1285 static MS_U32 DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
1286 MS_U32 LineLen)
1287 {
1288 MS_U32 i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
1289 GifByteType *Stack, *Suffix;
1290 MS_U32 *Prefix;
1291 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1292
1293 StackPtr = Private->StackPtr;
1294 Prefix = Private->Prefix;
1295 Suffix = Private->Suffix;
1296 Stack = Private->Stack;
1297 EOFCode = Private->EOFCode;
1298 ClearCode = Private->ClearCode;
1299 LastCode = Private->LastCode;
1300
1301 if (StackPtr != 0) {
1302 /* Let pop the stack off before continueing to read the gif file: */
1303 while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
1304 }
1305
1306 while (i < LineLen) { /* Decode LineLen items. */
1307 if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
1308 return GIF_ERROR;
1309 //printf("crntcode=%02x\n",CrntCode);
1310 //printf("Lastcode=%02x", LastCode);
1311 if (CrntCode == EOFCode) {
1312 /* Note however that usually we will not be here as we will stop */
1313 /* decoding as soon as we got all the pixel, or EOF code will */
1314 /* not be read at all, and MstDGifGetLine/Pixel clean everything. */
1315 if (i != LineLen - 1 || Private->PixelCount != 0) {
1316 _MstGifError = D_GIF_ERR_EOF_TOO_SOON;
1317 return GIF_ERROR;
1318 }
1319 i++;
1320 }
1321 else if (CrntCode == ClearCode) {
1322 /* We need to start over again: */
1323 for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
1324 Private->RunningCode = Private->EOFCode + 1;
1325 Private->RunningBits = Private->BitsPerPixel + 1;
1326 Private->MaxCode1 = 1 << Private->RunningBits;
1327 LastCode = Private->LastCode = NO_SUCH_CODE;
1328 }
1329 else {
1330 /* Its regular code - if in pixel range simply add it to output */
1331 /* stream, otherwise trace to codes linked list until the prefix */
1332 /* is in pixel range: */
1333 if (CrntCode < ClearCode) {
1334 /* This is simple - its pixel scalar, so add it to output: */
1335 Line[i++] = CrntCode;
1336 }
1337 else {
1338 /* Its a code to needed to be traced: trace the linked list */
1339 /* until the prefix is a pixel, while pushing the suffix */
1340 /* pixels on our stack. If we done, pop the stack in reverse */
1341 /* (thats what stack is good for!) order to output. */
1342 if (Prefix[CrntCode] == NO_SUCH_CODE) {
1343 /* Only allowed if CrntCode is exactly the running code: */
1344 /* In that case CrntCode = XXXCode, CrntCode or the */
1345 /* prefix code is last code and the suffix char is */
1346 /* exactly the prefix of last code! */
1347 if (CrntCode == Private->RunningCode - 2) {
1348 CrntPrefix = LastCode;
1349 Suffix[Private->RunningCode - 2] =
1350 Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
1351 LastCode, ClearCode);
1352 }
1353 else {
1354 _MstGifError = D_GIF_ERR_IMAGE_DEFECT;
1355 return GIF_ERROR;
1356 }
1357 }
1358 else
1359 CrntPrefix = CrntCode;
1360
1361 /* Now (if image is O.K.) we should not get an NO_SUCH_CODE */
1362 /* During the trace. As we might loop forever, in case of */
1363 /* defective image, we count the number of loops we trace */
1364 /* and stop if we got LZ_MAX_CODE. obviously we can not */
1365 /* loop more than that. */
1366 j = 0;
1367 while (j++ <= LZ_MAX_CODE &&
1368 CrntPrefix > ClearCode &&
1369 CrntPrefix <= LZ_MAX_CODE) {
1370 Stack[StackPtr++] = Suffix[CrntPrefix];
1371 CrntPrefix = Prefix[CrntPrefix];
1372 }
1373 if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
1374 _MstGifError = D_GIF_ERR_IMAGE_DEFECT;
1375 return GIF_ERROR;
1376 }
1377 /* Push the last character on stack: */
1378 Stack[StackPtr++] = CrntPrefix;
1379
1380 /* Now lets pop all the stack into output: */
1381 console_printf("----- put %d [0x%02x]\n ",StackPtr,CrntPrefix);
1382 while (StackPtr != 0 && i < LineLen)
1383 Line[i++] = Stack[--StackPtr];
1384 }
1385 if (LastCode != NO_SUCH_CODE) {
1386 Prefix[Private->RunningCode - 2] = LastCode;
1387 console_printf("add code %d prefix=%d\n", Private->RunningCode - 2,LastCode);
1388
1389 if (CrntCode == Private->RunningCode - 2) {
1390 /* Only allowed if CrntCode is exactly the running code: */
1391 /* In that case CrntCode = XXXCode, CrntCode or the */
1392 /* prefix code is last code and the suffix char is */
1393 /* exactly the prefix of last code! */
1394 Suffix[Private->RunningCode - 2] =
1395 DGifGetPrefixChar(Prefix, LastCode, ClearCode);
1396 }
1397 else {
1398 Suffix[Private->RunningCode - 2] =
1399 DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
1400 }
1401 }
1402 LastCode = CrntCode;
1403 //printf("Lastcode=%02x", LastCode);
1404 }
1405 }
1406
1407 Private->LastCode = LastCode;
1408 Private->StackPtr = StackPtr;
1409
1410 return GIF_OK;
1411 }
1412
1413 /******************************************************************************
1414 * Routine to trace the Prefixes linked list until we get a prefix which is *
1415 * not code, but a pixel value (less than ClearCode). Returns that pixel value.*
1416 * If image is defective, we might loop here forever, so we limit the loops to *
1417 * the maximum possible if image O.k. - LZ_MAX_CODE times. *
1418 ******************************************************************************/
1419 static MS_U32 DGifGetPrefixChar(MS_U32 *Prefix, MS_U32 Code, MS_U32 ClearCode)
1420 {
1421 MS_U32 i = 0;
1422
1423 while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
1424 return Code;
1425 }
1426
1427 /******************************************************************************
1428 * Interface for accessing the LZ codes directly. Set Code to the real code *
1429 * (12bits), or to -1 if EOF code is returned. *
1430 ******************************************************************************/
1431 MS_U32 MstDGifGetLZCodes(GifFileType *GifFile, MS_U32 *Code)
1432 {
1433 GifByteType *CodeBlock;
1434 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
1435
1436 if (!IS_READABLE(Private)) {
1437 /* This file was NOT open for reading: */
1438 _MstGifError = D_GIF_ERR_NOT_READABLE;
1439 return GIF_ERROR;
1440 }
1441
1442 if (DGifDecompressInput(GifFile, Code) == GIF_ERROR)
1443 return GIF_ERROR;
1444
1445 if (*Code == Private->EOFCode) {
1446 /* Skip rest of codes (hopefully only NULL terminating block): */
1447 do if (MstDGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
1448 return GIF_ERROR;
1449 while (CodeBlock != NULL);
1450
1451 *Code = -1;
1452 }
1453 else if (*Code == Private->ClearCode) {
1454 /* We need to start over again: */
1455 Private->RunningCode = Private->EOFCode + 1;
1456 Private->RunningBits = Private->BitsPerPixel + 1;
1457 Private->MaxCode1 = 1 << Private->RunningBits;
1458 }
1459
1460 return GIF_OK;
1461 }
1462
1463 /******************************************************************************
1464 * The LZ decompression input routine: *
1465 * This routine is responsable for the decompression of the bit stream from *
1466 * 8 bits (bytes) packets, into the real codes. *
1467 * Returns GIF_OK if read succesfully. *
1468 ******************************************************************************/
1469 static MS_U32 DGifDecompressInput(GifFileType *GifFile, MS_U32 *Code)
1470 {
1471 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
1472
1473 GifByteType NextByte;
1474 static MS_U32 CodeMasks[] = {
1475 0x0000, 0x0001, 0x0003, 0x0007,
1476 0x000f, 0x001f, 0x003f, 0x007f,
1477 0x00ff, 0x01ff, 0x03ff, 0x07ff,
1478 0x0fff
1479 };
1480
1481 console_printf("\n DGifDecompressInput :");
1482
1483
1484 while (Private->CrntShiftState < Private->RunningBits) {
1485 /* Needs to get more bytes from input stream for next code: */
1486 if (DGifBufferedInput(GifFile, Private->Buf, &NextByte)
1487 == GIF_ERROR) {
1488 return GIF_ERROR;
1489 }
1490
1491 console_printf(" %02x ",NextByte);
1492
1493 Private->CrntShiftDWord |=
1494 ((MS_U32) NextByte) << Private->CrntShiftState;
1495 Private->CrntShiftState += 8;
1496 }
1497 *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
1498
1499 Private->CrntShiftDWord >>= Private->RunningBits;
1500 Private->CrntShiftState -= Private->RunningBits;
1501
1502 /* If code cannt fit into RunningBits bits, must raise its size. Note */
1503 /* however that codes above 4095 are used for special signaling. */
1504 if (++Private->RunningCode > Private->MaxCode1 &&
1505 Private->RunningBits < LZ_BITS) {
1506 Private->MaxCode1 <<= 1;
1507 Private->RunningBits++;
1508 console_printf("run bits=%d\n",Private->RunningBits);
1509 }
1510
1511 console_printf("\n return code = 0x%04x \n",*Code);
1512
1513 return GIF_OK;
1514 }
1515
1516 /******************************************************************************
1517 * This routines read one gif data block at a time and buffers it internally *
1518 * so that the decompression routine could access it. *
1519 * The routine returns the next byte from its internal buffer (or read next *
1520 * block in if buffer empty) and returns GIF_OK if succesful. *
1521 ******************************************************************************/
1522 static MS_U32 DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
1523 GifByteType *NextByte)
1524 {
1525 if (Buf[0] == 0) {
1526 /* Needs to read the next buffer - this one is empty: */
1527 if (READ(GifFile, Buf, 1) != 1)
1528 {
1529 _MstGifError = D_GIF_ERR_READ_FAILED;
1530 return GIF_ERROR;
1531 }
1532 if (READ(GifFile,&Buf[1], Buf[0]) != Buf[0])
1533 {
1534 _MstGifError = D_GIF_ERR_READ_FAILED;
1535 return GIF_ERROR;
1536 }
1537 *NextByte = Buf[1];
1538 Buf[1] = 2; /* We use now the second place as last char read! */
1539 Buf[0]--;
1540 }
1541 else {
1542 *NextByte = Buf[Buf[1]++];
1543 Buf[0]--;
1544 }
1545
1546 return GIF_OK;
1547 }
1548 MS_U32 AddExtensionBlock(SavedImage *New, MS_U32 Len, char ExtData[])
1549 {
1550 ExtensionBlock *ep;
1551
1552 if (New->ExtensionBlocks == NULL)
1553 New->ExtensionBlocks = (ExtensionBlock *)malloc(sizeof(ExtensionBlock));
1554 else
1555 New->ExtensionBlocks =
1556 (ExtensionBlock *)realloc(New->ExtensionBlocks,
1557 sizeof(ExtensionBlock) * (New->ExtensionBlockCount + 1));
1558
1559 if (New->ExtensionBlocks == NULL)
1560 return(GIF_ERROR);
1561
1562 ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
1563
1564 if ((ep->Bytes = (char *)malloc(ep->ByteCount = Len)) == NULL)
1565 return(GIF_ERROR);
1566
1567 if (ExtData) {
1568 memcpy(ep->Bytes, ExtData, Len);
1569 ep->Function = New->Function;
1570 }
1571
1572 return(GIF_OK);
1573 }
1574
1575 void FreeExtension(SavedImage *Image)
1576 {
1577 ExtensionBlock *ep;
1578
1579 for (ep = Image->ExtensionBlocks;
1580 ep < Image->ExtensionBlocks + Image->ExtensionBlockCount;
1581 ep++)
1582 (void) free((char *)ep->Bytes);
1583 //free((char *)Image->ExtensionBlocks);
1584 Image->ExtensionBlocks = NULL;
1585 }
1586 void FreeSavedImages(GifFileType *GifFile)
1587 {
1588 SavedImage *sp;
1589
1590 for (sp = GifFile->SavedImages;
1591 sp < GifFile->SavedImages + GifFile->ImageCount;
1592 sp++)
1593 {
1594 if (sp->ImageDesc.ColorMap)
1595 MstFreeMapObject(sp->ImageDesc.ColorMap);
1596
1597 if (sp->RasterBits)
1598 free((char *)sp->RasterBits);
1599
1600 //if (sp->ExtensionBlocks)
1601 //(sp);
1602 }
1603 //free((char *) GifFile->SavedImages);
1604 GifFile->SavedImages=NULL;
1605 }
1606
1607 /******************************************************************************
1608 * This routine reads an entire GIF into core, hanging all its state info off *
1609 * the GifFileType pointer. Call DGifOpenFileName() or MstDGifOpenFileHandle() *
1610 * first to initialize I/O. Its inverse is EGifSpew(). *
1611 *
1612 ******************************************************************************/
1613 MS_U32 MstDGifSlurp(GifFileType *GifFile)
1614 {
1615 MS_U32 ImageSize;
1616 MS_U32 gif_err = 0;
1617 GifRecordType RecordType;
1618 SavedImage *sp;
1619 GifByteType *ExtData;
1620 SavedImage temp_save;
1621
1622
1623 temp_save.ExtensionBlocks=NULL;
1624 temp_save.ExtensionBlockCount=0;
1625
1626 do {
1627 if (MstDGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
1628 {
1629 gif_err = 1;
1630 break;
1631 }
1632
1633 switch (RecordType) {
1634 case IMAGE_DESC_RECORD_TYPE:
1635 if (MstDGifGetImageDesc(GifFile) == GIF_ERROR)
1636 {
1637 gif_err = 1;
1638 break;
1639 }
1640
1641 sp = &GifFile->SavedImages[GifFile->ImageCount-1];
1642 ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
1643
1644 sp->RasterBits
1645 = (char *) malloc(ImageSize * sizeof(GifPixelType));
1646
1647 if (MstDGifGetLine(GifFile, (GifPixelType *) sp->RasterBits, ImageSize)
1648 == GIF_ERROR)
1649 {
1650 gif_err = 1;
1651 break;
1652 }
1653
1654 if (temp_save.ExtensionBlocks) {
1655 sp->ExtensionBlocks = temp_save.ExtensionBlocks;
1656 sp->ExtensionBlockCount = temp_save.ExtensionBlockCount;
1657
1658 temp_save.ExtensionBlocks = NULL;
1659 temp_save.ExtensionBlockCount=0;
1660
1661 /* FIXME: The following is wrong. It is left in only for backwards
1662 * compatibility. Someday it should go away. Use the
1663 * sp->ExtensionBlocks->Function variable instead.
1664 */
1665 sp->Function = sp->ExtensionBlocks[0].Function;
1666
1667 }
1668
1669 break;
1670
1671 case EXTENSION_RECORD_TYPE:
1672 if (MstDGifGetExtension(GifFile,&temp_save.Function,&ExtData)==GIF_ERROR)
1673 {
1674 gif_err = 1;
1675 break;
1676 }
1677 while (ExtData != NULL) {
1678
1679 /* Create an extension block with our data */
1680 if (AddExtensionBlock(&temp_save, ExtData[0],(char *) &ExtData[1])
1681 == GIF_ERROR)
1682 {
1683 gif_err = 1;
1684 break;
1685 }
1686
1687
1688 if (MstDGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
1689 {
1690 gif_err = 1;
1691 break;
1692 }
1693 temp_save.Function = 0;
1694 }
1695 break;
1696
1697 case TERMINATE_RECORD_TYPE:
1698 break;
1699
1700 default: /* Should be trapped by MstDGifGetRecordType */
1701 break;
1702 }
1703 } while (RecordType != TERMINATE_RECORD_TYPE);
1704
1705 /* Just in case the Gif has an extension block without an associated
1706 * image... (Should we save this into a savefile structure with no image
1707 * instead? Have to check if the present writing code can handle that as
1708 * well....
1709 */
1710 if (temp_save.ExtensionBlocks)
1711 FreeExtension(&temp_save);
1712
1713 if (gif_err)
1714 return(GIF_ERROR);
1715 else
1716 return(GIF_OK);
1717
1718
1719
1720 }
1721 /******************************************************************************
1722 * This routine should be called last, to close the GIF file. *
1723 ******************************************************************************/
1724 MS_U32 MstDGifCloseFile(GifFileType *GifFile)
1725 {
1726 GifFilePrivateType *Private;
1727 //FILE *File;
1728
1729 if (GifFile == NULL) return GIF_ERROR;
1730
1731 Private = (GifFilePrivateType *) GifFile->Private;
1732
1733 if (!IS_READABLE(Private)) {
1734 /* This file was NOT open for reading: */
1735 _MstGifError = D_GIF_ERR_NOT_READABLE;
1736 return GIF_ERROR;
1737 }
1738
1739 //File = Private->File;
1740
1741 if (GifFile->Image.ColorMap)
1742 {
1743 MstFreeMapObject(GifFile->Image.ColorMap);
1744 GifFile->Image.ColorMap = NULL;
1745 }
1746
1747 if (GifFile->SColorMap)
1748 {
1749 MstFreeMapObject(GifFile->SColorMap);
1750 GifFile->SColorMap = NULL;
1751 }
1752
1753 if (Private)
1754 {
1755 free((char *) Private);
1756 Private = NULL;
1757 }
1758
1759 if (GifFile->SavedImages)
1760 {
1761 FreeSavedImages(GifFile);
1762 GifFile = NULL;
1763 }
1764
1765 return GIF_OK;
1766 }
1767
1768 #endif
1769