示例#1
0
        /// <summary>
        /// Encodes _ip and decodes the encoded data, then compares the decoded
        /// data against the original.
        /// Also calculates the compression rate.
        /// </summary>
        private void TestIt()
        {
            MemoryStream s = new MemoryStream();

            _e = new LzwEncoder(_ip);
            _e.Encode(s);
            int encodedByteCount = (int)s.Position;

            s.Seek(0, SeekOrigin.Begin);
            TableBasedImageData tbid = new TableBasedImageData(s, _ip.Count);

            s.Seek(0, SeekOrigin.Begin);
            byte[] encodedBytes = new byte[encodedByteCount];
            s.Read(encodedBytes, 0, encodedByteCount);

            Assert.AreEqual(_ip.Count, tbid.Pixels.Count, "Pixel counts differ");
            for (int i = 0; i < _ip.Count; i++)
            {
                Assert.AreEqual(_ip[i], tbid.Pixels[i], "pixel index " + i);
            }

            float compression = 100 - (100 * encodedByteCount / _ip.Count);

            WriteMessage("Original byte count: " + _ip.Count
                         + ". Encoded byte count: " + encodedByteCount
                         + ". Compression rate: " + compression + "%");
        }
示例#2
0
        /// <summary>
        /// Encodes and writes pixel data to the supplied stream
        /// </summary>
        /// <param name="indexedPixels">
        /// Collection of indices of the pixel colours within the active colour
        /// table.
        /// </param>
        /// <param name="outputStream">
        /// The stream to write to.
        /// </param>
        private static void WritePixels(IndexedPixels indexedPixels,
                                        Stream outputStream)
        {
            LzwEncoder encoder = new LzwEncoder(indexedPixels);

            encoder.Encode(outputStream);
        }
示例#3
0
        public void ConvertFrame()
        {
            for (var i = 0; i < Frames.Count; i++)
            {
                var  index = i;//(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  tmpBytes            = new List <byte>();

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

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

                tmpBytes.AddRange(tableBasedImageData.GetBytes());


                encoded.Add(index, tmpBytes);
                // 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.

                    bytes = binary.ToArray();
                    // encodeProgress.Completed = true;
                }

                // onProgress(encodeProgress);
            }

            currentStep++;
        }
示例#4
0
 public void NullPixels()
 {
     try
     {
         _e = new LzwEncoder(null);
     }
     catch (ArgumentNullException ex)
     {
         Assert.AreEqual("pixels", ex.ParamName);
         throw;
     }
 }
示例#5
0
 public void NullStream()
 {
     _e = new LzwEncoder(_ip);
     try
     {
         _e.Encode(null);
     }
     catch (ArgumentNullException ex)
     {
         Assert.AreEqual("outputStream", ex.ParamName);
         throw;
     }
 }
		private static void WriteFrames(IEnumerable<ImageFrame> frames, Stream stream)
		{
			foreach (var frame in frames)
			{
				var frameBytes = new List<byte>();
				if (frame.GraphicControlExtension != null)
				{
					frameBytes.AddRange(frame.GraphicControlExtension.ToBytes());
				}

				frame.ImageDescriptor.SortFlag = false;
				frame.ImageDescriptor.InterlaceFlag = false;

				frameBytes.AddRange(frame.ImageDescriptor.ToBytes());
				if (frame.ImageDescriptor.LocalColorTableFlag)
				{
					frameBytes.AddRange(frame.LocalColorTable);
				}

				stream.WriteBytes(frameBytes.ToArray());

				var transparentColorIndex = -1;
				if (frame.GraphicControlExtension != null && frame.GraphicControlExtension.TransparentColorFlag)
				{
					transparentColorIndex = frame.GraphicControlExtension.TransparentColorIndex;
				}

				var imageData = GetImageData(frame.Bitmap, frame.LocalColorTable, transparentColorIndex);

				var lzwEncoder = new LzwEncoder(imageData, (byte) frame.ColorDepth);
				lzwEncoder.Encode(stream);

				stream.WriteByte(Const.BlockTerminator);
			}

			stream.WriteByte(Const.EndIntroducer);
		}
示例#7
0
    // Encodes and writes pixel data.
    private void WritePixels()
    {
        LzwEncoder encoder = new LzwEncoder(_width, _height, _indexedPixels, _colorDepth);

        encoder.Encode(_memoryStream);
    }
示例#8
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);
        }
示例#9
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);
            }
        }