public static GraphicRenderingBlock Create(byte[] data, ref int offset) { GraphicRenderingBlock grb = new GraphicRenderingBlock(); // // Image descriptor. // Debug.Assert(data[offset] == IMAGE_SEPARATOR); offset++; grb.ImageLeftPosition = RawData.FetchLittleUshort(data, ref offset); grb.ImageTopPosition = RawData.FetchLittleUshort(data, ref offset); grb.ImageWidth = RawData.FetchLittleUshort(data, ref offset); grb.ImageHeight = RawData.FetchLittleUshort(data, ref offset); byte pak = data[offset++]; grb.LocalColorTableFlag = (pak & 0x80) != 0; grb.InterlaceFlag = (pak & 0x40) != 0; grb.SortFlag = (pak & 0x20) != 0; grb.LocalColorTableSize = (byte)(pak & 0x07); // // Local color table (optional). // if (grb.LocalColorTableFlag) { // Size is expressed as a power of 2. TableSize=7 is 256 entries, 3 bytes each. int tableLen = 1 << (grb.LocalColorTableSize + 1); grb.LocalColorTable = new byte[tableLen * 3]; for (int i = 0; i < tableLen * 3; i++) { grb.LocalColorTable[i] = data[offset++]; } } else { grb.LocalColorTable = new byte[0]; } // // Table based image data. // grb.ImageData = data; grb.ImageStartOffset = offset++; while (data[offset] != 0) { offset += data[offset] + 1; } grb.ImageEndOffset = offset++; return(grb); }
private bool Unpack(byte[] gifData) { // // Header. Signature ("GIF") + version ("87a" or "89a"). // if (RawData.CompareArrays(gifData, 0, GIF87A, 0, GIF87A.Length)) { FileVer = FileVersion.Gif87a; } else if (RawData.CompareArrays(gifData, 0, GIF89A, 0, GIF87A.Length)) { FileVer = FileVersion.Gif89a; } else { Debug.WriteLine("GIF signature not found"); return(false); } //Debug.WriteLine("GIF: found signature " + FileVer); byte pak; // // Logical screen descriptor. // int offset = GIF87A.Length; LogicalScreenWidth = RawData.FetchLittleUshort(gifData, ref offset); LogicalScreenHeight = RawData.FetchLittleUshort(gifData, ref offset); pak = gifData[offset++]; GlobalColorTableFlag = (pak & 0x80) != 0; ColorResolution = (byte)((pak >> 4) & 0x07); SortFlag = (pak & 0x08) != 0; GlobalColorTableSize = (byte)(pak & 0x07); BackgroundColorIndex = gifData[offset++]; PixelAspectRatio = gifData[offset++]; // // Global color table. // if (GlobalColorTableFlag) { // Size is expressed as a power of 2. TableSize=7 is 256 entries, 3 bytes each. int tableLen = 1 << (GlobalColorTableSize + 1); GlobalColorTable = new byte[tableLen * 3]; for (int i = 0; i < tableLen * 3; i++) { GlobalColorTable[i] = gifData[offset++]; } } else { GlobalColorTable = new byte[0]; } // // Various blocks follow. Continue until EOF is reached. // GraphicControlExtension lastGce = null; while (true) { if (offset >= gifData.Length) { Debug.WriteLine("Error: GIF unpacker ran off end of buffer"); return(false); } if (gifData[offset] == GIF_TRAILER) { break; } else if (gifData[offset] == EXTENSION_INTRODUCER) { if (gifData[offset + 1] == GRAPHIC_CONTROL_LABEL) { lastGce = GraphicControlExtension.Create(gifData, ref offset); } else { Debug.WriteLine("Skipping unknown extension 0x" + gifData[offset + 1].ToString("x2")); offset += 2; while (gifData[offset] != 0) { offset += gifData[offset] + 1; } offset++; } } else if (gifData[offset] == IMAGE_SEPARATOR) { GraphicRenderingBlock grb = GraphicRenderingBlock.Create(gifData, ref offset); if (grb != null) { if (lastGce != null) { grb.GraphicControlExt = lastGce; } ImageBlocks.Add(grb); } // this resets after the image lastGce = null; } else { Debug.WriteLine("Found unknown block start 0x" + gifData[offset].ToString("x2")); return(false); } } return(true); }