示例#1
0
        private void GeneratePalette()
        {
            //TODO: more ways to decide which color to get
            //Like removing similar colors (with less than 5% similarity) if there is more than 256 colors, etc.
            //I probably can do that, using the groupby method.

            ColorTable = NonIndexedPixels.AsParallel().GroupBy(x => x)
                         .OrderByDescending(g => g.Count()) //Order by most frequent values
                         .Select(g => g.FirstOrDefault())   //take the first among the group
                         .Take(MaximumNumberColor).ToList();

            #region Handle transparency

            //Make sure that the transparent color is added to list.
            if (TransparentColor.HasValue && (!IsFirstFrame || UseGlobalColorTable) && ColorTable.Count == MaximumNumberColor)
            {
                //Only adds if there is MaximumNumberColor colors, so I need to make sure that the color won't be ignored.
                //If there is less than MaximumNumberColor selected colors, it means that the transparent color is already selected.

                //If the color isn't on the list, add or replace.
                if (ColorTable.AsParallel().All(x => x != TransparentColor.Value))
                {
                    //Adds to the last spot, keeping it sorted. (Since all the colors are ordered by descending)
                    ColorTable.Insert(MaximumNumberColor - 1, TransparentColor.Value);

                    //Remove the exceding value at the last position.
                    ColorTable.RemoveAt(MaximumNumberColor);
                }
            }

            //I need to signal the other method that I won't need transparency.
            WillUseTransparency = !IsFirstFrame && TransparentColor.HasValue && ColorTable.Contains(TransparentColor.Value);

            #endregion
        }
示例#2
0
        private void HandleTransparency()
        {
            //ColorTable = NonIndexedPixels.AsParallel().GroupBy(x => x)
            //    .OrderByDescending(g => g.Count()) //Order by most frequent values
            //    .Select(g => g.FirstOrDefault()) //take the first among the group
            //    .Take(MaximumNumberColor).ToList();

            //Make sure that the transparent color is added to list.
            if (TransparentColor.HasValue && (!IsFirstFrame || UseGlobalColorTable))// && ColorTable.Count == MaximumNumberColor)
            {
                //Only adds if there is MaximumNumberColor colors, so I need to make sure that the color won't be ignored.
                //If there is less than MaximumNumberColor selected colors, it means that the transparent color is already selected.

                //If the color isn't on the list, add or replace.
                if (ColorTable.AsParallel().All(x => x != TransparentColor.Value))
                {
                    //Adds to the last spot, keeping it sorted. (Since all the colors are ordered by descending)
                    ColorTable.Insert(ColorTable.Count - 1, TransparentColor.Value);

                    //Remove the exceding value at the last position.

                    if (ColorTable.Count > MaximumNumberColor)
                    {
                        ColorTable.RemoveAt(MaximumNumberColor);
                    }
                }
            }

            //I need to signal the other method that I won't need transparency.
            WillUseTransparency = !IsFirstFrame && TransparentColor.HasValue && ColorTable.Contains(TransparentColor.Value);
        }
