Example #1
0
        /// <summary>
        /// Writes decoded pixel to buffer at a given position.
        /// </summary>
        /// <param name="buffer">The buffer to write to.</param>
        /// <param name="offset">The position to write to.</param>
        /// <returns>The number of bytes written.</returns>
        public int WriteTo(Span <byte> buffer, int offset)
        {
            if (this.Length == 0)
            {
                return(0);
            }

            if (this.Length == 1)
            {
                buffer[offset] = this.value;
                return(1);
            }

            LzwString e      = this;
            int       endIdx = this.Length - 1;

            if (endIdx >= buffer.Length)
            {
                TiffThrowHelper.ThrowImageFormatException("Error reading lzw compressed stream. Either pixel buffer to write to is to small or code length is invalid!");
            }

            for (int i = endIdx; i >= 0; i--)
            {
                buffer[offset + i] = e.value;
                e = e.previous;
            }

            return(this.Length);
        }
Example #2
0
        private void AddStringToTable(LzwString lzwString)
        {
            if (this.tableLength > this.table.Length)
            {
                TiffThrowHelper.ThrowImageFormatException($"TIFF LZW with more than {MaxBits} bits per code encountered (table overflow)");
            }

            this.table[this.tableLength++] = lzwString;

            if (this.tableLength > this.maxCode)
            {
                this.bitsPerCode++;

                if (this.bitsPerCode > MaxBits)
                {
                    // Continue reading MaxBits (12 bit) length codes.
                    this.bitsPerCode = MaxBits;
                }

                this.bitMask = BitmaskFor(this.bitsPerCode);
                this.maxCode = this.MaxCode();
            }

            if (lzwString.Length > this.maxString)
            {
                this.maxString = lzwString.Length;
            }
        }
Example #3
0
 private LzwString(byte value, byte firstChar, int length, LzwString previous)
 {
     this.value     = value;
     this.FirstChar = firstChar;
     this.Length    = length;
     this.previous  = previous;
 }
Example #4
0
        /// <summary>
        /// Decodes and decompresses all pixel indices from the stream.
        /// </summary>
        /// <param name="pixels">The pixel array to decode to.</param>
        public void DecodePixels(Span <byte> pixels)
        {
            // Adapted from the pseudo-code example found in the TIFF 6.0 Specification, 1992.
            // See Section 13: "LZW Compression"/"LZW Decoding", page 61+
            int code;
            int offset = 0;

            while ((code = this.GetNextCode()) != EoiCode)
            {
                if (code == ClearCode)
                {
                    this.Init();
                    code = this.GetNextCode();

                    if (code == EoiCode)
                    {
                        break;
                    }

                    if (this.table[code] == null)
                    {
                        TiffThrowHelper.ThrowImageFormatException($"Corrupted TIFF LZW: code {code} (table size: {this.tableLength})");
                    }

                    offset += this.table[code].WriteTo(pixels, offset);
                }
                else
                {
                    if (this.table[this.oldCode] == null)
                    {
                        TiffThrowHelper.ThrowImageFormatException($"Corrupted TIFF LZW: code {this.oldCode} (table size: {this.tableLength})");
                    }

                    if (this.IsInTable(code))
                    {
                        offset += this.table[code].WriteTo(pixels, offset);

                        this.AddStringToTable(this.table[this.oldCode].Concatenate(this.table[code].FirstChar));
                    }
                    else
                    {
                        LzwString outString = this.table[this.oldCode].Concatenate(this.table[this.oldCode].FirstChar);

                        offset += outString.WriteTo(pixels, offset);
                        this.AddStringToTable(outString);
                    }
                }

                this.oldCode = code;

                if (offset >= pixels.Length)
                {
                    break;
                }
            }
        }