private static void CheckExtension(ApplicationExtension ext)
        {
            // Check application identifier / authentication code
            Assert.AreEqual("BIGPANTS", ext.ApplicationIdentifier);
            Assert.AreEqual("1.3", ext.ApplicationAuthenticationCode);
            Assert.AreEqual(ErrorState.Ok, ext.ConsolidatedState);

            // Check number of blocks in application data
            Assert.AreEqual(3, ext.ApplicationData.Count);

            // Check application data block 1
            Assert.AreEqual(5, ext.ApplicationData[0].DeclaredBlockSize);
            Assert.AreEqual(5, ext.ApplicationData[0].ActualBlockSize);
            Assert.AreEqual((byte)'H', ext.ApplicationData[0][0]);
            Assert.AreEqual((byte)'E', ext.ApplicationData[0][1]);
            Assert.AreEqual((byte)'L', ext.ApplicationData[0][2]);
            Assert.AreEqual((byte)'L', ext.ApplicationData[0][3]);
            Assert.AreEqual((byte)'O', ext.ApplicationData[0][4]);
            Assert.AreEqual(ErrorState.Ok, ext.ApplicationData[0].ConsolidatedState);

            // Check application data block 2
            Assert.AreEqual(5, ext.ApplicationData[1].DeclaredBlockSize);
            Assert.AreEqual(5, ext.ApplicationData[1].ActualBlockSize);
            Assert.AreEqual((byte)'W', ext.ApplicationData[1][0]);
            Assert.AreEqual((byte)'O', ext.ApplicationData[1][1]);
            Assert.AreEqual((byte)'R', ext.ApplicationData[1][2]);
            Assert.AreEqual((byte)'L', ext.ApplicationData[1][3]);
            Assert.AreEqual((byte)'D', ext.ApplicationData[1][4]);
            Assert.AreEqual(ErrorState.Ok, ext.ApplicationData[1].ConsolidatedState);
        }
        private void ConstructorStreamTest(bool xmlDebugging)
        {
            Stream s = new MemoryStream();

            WriteApplicationIdentifier(s);
            WriteHello(s);
            WriteWorld(s);
            WriteBlockTerminator(s);

            s.Seek(0, SeekOrigin.Begin);               // point to beginning of stream

            _ext = new ApplicationExtension(s, xmlDebugging);

            CheckExtension(_ext);

            // Check block terminator
            Assert.AreEqual(0, _ext.ApplicationData[2].DeclaredBlockSize);
            Assert.AreEqual(0, _ext.ApplicationData[2].ActualBlockSize);
            Assert.AreEqual(ErrorState.Ok,
                            _ext.ApplicationData[2].ConsolidatedState);

            if (xmlDebugging)
            {
                Assert.AreEqual(ExpectedDebugXml, _ext.DebugXml);
            }
        }
        public void ConstructorIdentificationBlockTooLongTest()
        {
            ReportStart();
            byte[] identification = new byte[]
            {
                (byte)'N',
                (byte)'E',
                (byte)'T',
                (byte)'S',
                (byte)'C',
                (byte)'A',
                (byte)'P',
                (byte)'E',
                (byte)'2',
                (byte)'.',
                (byte)'0',
                (byte)'1',
            };
            DataBlock identificationBlock = new DataBlock(11, identification);
            DataBlock data = new DataBlock(1, new byte[] { 1 });
            Collection <DataBlock> applicationData = new Collection <DataBlock>();

            applicationData.Add(data);
            _ext = new ApplicationExtension(identificationBlock, applicationData);

            Assert.AreEqual("NETSCAPE", _ext.ApplicationIdentifier);
            Assert.AreEqual("2.0", _ext.ApplicationAuthenticationCode);
            Assert.AreEqual(identificationBlock, _ext.IdentificationBlock);
            Assert.AreEqual(applicationData, _ext.ApplicationData);
            Assert.AreEqual(ErrorState.IdentificationBlockTooLong, _ext.ErrorState);
            ReportEnd();
        }
Пример #4
0
        private static void CheckNetscapeExtension(Stream s, int loopCount)
        {
            // check netscape extension
            ApplicationExtension ae = new ApplicationExtension(s);

            Assert.AreEqual(ErrorState.Ok, ae.ConsolidatedState);
            NetscapeExtension ne = new NetscapeExtension(ae);

            Assert.AreEqual(ErrorState.Ok, ne.ConsolidatedState);
            Assert.AreEqual(loopCount, ne.LoopCount);
        }
Пример #5
0
        public void StartGif()
        {
            Width                = (ushort)(Frames[0].Texture.width);
            Height               = (ushort)(Frames[0].Texture.height);
            globalColorTable     = new List <Color>();
            applicationExtension = new ApplicationExtension();
            // byteList = new List<byte>();
            encoded        = new Dictionary <int, List <byte> >();
            colorTables    = new List <Color> [Frames.Count];
            distinctColors = new Dictionary <int, List <Color> >();

            currentStep++;
        }