示例#3
0
        private void WriteGraphicControlExtension(int delay)
        {
            WriteByte(0x21); //Extension Introducer.
            WriteByte(0xf9); //Extension Label.
            WriteByte(0x04); //Block size.

            //Packed fields
            var bitArray = new BitArray(8);

            //Reserved for future use. Hahahaha. Yeah...
            bitArray.Set(0, false);
            bitArray.Set(1, false);
            bitArray.Set(2, false);

            #region Disposal Method

            //Use Inplace if you want to Leave the last frame pixel.
            //GCE_DISPOSAL_NONE = Undefined = 0
            //GCE_DISPOSAL_INPLACE = Leave = 1
            //GCE_DISPOSAL_BACKGROUND = Restore Background = 2
            //GCE_DISPOSAL_RESTORE = Restore Previous = 3

            //If transparency is set
            //First frame as "Leave" with no Transparency. IsFirstFrame
            //Following frames as "Undefined" with Transparency.

            //Was TransparentColor.HasValue &&
            if (IsFirstFrame)
            {
                //Leave.
                bitArray.Set(3, false);
                bitArray.Set(4, false);
                bitArray.Set(5, true);
            }
            else
            {
                //Undefined.
                bitArray.Set(3, false);
                bitArray.Set(4, false);
                bitArray.Set(5, false);
            }

            #endregion

            //User Input Flag.
            bitArray.Set(6, false);

            //Transparent Color Flag, uses tranparency?
            bitArray.Set(7, !IsFirstFrame && CurrentTransparentColor.HasValue && ColorTable.Contains(CurrentTransparentColor.Value));

            //Write the packed fields.
            WriteByte(ConvertToByte(bitArray));
            WriteShort(delay / 10);                 //Delay x 1/100 seconds. Minimum of 10ms. Centiseconds.
            WriteByte(FindTransparentColorIndex()); //Transparency Index.
            WriteByte(0);                           //Terminator.
        }
示例#4
0
        private int FindTransparentColorIndex()
        {
            if (IsFirstFrame || !CurrentTransparentColor.HasValue || !ColorTable.Contains(CurrentTransparentColor.Value))
            {
                return(0);
            }

            var index = ColorTable.IndexOf(CurrentTransparentColor.Value);

            return(index > -1 ? index : 0);
        }
示例#5
0
        private void ReadPixels(string path)
        {
            var image     = path.SourceFrom();
            var pixelUtil = new PixelUtil(image);

            pixelUtil.LockBits();

            CurrentTransparentColor = TransparentColor;

            //if (QuantizationType == ColorQuantizationType.Grayscale)
            //{
            //    var quantizer = new GrayscaleQuantizer { MaxColors = MaximumNumberColor };
            //    IndexedPixels = quantizer.Quantize(pixelUtil.Pixels);
            //    ColorTable = quantizer.ColorTable;
            //}
            //else
            //{
            var quantizer = new OctreeQuantizer
            {
                MaxColors        = MaximumNumberColor,
                TransparentColor = !IsFirstFrame || UseGlobalColorTable ? CurrentTransparentColor : null
            };

            IndexedPixels = quantizer.Quantize(pixelUtil.Pixels);
            ColorTable    = quantizer.ColorTable;
            //}

            pixelUtil.UnlockBits();

            if (quantizer.TransparentColor != null)
            {
                CurrentTransparentColor = quantizer.TransparentColor;
            }

            //I need to signal the other method that I won't need transparency.
            WillUseTransparency = !IsFirstFrame && CurrentTransparentColor.HasValue && ColorTable.Contains(CurrentTransparentColor.Value);
        }
示例#6
0
        private void GeneratePalette(string path)
        {
            var colorList = new List <Color>();

            NonIndexedPixels = new List <Color>();

            #region Get the Pixels

            var image     = path.SourceFrom();
            var pixelUtil = new PixelUtil(image);
            pixelUtil.LockBits();

            for (int x = 0; x < image.PixelWidth; x++)
            {
                for (int y = 0; y < image.PixelHeight; y++)
                {
                    colorList.Add(pixelUtil.GetPixel(x, y));
                }
            }

            pixelUtil.UnlockBits();

            #endregion

            //Save all the pixels in a property.
            NonIndexedPixels.AddRange(colorList);

            //TODO: more ways to decide which color to get
            //Like removing similar colors (with less than 5% similarity) if there is more than 256 colors, etc.
            //I probably can do that, using the groupby method.

            //if (NonIndexedPixels.Count == 100)
            //{
            //    ColorTable = new List<Color>
            //    {
            //        Color.FromRgb(255, 255, 255),
            //        Color.FromRgb(255, 0, 0),
            //        Color.FromRgb(0, 0, 255)
            //    };

            //    return;
            //}

            ColorTable = colorList.GroupBy(x => x)          //Grouping based on its value
                         .OrderByDescending(g => g.Count()) //Order by most frequent values
                         .Select(g => g.FirstOrDefault())   //take the first among the group
                         .Take(256).ToList();

            //Make sure that the transparent color is added to list.
            if (!IsFirstFrame && TransparentColor.HasValue && ColorTable.Count == 256)
            {
                //Only adds if there is 256 colors, so I need to make sure that the color won't be ignored.
                //If there is less than 256 selected colors, it means that the transparent color is already selected.

                //If the color isn't on the list, add or replace.
                if (ColorTable.All(x => x != TransparentColor.Value))
                {
                    //Adds to the last spot, keeping it sorted. (Since all the colors are ordered by descending)
                    ColorTable.Insert(255, TransparentColor.Value);

                    //Remove the exceding value at the last position.
                    ColorTable.RemoveAt(256);
                }
            }

            //I need to signal the other method that I won't need transparency.
            WillUseTransparency = TransparentColor.HasValue && ColorTable.Contains(TransparentColor.Value);
        }
