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 }
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); }
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. }
private int FindTransparentColorIndex() { if (IsFirstFrame || !CurrentTransparentColor.HasValue || !ColorTable.Contains(CurrentTransparentColor.Value)) { return(0); } var index = ColorTable.IndexOf(CurrentTransparentColor.Value); return(index > -1 ? index : 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); }
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); }
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); }
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. }