Пример #6
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //services.AddDbContext<TestDBContext>(options =>
            //            options.UseSqlServer(Configuration.GetConnectionString("TestDBConnection")));

            //services.AddDatabaseDeveloperPageExceptionFilter();
            services.AddControllersWithViews();
            // In production, the Angular files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/dist";
            });
            ApplicationExtension.RegisterApplicationDependencies(services, this.Configuration);
        }
        public void WriteToStreamTest()
        {
            ReportStart();
            byte[] identificationData = new byte[]
            {
                (byte)'B', (byte)'I', (byte)'G', (byte)'P',
                (byte)'A', (byte)'N', (byte)'T', (byte)'S',
                (byte)'1', (byte)'.', (byte)'3'
            };
            DataBlock identificationBlock = new DataBlock(11, identificationData);

            byte[] helloData = new byte[]
            {
                (byte)'H', (byte)'E', (byte)'L', (byte)'L', (byte)'O'
            };
            DataBlock helloBlock = new DataBlock(5, helloData);

            byte[] worldData = new byte[]
            {
                (byte)'W', (byte)'O', (byte)'R', (byte)'L', (byte)'D'
            };
            DataBlock worldBlock = new DataBlock(5, worldData);

            DataBlock blockTerminator = new DataBlock(0, new byte[] { 0 });

            Collection <DataBlock> applicationData = new Collection <DataBlock>();

            applicationData.Add(helloBlock);
            applicationData.Add(worldBlock);
            applicationData.Add(blockTerminator);

            _ext = new ApplicationExtension(identificationBlock, applicationData);

            MemoryStream s = new MemoryStream();

            _ext.WriteToStream(s);
            s.Seek(0, SeekOrigin.Begin);

            ApplicationExtension e = new ApplicationExtension(s);

            CheckExtension(e);
            ReportEnd();
        }
