コード例 #1
0
        public bool UpdateVariables(IList <FileFragment> list, ref int index, ref List <int> changed)
        {
            //Starting saftey thingy
            if (index == 0)
            {
                (list[index] as GIFFileFragment).SectionType = SectionTypes.Header;
                return(false);
            }

            List <SectionTypes> SectionTypeQueue = new List <SectionTypes>();
            bool exists = new PackedGlobalColorTableInfo(BinaryFileInterpreter.ReadFileAs <byte>(list[3].Path)).Exists;

            if (index <= (exists ? 6 : 5))
            {
                SectionTypeQueue.AddRange(new SectionTypes[]
                {
                    SectionTypes.Header,
                    SectionTypes.Width,
                    SectionTypes.Height,
                    SectionTypes.GlobalColorTablePacked,
                    SectionTypes.ColorIndex,
                    SectionTypes.PixelAspectRatio
                });
                if (exists)
                {
                    SectionTypeQueue.Add(SectionTypes.ColorTable);
                }
                index = 0;
            }
            else
            {
                index = FindSectionOfType(list, index, SectionTypes.Sentinal, SectionTypes.Trailer);
                switch ((list[index] as GIFFileFragment).SectionType)
                {
                case (SectionTypes.Trailer):
                    index++;
                    goto case (SectionTypes.Sentinal);

                case (SectionTypes.Sentinal):
                    switch (BinaryFileInterpreter.ReadFileAs <byte>(list[index].Path))
                    {
                    case ((byte)','):
                        SectionTypeQueue.AddRange(new SectionTypes[]
                        {
                            SectionTypes.Sentinal,
                            SectionTypes.XOffset,
                            SectionTypes.YOffset,
                            SectionTypes.Width,
                            SectionTypes.Height,
                            SectionTypes.LocalColorTablePacked
                        });
                        bool lctexists = new PackedLocalColorTableInfo(BinaryFileInterpreter.ReadFileAs <byte>(list[index + 5].Path)).Exists;
                        if (lctexists)
                        {
                            SectionTypeQueue.Add(SectionTypes.ColorTable);
                        }
                        SectionTypeQueue.Add(SectionTypes.Unknown);         //Unencoded length?
                        //Need to +8 if the local color table exists
                        SectionTypeQueue.AddRange(LabelDataSections(list, index + (lctexists ? 8 : 7), true));
                        break;

                    case ((byte)'!'):
                        SectionTypeQueue.AddRange(new SectionTypes[]
                        {
                            SectionTypes.Sentinal,
                            SectionTypes.ExtensionType
                        });
                        switch (BinaryFileInterpreter.ReadFileAs <byte>(list[index + 1].Path))
                        {
                        //Plain Text
                        case (0x01):
                            SectionTypeQueue.AddRange(new SectionTypes[]
                            {
                                SectionTypes.Length,
                                SectionTypes.XOffset,
                                SectionTypes.YOffset,
                                SectionTypes.Width,
                                SectionTypes.Height,
                                SectionTypes.Width,
                                SectionTypes.Height,
                                SectionTypes.ColorIndex,
                                SectionTypes.ColorIndex
                            });
                            SectionTypeQueue.AddRange(LabelDataSections(list, index + 11, false));
                            break;

                        //Graphics Control
                        case (0xF9):
                            SectionTypeQueue.AddRange(new SectionTypes[]
                            {
                                SectionTypes.Length,
                                SectionTypes.GraphicsControlPacked,
                                SectionTypes.DelayTime,
                                SectionTypes.ColorIndex
                            });
                            break;

                        //Comment
                        case (0xFE):
                            SectionTypeQueue.AddRange(LabelDataSections(list, index + 2, false));
                            break;

                        //Application
                        case (0xFF):
                            SectionTypeQueue.AddRange(new SectionTypes[]
                            {
                                SectionTypes.Length,
                                SectionTypes.ApplicationIdentifier,
                                SectionTypes.ApplicationAuthCode
                            });
                            SectionTypeQueue.AddRange(LabelDataSections(list, index + 5, false));
                            break;

                        //Unknown
                        default:
                            SectionTypeQueue.Add(SectionTypes.Unknown);
                            break;
                        }
                        SectionTypeQueue.Add(SectionTypes.Trailer);
                        break;

                    case ((byte)';'):
                        SectionTypeQueue.Add(SectionTypes.EndOfFile);
                        EndOfFileIndex = index;         //TODO check this again
                        break;

                    default:
                        SectionTypeQueue.Add(SectionTypes.Unknown);
                        break;
                    }
                    break;
                }
            }

            bool didWork = false;

            for (int i = 0; i < SectionTypeQueue.Count; i++) //TODO is this confusing having i++ all the way up here?
            {
                if ((list[index] as GIFFileFragment).SectionType != SectionTypeQueue[i])
                {
                    (list[index] as GIFFileFragment).SectionType = SectionTypeQueue[i];
                    changed.Add(index);
                    didWork = true;
                }
                index++;
            }
            return(didWork);
        }
