CSharpImageLibrary.Headers.GIF_Header.Load C# (CSharp) Method

Load() protected method

Read header from stream.
protected Load ( Stream stream ) : long
stream Stream Stream containing header.
return long
        protected override long Load(Stream stream)
        {
            base.Load(stream);

            // Read partial header to determine full header size
            byte[] temp = new byte[19];  // for later
            stream.Read(temp, 0, 13); // Partial header only 13 bytes long

            if (!CheckIdentifier(temp))
                throw new FormatException("Stream is not a GIF Image");

            // Read version (not used)
            Version = "8";
            for(int i = 4; i < 6; i++)
                Version += (char)temp[i];

            if (Version != "89a" && Version != "87a")
                Console.WriteLine($"Header version ({Version}) is incorrect. Must be 89a or 87a.");

            // Canvas Width
            CanvasWidth = BitConverter.ToInt16(temp, 6);

            // Canvas Height
            CanvasHeight = BitConverter.ToInt16(temp, 8);

            // Packed Field
            byte tempByte = temp[9];
            HasGlobalColourTable = (tempByte & 0x80) == 0x80;
            ColourResolution_BPP = tempByte & 0x70;
            ColourSortFlag = (tempByte & 0x08) == 0x08;
            GlobalColourTableSize = tempByte & 0x07;

            // Background colour index
            BackgroundColourIndex = temp[10];
            PixelAspectRatio = temp[11];

            // Read colour table
            if (HasGlobalColourTable)
            {
                int estimatedSize = (int)Math.Pow(2, ColourResolution_BPP + 1);
                if (GlobalColourTableSize != estimatedSize)
                    Console.WriteLine($"Global table size incorrect in header. Header = {GlobalColourTableSize}, should be {estimatedSize}");

                GlobalColourTable = stream.ReadBytes(estimatedSize);
            }

            while (stream.Position < stream.Length)
            {
                stream.Read(temp, 0, 19);

                // Need to search for some reason
                bool found = false;
                for (int i = 0; i < 19; i++)
                {
                    if (temp[i] == 0x21 || temp[i] == 0x2C)
                    {
                        stream.Position -= (19-i);
                        found = true;
                        break;
                    }
                }

                // Nothing of interest found, start again from new position
                if (!found)
                    continue;

                // Refresh from new position
                stream.Read(temp, 0, 19);

                if (temp[0] == 0x21)  // Extension indicator
                {
                    if (temp[1] == 0xFF)  // Animated properties indicator
                    {
                        // Ignore bytes 3-16 (1 based)
                        AnimationLoopCount = BitConverter.ToInt16(temp, 16);
                    }
                    else if (temp[1] == 0xF9)
                    {
                        // Skip byte size (why is it even there?)
                        DisposalMethod = temp[3] & 0x1C;
                        UserInputFlag = (temp[3] & 0x02) == 1;
                        TransparentColourFlag = (temp[3] & 0x01) == 1;
                        AnimationDelayTime = BitConverter.ToInt16(temp, 4);
                        TransparentColourIndex = temp[6];
                    }
                    else
                        stream.Seek(-18, SeekOrigin.Current); // Skip ignored optionals ideally, BUT this could also be false match i.e. not an extension block, so we can only skip that identifier and keep looking.
                }
                else
                    break;
            }

            // Read first image descriptor block
            if (temp[0] != 0x2C)
                throw new InvalidDataException($"Image Descriptor incorrect. Got: {temp[0]}, expected: {0x2C}.");

            ImageLeft = BitConverter.ToInt16(temp, 1);
            ImageTop = BitConverter.ToInt16(temp, 3);
            Width = BitConverter.ToInt16(temp, 5);
            Height = BitConverter.ToInt16(temp, 7);

            // Packed byte
            tempByte = temp[9];
            HasLocalColourTables = (tempByte & 0x80) == 1;
            IsInterlaced = (tempByte & 0x70) == 1;
            LocalSortFlag = (tempByte & 0x40) == 1;
            LocalColourTableSize = tempByte & 0x07;

            return stream.Position;
        }