Пример #8
0
        public override void ShowDialog(PropertyItemValue propertyValue, IInputElement commandSource)
        {
            if (propertyValue == null)
            {
                return;
            }
            if (propertyValue.ParentProperty.IsReadOnly)
            {
                return;
            }

            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.AllowMultiple = false;

            openFileDialog.Filters = new List <FileDialogFilter>
            {
                new FileDialogFilter()
                {
                    Name         = "Image Files (*.jpg, *.png, *.bmp)"
                    , Extensions = new List <string>()
                    {
                        "jpg", "png", "bmp"
                    }
                }
            };

            var mainWindow = ApplicationExtension.GetMainWindow();

            openFileDialog.ShowAsync(mainWindow).ContinueWith(x =>
            {
                if (x.IsFaulted == false)
                {
                    string result = x.Result.FirstOrDefault();

                    if (string.IsNullOrEmpty(result) == false)
                    {
                        propertyValue.StringValue = result;
                    }
                }
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }
Пример #9
0
        public FileBrowserDialogPropertyValueEditor()
        {
            //little ugly search for the resource
            var mainWindow = ApplicationExtension.GetMainWindow();

            if (mainWindow != null)
            {
                object res = null;
                foreach (var item in mainWindow.FindChildren <UserControl>(true))
                {
                    if (item.TryFindResource(LocalResources.FileBrowserEditorKey, out res))
                    {
                        break;
                    }
                }


                InlineTemplate = res;
            }
        }
Пример #10
0
        public override void ShowDialog(PropertyItemValue propertyValue, IInputElement commandSource)
        {
            if (propertyValue == null)
            {
                return;
            }
            if (propertyValue.ParentProperty.IsReadOnly)
            {
                return;
            }

            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.AllowMultiple = false;

            var property = propertyValue.ParentProperty;

            if (property != null)
            {
                var optionsAttribute = (OpenFileDialogOptionsAttribute)property.Attributes[typeof(OpenFileDialogOptionsAttribute)];
                if (optionsAttribute != null)
                {
                    optionsAttribute.ConfigureDialog(openFileDialog);
                }
            }

            var mainWindow = ApplicationExtension.GetMainWindow();

            openFileDialog.ShowAsync(mainWindow).ContinueWith(x =>
            {
                if (x.IsFaulted == false)
                {
                    string result = x.Result.FirstOrDefault();

                    if (string.IsNullOrEmpty(result) == false)
                    {
                        propertyValue.StringValue = result;
                    }
                }
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }
        /// <summary>
        /// Populates the application extension byte[] from the source image, and performs lexical parsing on the array.
        /// </summary>
        /// <param name="bytes"></param>
        public static ApplicationExtension ParseApplicationExtension(byte[] bytes)
        {
            ApplicationExtension ae = new ApplicationExtension()
            {
                Bytes               = (byte[])bytes.Clone(),
                TotalBlockLength    = bytes.Length,
                ExtensionIntroducer = bytes[0],
                ExtensionLabel      = bytes[1],
                MainBlockSize       = bytes[2],
                MainBlock           = new byte[bytes[2]]
            };

            Array.Copy(bytes, 3, ae.MainBlock, 0, ae.MainBlockSize);

            ae.SubBlockSize = ae.Bytes[ae.MainBlockSize + 3];

            if (ae.IsNetscapeExtension())
            {
                ae.SubBlock = new byte[ae.SubBlockSize];
                Array.Copy(bytes, ae.MainBlockSize + 3, ae.SubBlock, 0, ae.SubBlockSize);
            }
            else if (ae.IsXmpDataExtension())
            {
                int blockTerminatorIndex = ApplicationExtension.GetXmpExtensionBlockTerminatorIndex(bytes).Value;

                //  todo: offer propert support for XMP Data extensions
                //  ae.SubBlockSize = blockTerminatorIndex - (ae.MainBlock.Length + 3);
                //  ae.SubBlock = new byte[ae.SubBlockSize];
                //  Array.Copy(bytes, ae.SubBlock, ae.SubBlockSize);
                //  ae.TotalBlockLength = ApplicationExtension.MainBlockSize + ApplicationExtension.SubBlockSize + 4;
            }

            if (bytes[ae.TotalBlockLength - 1] != (byte)Global.BlockTerminator)
            {
                throw new ApplicationExtensionParserException();
            }
            else
            {
                return(ae);
            }
        }
        private void ConstructorStreamTestNoBlockTerminator(bool xmlDebugging)
        {
            Stream s = new MemoryStream();

            WriteApplicationIdentifier(s);
            WriteHello(s);
            WriteWorld(s);
            // Don't write a block terminator - that's the point of this test

            s.Seek(0, SeekOrigin.Begin);               // point to start of stream

            // Instantiate the ApplicationExtension
            _ext = new ApplicationExtension(s, xmlDebugging);

            Assert.AreEqual(ErrorState.EndOfInputStream, _ext.ConsolidatedState);

            if (xmlDebugging)
            {
                Assert.AreEqual(ExpectedDebugXml, _ext.DebugXml);
            }
        }
        public void ConstructorTest()
        {
            byte[] idData = new byte[]
            {
                (byte)'N',
                (byte)'E',
                (byte)'T',
                (byte)'S',
                (byte)'C',
                (byte)'A',
                (byte)'P',
                (byte)'E',
                (byte)'2',
                (byte)'.',
                (byte)'0',
            };
            DataBlock idBlock = new DataBlock(11, idData);

            Collection <DataBlock> appData = new Collection <DataBlock>();

            // First byte in the data block is always 1 for a netscape extension
            // Second and third bytes are the loop count, lsb first
            byte[] loopCount = new byte[] { 1, 4, 0 };
            appData.Add(new DataBlock(3, loopCount));

            // Add the block terminator
            appData.Add(new DataBlock(0, new byte[0]));

            ApplicationExtension appExt
                = new ApplicationExtension(idBlock, appData);

            _ne = new NetscapeExtension(appExt);

            Assert.AreEqual(4, _ne.LoopCount);
            Assert.AreEqual("NETSCAPE", _ne.ApplicationIdentifier);
            Assert.AreEqual("2.0", _ne.ApplicationAuthenticationCode);
            Assert.AreEqual(ErrorState.Ok, _ne.ConsolidatedState);
        }
        public void ConstructorIdentificationBlockTooShortTest()
        {
            ReportStart();
            byte[] identification = new byte[]
            {
                (byte)'N',
                (byte)'E',
                (byte)'T',
                (byte)'S',
                (byte)'C',
                (byte)'A',
                (byte)'P',
                (byte)'E',
                (byte)'2',
                (byte)'.',
            };
            DataBlock identificationBlock = new DataBlock(11, identification);
            DataBlock data = new DataBlock(1, new byte[] { 1 });
            Collection <DataBlock> applicationData = new Collection <DataBlock>();

            applicationData.Add(data);

            try
            {
                _ext = new ApplicationExtension(identificationBlock,
                                                applicationData);
            }
            catch (ArgumentException ex)
            {
                string message
                    = "The identification block should be 11 bytes long but "
                      + "is only 10 bytes.";
                StringAssert.Contains(message, ex.Message);
                ReportEnd();
                throw;
            }
        }
        public void ConstructorTestNotNetscape()
        {
            byte[] idData = new byte[]
            {
                (byte)'B',
                (byte)'I',
                (byte)'G',
                (byte)'P',
                (byte)'A',
                (byte)'N',
                (byte)'T',
                (byte)'S',
                (byte)'2',
                (byte)'.',
                (byte)'0',
            };
            DataBlock idBlock = new DataBlock(11, idData);

            ApplicationExtension appExt
                = new ApplicationExtension(idBlock, new Collection <DataBlock>());

            try
            {
                _ne = new NetscapeExtension(appExt);
            }
            catch (ArgumentException ex)
            {
                string message
                    = "The application identifier is not 'NETSCAPE' "
                      + "therefore this application extension is not a "
                      + "Netscape extension. Application identifier: BIGPANTS";
                StringAssert.Contains(message, ex.Message);
                Assert.AreEqual("applicationExtension", ex.ParamName);
                throw;
            }
        }
        public void ConstructorTestNot2Point0()
        {
            byte[] idData = new byte[]
            {
                (byte)'N',
                (byte)'E',
                (byte)'T',
                (byte)'S',
                (byte)'C',
                (byte)'A',
                (byte)'P',
                (byte)'E',
                (byte)'3',
                (byte)'.',
                (byte)'0',
            };
            DataBlock idBlock = new DataBlock(11, idData);

            ApplicationExtension appExt
                = new ApplicationExtension(idBlock, new Collection <DataBlock>());

            try
            {
                _ne = new NetscapeExtension(appExt);
            }
            catch (ArgumentException ex)
            {
                string message
                    = "The application authentication code is not '2.0' "
                      + "therefore this application extension is not a "
                      + "Netscape extension. Application authentication code: 3.0";
                StringAssert.Contains(message, ex.Message);
                Assert.AreEqual("applicationExtension", ex.ParamName);
                throw;
            }
        }
Пример #17
0
        /// <summary>
        /// Main file parser. Reads GIF content blocks.
        /// </summary>
        /// <param name="inputStream">
        /// Input stream from which the GIF data is to be read.
        /// </param>
        private void ReadContents(Stream inputStream)
        {
            // read GIF file content blocks
            bool done = false;
            GraphicControlExtension lastGce = null;
            string message;             // for error conditions

            while (!done && ConsolidatedState == ErrorState.Ok)
            {
                int code = Read(inputStream);
                MyProgressCounters[_readStreamCounterText].Value
                    = (int)inputStream.Position;
                WriteCodeToDebugXml(code);

                switch (code)
                {
                case CodeImageSeparator:
                    WriteDebugXmlComment("0x2C - image separator");
                    AddFrame(inputStream, lastGce);
                    MyProgressCounters[_readStreamCounterText].Value
                        = (int)inputStream.Position;
                    break;

                case CodeExtensionIntroducer:
                    WriteDebugXmlComment("0x21 - extension introducer");
                    code = Read(inputStream);
                    MyProgressCounters[_readStreamCounterText].Value
                        = (int)inputStream.Position;
                    WriteCodeToDebugXml(code);
                    switch (code)
                    {
                    case CodePlaintextLabel:
                        // FEATURE: handle plain text extension
                        WriteDebugXmlComment("0x01 - plain text extension");
                        SkipBlocks(inputStream);
                        MyProgressCounters[_readStreamCounterText].Value
                            = (int)inputStream.Position;
                        break;

                    case CodeGraphicControlLabel:
                        WriteDebugXmlComment("0xF9 - graphic control label");
                        lastGce = new GraphicControlExtension(inputStream,
                                                              XmlDebugging);
                        MyProgressCounters[_readStreamCounterText].Value
                            = (int)inputStream.Position;
                        WriteDebugXmlNode(lastGce.DebugXmlReader);
                        break;

                    case CodeCommentLabel:
                        // FEATURE: handle comment extension
                        WriteDebugXmlComment("0xFE - comment extension");
                        SkipBlocks(inputStream);
                        MyProgressCounters[_readStreamCounterText].Value
                            = (int)inputStream.Position;
                        break;

                    case CodeApplicationExtensionLabel:
                        WriteDebugXmlComment("0xFF - application extension label");
                        ApplicationExtension ext
                            = new ApplicationExtension(inputStream,
                                                       XmlDebugging);
                        MyProgressCounters[_readStreamCounterText].Value
                            = (int)inputStream.Position;
                        WriteDebugXmlNode(ext.DebugXmlReader);
                        if (ext.ApplicationIdentifier == "NETSCAPE" &&
                            ext.ApplicationAuthenticationCode == "2.0")
                        {
                            _netscapeExtension = new NetscapeExtension(ext);
                        }
                        else
                        {
                            // TESTME: ReadContents - non-Netscape application extension
                            _applicationExtensions.Add(ext);
                        }
                        break;

                    default:                                      // uninteresting extension
                        // TESTME: ReadContents - uninteresting extension
                        WriteDebugXmlComment("Ignoring this extension");
                        SkipBlocks(inputStream);
                        MyProgressCounters[_readStreamCounterText].Value
                            = (int)inputStream.Position;
                        break;
                    }
                    break;

                case CodeTrailer:
                    // We've reached an explicit end-of-data marker, so stop
                    // processing the stream.
                    WriteDebugXmlComment("0x3B - end of data");
                    done = true;
                    break;

                case 0x00:                          // bad byte, but keep going and see what happens
                    WriteDebugXmlComment("0x00 - unexpected code");
                    message
                        = "Unexpected block terminator encountered at "
                          + "position " + inputStream.Position
                          + " after reading " + _frames.Count + " frames.";
                    SetStatus(ErrorState.UnexpectedBlockTerminator,
                              message);
                    break;

                case -1:                         // reached the end of the input stream
                    WriteDebugXmlComment("-1 - end of input stream");
                    message
                        = "Reached the end of the input stream without "
                          + "encountering trailer 0x3b";
                    SetStatus(ErrorState.EndOfInputStream, message);
                    break;

                default:
                    WriteDebugXmlComment("Not a recognised code");
                    message
                        = "Bad data block introducer: 0x"
                          + code.ToString("X", CultureInfo.InvariantCulture).PadLeft(2, '0')
                          + " (" + code + ") at position " + inputStream.Position
                          + " ("
                          + inputStream.Position.ToString("X",
                                                          CultureInfo.InvariantCulture)
                          + " hex) after reading "
                          + _frames.Count + " frames.";
                    SetStatus(ErrorState.BadDataBlockIntroducer, message);
                    break;
                }
            }
        }
Пример #18
0
        /// <summary>
        /// Encode GIF in multiple threads.
        /// </summary>
        public void EncodeParallel(Action <EncodeProgress> onProgress, int scale = 1)        // TODO: Refact.
        {
            if (_free)
            {
                throw new Exception("The Free version doesn't support this feature. Please consider buying the Full version of Power GIF.");
            }

            const string header               = "GIF89a";
            var          width                = (ushort)(Frames[0].Texture.width * scale);
            var          height               = (ushort)(Frames[0].Texture.height * scale);
            var          globalColorTable     = new List <Color32>();
            var          applicationExtension = new ApplicationExtension();
            var          encoded              = new Dictionary <int, List <byte> >();
            var          encodeProgress       = new EncodeProgress {
                FrameCount = Frames.Count
            };
            var colorTables      = new List <Color32> [Frames.Count];
            var distinctColors   = new Dictionary <int, List <Color32> >();
            var manualResetEvent = new ManualResetEvent(false);

            for (var i = 0; i < Frames.Count; i++)
            {
                var frame = Frames[i];

                ThreadPool.QueueUserWorkItem(context =>
                {
                    var distinct = frame.Texture.GetPixels32().Distinct().ToList();

                    lock (distinctColors)
                    {
                        distinctColors.Add((int)context, distinct);

                        if (distinctColors.Count == Frames.Count)
                        {
                            manualResetEvent.Set();
                        }
                    }
                }, i);
            }

            manualResetEvent.WaitOne();

            for (var i = 0; i < Frames.Count; i++)
            {
                var colors = distinctColors[i];
                var add    = colors.Where(j => !globalColorTable.Contains(j)).ToList();

                if (globalColorTable.Count + add.Count <= 256)
                {
                    globalColorTable.AddRange(add);
                    colorTables[i] = globalColorTable;
                }
                else if (colors.Count <= 256)                 // Introduce local color table.
                {
                    colorTables[i] = colors;
                }
                else
                {
                    onProgress(new EncodeProgress {
                        Completed = true, Exception = new Exception($"Frame #{i} contains more than 256 colors!")
                    });
                    return;
                }
            }

            ReplaceTransparentColor(ref globalColorTable);

            for (var i = 0; i < Frames.Count; i++)             // Don't use Parallel.For to leave .NET compatibility.
            {
                ThreadPool.QueueUserWorkItem(context =>
                {
                    var index                 = (int)context;
                    var colorTable            = colorTables[index];
                    var localColorTableFlag   = (byte)(colorTable == globalColorTable ? 0 : 1);
                    var localColorTableSize   = GetColorTableSize(colorTable);
                    byte transparentColorFlag = 0, transparentColorIndex = 0;
                    byte max;
                    var colorIndexes            = GetColorIndexes(Frames[index].Texture, scale, colorTable, localColorTableFlag, ref transparentColorFlag, ref transparentColorIndex, out max);
                    var graphicControlExtension = new GraphicControlExtension(4, 0, (byte)Frames[index].DisposalMethod, 0, transparentColorFlag, (ushort)(100 * Frames[index].Delay), transparentColorIndex);
                    var imageDescriptor         = new ImageDescriptor(0, 0, width, height, localColorTableFlag, 0, 0, 0, localColorTableSize);
                    var minCodeSize             = LzwEncoder.GetMinCodeSize(max);
                    var lzw = LzwEncoder.Encode(colorIndexes, minCodeSize);
                    var tableBasedImageData = new TableBasedImageData(minCodeSize, lzw);
                    var bytes = new List <byte>();

                    bytes.AddRange(graphicControlExtension.GetBytes());
                    bytes.AddRange(imageDescriptor.GetBytes());

                    if (localColorTableFlag == 1)
                    {
                        bytes.AddRange(ColorTableToBytes(colorTable, localColorTableSize));
                    }

                    bytes.AddRange(tableBasedImageData.GetBytes());

                    lock (encoded)
                    {
                        encoded.Add(index, bytes);
                        encodeProgress.Progress++;

                        if (encoded.Count == Frames.Count)
                        {
                            var globalColorTableSize    = GetColorTableSize(globalColorTable);
                            var logicalScreenDescriptor = new LogicalScreenDescriptor(width, height, 1, 7, 0, globalColorTableSize, 0, 0);
                            var binary = new List <byte>();

                            binary.AddRange(Encoding.UTF8.GetBytes(header));
                            binary.AddRange(logicalScreenDescriptor.GetBytes());
                            binary.AddRange(ColorTableToBytes(globalColorTable, globalColorTableSize));
                            binary.AddRange(applicationExtension.GetBytes());
                            binary.AddRange(encoded.OrderBy(j => j.Key).SelectMany(j => j.Value));
                            binary.Add(0x3B);                         // GIF Trailer.

                            encodeProgress.Bytes     = binary.ToArray();
                            encodeProgress.Completed = true;
                        }

                        onProgress(encodeProgress);
                    }
                }, i);
            }
        }
Пример #19
0
        /// <summary>
        /// Iterator can be used for large GIF-files in order to display progress bar.
        /// </summary>
        public IEnumerable <List <byte> > EncodeIterator(int scale = 1)
        {
            if (_free)
            {
                if (Frames[0].Texture.width > 256 || Frames[0].Texture.height > 256)
                {
                    throw new Exception("The free version has maximum supported size 256x256 px. Please consider buying the Full version of Power GIF.");
                }
                if (Frames.Count > 20)
                {
                    throw new Exception("The Free version is limited by 20 frames. Please consider buying the Full version of Power GIF.");
                }
            }

            const string header               = "GIF89a";
            var          width                = (ushort)(Frames[0].Texture.width * scale);
            var          height               = (ushort)(Frames[0].Texture.height * scale);
            var          globalColorTable     = new List <Color32>();
            var          applicationExtension = new ApplicationExtension();
            var          bytes                = new List <byte>();
            var          colorTables          = new List <Color32> [Frames.Count];
            var          distinctColors       = new Dictionary <int, List <Color32> >();
            var          manualResetEvent     = new ManualResetEvent(false);

            for (var i = 0; i < Frames.Count; i++)
            {
                var frame = Frames[i];

                ThreadPool.QueueUserWorkItem(context =>
                {
                    var distinct = frame.Texture.GetPixels32().Distinct().ToList();

                    lock (distinctColors)
                    {
                        distinctColors.Add((int)context, distinct);

                        if (distinctColors.Count == Frames.Count)
                        {
                            manualResetEvent.Set();
                        }
                    }
                }, i);
            }

            manualResetEvent.WaitOne();

            for (var i = 0; i < Frames.Count; i++)
            {
                var colors = distinctColors[i];
                var add    = colors.Where(j => !globalColorTable.Contains(j)).ToList();

                if (globalColorTable.Count + add.Count <= 256)
                {
                    globalColorTable.AddRange(add);
                    colorTables[i] = globalColorTable;
                }
                else if (add.Count <= 256)                 // Introducing local color table
                {
                    colorTables[i] = colors;
                }
                else
                {
                    throw new Exception($"Frame #{i} contains more than 256 colors!");
                }
            }

            ReplaceTransparentColor(ref globalColorTable);

            for (var i = 0; i < Frames.Count; i++)
            {
                var  frame = Frames[i];
                var  colorTable = colorTables[i];
                var  localColorTableFlag = (byte)(colorTable == globalColorTable ? 0 : 1);
                var  localColorTableSize = GetColorTableSize(colorTable);
                byte transparentColorFlag = 0, transparentColorIndex = 0;
                byte max;
                var  colorIndexes            = GetColorIndexes(frame.Texture, scale, colorTable, localColorTableFlag, ref transparentColorFlag, ref transparentColorIndex, out max);
                var  graphicControlExtension = new GraphicControlExtension(4, 0, (byte)frame.DisposalMethod, 0, transparentColorFlag, (ushort)(100 * frame.Delay), transparentColorIndex);
                var  imageDescriptor         = new ImageDescriptor(0, 0, width, height, localColorTableFlag, 0, 0, 0, localColorTableSize);
                var  minCodeSize             = LzwEncoder.GetMinCodeSize(max);
                var  lzw = LzwEncoder.Encode(colorIndexes, minCodeSize);
                var  tableBasedImageData = new TableBasedImageData(minCodeSize, lzw);

                bytes.Clear();
                bytes.AddRange(graphicControlExtension.GetBytes());
                bytes.AddRange(imageDescriptor.GetBytes());

                if (localColorTableFlag == 1)
                {
                    bytes.AddRange(ColorTableToBytes(colorTable, localColorTableSize));
                }

                bytes.AddRange(tableBasedImageData.GetBytes());

                yield return(bytes);
            }

            yield return(new List <byte> {
                0x3B
            });                                               // GIF Trailer.

            // Then output GIF header as last iterator element! This way we can build global color table "on fly" instead of expensive building operation.

            var globalColorTableSize    = GetColorTableSize(globalColorTable);
            var logicalScreenDescriptor = new LogicalScreenDescriptor(width, height, 1, 7, 0, globalColorTableSize, 0, 0);

            bytes.Clear();
            bytes.AddRange(Encoding.UTF8.GetBytes(header));
            bytes.AddRange(logicalScreenDescriptor.GetBytes());
            bytes.AddRange(ColorTableToBytes(globalColorTable, globalColorTableSize));
            bytes.AddRange(applicationExtension.GetBytes());

            yield return(bytes);
        }
Пример #20
0
        /// <summary>
        /// Compiles the parsed tokens/components back into a byte array.
        /// </summary>
        public void CompileByteArray()
        {
            List <byte> output = new List <byte>();

            output.AddRange(DataStream.Header.Bytes);
            output.AddRange(DataStream.LogicalScreen.LogicalScreenDescriptor.Bytes);

            if (DataStream.LogicalScreen.GlobalColorTable != null)
            {
                output.AddRange(DataStream.LogicalScreen.GlobalColorTable.Bytes);
            }

            foreach (DataBlock db in DataStream.DataBlocks)
            {
                if (db is GraphicBlock)
                {
                    GraphicBlock gb = (GraphicBlock)db;

                    if (gb.GraphicControlExtension != null)
                    {
                        output.AddRange(gb.GraphicControlExtension.Bytes);
                    }

                    if (gb.GraphicRenderingBlock is PlainTextExtension)
                    {
                        PlainTextExtension pte = (PlainTextExtension)gb.GraphicRenderingBlock;

                        output.AddRange(pte.Bytes);
                    }
                    else if (gb.GraphicRenderingBlock is TableBasedImage)
                    {
                        TableBasedImage tbi = (TableBasedImage)gb.GraphicRenderingBlock;

                        output.AddRange(tbi.ImageDescriptor.Bytes);

                        if (tbi.LocalColorTable != null)
                        {
                            output.AddRange(tbi.LocalColorTable.Bytes);
                        }

                        output.AddRange(tbi.ImageData.Bytes);
                    }
                }
                else if (db is SpecialPurposeBlock)
                {
                    SpecialPurposeBlock spb = (SpecialPurposeBlock)db;

                    if (spb is ApplicationExtension)
                    {
                        ApplicationExtension ae = (ApplicationExtension)spb;

                        output.AddRange(ae.Bytes);
                    }
                    else if (spb is CommentExtension)
                    {
                        CommentExtension ce = (CommentExtension)spb;

                        output.AddRange(ce.Bytes);
                    }
                }
            }

            output.AddRange(DataStream.Trailer.Bytes);

            DataStream.Bytes = output.ToArray();
        }
Пример #21
0
        public void WikipediaExampleTest()
        {
            ReportStart();
            _e = new AnimatedGifEncoder();
            GifFrame frame = new GifFrame(WikipediaExample.ExpectedBitmap);

            frame.Delay = WikipediaExample.DelayTime;
            _e.AddFrame(frame);

            // TODO: some way of creating/testing a UseLocal version of WikipediaExample
            string fileName = "WikipediaExampleUseGlobal.gif";

            _e.WriteToFile(fileName);
            Stream s = File.OpenRead(fileName);

            int code;

            // check GIF header
            GifHeader gh = new GifHeader(s);

            Assert.AreEqual(ErrorState.Ok, gh.ConsolidatedState);

            // check logical screen descriptor
            LogicalScreenDescriptor lsd = new LogicalScreenDescriptor(s);

            Assert.AreEqual(ErrorState.Ok, lsd.ConsolidatedState);
            WikipediaExample.CheckLogicalScreenDescriptor(lsd);

            // read global colour table
            ColourTable gct
                = new ColourTable(s, WikipediaExample.GlobalColourTableSize);

            Assert.AreEqual(ErrorState.Ok, gct.ConsolidatedState);
            // cannot compare global colour table as different encoders will
            // produce difference colour tables.
//			WikipediaExample.CheckGlobalColourTable( gct );

            // check for extension introducer
            code = ExampleComponent.CallRead(s);
            Assert.AreEqual(GifComponent.CodeExtensionIntroducer, code);

            // check for app extension label
            code = ExampleComponent.CallRead(s);
            Assert.AreEqual(GifComponent.CodeApplicationExtensionLabel, code);

            // check netscape extension
            ApplicationExtension ae = new ApplicationExtension(s);

            Assert.AreEqual(ErrorState.Ok, ae.ConsolidatedState);
            NetscapeExtension ne = new NetscapeExtension(ae);

            Assert.AreEqual(ErrorState.Ok, ne.ConsolidatedState);
            Assert.AreEqual(0, ne.LoopCount);

            // check for extension introducer
            code = ExampleComponent.CallRead(s);
            Assert.AreEqual(GifComponent.CodeExtensionIntroducer, code);

            // check for gce label
            code = ExampleComponent.CallRead(s);
            Assert.AreEqual(GifComponent.CodeGraphicControlLabel, code);

            // check graphic control extension
            GraphicControlExtension gce = new GraphicControlExtension(s);

            Assert.AreEqual(ErrorState.Ok, gce.ConsolidatedState);
            WikipediaExample.CheckGraphicControlExtension(gce);

            // check for image separator
            code = ExampleComponent.CallRead(s);
            Assert.AreEqual(GifComponent.CodeImageSeparator, code);

            // check for image descriptor
            ImageDescriptor id = new ImageDescriptor(s);

            Assert.AreEqual(ErrorState.Ok, id.ConsolidatedState);
            WikipediaExample.CheckImageDescriptor(id);

            // read, decode and check image data
            // Cannot compare encoded LZW data directly as different encoders
            // will create different colour tables, so even if the bitmaps are
            // identical, the colour indices will be different
            int pixelCount = WikipediaExample.FrameSize.Width
                             * WikipediaExample.FrameSize.Height;
            TableBasedImageData tbid = new TableBasedImageData(s, pixelCount);

            for (int y = 0; y < WikipediaExample.LogicalScreenSize.Height; y++)
            {
                for (int x = 0; x < WikipediaExample.LogicalScreenSize.Width; x++)
                {
                    int i = (y * WikipediaExample.LogicalScreenSize.Width) + x;
                    Assert.AreEqual(WikipediaExample.ExpectedBitmap.GetPixel(x, y),
                                    gct[tbid.Pixels[i]],
                                    "X: " + x + ", Y: " + y);
                }
            }

            // Check for block terminator after image data
            code = ExampleComponent.CallRead(s);
            Assert.AreEqual(0x00, code);

            // check for GIF trailer
            code = ExampleComponent.CallRead(s);
            Assert.AreEqual(GifComponent.CodeTrailer, code);

            // check we're at the end of the stream
            code = ExampleComponent.CallRead(s);
            Assert.AreEqual(-1, code);
            s.Close();

            _d = new GifDecoder(fileName);
            _d.Decode();
            Assert.AreEqual(ErrorState.Ok, _d.ConsolidatedState);
            BitmapAssert.AreEqual(WikipediaExample.ExpectedBitmap,
                                  (Bitmap)_d.Frames[0].TheImage,
                                  "");
            ReportEnd();
        }
Пример #22
0
        private static List <Block> ReadBlocks(byte[] bytes, ref int startIndex)
        {
            var blocks = new List <Block>();
            var index  = startIndex;

            while (true)
            {
                switch (bytes[index])
                {
                case Block.ExtensionIntroducer:
                {
                    Block extension;

                    switch (bytes[index + 1])
                    {
                    case Block.PlainTextExtensionLabel:
                        extension = new PlainTextExtension(bytes, ref index);
                        break;

                    case Block.GraphicControlExtensionLabel:
                        extension = new GraphicControlExtension(bytes, ref index);
                        break;

                    case Block.CommentExtensionLabel:
                        extension = new CommentExtension(bytes, ref index);
                        break;

                    case Block.ApplicationExtensionLabel:
                        extension = new ApplicationExtension(bytes, ref index);
                        break;

                    default:
                        throw new NotSupportedException("Unknown extension!");
                    }

                    blocks.Add(extension);
                    break;
                }

                case Block.ImageDescriptorLabel:
                {
                    var descriptor = new ImageDescriptor(bytes, ref index);

                    blocks.Add(descriptor);

                    if (descriptor.LocalColorTableFlag == 1)
                    {
                        var localColorTable = new ColorTable(descriptor.LocalColorTableSize, bytes, ref index);

                        blocks.Add(localColorTable);
                    }

                    var data = new TableBasedImageData(bytes, ref index);

                    blocks.Add(data);

                    break;
                }

                case 0x3B:                         // End
                {
                    return(blocks);
                }

                default:
                    throw new NotSupportedException($"Unsupported GIF block: {bytes[index]:X}.");
                }
            }
        }
Пример #23
0
        /// <summary>
        /// Tokenizes the GIF image's byte[] into constituent components.
        /// </summary>
        public static DataStream ParseDataStream(byte[] data)
        {
            DataStream ds = new DataStream();

            using (MemoryStream ms = new MemoryStream(data))
            {
                using (BinaryReader br = new BinaryReader(ms))
                {
                    ds.Header = VcvjParser.ParseHeader(br.ReadBytes(Header.TotalBlockLength));

                    ds.LogicalScreen = new LogicalScreen()
                    {
                        LogicalScreenDescriptor = VcvjParser.ParseLogicalScreenDescriptor(br.ReadBytes(LogicalScreenDescriptor.TotalBlockLength))
                    };

                    if (ds.LogicalScreen.LogicalScreenDescriptor.HasGlobalColorTable)
                    {
                        ds.LogicalScreen.GlobalColorTable = VcvjParser.ParseGlobalColorTable(
                            br.ReadBytes(ds.LogicalScreen.LogicalScreenDescriptor.GlobalColorTableLength)
                            );
                    }

                    while (br.PeekChar() != -1)
                    {
                        long currentIndex = br.BaseStream.Position;
                        byte currentByte  = data[currentIndex];
                        byte?nextByte     = currentIndex + 1 < data.Length ? (byte?)data[currentIndex + 1] : (byte?)null;

                        if (ParserUtils.IsTrailerMarker(currentByte))
                        {
                            ds.Trailer = new Trailer(br.ReadByte());
                            continue;
                        }
                        else if (ParserUtils.IsApplicationExtensionBlock(currentByte, nextByte))
                        {
                            ApplicationExtension ae = VcvjParser.ParseApplicationExtension(
                                br.ReadBytes(VcvjParser.GetApplicationExtensionBlockLength(currentIndex, ref data))
                                );

                            ds.DataBlocks.Add(ae);
                            continue;
                        }
                        else if (ParserUtils.IsCommentExtensionBlock(currentByte, nextByte))
                        {
                            int totalBlockLength = data[currentIndex + 2] + 4;
                            CommentExtension ce  = VcvjParser.ParseCommentExtension(br.ReadBytes(totalBlockLength));

                            ds.DataBlocks.Add(ce);
                            continue;
                        }
                        else
                        {
                            GraphicBlock gb = new GraphicBlock();

                            if (ParserUtils.IsGraphicControlExtensionBlock(currentByte, nextByte))
                            {
                                gb.GraphicControlExtension = VcvjParser.ParseGraphicControlExtension(
                                    br.ReadBytes(8)
                                    );

                                currentIndex = br.BaseStream.Position;
                                currentByte  = data[currentIndex];
                                nextByte     = data[currentIndex + 1];
                            }

                            if (ParserUtils.IsImageDescriptor(currentByte))
                            {
                                TableBasedImage tbi = new TableBasedImage()
                                {
                                    ImageDescriptor = VcvjParser.ParseImageDescriptor(
                                        br.ReadBytes(10)
                                        )
                                };

                                if (tbi.ImageDescriptor.LocalColorTableFlag)
                                {
                                    tbi.LocalColorTable = VcvjParser.ParseLocalColorTable(
                                        br.ReadBytes(tbi.ImageDescriptor.LocalColorTableLength)
                                        );
                                }

                                currentIndex = br.BaseStream.Position;
                                currentByte  = data[currentIndex];
                                nextByte     = data[currentIndex + 1];

                                tbi.ImageData = VcvjParser.ParseImageData(
                                    br.ReadBytes(VcvjParser.GetImageDataBlockLength(currentIndex, ref data))
                                    );

                                gb.GraphicRenderingBlock = tbi;

                                ds.DataBlocks.Add(gb);
                                continue;
                            }
                            else if (ParserUtils.IsPlaintextExtension(currentByte, nextByte))
                            {
                                //GraphicBlock gb = new GraphicBlock()
                                //{
                                //};
                            }
                            else if (ParserUtils.IsApplicationExtensionBlock(currentByte, nextByte))
                            {
                                ApplicationExtension ae = VcvjParser.ParseApplicationExtension(
                                    br.ReadBytes(VcvjParser.GetApplicationExtensionBlockLength(currentIndex, ref data))
                                    );

                                ds.DataBlocks.Add(ae);
                                continue;
                            }
                            else if (ParserUtils.IsCommentExtensionBlock(currentByte, nextByte))
                            {
                                int totalBlockLength = data[currentIndex + 2] + 4;
                                CommentExtension ce  = VcvjParser.ParseCommentExtension(br.ReadBytes(totalBlockLength));

                                ds.DataBlocks.Add(ce);
                                continue;
                            }
                            else
                            {
                                throw new UnidentifiedBlockException(
                                          string.Format(
                                              "The current byte is {0} and the next one is {1}. Not really sure what to make of this.",
                                              currentByte.ToString(),
                                              String.IsNullOrEmpty(nextByte.ToString()) ? "null" : nextByte.ToString()
                                              )
                                          );
                            }
                        }
                    }
                }
            }
            return(ds);
        }
Пример #24
0
        /// <summary>
        /// Returns the length of the parsed data stream byte[].
        /// </summary>
        /// <returns></returns>
        public int GetLength()
        {
            int length = 0;

            length += Header.TotalBlockLength + LogicalScreenDescriptor.TotalBlockLength + Trailer.TotalBlockLength;

            if (LogicalScreen.GlobalColorTable != null)
            {
                length += LogicalScreen.GlobalColorTable.TotalBlockLength;
            }

            foreach (DataBlock db in DataBlocks)
            {
                if (db is GraphicBlock)
                {
                    GraphicBlock gb = (GraphicBlock)db;

                    if (gb.GraphicControlExtension != null)
                    {
                        length += GraphicControlExtension.TotalBlockLength;
                    }

                    if (gb.GraphicRenderingBlock is PlainTextExtension)
                    {
                        PlainTextExtension pte = (PlainTextExtension)gb.GraphicRenderingBlock;

                        length += pte.TotalBlockLength;
                    }
                    else if (gb.GraphicRenderingBlock is TableBasedImage)
                    {
                        TableBasedImage tbi = (TableBasedImage)gb.GraphicRenderingBlock;

                        length += tbi.ImageData.TotalBlockLength + ImageDescriptor.TotalBlockLength;

                        if (tbi.LocalColorTable != null)
                        {
                            length += tbi.LocalColorTable.TotalBlockLength;
                        }
                    }
                }
                else if (db is SpecialPurposeBlock)
                {
                    SpecialPurposeBlock spb = (SpecialPurposeBlock)db;

                    if (spb is ApplicationExtension)
                    {
                        ApplicationExtension ae = (ApplicationExtension)spb;

                        length += ae.TotalBlockLength;
                    }
                    else if (spb is CommentExtension)
                    {
                        CommentExtension ce = (CommentExtension)spb;

                        length += ce.TotalBlockLength;
                    }
                }
            }

            return(length);
        }