/// <summary>Reads Graphics Control Extension values</summary>
        /// <exception cref="System.IO.IOException"/>
        private static void ReadGraphicControlExt(GifImageHelper.GifParameters gif)
        {
            gif.input.Read();
            // block size
            int packed = gif.input.Read();

            // packed fields
            gif.dispose = (packed & 0x1c) >> 2;
            // disposal method
            if (gif.dispose == 0)
            {
                gif.dispose = 1;
            }
            // elect to keep old image if discretionary
            gif.transparency = (packed & 1) != 0;
            gif.delay        = ReadShort(gif) * 10;
            // delay in milliseconds
            gif.transIndex = gif.input.Read();
            // transparent color index
            gif.input.Read();
        }
Beispiel #2
0
        private static bool DecodeImageData(GifImageHelper.GifParameters gif)
        {
            int  NullCode = -1;
            int  npix     = gif.iw * gif.ih;
            int  available;
            int  clear;
            int  code_mask;
            int  code_size;
            int  end_of_information;
            int  in_code;
            int  old_code;
            int  bits;
            int  code;
            int  count;
            int  i;
            int  datum;
            int  data_size;
            int  first;
            int  top;
            int  bi;
            bool skipZero = false;

            if (gif.prefix == null)
            {
                gif.prefix = new short[MAX_STACK_SIZE];
            }
            if (gif.suffix == null)
            {
                gif.suffix = new byte[MAX_STACK_SIZE];
            }
            if (gif.pixelStack == null)
            {
                gif.pixelStack = new byte[MAX_STACK_SIZE + 1];
            }
            gif.m_line_stride = (gif.iw * gif.m_bpc + 7) / 8;
            gif.m_out         = new byte[gif.m_line_stride * gif.ih];
            int pass = 1;
            int inc  = gif.interlace ? 8 : 1;
            int line = 0;
            int xpos = 0;

            //  Initialize GIF data stream decoder.
            data_size          = gif.input.Read();
            clear              = 1 << data_size;
            end_of_information = clear + 1;
            available          = clear + 2;
            old_code           = NullCode;
            code_size          = data_size + 1;
            code_mask          = (1 << code_size) - 1;
            for (code = 0; code < clear; code++)
            {
                gif.prefix[code] = 0;
                gif.suffix[code] = (byte)code;
            }
            //  Decode GIF pixel stream.
            datum = bits = count = first = top = bi = 0;
            for (i = 0; i < npix;)
            {
                if (top == 0)
                {
                    if (bits < code_size)
                    {
                        //  Load bytes until there are enough bits for a code.
                        if (count == 0)
                        {
                            // Read a new data block.
                            count = ReadBlock(gif);
                            if (count <= 0)
                            {
                                skipZero = true;
                                break;
                            }
                            bi = 0;
                        }
                        datum += (gif.block[bi] & 0xff) << bits;
                        bits  += 8;
                        bi++;
                        count--;
                        continue;
                    }
                    //  Get the next code.
                    code    = datum & code_mask;
                    datum >>= code_size;
                    bits   -= code_size;
                    //  Interpret the code
                    if (code > available || code == end_of_information)
                    {
                        break;
                    }
                    if (code == clear)
                    {
                        //  Reset decoder.
                        code_size = data_size + 1;
                        code_mask = (1 << code_size) - 1;
                        available = clear + 2;
                        old_code  = NullCode;
                        continue;
                    }
                    if (old_code == NullCode)
                    {
                        gif.pixelStack[top++] = gif.suffix[code];
                        old_code = code;
                        first    = code;
                        continue;
                    }
                    in_code = code;
                    if (code == available)
                    {
                        gif.pixelStack[top++] = (byte)first;
                        code = old_code;
                    }
                    while (code > clear)
                    {
                        gif.pixelStack[top++] = gif.suffix[code];
                        code = gif.prefix[code];
                    }
                    first = gif.suffix[code] & 0xff;
                    //  Add a new string to the string table,
                    if (available >= MAX_STACK_SIZE)
                    {
                        break;
                    }
                    gif.pixelStack[top++] = (byte)first;
                    gif.prefix[available] = (short)old_code;
                    gif.suffix[available] = (byte)first;
                    available++;
                    if ((available & code_mask) == 0 && available < MAX_STACK_SIZE)
                    {
                        code_size++;
                        code_mask += available;
                    }
                    old_code = in_code;
                }
                //  Pop a pixel off the pixel stack.
                top--;
                i++;
                SetPixel(xpos, line, gif.pixelStack[top], gif);
                ++xpos;
                if (xpos >= gif.iw)
                {
                    xpos  = 0;
                    line += inc;
                    if (line >= gif.ih)
                    {
                        if (gif.interlace)
                        {
                            do
                            {
                                pass++;
                                switch (pass)
                                {
                                case 2: {
                                    line = 4;
                                    break;
                                }

                                case 3: {
                                    line = 2;
                                    inc  = 4;
                                    break;
                                }

                                case 4: {
                                    line = 1;
                                    inc  = 2;
                                    break;
                                }

                                default: {
                                    // this shouldn't happen
                                    line = gif.ih - 1;
                                    inc  = 0;
                                    break;
                                }
                                }
                            }while (line >= gif.ih);
                        }
                        else
                        {
                            // this shouldn't happen
                            line = gif.ih - 1;
                            inc  = 0;
                        }
                    }
                }
            }
            return(skipZero);
        }