示例#7
0
        private void ReadPixels(byte[] pixels)
        {
            if (QuantizationType == ColorQuantizationType.Neural)
            {
                #region Neural

                if (GlobalQuantizer == null || !UseGlobalColorTable)
                {
                    GlobalQuantizer = new NeuralQuantizer(SamplingFactor, MaximumNumberColor)
                    {
                        MaxColors        = MaximumNumberColor,
                        TransparentColor = !IsFirstFrame || UseGlobalColorTable || UseFullTransparency ? TransparentColor : null
                    };

                    GlobalQuantizer.FirstPass(pixels);
                    ColorTable = GlobalQuantizer.GetPalette();
                }

                //Indexes the pixels to the color table.
                IndexedPixels = GlobalQuantizer.SecondPass(pixels);

                #endregion
            }
            else if (QuantizationType == ColorQuantizationType.Octree)
            {
                #region Octree

                var quantizer = new OctreeQuantizer
                {
                    MaxColors        = MaximumNumberColor,
                    TransparentColor = !IsFirstFrame || UseGlobalColorTable || UseFullTransparency ? TransparentColor : null
                };

                IndexedPixels = quantizer.Quantize(pixels);
                ColorTable    = quantizer.ColorTable;

                #endregion
            }
            else if (QuantizationType == ColorQuantizationType.MedianCut)
            {
                #region Median cut

                if (GlobalQuantizer == null || !UseGlobalColorTable)
                {
                    GlobalQuantizer = new MedianCutQuantizer
                    {
                        MaxColors        = MaximumNumberColor,
                        TransparentColor = !IsFirstFrame || UseGlobalColorTable || UseFullTransparency ? TransparentColor : null
                    };

                    GlobalQuantizer.FirstPass(pixels);
                    ColorTable = GlobalQuantizer.GetPalette();
                }

                //Indexes the pixels to the color table.
                IndexedPixels = GlobalQuantizer.SecondPass(pixels);

                #endregion
            }
            else if (QuantizationType == ColorQuantizationType.Grayscale)
            {
                #region Grayscale

                //This quantizer uses a fixed palette (generated during object instantiation), so most calculations are called one time.
                if (GlobalQuantizer == null)
                {
                    //Since the color table does not change among frames, it can be stored globally.
                    UseGlobalColorTable = true;

                    var transparent = !IsFirstFrame || UseGlobalColorTable || UseFullTransparency ? TransparentColor : null;

                    GlobalQuantizer = new GrayscaleQuantizer(transparent, MaximumNumberColor)
                    {
                        MaxColors        = MaximumNumberColor,
                        TransparentColor = transparent
                    };

                    ColorTable = GlobalQuantizer.GetPalette();
                }

                //Each frame still needs to be quantized.
                IndexedPixels = GlobalQuantizer.SecondPass(pixels);

                #endregion
            }
            else if (QuantizationType == ColorQuantizationType.MostUsed)
            {
                #region Most used colors

                if (GlobalQuantizer == null || !UseGlobalColorTable)
                {
                    GlobalQuantizer = new MostUsedQuantizer
                    {
                        MaxColors        = MaximumNumberColor,
                        TransparentColor = !IsFirstFrame || UseGlobalColorTable || UseFullTransparency ? TransparentColor : null
                    };

                    GlobalQuantizer.FirstPass(pixels);
                    ColorTable = GlobalQuantizer.GetPalette();
                }

                //Indexes the pixels to the color table.
                IndexedPixels = GlobalQuantizer.SecondPass(pixels);

                #endregion
            }
            else
            {
                #region Palette

                //This quantizer uses a fixed palette (generated during object instantiation), so it will be only called once.
                if (GlobalQuantizer == null)
                {
                    //Since the color table does not change among frames, it can be stored globally.
                    UseGlobalColorTable = true;

                    var transparent = !IsFirstFrame || UseGlobalColorTable || UseFullTransparency ? TransparentColor : null;

                    //TODO: Pass the palette.
                    //Default palettes: Windows, etc.
                    //User submitted > Presets > Generate palette based on first frame.

                    GlobalQuantizer = new PaletteQuantizer(new ArrayList())
                    {
                        MaxColors        = MaximumNumberColor,
                        TransparentColor = transparent
                    };

                    ColorTable = GlobalQuantizer.GetPalette();
                }

                //Each frame still needs to be quantized.
                IndexedPixels = GlobalQuantizer.SecondPass(pixels);

                #endregion
            }

            //I need to signal the other method that I'll need transparency.
            ColorTableHasTransparency = TransparentColor.HasValue && ColorTable.Contains(TransparentColor.Value);
        }
