/// <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(); }
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); }
/// <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); } }
/// <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); }