Ejemplo n.º 1
0
        ImageData ReadV5(Stream stream, TlgMetaData info)
        {
            using (var src = new ArcView.Reader(stream))
            {
                int width       = (int)info.Width;
                int height      = (int)info.Height;
                int colors      = info.BPP / 8;
                int blockheight = src.ReadInt32();
                int blockcount  = (height - 1) / blockheight + 1;

                // skip block size section
                src.BaseStream.Seek(blockcount * 4, SeekOrigin.Current);

                int stride     = width * 4;
                var image_bits = new byte[height * stride];
                var text       = new byte[4096];
                for (int i = 0; i < 4096; ++i)
                {
                    text[i] = 0;
                }

                var       inbuf  = new byte[blockheight * width + 10];
                byte [][] outbuf = new byte[4][];
                for (int i = 0; i < colors; i++)
                {
                    outbuf[i] = new byte[blockheight * width + 10];
                }

                int z        = 0;
                int prevline = -1;
                for (int y_blk = 0; y_blk < height; y_blk += blockheight)
                {
                    // read file and decompress
                    for (int c = 0; c < colors; c++)
                    {
                        byte mark = src.ReadByte();
                        int  size;
                        size = src.ReadInt32();
                        if (mark == 0)
                        {
                            // modified LZSS compressed data
                            if (size != src.Read(inbuf, 0, size))
                            {
                                return(null);
                            }
                            z = TVPTLG5DecompressSlide(outbuf[c], inbuf, size, text, z);
                        }
                        else
                        {
                            // raw data
                            src.Read(outbuf[c], 0, size);
                        }
                    }

                    // compose colors and store
                    int y_lim = y_blk + blockheight;
                    if (y_lim > height)
                    {
                        y_lim = height;
                    }
                    int outbuf_pos = 0;
                    for (int y = y_blk; y < y_lim; y++)
                    {
                        int current     = y * stride;
                        int current_org = current;
                        if (prevline >= 0)
                        {
                            // not first line
                            switch (colors)
                            {
                            case 3:
                                TVPTLG5ComposeColors3To4(image_bits, current, prevline,
                                                         outbuf, outbuf_pos, width);
                                break;

                            case 4:
                                TVPTLG5ComposeColors4To4(image_bits, current, prevline,
                                                         outbuf, outbuf_pos, width);
                                break;
                            }
                        }
                        else
                        {
                            // first line
                            switch (colors)
                            {
                            case 3:
                                for (int pr = 0, pg = 0, pb = 0, x = 0;
                                     x < width; x++)
                                {
                                    int b = outbuf[0][outbuf_pos + x];
                                    int g = outbuf[1][outbuf_pos + x];
                                    int r = outbuf[2][outbuf_pos + x];
                                    b += g; r += g;
                                    image_bits[current++] = (byte)(pb += b);
                                    image_bits[current++] = (byte)(pg += g);
                                    image_bits[current++] = (byte)(pr += r);
                                    image_bits[current++] = 0xff;
                                }
                                break;

                            case 4:
                                for (int pr = 0, pg = 0, pb = 0, pa = 0, x = 0;
                                     x < width; x++)
                                {
                                    int b = outbuf[0][outbuf_pos + x];
                                    int g = outbuf[1][outbuf_pos + x];
                                    int r = outbuf[2][outbuf_pos + x];
                                    int a = outbuf[3][outbuf_pos + x];
                                    b += g; r += g;
                                    image_bits[current++] = (byte)(pb += b);
                                    image_bits[current++] = (byte)(pg += g);
                                    image_bits[current++] = (byte)(pr += r);
                                    image_bits[current++] = (byte)(pa += a);
                                }
                                break;
                            }
                        }
                        outbuf_pos += width;
                        prevline    = current_org;
                    }
                }
                PixelFormat format = 4 == colors ? PixelFormats.Bgra32 : PixelFormats.Bgr32;
                return(ImageData.Create(info, format, null, image_bits, stride));
            }
        }
