xref: /utopia/UTPA2-700.0.x/modules/gpd/drv/gpd/dgif_lib.c (revision 53ee8cc121a030b8d368113ac3e966b4705770ef)
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