コード例 #2
0
        //I now have a newfound hatred for .gif after writing this code
        public void ParseTo(string filename, ref List <FileFragmentReference> output)
        {
            using (BinaryReader br = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read)))
            {
                //Header
                string fileHeader = br.ReadString(6);
                output.Add(new GIFFileFragment(0, 6, new string[] { "Header", "Header" },
                                               headerTypes.Contains(fileHeader) ? Validity.Valid : Validity.HardInvalid,
                                               $"File header = {fileHeader}", SectionTypes.Header));

                //Logical Screen Descriptor
                short LSDwidth = br.ReadInt16();
                output.Add(new GIFFileFragment(6, 2, new string[] { "Header", "Logical Screen Descriptor", "Width" },
                                               (LSDwidth >= 0) ? Validity.Valid : Validity.HardInvalid,
                                               $"Width = {LSDwidth}", SectionTypes.Width));
                short LSDheight = br.ReadInt16();
                output.Add(new GIFFileFragment(8, 2, new string[] { "Header", "Logical Screen Descriptor", "Height" },
                                               (LSDheight >= 0) ? Validity.Valid : Validity.HardInvalid,
                                               $"Height = {LSDheight}", SectionTypes.Height));

                PackedGlobalColorTableInfo globalColorTableInfo = new PackedGlobalColorTableInfo(br.ReadByte());

                //TODO validate all of these
                output.Add(new GIFFileFragment(10, 1, new string[] { "Header", "Packed Byte" },
                                               globalColorTableInfo.ToString(), SectionTypes.GlobalColorTablePacked));

                output.Add(new GIFFileFragment(11, 1, new string[] { "Header", "Background Color Index" },
                                               Validity.Unknown, SectionTypes.ColorIndex));

                output.Add(new GIFFileFragment(12, 1, new string[] { "Header", "Pixel Aspect Ratio" },
                                               Validity.Unknown, SectionTypes.PixelAspectRatio));

                br.BaseStream.Seek(2, SeekOrigin.Current);

                int GCTLength = 3 * (1 << (globalColorTableInfo.BitsPerEntry + 1));
                if (globalColorTableInfo.Exists)
                {
                    //TODO split more?
                    output.Add(new GIFFileFragment(13, (ulong)GCTLength,
                                                   new string[] { "Header", "Global Color Table" },
                                                   SectionTypes.ColorTable));
                    br.BaseStream.Seek(GCTLength, SeekOrigin.Current);
                }

                //Loop through sections
                //TODO seperate section counts for extensions and images
                for (int section = 1; br.BaseStream.Position < br.BaseStream.Length; section++)
                {
                    //Switch off of section header
                    switch (br.ReadByte())
                    {
                        #region Image
                    case ((byte)','):
                        output.Add(new GIFFileFragment(br.BaseStream.Position - 1, 1,
                                                       new string[] { $"Image {section}", "Sentinal" },
                                                       Validity.Valid, SectionTypes.Sentinal)); //I would really hope this is valid if we've made it to this case...

                        output.AddRange(ReadLeftTopWidthHeight(br, $"Image {section}", LSDwidth, LSDheight));

                        PackedLocalColorTableInfo localColorTableInfo = new PackedLocalColorTableInfo(br.ReadByte());

                        //TODO Validate?
                        output.Add(new GIFFileFragment(br.BaseStream.Position - 1, 1,
                                                       new string[] { $"Image {section}", "Packed Byte" },
                                                       localColorTableInfo.ToString(), SectionTypes.LocalColorTablePacked));

                        if (localColorTableInfo.Exists)
                        {
                            int LCTLength = 3 * (1 << (localColorTableInfo.BitsPerEntry + 1));
                            //TODO split more?
                            output.Add(new GIFFileFragment(br.BaseStream.Position, LCTLength,
                                                           new string[] { $"Image {section}", "Local Color Table" }, SectionTypes.ColorTable));
                            br.BaseStream.Seek(LCTLength, SeekOrigin.Current);
                        }

                        //TODO what even is this????????
                        output.Add(new GIFFileFragment(br.BaseStream.Position, 1, new string[] { $"Image {section}", "Unencoded Length" },
                                                       br.ReadByte().ToString(), SectionTypes.Unknown /*TODO uncompressed length?*/));

                        output.AddRange(ReadDataSections(br, $"Image {section}", "Image Data", false, true, Validity.OutOfScope));
                        break;
                        #endregion

                        #region Extension
                    case ((byte)'!'):
                        output.Add(new GIFFileFragment(br.BaseStream.Position - 1, 1,
                                                       new string[] { $"Extension {section}", "Sentinal" }, Validity.Valid, SectionTypes.Sentinal));

                        byte type = br.ReadByte();     //TODO Validate this by making a list of all types
                        output.Add(new GIFFileFragment(br.BaseStream.Position - 1, 1,
                                                       new string[] { $"Extension {section}", "Type" }, Validity.Unchecked, SectionTypes.ExtensionType));
                        switch (type)
                        {
                            #region Plain Text
                        case (0x01):
                            byte plainTextSize = br.ReadByte();         //Should always be 0x0Ch
                            output.Add(new GIFFileFragment(br.BaseStream.Position - 1, 1,
                                                           new string[] { $"Extension {section}", "Plain Text Block Length" },
                                                           plainTextSize == 0x0C ? Validity.Valid : Validity.HardInvalid, SectionTypes.Length)); //tbh, this value not being 0x0C would be a hard invalid for filephoenix rn

                            output.AddRange(ReadLeftTopWidthHeight(br, $"Extension {section}", LSDwidth, LSDheight));

                            //TODO validate one byte
                            output.Add(new GIFFileFragment(br.BaseStream.Position, 1,
                                                           new string[] { $"Extension {section}", "Character Cell Width" }, Validity.Valid,
                                                           br.ReadByte().ToString(), SectionTypes.Width));
                            output.Add(new GIFFileFragment(br.BaseStream.Position, 1,
                                                           new string[] { $"Extension {section}", "Character Cell Height" }, Validity.Valid,
                                                           br.ReadByte().ToString(), SectionTypes.Height));

                            //TODO this is flawed since it needs to fall back to the Local Color table if !GCTExists
                            //Also, if both the GCT and LCT aren't there? Oh boy...
                            int maxIndex = GCTLength / 3;

                            byte TextColorIndex = br.ReadByte();
                            output.Add(new GIFFileFragment(br.BaseStream.Position, 1,
                                                           new string[] { $"Extension {section}", "Text Color Index" },
                                                           TextColorIndex < maxIndex ? Validity.Valid : Validity.HardInvalid,
                                                           TextColorIndex.ToString(), SectionTypes.ColorIndex));

                            byte BackColorIndex = br.ReadByte();
                            output.Add(new GIFFileFragment(br.BaseStream.Position, 1,
                                                           new string[] { $"Extension {section}", "Text Background Color Index" },
                                                           BackColorIndex < maxIndex ? Validity.Valid : Validity.HardInvalid, BackColorIndex.ToString(),
                                                           SectionTypes.ColorIndex));

                            output.AddRange(ReadDataSections(br, $"Extension {section}", "Plain Text", true, false, Validity.Valid));
                            break;
                            #endregion

                            #region Graphics Control
                        case (0xF9):
                            byte graphicsControlSize = br.ReadByte();         //Should always be 0x04
                            output.Add(new GIFFileFragment(br.BaseStream.Position - 1, 1,
                                                           new string[] { $"Extension {section}", "Graphics Control Block Length" },
                                                           graphicsControlSize == 0x04 ? Validity.Valid : Validity.HardInvalid, SectionTypes.Length));

                            PackedGraphicsControlInfo graphicsControlInfo = new PackedGraphicsControlInfo(br.ReadByte());

                            output.Add(new GIFFileFragment(br.BaseStream.Position - 1, 1,
                                                           new string[] { $"Extension {section}", "Packed Byte" }, graphicsControlInfo.ToString(),
                                                           SectionTypes.GraphicsControlPacked));

                            //In Centiseconds (hundreths of seconds)
                            short DelayTime = br.ReadInt16();
                            output.Add(new GIFFileFragment(br.BaseStream.Position - 2, 2,
                                                           new string[] { $"Extension {section}", "Delay Time" },
                                                           0 <= DelayTime ? Validity.Valid : Validity.HardInvalid, //TODO check if this is hard or soft
                                                           SectionTypes.DelayTime));

                            output.Add(new GIFFileFragment(br.BaseStream.Position, 1,
                                                           new string[] { $"Extension {section}", "Transparent Color Index" },
                                                           br.ReadByte() < GCTLength / 3 ? Validity.Valid : Validity.HardInvalid, //TODO < or <=?
                                                           SectionTypes.ColorIndex));
                            break;
                            #endregion

                            #region Comment
                        case (0xFE):
                            output.AddRange(ReadDataSections(br, $"Extension {section}", "Comment", true, false, Validity.Valid));
                            break;
                            #endregion

                            #region Application
                        case (0xFF):
                            //TODO kind of unrealistic to parse all possible application chunks... right?
                            byte applicationSize = br.ReadByte();         //Should always be 0x0B
                            output.Add(new GIFFileFragment(br.BaseStream.Position - 1, 1,
                                                           new string[] { $"Extension {section}", "Application Extension Length" },
                                                           applicationSize == 0x0B ? Validity.Valid : Validity.HardInvalid,
                                                           SectionTypes.Length));

                            output.Add(new GIFFileFragment(br.BaseStream.Position, 8,
                                                           new string[] { $"Extension {section}", "Identifier" },
                                                           Validity.Valid, br.ReadString(8), SectionTypes.ApplicationIdentifier));

                            output.Add(new GIFFileFragment(br.BaseStream.Position, 3,
                                                           new string[] { $"Extension {section}", "Authentication Code" },
                                                           Validity.Valid, string.Join(", ", br.ReadBytes(3)), //This could be human readable, or not, so byte[] jsut to be sure
                                                           SectionTypes.ApplicationAuthCode));

                            output.AddRange(ReadDataSections(br, $"Extension {section}", "Application", false, false, Validity.Valid));
                            break;
                            #endregion

                            #region Unknown
                        default:
                            output.Add(FindNextSection(br, true,
                                                       new string[] { $"Extension {section}", "Unknown Extension Data" }, Validity.Unknown));
                            break;
                            #endregion
                        }
                        output.Add(new GIFFileFragment(br.BaseStream.Position, 1,
                                                       new string[] { $"Extension {section}", "Extension Block Trailer" },
                                                       br.ReadByte() == 0 ? Validity.Valid : Validity.SoftInvalid, SectionTypes.Trailer));
                        break;
                        #endregion

                        #region End of file
                    case ((byte)';'):
                        output.Add(new GIFFileFragment(br.BaseStream.Position - 1, 1,
                                                       new string[] { $"End Of File Marker {section}" },
                                                       (br.BaseStream.Position != br.BaseStream.Length || EndOfFileIndex != null) ? Validity.SoftInvalid : Validity.Valid
                                                       , SectionTypes.EndOfFile));
                        EndOfFileIndex = output.Count - 1;
                        break;
                        #endregion

                        #region Unknown
                    default:
                        br.BaseStream.Position--;
                        output.Add(FindNextSection(br, false, new string[] { $"Unknown Section {section}" }, Validity.HardInvalid));
                        break;
                        #endregion
                    }
                }
            }
        }