예제 #1
0
파일: GIF2.cpp 프로젝트: rn10950/RetroZilla
/* Perform Lempel-Ziv-Welch decoding */
static int do_lzw(gif_struct *gs, const PRUint8 *q)
{
  int code;
  int incode;
  const PRUint8 *ch;

  /* Copy all the decoder state variables into locals so the compiler
   * won't worry about them being aliased.  The locals will be homed
   * back into the GIF decoder structure when we exit.
   */
  int avail       = gs->avail;
  int bits        = gs->bits;
  int codesize    = gs->codesize;
  int codemask    = gs->codemask;
  int count       = gs->count;
  int oldcode     = gs->oldcode;
  int clear_code  = gs->clear_code;
  PRUint8 firstchar = gs->firstchar;
  PRInt32 datum     = gs->datum;
  PRUint16 *prefix  = gs->prefix;
  PRUint8 *stackp   = gs->stackp;
  PRUint8 *suffix   = gs->suffix;
  PRUint8 *stack    = gs->stack;
  PRUint8 *rowp     = gs->rowp;
  PRUint8 *rowend   = gs->rowend;
  PRUintn rows_remaining = gs->rows_remaining;

  if (rowp == rowend)
    return 0;

#define OUTPUT_ROW(gs)                                                  \
  PR_BEGIN_MACRO                                                        \
    output_row(gs);                                                     \
    rows_remaining--;                                                   \
    rowp = gs->rowp;                                                    \
    if (!rows_remaining)                                                \
      goto END;                                                         \
  PR_END_MACRO

  for (ch = q; count-- > 0; ch++)
  {
    /* Feed the next byte into the decoder's 32-bit input buffer. */
    datum += ((int32) *ch) << bits;
    bits += 8;

    /* Check for underflow of decoder's 32-bit input buffer. */
    while (bits >= codesize)
    {
      /* Get the leading variable-length symbol from the data stream */
      code = datum & codemask;
      datum >>= codesize;
      bits -= codesize;

      /* Reset the dictionary to its original state, if requested */
      if (code == clear_code) {
        codesize = gs->datasize + 1;
        codemask = (1 << codesize) - 1;
        avail = clear_code + 2;
        oldcode = -1;
        continue;
      }

      /* Check for explicit end-of-stream code */
      if (code == (clear_code + 1)) {
        /* end-of-stream should only appear after all image data */
        if (rows_remaining != 0)
          return -1;
        return 0;
      }

      if (oldcode == -1) {
        *rowp++ = suffix[code];
        if (rowp == rowend)
          OUTPUT_ROW(gs);

        firstchar = oldcode = code;
        continue;
      }

      incode = code;
      if (code >= avail) {
        *stackp++ = firstchar;
        code = oldcode;

        if (stackp == stack + MAX_BITS)
          return -1;
      }

      while (code >= clear_code)
      {
        if (code == prefix[code])
          return -1;

        *stackp++ = suffix[code];
        code = prefix[code];

        if (stackp == stack + MAX_BITS || code >= MAX_BITS)
          return -1;
      }

      *stackp++ = firstchar = suffix[code];

      /* Define a new codeword in the dictionary. */
      if (avail < 4096) {
        prefix[avail] = oldcode;
        suffix[avail] = firstchar;
        avail++;

        /* If we've used up all the codewords of a given length
         * increase the length of codewords by one bit, but don't
         * exceed the specified maximum codeword size of 12 bits.
         */
        if (((avail & codemask) == 0) && (avail < 4096)) {
          codesize++;
          codemask += avail;
        }
      }
      oldcode = incode;

        /* Copy the decoded data out to the scanline buffer. */
      do {
        *rowp++ = *--stackp;
        if (rowp == rowend) {
          OUTPUT_ROW(gs);
        }
      } while (stackp > stack);
    }
  }

  END:

  /* Home the local copies of the GIF decoder state variables */
  gs->avail = avail;
  gs->bits = bits;
  gs->codesize = codesize;
  gs->codemask = codemask;
  gs->count = count;
  gs->oldcode = oldcode;
  gs->firstchar = firstchar;
  gs->datum = datum;
  gs->stackp = stackp;
  gs->rowp = rowp;
  gs->rows_remaining = rows_remaining;

  return 0;
}
예제 #2
0
/* Perform Lempel-Ziv-Welch decoding */
bool
nsGIFDecoder2::DoLzw(const uint8_t *q)
{
  if (!mGIFStruct.rows_remaining)
    return true;

  /* Copy all the decoder state variables into locals so the compiler
   * won't worry about them being aliased.  The locals will be homed
   * back into the GIF decoder structure when we exit.
   */
  int avail       = mGIFStruct.avail;
  int bits        = mGIFStruct.bits;
  int codesize    = mGIFStruct.codesize;
  int codemask    = mGIFStruct.codemask;
  int count       = mGIFStruct.count;
  int oldcode     = mGIFStruct.oldcode;
  const int clear_code = ClearCode();
  uint8_t firstchar = mGIFStruct.firstchar;
  int32_t datum     = mGIFStruct.datum;
  uint16_t *prefix  = mGIFStruct.prefix;
  uint8_t *stackp   = mGIFStruct.stackp;
  uint8_t *suffix   = mGIFStruct.suffix;
  uint8_t *stack    = mGIFStruct.stack;
  uint8_t *rowp     = mGIFStruct.rowp;

  uint32_t bpr = mGIFStruct.width;
  if (!mGIFStruct.images_decoded) 
    bpr *= sizeof(uint32_t);
  uint8_t *rowend   = mImageData + (bpr * mGIFStruct.irow) + mGIFStruct.width;

#define OUTPUT_ROW()                                        \
  PR_BEGIN_MACRO                                            \
    if (!OutputRow())                                       \
      goto END;                                             \
    rowp = mImageData + mGIFStruct.irow * bpr;              \
    rowend = rowp + mGIFStruct.width;                       \
  PR_END_MACRO

  for (const uint8_t* ch = q; count-- > 0; ch++)
  {
    /* Feed the next byte into the decoder's 32-bit input buffer. */
    datum += ((int32_t) *ch) << bits;
    bits += 8;

    /* Check for underflow of decoder's 32-bit input buffer. */
    while (bits >= codesize)
    {
      /* Get the leading variable-length symbol from the data stream */
      int code = datum & codemask;
      datum >>= codesize;
      bits -= codesize;

      /* Reset the dictionary to its original state, if requested */
      if (code == clear_code) {
        codesize = mGIFStruct.datasize + 1;
        codemask = (1 << codesize) - 1;
        avail = clear_code + 2;
        oldcode = -1;
        continue;
      }

      /* Check for explicit end-of-stream code */
      if (code == (clear_code + 1)) {
        /* end-of-stream should only appear after all image data */
        return (mGIFStruct.rows_remaining == 0);
      }

      if (oldcode == -1) {
        if (code >= MAX_BITS)
          return false;
        *rowp++ = suffix[code] & mColorMask; // ensure index is within colormap
        if (rowp == rowend)
          OUTPUT_ROW();

        firstchar = oldcode = code;
        continue;
      }

      int incode = code;
      if (code >= avail) {
        *stackp++ = firstchar;
        code = oldcode;

        if (stackp >= stack + MAX_BITS)
          return false;
      }

      while (code >= clear_code)
      {
        if ((code >= MAX_BITS) || (code == prefix[code]))
          return false;

        *stackp++ = suffix[code];
        code = prefix[code];

        if (stackp == stack + MAX_BITS)
          return false;
      }

      *stackp++ = firstchar = suffix[code];

      /* Define a new codeword in the dictionary. */
      if (avail < 4096) {
        prefix[avail] = oldcode;
        suffix[avail] = firstchar;
        avail++;

        /* If we've used up all the codewords of a given length
         * increase the length of codewords by one bit, but don't
         * exceed the specified maximum codeword size of 12 bits.
         */
        if (((avail & codemask) == 0) && (avail < 4096)) {
          codesize++;
          codemask += avail;
        }
      }
      oldcode = incode;

      /* Copy the decoded data out to the scanline buffer. */
      do {
        *rowp++ = *--stackp & mColorMask; // ensure index is within colormap
        if (rowp == rowend)
          OUTPUT_ROW();
      } while (stackp > stack);
    }
  }

  END:

  /* Home the local copies of the GIF decoder state variables */
  mGIFStruct.avail = avail;
  mGIFStruct.bits = bits;
  mGIFStruct.codesize = codesize;
  mGIFStruct.codemask = codemask;
  mGIFStruct.count = count;
  mGIFStruct.oldcode = oldcode;
  mGIFStruct.firstchar = firstchar;
  mGIFStruct.datum = datum;
  mGIFStruct.stackp = stackp;
  mGIFStruct.rowp = rowp;

  return true;
}