示例#8
0
        private void WriteGraphicControlExtension(int delay)
        {
            WriteByte(0x21); //Extension Introducer.
            WriteByte(0xf9); //Extension Label.
            WriteByte(0x04); //Block size.

            //Packed fields
            var bitArray = new BitArray(8);

            //Reserved for future use. Hahahaha. Yeah...
            bitArray.Set(0, false);
            bitArray.Set(1, false);
            bitArray.Set(2, false);

            #region Disposal Method

            //Use Inplace if you want to Leave the last frame pixel.
            //GCE_DISPOSAL_NONE = Undefined = 0
            //GCE_DISPOSAL_INPLACE = Leave = 1
            //GCE_DISPOSAL_BACKGROUND = Restore Background = 2
            //GCE_DISPOSAL_RESTORE = Restore Previous = 3

            //If transparency is set
            //First frame as "Leave" with no Transparency. IsFirstFrame
            //Following frames as "Undefined" with Transparency.

            //Was TransparentColor.HasValue &&
            if (IsFirstFrame)
            {
                //Leave.
                bitArray.Set(3, false);
                bitArray.Set(4, false);
                bitArray.Set(5, true);
            }
            else
            {
                //Undefined.
                bitArray.Set(3, false);
                bitArray.Set(4, false);
                bitArray.Set(5, false);
            }

            #endregion

            //User Input Flag.
            bitArray.Set(6, false);

            //Transparent Color Flag, uses tranparency?
            bitArray.Set(7, !IsFirstFrame && CurrentTransparentColor.HasValue && ColorTable.Contains(CurrentTransparentColor.Value));

            //Write the packed fields.
            WriteByte(ConvertToByte(bitArray));

            //Calculates the delay, taking into consideration overall rounding.
            OrganicTime  += delay;
            delay         = (int)Math.Round((OrganicTime > delay ? OrganicTime - AdjustedTime * 10 : delay) / 10.0f, MidpointRounding.AwayFromZero);
            AdjustedTime += delay;
            //WriteShort((int)Math.Round(delay / 10.0f, MidpointRounding.AwayFromZero));

            WriteShort(delay);
            WriteByte(FindTransparentColorIndex()); //Transparency Index.
            WriteByte(0);                           //Terminator.
        }