/* 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; }
/* 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; }