Ejemplo n.º 2
0
        ImageData ReadV6(Stream stream, TlgMetaData info)
        {
            using (var src = new ArcView.Reader(stream))
            {
                int width          = (int)info.Width;
                int height         = (int)info.Height;
                int colors         = info.BPP / 8;
                int max_bit_length = src.ReadInt32();

                int x_block_count = ((width - 1) / TVP_TLG6_W_BLOCK_SIZE) + 1;
                int y_block_count = ((height - 1) / TVP_TLG6_H_BLOCK_SIZE) + 1;
                int main_count    = width / TVP_TLG6_W_BLOCK_SIZE;
                int fraction      = width - main_count * TVP_TLG6_W_BLOCK_SIZE;

                var image_bits   = new uint[height * width];
                var bit_pool     = new byte[max_bit_length / 8 + 5];
                var pixelbuf     = new uint[width * TVP_TLG6_H_BLOCK_SIZE + 1];
                var filter_types = new byte[x_block_count * y_block_count];
                var zeroline     = new uint[width];
                var LZSS_text    = new byte[4096];

                // initialize zero line (virtual y=-1 line)
                uint zerocolor = 3 == colors ? 0xff000000 : 0x00000000;
                for (var i = 0; i < width; ++i)
                {
                    zeroline[i] = zerocolor;
                }

                uint[] prevline       = zeroline;
                int    prevline_index = 0;

                // initialize LZSS text (used by chroma filter type codes)
                int p = 0;
                for (uint i = 0; i < 32 * 0x01010101; i += 0x01010101)
                {
                    for (uint j = 0; j < 16 * 0x01010101; j += 0x01010101)
                    {
                        LZSS_text[p++] = (byte)(i & 0xff);
                        LZSS_text[p++] = (byte)(i >> 8 & 0xff);
                        LZSS_text[p++] = (byte)(i >> 16 & 0xff);
                        LZSS_text[p++] = (byte)(i >> 24 & 0xff);
                        LZSS_text[p++] = (byte)(j & 0xff);
                        LZSS_text[p++] = (byte)(j >> 8 & 0xff);
                        LZSS_text[p++] = (byte)(j >> 16 & 0xff);
                        LZSS_text[p++] = (byte)(j >> 24 & 0xff);
                    }
                }
                // read chroma filter types.
                // chroma filter types are compressed via LZSS as used by TLG5.
                {
                    int    inbuf_size = src.ReadInt32();
                    byte[] inbuf      = src.ReadBytes(inbuf_size);
                    if (inbuf_size != inbuf.Length)
                    {
                        return(null);
                    }
                    TVPTLG5DecompressSlide(filter_types, inbuf, inbuf_size, LZSS_text, 0);
                }

                // for each horizontal block group ...
                for (int y = 0; y < height; y += TVP_TLG6_H_BLOCK_SIZE)
                {
                    int ylim = y + TVP_TLG6_H_BLOCK_SIZE;
                    if (ylim >= height)
                    {
                        ylim = height;
                    }

                    int pixel_count = (ylim - y) * width;

                    // decode values
                    for (int c = 0; c < colors; c++)
                    {
                        // read bit length
                        int bit_length = src.ReadInt32();

                        // get compress method
                        int method = (bit_length >> 30) & 3;
                        bit_length &= 0x3fffffff;

                        // compute byte length
                        int byte_length = bit_length / 8;
                        if (0 != (bit_length % 8))
                        {
                            byte_length++;
                        }

                        // read source from input
                        src.Read(bit_pool, 0, byte_length);

                        // decode values
                        // two most significant bits of bitlength are
                        // entropy coding method;
                        // 00 means Golomb method,
                        // 01 means Gamma method (not yet suppoted),
                        // 10 means modified LZSS method (not yet supported),
                        // 11 means raw (uncompressed) data (not yet supported).

                        switch (method)
                        {
                        case 0:
                            if (c == 0 && colors != 1)
                            {
                                TVPTLG6DecodeGolombValuesForFirst(pixelbuf, pixel_count, bit_pool);
                            }
                            else
                            {
                                TVPTLG6DecodeGolombValues(pixelbuf, c * 8, pixel_count, bit_pool);
                            }
                            break;

                        default:
                            throw new InvalidFormatException("Unsupported entropy coding method");
                        }
                    }

                    // for each line
                    int ft        = (y / TVP_TLG6_H_BLOCK_SIZE) * x_block_count; // within filter_types
                    int skipbytes = (ylim - y) * TVP_TLG6_W_BLOCK_SIZE;

                    for (int yy = y; yy < ylim; yy++)
                    {
                        int curline = yy * width;

                        int dir     = (yy & 1) ^ 1;
                        int oddskip = ((ylim - yy - 1) - (yy - y));
                        if (0 != main_count)
                        {
                            int start =
                                ((width < TVP_TLG6_W_BLOCK_SIZE) ? width : TVP_TLG6_W_BLOCK_SIZE) *
                                (yy - y);
                            TVPTLG6DecodeLineGeneric(
                                prevline, prevline_index,
                                image_bits, curline,
                                width, 0, main_count,
                                filter_types, ft,
                                skipbytes,
                                pixelbuf, start,
                                zerocolor, oddskip, dir);
                        }

                        if (main_count != x_block_count)
                        {
                            int ww = fraction;
                            if (ww > TVP_TLG6_W_BLOCK_SIZE)
                            {
                                ww = TVP_TLG6_W_BLOCK_SIZE;
                            }
                            int start = ww * (yy - y);
                            TVPTLG6DecodeLineGeneric(
                                prevline, prevline_index,
                                image_bits, curline,
                                width, main_count, x_block_count,
                                filter_types, ft,
                                skipbytes,
                                pixelbuf, start,
                                zerocolor, oddskip, dir);
                        }
                        prevline       = image_bits;
                        prevline_index = curline;
//                        Array.Copy (image_bits, curline, prevline, 0, width);
                    }
                }
                unsafe
                {
                    fixed(void *data = image_bits)
                    {
                        int         stride = width * 4;
                        PixelFormat format = 32 == info.BPP ? PixelFormats.Bgra32 : PixelFormats.Bgr32;
                        var         bitmap = BitmapSource.Create(width, height, ImageData.DefaultDpiX, ImageData.DefaultDpiY,
                                                                 format, null, (IntPtr)data, height * stride, stride);

                        bitmap.Freeze();
                        return(new ImageData(bitmap, info));
                    }
                }
            }
        }