⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gif.c

📁 嵌入式下基于MiniGUI的Web Browser
💻 C
📖 第 1 页 / 共 3 页
字号:
 * Return Value * 0 = There wasn't enough bytes read yet to read the whole datablock * otherwise the size of the data blocks */static inline size_t Gif_data_blocks(const guchar *Buf, size_t BSize){   size_t Size = 0;   if (BSize < 1)      return 0;   while (Buf[0]) {      if (BSize <= (size_t)(Buf[0] + 1))         return 0;      Size += Buf[0] + 1;      BSize -= Buf[0] + 1;      Buf += Buf[0] + 1;   }   return Size + 1;}/* * This is a GIF extension.  We ignore it with this routine. * Buffer points to just after the extension label. * * Return Value * 0 -- block not processed * otherwise the size of the extension label. */static inline size_t Gif_do_generic_ext(const guchar *Buf, size_t BSize){   size_t Size = Buf[0] + 1, DSize;   /* The Block size (the first byte) is supposed to be a specific size    * for each extension... we don't check.    */   if (Buf[0] > BSize)      return 0;   DSize = Gif_data_blocks(Buf + Size, BSize - Size);   if (!DSize)      return 0;   Size += DSize;   return Size <= BSize ? Size : 0;}/* * ? */static inline size_t Gif_do_gc_ext(DilloGif *gif, const guchar *Buf, size_t BSize){   /* Graphic Control Extension */   size_t Size = Buf[0] + 2;   guint Flags;   if (Size > BSize)      return 0;   Buf++;   Flags = Buf[0];#ifdef ENABLE_ANIMATION   /* The packed fields */   gif->disposal = (Buf[0] >> 2) & 0x7;   gif->inputFlag = (Buf[0] >> 1) & 0x1;   /* Delay time */   gif->delayTime = LM_to_uint(Buf[1], Buf[2]);#endif   /* Transparent color index, may not be valid  (unless flag is set) */   if ((Flags & 0x1)) {      gif->transparent = Buf[3];   }   return Size;}#define App_Ext  (0xff)#define Cmt_Ext  (0xfe)#define GC_Ext   (0xf9)#define Txt_Ext  (0x01)/* * ? * Return value: *    TRUE when the extension is over */static size_t Gif_do_extension(DilloGif *gif, guint Label,                               const guchar *buf,                               size_t BSize){   switch (Label) {   case GC_Ext:         /* Graphics extension */      return Gif_do_gc_ext(gif, buf, BSize);   case Cmt_Ext:                /* Comment extension */      return Gif_data_blocks(buf, BSize);   case Txt_Ext:                /* Plain text Extension */      /* This extension allows (rcm thinks) the image to be rendered as text.       */   case App_Ext:                /* Application Extension */   default:      return Gif_do_generic_ext(buf, BSize);    /*Ignore Extension */   }}/* --- General Image Decoder ----------------------------------------------- *//* Here begins the new push-oriented decoder. *//* * ? */static void Gif_lwz_init(DilloGif *gif){#ifdef ENABLE_ANIMATION   if (gif->spill_lines != NULL) {      gint i;      for (i = 0; i < gif->num_spill_lines_max; i++)         g_free (gif->spill_lines[i]);      g_free (gif->spill_lines);   }#endif   gif->num_spill_lines_max = 1;   gif->spill_lines = g_malloc (sizeof(guchar *) * gif->num_spill_lines_max);   gif->spill_lines[0] = g_malloc (gif->Width);   gif->bits_in_window = 0;   /* First code in table = clear_code +1    * Last code in table = first code in table    * clear_code = (1<< input code size)    */   gif->last_code = (1 << gif->input_code_size) + 1;   memset(gif->code_and_byte, 0,          (1 + gif->last_code) * sizeof(gif->code_and_byte[0]));   gif->code_size = gif->input_code_size + 1;   gif->line_index = 0;#ifdef ENABLE_ANIMATION   gif->packet_size = 0;   gif->window = 0;#endif}/* * Send the image line to the dicache, also handling the interlacing. */static void Gif_emit_line(DilloGif *gif, const guchar *linebuf){#ifdef ENABLE_ANIMATION   if (gif->new_frame) {      memcpy (gif->new_frame->bits + gif->new_frame->width * gif->y,                       linebuf, gif->new_frame->width);   }   if (gif->Image->dw->nr_frames < 2) {      a_Dicache_write(gif->Image, gif->url, gif->version, linebuf, 0, gif->y);   }#else      a_Dicache_write(gif->Image, gif->url, gif->version, linebuf, 0, gif->y);#endif   if (gif->Flags & INTERLACE) {      switch (gif->pass) {      case 0:      case 1:         gif->y += 8;         break;      case 2:         gif->y += 4;         break;      case 3:         gif->y += 2;         break;      }      if (gif->y >= gif->Height) {         gif->pass++;         switch (gif->pass) {         case 1:            gif->y = 4;            break;         case 2:            gif->y = 2;            break;         case 3:            gif->y = 1;            break;         default:            /* arriving here is an error in the input image. */            gif->y = 0;            break;         }      }   } else {      if (gif->y < gif->Height)         gif->y++;   }}/* * I apologize for the large size of this routine and the goto error * construct - I almost _never_ do that. I offer the excuse of * optimizing for speed. * * RCM -- busted these down into smaller subroutines... still very hard to * read. *//* * Decode the packetized lwz bytes */static void Gif_literal(DilloGif *gif, guint code){   gif->linebuf[gif->line_index++] = code;   if (gif->line_index >= gif->Width) {      Gif_emit_line(gif, gif->linebuf);      gif->line_index = 0;   }   gif->length[gif->last_code + 1] = 2;   gif->code_and_byte[gif->last_code + 1] = (code << 8);   gif->code_and_byte[gif->last_code] |= code;}/* * ? *//* Profiling reveals over half the GIF time is spent here: */static void Gif_sequence(DilloGif *gif, guint code){   guint o_index, o_size, orig_code;   guint sequence_length = gif->length[code];   guint line_index = gif->line_index;   gint num_spill_lines;   gint spill_line_index = gif->spill_line_index;   guchar *last_byte_ptr, *obuf;   gif->length[gif->last_code + 1] = sequence_length + 1;   gif->code_and_byte[gif->last_code + 1] = (code << 8);   /* We're going to traverse the sequence backwards. Thus,    * we need to allocate spill lines if the sequence won't    * fit entirely within the present scan line. */   if (line_index + sequence_length <= gif->Width) {      num_spill_lines = 0;      obuf = gif->linebuf;      o_index = line_index + sequence_length;      o_size = sequence_length - 1;   } else {      num_spill_lines = (line_index + sequence_length - 1) /          gif->Width;      o_index = (line_index + sequence_length - 1) % gif->Width + 1;      if (num_spill_lines > gif->num_spill_lines_max) {         /* Allocate more spill lines. */         spill_line_index = gif->num_spill_lines_max;         gif->num_spill_lines_max = num_spill_lines << 1;         gif->spill_lines = g_realloc(gif->spill_lines,                                      gif->num_spill_lines_max *                                      sizeof(guchar *));         for (; spill_line_index < gif->num_spill_lines_max;              spill_line_index++)            gif->spill_lines[spill_line_index] =                g_malloc(gif->Width);      }      spill_line_index = num_spill_lines - 1;      obuf = gif->spill_lines[spill_line_index];      o_size = o_index;   }   gif->line_index = o_index;   /* for afterwards */   /* for fixing up later if last_code == code */   orig_code = code;   last_byte_ptr = obuf + o_index - 1;   /* spill lines are allocated, and we are clear to    * write. This loop does not write the first byte of    * the sequence, however (last byte traversed). */   while (sequence_length > 1) {      sequence_length -= o_size;      /* Write o_size bytes to       * obuf[o_index - o_size..o_index). */      for (; o_size > 0 && o_index > 0; o_size--) {         guint code_and_byte = gif->code_and_byte[code];         DEBUG_MSG(5, "%d ", gif->code_and_byte[code] & 255);         obuf[--o_index] = code_and_byte & 255;         code = code_and_byte >> 8;      }      /* Prepare for writing to next line. */      if (o_index == 0) {         if (spill_line_index > 0) {            spill_line_index--;            obuf = gif->spill_lines[spill_line_index];            o_size = gif->Width;         } else {            obuf = gif->linebuf;            o_size = sequence_length - 1;         }         o_index = gif->Width;      }   }   /* Ok, now we write the first byte of the sequence. */   /* We are sure that the code is literal. */   DEBUG_MSG(5, "%d", code);   obuf[--o_index] = code;   gif->code_and_byte[gif->last_code] |= code;   /* Fix up the output if the original code was last_code. */   if (orig_code == gif->last_code) {      *last_byte_ptr = code;      DEBUG_MSG(5, " fixed (%d)!", code);   }   DEBUG_MSG(5, "\n");   /* Output any full lines. */   if (gif->line_index >= gif->Width) {      Gif_emit_line(gif, gif->linebuf);      gif->line_index = 0;   }   if (num_spill_lines) {      if (gif->line_index)         Gif_emit_line(gif, gif->linebuf);      for (spill_line_index = 0;           spill_line_index < num_spill_lines - (gif->line_index ? 1 : 0);           spill_line_index++)         Gif_emit_line(gif, gif->spill_lines[spill_line_index]);   }   if (num_spill_lines) {      /* Swap the last spill line with the gif line, using       * linebuf as the swap temporary. */      guchar *linebuf = gif->spill_lines[num_spill_lines - 1];      gif->spill_lines[num_spill_lines - 1] = gif->linebuf;      gif->linebuf = linebuf;   }   gif->spill_line_index = spill_line_index;}/* * ? * * Return Value: *   2 -- quit *   1 -- new last code needs to be done *   0 -- okay, but reset the code table *   < 0 on error *   -1 if the decompression code was not in the lookup table */static gint Gif_process_code(DilloGif *gif, guint code, guint clear_code){   /* A short table describing what to do with the code:    * code < clear_code  : This is uncompressed, raw data    * code== clear_code  : Reset the decompression table    * code== clear_code+1: End of data stream    * code > clear_code+1: Compressed code; look up in table    */   if (code < clear_code) {      /* a literal code. */      DEBUG_MSG(5, "literal\n");      Gif_literal(gif, code);      return 1;   } else if (code >= clear_code + 2) {      /* a sequence code. */      if (code > gif->last_code)         return -1;      Gif_sequence(gif, code);      return 1;   } else if (code == clear_code) {      /* clear code. Resets the whole table */      DEBUG_MSG(5, "clear\n");      return 0;   } else {      /* end code. */      DEBUG_MSG(5, "end\n");      return 2;   }}/* * ? */static gint Gif_decode(DilloGif *gif, const guchar *buf, size_t bsize){   /*    * Data block processing.  The image stuff is a series of data blocks.    * Each data block is 1 to 256 bytes long.  The first byte is the length    * of the data block.  0 == the last data block.    */   size_t bufsize, packet_size;   guint clear_code;   guint window;   gint bits_in_window;   guint code;   gint code_size;   guint code_mask;   bufsize = bsize;   /* Want to get all inner loop state into local variables. */   packet_size = gif->packet_size;   window = gif->window;   bits_in_window = gif->bits_in_window;   code_size = gif->code_size;   code_mask = (1 << code_size) - 1;   clear_code = 1 << gif->input_code_size;   /* If packet size == 0, we are at the start of a data block.    * The first byte of the data block indicates how big it is (0 == last    * datablock)    * packet size is set to this size; it indicates how much of the data block    * we have left to process.    */   while (bufsize > 0) {      /* lwz_bytes is the number of remaining lwz bytes in the packet. */      gint lwz_bytes = MIN(packet_size, bufsize);      bufsize -= lwz_bytes;      packet_size -= lwz_bytes;      for (; lwz_bytes > 0; lwz_bytes--) {         /* printf ("%d ", *buf) would print the depacketized lwz stream. */         /* Push the byte onto the "end" of the window (MSB).  The low order          * bits always come first in the LZW stream. */         window = (window >> 8) | (*buf++ << 24);         bits_in_window += 8;         while (bits_in_window >= code_size) {            /* Extract the code.  The code is code_size (3 to 12) bits long,             * at the start of the window */            code = (window >> (32 - bits_in_window)) & code_mask;            DEBUG_MSG(5, "code = %d, clear_code = %d", code, clear_code);            bits_in_window -= code_size;            switch (Gif_process_code(gif, code, clear_code)) {            case 1:             /* Increment last code */               gif->last_code++;               /*gif->code_and_byte[gif->last_code+1]=0; */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -