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

📄 gif.c

📁 基于minigui的浏览器. 这是最新版本.
💻 C
📖 第 1 页 / 共 2 页
字号:
      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, ", 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; */               if ((gif->last_code & code_mask) == 0) {                  if (gif->last_code == (1 << MAX_LWZ_BITS))                     gif->last_code--;                  else {                     code_size++;                     code_mask = (1 << code_size) - 1;                  }               }               break;            case 0:         /* Reset codes size and mask */               gif->last_code = clear_code + 1;               code_size = gif->input_code_size + 1;               code_mask = (1 << code_size) - 1;               break;            case 2:         /* End code... consume remaining data chunks..? */               goto error;  /* Could clean up better? */            default:               printf("dillo_gif_decode: error!\n");               goto error;            }         }      }      /* We reach here if       * a) We have reached the end of the data block;       * b) we ran out of data before reaching the end of the data block       */      if (bufsize <= 0)         break;                 /* We are out of data; */      /* Start of new data block */      bufsize--;      if (!(packet_size = *buf++)) {         /* This is the "block terminator" -- the last data block */         gif->state = 999;     /* BUG: should Go back to getting GIF blocks. */         break;      }   }   gif->packet_size = packet_size;   gif->window = window;   gif->bits_in_window = bits_in_window;   gif->code_size = code_size;   return bsize - bufsize; error:   gif->state = 999;   return bsize - bufsize;}/* * ? */static gint Gif_check_sig(DilloGif *gif, const guchar *ibuf, gint ibsize){   /* at beginning of file - read magic number */   if (ibsize < 6)      return 0;   if (strncmp(ibuf, "GIF", 3) != 0) {      gif->state = 999;      return 6;   }   if (strncmp(ibuf + 3, "87a", 3) != 0 &&       strncmp(ibuf + 3, "89a", 3) != 0) {      gif->state = 999;      return 6;   }   gif->state = 1;   return 6;}/* Read the color map * * Implements, from the spec: * Global Color Table * Local Color Table */static inline size_t Gif_do_color_table(DilloGif *gif, void *Buf,                    const guchar *buf, size_t bsize, size_t CT_Size){   size_t Size = 3 * (1 << (1 + CT_Size));   if (Size > bsize)      return 0;   gif->ColorMap_ofs = (gulong) buf - (gulong) Buf;   gif->NumColors = (1 << (1 + CT_Size));   return Size;}/* * This implements, from the spec: * <Logical Screen> ::= Logical Screen Descriptor [Global Color Table] */static size_t Gif_get_descriptor(DilloGif *gif, void *Buf,                                 const guchar *buf, gint bsize){   /* screen descriptor */   size_t Size = 7,           /* Size of descriptor */          mysize;             /* Size of color table */   guchar Flags;   if (bsize < 7)      return 0;   Flags = buf[4];   if (Flags & LOCALCOLORMAP) {      mysize = Gif_do_color_table(                  gif, Buf, buf + 7, (size_t)bsize - 7, Flags & (size_t)0x7);      if (!mysize)         return 0;      Size += mysize;           /* Size of the color table that follows */      gif->Background = buf[5];   }   /*   gif->Width = LM_to_uint(buf[0], buf[1]);        gif->Height = LM_to_uint(buf[2], buf[3]); */   gif->ColorResolution = (((buf[4] & 0x70) >> 3) + 1);   /*   gif->AspectRatio     = buf[6]; */   return Size;}/* * This implements, from the spec: * <Table-Based Image> ::= Image Descriptor [Local Color Table] Image Data * * ('Buf' points to just after the Image separator) * we should probably just check that the local stuff is consistent * with the stuff at the header. For now, we punt... */static size_t Gif_do_img_desc(DilloGif *gif, void *Buf,                              const guchar *buf, size_t bsize){   guchar Flags;   size_t Size = 9 + 1; /* image descriptor size + first byte of image data */   if (bsize < 10)      return 0;   gif->Width   = LM_to_uint(buf[4], buf[5]);   gif->Height  = LM_to_uint(buf[6], buf[7]);   gif->linebuf = g_malloc(gif->Width);   a_Dicache_set_parms(gif->url, gif->version, gif->Image,                       gif->Width, gif->Height, DILLO_IMG_TYPE_INDEXED);   Flags = buf[8];   gif->Flags |= Flags & INTERLACE;   gif->pass = 0;   bsize -= 9;   buf += 9;   if (Flags & LOCALCOLORMAP) {      size_t LSize = Gif_do_color_table(                        gif, Buf, buf, bsize, Flags & (size_t)0x7);      if (!LSize)         return 0;      Size += LSize;      buf += LSize;      bsize -= LSize;   }   /* Finally, get the first byte of the LZW image data */   if (bsize < 1)      return 0;   gif->input_code_size = *buf++;   if (gif->input_code_size > 8) {      gif->state = 999;      return Size;   }   gif->y = 0;   Gif_lwz_init(gif);   gif->spill_line_index = 0;   gif->state = 3;              /*Process the lzw data next */   if (gif->Image && gif->ColorMap_ofs) {      a_Dicache_set_cmap(gif->url, gif->version, gif->Image,                         (guchar *) Buf + gif->ColorMap_ofs,                         gif->NumColors, 256, gif->transparent);   }   return Size;}/* --- Top level data block processors ------------------------------------ */#define Img_Desc (0x2c)#define Trailer  (0x3B)#define Ext_Id   (0x21)/* * This identifies which kind of GIF blocks are next, and processes them. * It returns if there isn't enough data to process the next blocks, or if * the next block is the lzw data (which is streamed differently) * * This implements, from the spec, <Data>* Trailer * <Data> ::= <Graphic Block> | <Special-Purpose Block> * <Special-Purpose Block> ::= Application Extension | Comment Extension * <Graphic Block> ::= [Graphic Control Extension] <Graphic-Rendering Block> * <Graphic-Rendering Block> ::= <Table-Based Image> | Plain Text Extension * * <Data>* --> GIF_Block * <Data>  --> while (...) * <Special-Purpose Block> --> Gif_do_extension * Graphic Control Extension --> Gif_do_extension * Plain Text Extension --> Gif_do_extension * <Table-Based Image> --> Gif_do_img_desc * * Return Value * 0 if not enough data is present, otherwise the number of bytes * "consumed" */static size_t GIF_Block(DilloGif * gif, void *Buf,                        const guchar *buf, size_t bsize){   size_t Size = 0, mysize;   guchar C;   if (bsize < 1)      return 0;   while (gif->state == 2) {      if (bsize < 1)         return Size;      bsize--;      switch (*buf++) {      case Ext_Id:         /* get the extension type */         if (bsize < 2)            return Size;         /* Have the extension block intepreted. */         C = *buf++;         bsize--;         mysize = Gif_do_extension(gif, C, buf, bsize);         if (!mysize)            /* Not all of the extension is there.. quit until more data             * arrives */            return Size;         bsize -= mysize;         buf += mysize;         /* Increment the amount consumed by the extension introducer          * and id, and extension block size */         Size += mysize + 2;         /* Do more GIF Blocks */         continue;      case Img_Desc:            /* Image descriptor */         mysize = Gif_do_img_desc(gif, Buf, buf, bsize);         if (!mysize)            return Size;         /* Increment the amount consumed by the Image Separator and the          * Resultant blocks */         Size += 1 + mysize;         return Size;      case Trailer:         gif->state = 999;      /* BUG: should close the rest of the file */         return Size + 1;         break;                 /* GIF terminator */      default:                  /* Unknown */         /* gripe and complain */         MSG ("gif.c::GIF_Block: Error, 0x%x found\n", *(buf-1));         gif->state = 999;         return Size + 1;      }   }   return Size;}/* * Process some bytes from the input gif stream. It's a state machine. * * From the GIF spec: * <GIF Data Stream> ::= Header <Logical Screen> <Data>* Trailer * * <GIF Data Stream> --> Gif_process_bytes * Header            --> State 0 * <Logical Screen>  --> State 1 * <Data>*           --> State 2 * Trailer           --> State > 3 * * State == 3 is special... this is inside of <Data> but all of the stuff in * there has been gotten and set up.  So we stream it outside. */static size_t Gif_process_bytes(DilloGif *gif, const guchar *ibuf,                                gint bufsize, void *Buf){   gint tmp_bufsize = bufsize;   size_t mysize;   switch (gif->state) {   case 0:      mysize = Gif_check_sig(gif, ibuf, tmp_bufsize);      if (!mysize)         break;      tmp_bufsize -= mysize;      ibuf += mysize;      if (gif->state != 1)         break;   case 1:      mysize = Gif_get_descriptor(gif, Buf, ibuf, tmp_bufsize);      if (!mysize)         break;      tmp_bufsize -= mysize;      ibuf += mysize;      gif->state = 2;   case 2:      /* Ok, this loop construction looks weird.  It implements the <Data>* of       * the GIF grammar.  All sorts of stuff is allocated to set up for the       * decode part (state ==2) and then there is the actual decode part (3)       */      mysize = GIF_Block(gif, Buf, ibuf, (size_t)tmp_bufsize);      if (!mysize)         break;      tmp_bufsize -= mysize;      ibuf += mysize;      if (gif->state != 3)         break;   case 3:      /* get an image byte */      /* The users sees all of this stuff */      mysize = Gif_decode(gif, ibuf, (size_t)tmp_bufsize);      if (mysize == 0)         break;      ibuf += mysize;      tmp_bufsize -= mysize;   default:      /* error - just consume all input */      tmp_bufsize = 0;      break;   }   DEBUG_MSG(5, "Gif_process_bytes: final state %d, %ld bytes consumed\n",             gif->state, (glong)(bufsize - tmp_bufsize));   return bufsize - tmp_bufsize;}#endif /* ENABLE_GIF */

⌨️ 快捷键说明

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