Beispiel #3
0
        /// <summary>Reads next frame image</summary>
        private static void ReadFrame(GifImageHelper.GifParameters gif)
        {
            // (sub)image position & size
            gif.ix = ReadShort(gif);
            gif.iy = ReadShort(gif);
            gif.iw = ReadShort(gif);
            gif.ih = ReadShort(gif);
            int packed = gif.input.Read();

            // 1 - local color table flag
            gif.lctFlag = (packed & 0x80) != 0;
            // 2 - interlace flag
            gif.interlace = (packed & 0x40) != 0;
            // 3 - sort flag
            // 4-5 - reserved
            // 6-8 - local color table size
            gif.lctSize = 2 << (packed & 7);
            gif.m_bpc   = NewBpc(gif.m_gbpc);
            if (gif.lctFlag)
            {
                // read table
                gif.m_curr_table = ReadColorTable((packed & 7) + 1, gif);
                gif.m_bpc        = NewBpc((packed & 7) + 1);
            }
            else
            {
                gif.m_curr_table = gif.m_global_table;
            }
            if (gif.transparency && gif.transIndex >= gif.m_curr_table.Length / 3)
            {
                gif.transparency = false;
            }
            // Acrobat 5.05 doesn't like this combination
            if (gif.transparency && gif.m_bpc == 1)
            {
                byte[] tp = new byte[12];
                Array.Copy(gif.m_curr_table, 0, tp, 0, 6);
                gif.m_curr_table = tp;
                gif.m_bpc        = 2;
            }
            // decode pixel data
            bool skipZero = DecodeImageData(gif);

            if (!skipZero)
            {
                Skip(gif);
            }
            try {
                Object[] colorspace = new Object[4];
                colorspace[0] = "/Indexed";
                colorspace[1] = "/DeviceRGB";
                int len = gif.m_curr_table.Length;
                colorspace[2] = len / 3 - 1;
                colorspace[3] = PdfEncodings.ConvertToString(gif.m_curr_table, null);
                IDictionary <String, Object> ad = new Dictionary <String, Object>();
                ad.Put("ColorSpace", colorspace);
                RawImageData img = new RawImageData(gif.m_out, ImageType.GIF);
                RawImageHelper.UpdateRawImageParameters(img, gif.iw, gif.ih, 1, gif.m_bpc, gif.m_out);
                RawImageHelper.UpdateImageAttributes(img, ad);
                gif.image.AddFrame(img);
                if (gif.transparency)
                {
                    img.SetTransparency(new int[] { gif.transIndex, gif.transIndex });
                }
            }
            catch (Exception e) {
                throw new iText.IO.IOException(iText.IO.IOException.GifImageException, e);
            }
        }
Beispiel #4
0
 /// <summary>Reads next 16-bit value, LSB first</summary>
 private static int ReadShort(GifImageHelper.GifParameters gif)
 {
     // read 16-bit value, LSB first
     return(gif.input.Read() | gif.input.Read() << 8);
 }