Exemplo n.º 1
0
        private BufferPtr NextLine()
        {
            var pbRet = BufferPtr.FromPtr(_pbBitsOutCur);

            _pbBitsOutCur.Incr(_cbStride);              // f*****g upside down dibs!
            _linesLeft--;
            return(pbRet);
        }
Exemplo n.º 2
0
        public void Decompress(out byte[] data, out int length)
        {
            int fc;

            // Initialize for decoding a new image...
            const int size = 8;

            InitExp(size);

            // Initialize in case they forgot to put in a clear code.
            // (This shouldn't happen, but we'll try and decode it anyway...)
            var oc = fc = 0;

            // Allocate space for the decode buffer
            var buf = NextLine();

            // Set up the stack pointer and decode buffer pointer
            var sp     = new BufferPtr(_stack);
            var bufPtr = BufferPtr.FromPtr(buf);
            var bufCnt = _width;

            // This is the main loop.  For each code we get we pass through the
            // linked list of prefix codes, pushing the corresponding "character" for
            // each code onto the stack.  When the list reaches a single "character"
            // we push that on the stack too, and then start unstacking each
            // character for output in the correct order.  Special handling is
            // included for the clear code, and the whole thing ends when we get
            // an ending code.
            var c = GetNextCode();

            while (c != _ending)
            {
                // If we had a file error, return without completing the decode
                if (c < 0)
                {
                    break;
                }

                // If the code is a clear code, reinitialize all necessary items.
                if (c == _clear)
                {
                    _currSize = size + 1;
                    _slot     = _newCodes;
                    _topSlot  = 1 << _currSize;

                    // Continue reading codes until we get a non-clear code
                    // (Another unlikely, but possible case...)
                    c = GetNextCode();
                    while (c == _clear)
                    {
                        c = GetNextCode();
                    }

                    // If we get an ending code immediately after a clear code
                    // (Yet another unlikely case), then break out of the loop.
                    if (c == _ending)
                    {
                        break;
                    }

                    // Finally, if the code is beyond the range of already set codes,
                    // (This one had better NOT happen...  I have no idea what will
                    // result from this, but I doubt it will look good...) then set it
                    // to color zero.
                    if (c >= _slot)
                    {
                        c = 0;
                    }

                    oc = fc = c;

                    // And var us not forget to put the char into the buffer... And
                    // if, on the off chance, we were exactly one pixel from the end
                    // of the line, we have to send the buffer to the out_line()
                    // routine...
                    bufPtr.Set((byte)c);
                    bufPtr.Incr();

                    if (--bufCnt == 0)
                    {
                        buf    = NextLine();
                        bufPtr = BufferPtr.FromPtr(buf);
                        bufCnt = _width;
                    }
                }
                else
                {
                    // In this case, it's not a clear code or an ending code, so
                    // it must be a code code...  So we can now decode the code into
                    // a stack of character codes. (Clear as mud, right?)
                    var code = c;

                    // Here we go again with one of those off chances...  If, on the
                    // off chance, the code we got is beyond the range of those already
                    // set up (Another thing which had better NOT happen...) we trick
                    // the decoder into thinking it actually got the last code read.
                    // (Hmmn... I'm not sure why this works...  But it does...)
                    if (code >= _slot)
                    {
                        if (code > _slot)
                        {
                            ++_badCodeCount;
                        }
                        code = oc;
                        sp.Set((byte)fc);
                        sp.Incr();
                    }

                    // Here we scan back along the linked list of prefixes, pushing
                    // helpless characters (ie. suffixes) onto the stack as we do so.
                    while (code >= _newCodes)
                    {
                        sp.Set(_suffix[code]);
                        sp.Incr();
                        code = _prefix[code];
                    }

                    // Push the last character on the stack, and set up the new
                    // prefix and suffix, and if the required slot number is greater
                    // than that allowed by the current bit size, increase the bit
                    // size.  (NOTE - If we are all full, we *don't* save the new
                    // suffix and prefix...  I'm not certain if this is correct...
                    // it might be more proper to overwrite the last code...
                    sp.Set((byte)code);
                    sp.Incr();
                    if (_slot < _topSlot)
                    {
                        fc               = code;
                        _suffix[_slot]   = (byte)fc;                            // = code;
                        _prefix[_slot++] = oc;
                        oc               = c;
                    }
                    if (_slot >= _topSlot)
                    {
                        if (_currSize < 12)
                        {
                            _topSlot <<= 1;
                            ++_currSize;
                        }
                    }

                    // Now that we've pushed the decoded string (in reverse order)
                    // onto the stack, lets pop it off and put it into our decode
                    // buffer...  And when the decode buffer is full, write another
                    // line...
                    while (sp.GetPos() > 0)
                    {
                        sp.Decr();
                        bufPtr.Set(sp.Get());
                        bufPtr.Incr();
                        if (--bufCnt == 0)
                        {
                            buf    = NextLine();
                            bufPtr = buf;
                            bufCnt = _width;
                        }
                    }
                }
                c = GetNextCode();
            }

            data   = _pbBitsOutCur.GetBuffer();
            length = _pstm.GetPos();
        }
Exemplo n.º 3
0
        private int GetNextCode()
        {
            int ret;

            if (_numBitsLeft == 0)
            {
                if (_numAvailBytes <= 0)
                {
                    // Out of bytes in current block, so read next block
                    _pBytes        = new BufferPtr(_byteBuff);
                    _numAvailBytes = GetByte();
                    if (_numAvailBytes < 0)
                    {
                        return(_numAvailBytes);
                    }

                    if (_numAvailBytes > 0)
                    {
                        for (var i = 0; i < _numAvailBytes; ++i)
                        {
                            var x = GetByte();
                            if (x < 0)
                            {
                                return(x);
                            }
                            _byteBuff[i] = (byte)x;
                        }
                    }
                }
                _b1 = _pBytes.Get();
                _pBytes.Incr();
                _numBitsLeft = 8;
                --_numAvailBytes;
            }

            ret = _b1 >> (8 - _numBitsLeft);
            while (_currSize > _numBitsLeft)
            {
                if (_numAvailBytes <= 0)
                {
                    // Out of bytes in current block, so read next block
                    _pBytes        = new BufferPtr(_byteBuff);
                    _numAvailBytes = GetByte();
                    if (_numAvailBytes < 0)
                    {
                        return(_numAvailBytes);
                    }

                    if (_numAvailBytes > 0)
                    {
                        for (var i = 0; i < _numAvailBytes; ++i)
                        {
                            var x = GetByte();
                            if (x < 0)
                            {
                                return(x);
                            }
                            _byteBuff[i] = (byte)x;
                        }
                    }
                }
                _b1 = _pBytes.Get();
                _pBytes.Incr();
                ret          |= _b1 << _numBitsLeft;
                _numBitsLeft += 8;
                --_numAvailBytes;
            }
            _numBitsLeft -= _currSize;
            ret          &= _codeMask[_currSize];
            return(ret);
        }