/// <summary> /// Adds all the colors from a source image to a given color quantizer. /// </summary> /// <param name="image">The image to be processed.</param> /// <param name="quantizer">The target color quantizer.</param> public static void AddColorsToQuantizer(this Image image, IColorQuantizer quantizer) { // checks whether a source image is valid if (image == null) { const String message = "Cannot add colors from a null image."; throw new ArgumentNullException(message); } // checks whether the quantizer is valid if (quantizer == null) { const String message = "Cannot add colors to a null quantizer."; throw new ArgumentNullException(message); } // determines which method of color retrieval to use Boolean isImageIndexed = image.PixelFormat.IsIndexed(); ColorPalette palette = image.Palette; // use different scanning method depending whether the image format is indexed Action<Pixel> scan = isImageIndexed ? (Action<Pixel>) (pixel => quantizer.AddColor(palette.Entries[pixel.Index])) : (pixel => quantizer.AddColor(pixel.Color)); // performs the image scan, using a chosen method image.ProcessImagePixels(ImageLockMode.ReadOnly, scan); }
public static List <Color> SynthetizeImagePalette(Image sourceImage, IColorQuantizer quantizer, Int32 colorCount, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(sourceImage, "sourceImage"); // wraps source image to a buffer using (ImageBuffer source = new ImageBuffer(sourceImage, ImageLockMode.ReadOnly)) { return(source.SynthetizePalette(quantizer, colorCount, parallelTaskCount)); } }
public static void ScanImageColors(Image sourceImage, IColorQuantizer quantizer, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(sourceImage, "sourceImage"); // wraps source image to a buffer using (ImageBuffer source = new ImageBuffer(sourceImage, ImageLockMode.ReadOnly)) { source.ScanColors(quantizer, parallelTaskCount); } }
public static void CorrectImageGamma(Image sourceImage, Single gamma, IColorQuantizer quantizer, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(sourceImage, "sourceImage"); // wraps source image to a buffer using (ImageBuffer source = new ImageBuffer(sourceImage, ImageLockMode.ReadOnly)) { source.CorrectGamma(gamma, quantizer, parallelTaskCount); } }
public static void ChangeFormat(Image sourceImage, PixelFormat targetFormat, IColorQuantizer quantizer, out Image targetImage, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(sourceImage, "sourceImage"); // wraps source image to a buffer using (ImageBuffer source = new ImageBuffer(sourceImage, ImageLockMode.ReadOnly)) { ChangeFormat(source, targetFormat, quantizer, out targetImage, parallelTaskCount); } }
public void ChangeFormat(ImageBuffer target, IColorQuantizer quantizer, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(target, "target"); Guard.CheckNull(quantizer, "quantizer"); // gathers some information about the target format Boolean hasSourceAlpha = PixelFormat.HasAlpha(); Boolean hasTargetAlpha = target.PixelFormat.HasAlpha(); Boolean isTargetIndexed = target.PixelFormat.IsIndexed(); Boolean isSourceDeepColor = PixelFormat.IsDeepColor(); Boolean isTargetDeepColor = target.PixelFormat.IsDeepColor(); // step 1 to 3 - prepares the palettes if (isTargetIndexed) { SynthetizePalette(quantizer, target.PixelFormat.GetColorCount(), parallelTaskCount); } // prepares the quantization function TransformPixelFunction changeFormat = (sourcePixel, targetPixel) => { // if both source and target formats are deep color formats, copies a value directly if (isSourceDeepColor && isTargetDeepColor) { //UInt64 value = sourcePixel.Value; //targetPixel.SetValue(value); } else { // retrieves a source image color Color color = GetColorFromPixel(sourcePixel); // if alpha is not present in the source image, but is present in the target, make one up if (!hasSourceAlpha && hasTargetAlpha) { Int32 argb = 255 << 24 | color.R << 16 | color.G << 8 | color.B; color = Color.FromArgb(argb); } // sets the color to a target pixel SetColorToPixel(targetPixel, color, quantizer); } // allows to write (obviously) the transformed pixel return(true); }; // step 5 - generates the target image IList <Point> standardPath = new StandardPathProvider().GetPointPath(Width, Height); TransformPerPixel(target, standardPath, changeFormat, parallelTaskCount); }
// TODO: Make quantizer optional? public Index2(int indexDepth, IImageFormat paletteFormat, IColorQuantizer quantizer, ByteOrder byteOrder = ByteOrder.LittleEndian) { if (indexDepth % 8 != 0) { throw new InvalidOperationException("IndexDepth needs to be dividable by 8."); } _indexDepth = indexDepth; _paletteFormat = paletteFormat; _byteOrder = byteOrder; _quantizer = quantizer; }
public List <Color> SynthetizePalette(IColorQuantizer quantizer, Int32 colorCount, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(quantizer, "quantizer"); // Step 1 - prepares quantizer for another round quantizer.Prepare(this); // Step 2 - scans the source image for the colors ScanColors(quantizer, parallelTaskCount); // Step 3 - synthetises the palette, and returns the result return(quantizer.GetPalette(colorCount)); }
private void ChangeQuantizer() { activeQuantizer = quantizerList[listMethod.SelectedIndex]; // turns off the color option for the uniform quantizer, as it doesn't make sense listColors.Enabled = turnOnEvents && listMethod.SelectedIndex != 1; if (listMethod.SelectedIndex == 1) { turnOnEvents = false; listColors.SelectedIndex = 7; turnOnEvents = true; } }
public ImageQuantizerViewModel(GeneralSettings generalSettings, IFileDialog fileDialog, IImageBuffer imageBuffer, IEnumerable <IColorQuantizer> quantizerList, ILogger logger) { _generalSettings = generalSettings; _imageBuffer = imageBuffer; _fileDialog = fileDialog; QuantizerList = quantizerList.ToList(); selectedQuantizer = QuantizerList[0]; selectedColorCount = ColorCountList[4]; OpenCommand = new DelegateCommand(LoadImageAndQuantize); SaveCommand = new DelegateCommand(DialogSaveImage); _logger = logger; }
public static Image QuantizeImage(Image sourceImage, IColorQuantizer quantizer, IColorDitherer ditherer, Int32 colorCount, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(sourceImage, "sourceImage"); // lock mode ImageLockMode lockMode = ditherer == null ? ImageLockMode.ReadOnly : ImageLockMode.ReadWrite; // wraps source image to a buffer using (ImageBuffer source = new ImageBuffer(sourceImage, lockMode)) { return(QuantizeImage(source, quantizer, ditherer, colorCount, parallelTaskCount)); } }
public void Dither(ImageBuffer target, IColorDitherer ditherer, IColorQuantizer quantizer, Int32 colorCount, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(target, "target"); Guard.CheckNull(ditherer, "ditherer"); Guard.CheckNull(quantizer, "quantizer"); // prepares ditherer for another round ditherer.Prepare(quantizer, colorCount, this, target); // processes the image via the ditherer IList <Point> path = ditherer.GetPointPath(Width, Height); TransformPerPixel(target, path, ditherer.ProcessPixel, parallelTaskCount); }
private void SetPalette(ColorPalette palette) { if (!_pixelFormat.IsIndexed()) { throw new InvalidOperationException("Not possible to set palette for non-indexed pixel formats."); } if (palette == null || palette.Entries == null) { throw new ArgumentNullException("palette"); } _palette = palette; _quantizer = null; UpdateQuantizer(); }
public Pattern(PatternEditor editor, DesignPattern pattern) { _Type = pattern.Type; Result = new Bitmap(1, 1); Quantizer = Quantizers[0]; ColorCache = ColorCaches[0]; Editor = editor; DesignPattern = pattern; Colors = pattern.GetPixels(); Info = DesignPatternInformation.Types[pattern.Type]; UpscaledPreviewTexture = new UnityEngine.Texture2D(Width * 4, Height * 4, UnityEngine.TextureFormat.RGB24, false); PreviewTexture = new UnityEngine.Texture2D(Width, Height, UnityEngine.TextureFormat.ARGB32, false); }
private void UpdateQuantizer() { if (!_pixelFormat.IsIndexed() || _quantizer != null) { return; } _quantizer = new DistinctSelectionQuantizer(); _quantizer.Prepare(this); // Pass: scan ImageBuffer.ProcessPerPixel(this, null, ParallelTaskCount, (passIndex, pixel) => { var color = pixel.GetColor(); _quantizer.AddColor(color, pixel.X, pixel.Y); return(true); }); }
public void ScanColors(IColorQuantizer quantizer, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(quantizer, "quantizer"); // determines which method of color retrieval to use IList <Point> path = quantizer.GetPointPath(Width, Height); // use different scanning method depending whether the image format is indexed ProcessPixelFunction scanColors = pixel => { quantizer.AddColor(GetColorFromPixel(pixel), pixel.X, pixel.Y); return(false); }; // performs the image scan, using a chosen method ProcessPerPixel(path, scanColors, parallelTaskCount); }
public static Image QuantizeImage(ImageBuffer source, IColorQuantizer quantizer, IColorDitherer ditherer, Int32 colorCount, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(source, "source"); // creates a target bitmap in an appropriate format PixelFormat targetPixelFormat = Extend.GetFormatByColorCount(colorCount); Image result = new Bitmap(source.Width, source.Height, targetPixelFormat); // lock mode ImageLockMode lockMode = ditherer == null ? ImageLockMode.WriteOnly : ImageLockMode.ReadWrite; // wraps target image to a buffer using (ImageBuffer target = new ImageBuffer(result, lockMode)) { source.Quantize(target, quantizer, ditherer, colorCount, parallelTaskCount); return(result); } }
public void SetColorToPixel(Pixel pixel, Color color, IColorQuantizer quantizer) { // determines whether the format is indexed if (pixel.IsIndexed) { // last chance if quantizer is provided, use it if (quantizer != null) { Byte index = (Byte)quantizer.GetPaletteIndex(color, pixel.X, pixel.Y); pixel.Index = index; } else // cannot write color to an index format { String message = string.Format("Cannot retrieve color for an indexed format. Use GetPixelIndex() instead."); throw new NotSupportedException(message); } } else // sets color to a non-indexed format { pixel.Color = color; } }
public void SetColor(Color color, IColorQuantizer quantizer) { // determines whether the format is indexed if (IsIndexed) { // last chance if quantizer is provided, use it if (quantizer != null) { Byte index = (Byte)quantizer.GetPaletteIndex(color, X, Y); ((IIndexedPixel)pixelData).SetIndex(bitOffset, index); } else // cannot write color to an index format { String message = string.Format("Cannot retrieve color for an indexed format. Use GetPixelIndex() instead."); throw new NotSupportedException(message); } } else // sets color to a non-indexed format { ((INonIndexedPixel)pixelData).SetColor(color); } }
/// <summary> /// Creates a new instance of <see cref="QuantizationSettings"/>. /// </summary> /// <param name="quantizer">The quantizer to use.</param> /// <param name="width">The width of the image.</param> /// <param name="height">The height of the image.</param> public QuantizationSettings(IColorQuantizer quantizer, int width, int height) { if (width <= 0) { throw new ArgumentOutOfRangeException(nameof(width)); } if (height <= 0) { throw new ArgumentOutOfRangeException(nameof(height)); } Quantizer = quantizer ?? throw new ArgumentNullException(nameof(quantizer)); Width = width; Height = height; Ditherer = null; ColorCache = new EuclideanDistanceColorCache(); ColorModel = ColorModel.RGB; ColorCount = 256; ParallelCount = 8; }
private void ChangeQuantizer() { activeQuantizer = quantizerList[(int)Method]; // applies current UI selection if (activeQuantizer is BaseColorCacheQuantizer) { BaseColorCacheQuantizer quantizer = (BaseColorCacheQuantizer)activeQuantizer; quantizer.ChangeCacheProvider(activeColorCache); } if (Method == EMethod.UniformQuantization || Method == EMethod.NeuQuantQuantizer || Method == EMethod.OptimalPalette) { ColorCount = EColor.Color256; } if (Method == EMethod.NESQuantizer) { ColorCount = EColor.Color64; } }
//============================================================ // <T>序列化位图数据。</T> // // @params output 输出流 // @params colorCount 调色板颜色数量 // @params pixelCount 分块的像素个数 //============================================================ public bool Serialize(IOutput output, SIntRectangle rect, int colorCount) { // 写入设置 output.WriteBool(_optionAlpha); // 写入属性 output.WriteUint16((ushort)_size.Width); output.WriteUint16((ushort)_size.Height); output.WriteUint16((ushort)rect.Left); output.WriteUint16((ushort)rect.Top); output.WriteUint16((ushort)rect.Width); output.WriteUint16((ushort)rect.Height); // 若不支持半透明,去掉一个颜色,添加一个透明色 //if (!_optionAlpha) { // colorCount--; //} // 写入头信息 FPictureQuantizer pictureQuantizer = null; IColorQuantizer colorQuantizer = null; if (_optionAlpha) { pictureQuantizer = new FPictureQuantizer(EColorQuantizer.Octree); colorQuantizer = pictureQuantizer.LoadQuantizerColors(_bitmap, rect, FPictureQuantizer.EQuantizedMode.Rgb); } else { pictureQuantizer = new FPictureQuantizer(EColorQuantizer.Octree16); colorQuantizer = pictureQuantizer.LoadQuantizerColors(_bitmap, rect, FPictureQuantizer.EQuantizedMode.Color); } using (FByteStream stream = new FByteStream()) { SerializeUnpack(stream, colorQuantizer, rect, colorCount); output.WriteInt32(stream.Length); output.WriteBytes(stream.Memory, 0, stream.Length); } return(true); }
private Graphics(Image bitmap) { _bitmap = bitmap; _quantizer = new DistinctSelectionQuantizer(); this.matrix = new Matrix(); }
public static void DitherImage(ImageBuffer source, ImageBuffer target, IColorDitherer ditherer, IColorQuantizer quantizer, Int32 colorCount, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(source, "source"); // use other override to calculate error source.Dither(target, ditherer, quantizer, colorCount, parallelTaskCount); }
private void SetPalette(ColorPalette palette) { if (!_pixelFormat.IsIndexed()) throw new InvalidOperationException("Not possible to set palette for non-indexed pixel formats."); if (palette == null || palette.Entries == null) throw new ArgumentNullException("palette"); _palette = palette; _quantizer = null; UpdateQuantizer(); }
public static void DitherImage(Image sourceImage, Image targetImage, IColorDitherer ditherer, IColorQuantizer quantizer, Int32 colorCount, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(sourceImage, "sourceImage"); Guard.CheckNull(targetImage, "targetImage"); // wraps source image to a buffer using (ImageBuffer source = new ImageBuffer(sourceImage, ImageLockMode.ReadOnly)) using (ImageBuffer target = new ImageBuffer(targetImage, ImageLockMode.ReadOnly)) { // use other override to calculate error source.Dither(target, ditherer, quantizer, colorCount, parallelTaskCount); } }
//============================================================ // <T>序列化位图的一个区块。</T> // // @params output 输出流 // @params colorQuantizer 颜色优化器 // @params rect 序列化的矩形区域 // @params colorCount 颜色数量 //============================================================ protected bool SerializeUnpackBlock(IOutput output, IColorQuantizer colorQuantizer, SIntRectangle rect, int colorCount) { int blockWidth = rect.Width; int blockHeight = rect.Height; output.WriteUint16((ushort)blockWidth); output.WriteUint16((ushort)blockHeight); // 构造调色板 Color[] palette = null; if (_optionAlpha) { palette = colorQuantizer.MakePalette(colorCount).ToArray(); if (0 == palette.Length) { RMoCore.TrackConsole.Write(this, "SerializeBlock", "Palette color is empty."); return(false); } } else { List <Color> colorList = colorQuantizer.MakePalette(colorCount); if (0 == colorList.Count) { RMoCore.TrackConsole.Write(this, "SerializeBlock", "Palette color is empty."); return(false); } colorList.Add(Color.Transparent); palette = colorList.ToArray(); } // 输出颜色数组 int x = rect.Left; int y = rect.Top; // 写入数组 if (_optionAlpha) { // 写入索引颜色和透明度 for (int h = 0; h < blockHeight; h++) { for (int w = 0; w < blockWidth; w++) { Color color = _native.GetPixel(x + w, y + h); int index = colorQuantizer.FindPaletteIndex(Color.FromArgb(255, color)); Color c = Color.FromArgb(color.A, palette[index]); output.WriteInt32(c.ToArgb()); } } } else { // 写入带透明的索引颜色 for (int h = 0; h < blockHeight; h++) { for (int w = 0; w < blockWidth; w++) { Color color = _native.GetPixel(x + w, y + h); int index = colorQuantizer.FindPaletteIndex(color); output.WriteInt32(palette[index].ToArgb()); } } } return(true); }
//============================================================ // <T>序列化位图的一个区块。</T> // // @params output 输出流 // @params colorQuantizer 颜色优化器 // @params rect 序列化的矩形区域 // @params colorCount 颜色数量 //============================================================ protected bool SerializeBlock(IOutput output, IColorQuantizer colorQuantizer, SIntRectangle rect, int colorCount) { int blockWidth = rect.Width; int blockHeight = rect.Height; output.WriteUint16((ushort)blockWidth); output.WriteUint16((ushort)blockHeight); // 构造调色板 Color[] palette = null; if (_optionAlpha) { palette = colorQuantizer.MakePalette(colorCount).ToArray(); if (0 == palette.Length) { RMoCore.TrackConsole.Write(this, "SerializeBlock", "Palette color is empty."); return(false); } } else { List <Color> colorList = colorQuantizer.MakePalette(colorCount); if (0 == colorList.Count) { RMoCore.TrackConsole.Write(this, "SerializeBlock", "Palette color is empty."); return(false); } colorList.Add(Color.Transparent); palette = colorList.ToArray(); } // 输出调色板 int paletteCount = palette.Length; output.WriteUint16((ushort)paletteCount); foreach (Color color in palette) { if (_optionAlpha) { output.WriteInt32(color.ToArgb() & 0x00FFFFFF); } else { output.WriteInt32(color.ToArgb()); } } // _logger.Debug(this, "SerializeIndexed", "block_size={0}x{1}, color={2}, alpha={3}", blockWidth, blockHeight, paletteCount, _optionAlpha); // 输出颜色数组 int x = rect.Left; int y = rect.Top; // 透明色索引 int transparentIndex = palette.Length - 1; int size = blockWidth * blockHeight; // 写入数组 int postion = 0; byte[] bytes = null; if (_optionAlpha) { // 写入索引颜色和透明度 bytes = new byte[size * 2]; for (int h = 0; h < blockHeight; h++) { for (int w = 0; w < blockWidth; w++) { Color color = _native.GetPixel(x + w, y + h); int index = colorQuantizer.FindPaletteIndex(Color.FromArgb(255, color)); bytes[postion++] = (byte)index; bytes[postion++] = color.A; } } } else { // 写入带透明的索引颜色 bytes = new byte[size]; for (int h = 0; h < blockHeight; h++) { for (int w = 0; w < blockWidth; w++) { Color color = _native.GetPixel(x + w, y + h); int index = colorQuantizer.FindPaletteIndex(color); bytes[postion++] = (byte)index; } } } output.WriteBytes(bytes, 0, postion); return(true); }
public static Image QuantizeImage(Image sourceImage, IColorQuantizer quantizer, Int32 colorCount, Int32 parallelTaskCount = 4) { // performs the pure quantization wihout dithering return QuantizeImage(sourceImage, quantizer, null, colorCount, parallelTaskCount); }
public void Dither(ImageBuffer target, IColorDitherer ditherer, IColorQuantizer quantizer, Int32 colorCount, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(target, "target"); Guard.CheckNull(ditherer, "ditherer"); Guard.CheckNull(quantizer, "quantizer"); // prepares ditherer for another round ditherer.Prepare(quantizer, colorCount, this, target); // processes the image via the ditherer IList<Point> path = ditherer.GetPointPath(Width, Height); TransformPerPixel(target, path, ditherer.ProcessPixel, parallelTaskCount); }
public void Quantize(ImageBuffer target, IColorQuantizer quantizer, Int32 colorCount, Int32 parallelTaskCount = 4) { // performs the pure quantization wihout dithering Quantize(target, quantizer, null, colorCount, parallelTaskCount); }
public void CorrectGamma(Single gamma, IColorQuantizer quantizer, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(quantizer, "quantizer"); // determines which method of color retrieval to use IList<Point> path = quantizer.GetPointPath(Width, Height); // calculates gamma ramp Int32[] gammaRamp = new Int32[256]; for (Int32 index = 0; index < 256; ++index) { gammaRamp[index] = Clamp((Int32) ((255.0f*Math.Pow(index/255.0f, 1.0f/gamma)) + 0.5f)); } // use different scanning method depending whether the image format is indexed ProcessPixelFunction correctGamma = pixel => { Color oldColor = GetColorFromPixel(pixel); Int32 red = gammaRamp[oldColor.R]; Int32 green = gammaRamp[oldColor.G]; Int32 blue = gammaRamp[oldColor.B]; Color newColor = Color.FromArgb(red, green, blue); SetColorToPixel(pixel, newColor, quantizer); return true; }; // performs the image scan, using a chosen method ProcessPerPixel(path, correctGamma, parallelTaskCount); }
public void ChangeFormat(ImageBuffer target, IColorQuantizer quantizer, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(target, "target"); Guard.CheckNull(quantizer, "quantizer"); // gathers some information about the target format Boolean hasSourceAlpha = PixelFormat.HasAlpha(); Boolean hasTargetAlpha = target.PixelFormat.HasAlpha(); Boolean isTargetIndexed = target.PixelFormat.IsIndexed(); Boolean isSourceDeepColor = PixelFormat.IsDeepColor(); Boolean isTargetDeepColor = target.PixelFormat.IsDeepColor(); // step 1 to 3 - prepares the palettes if (isTargetIndexed) SynthetizePalette(quantizer, target.PixelFormat.GetColorCount(), parallelTaskCount); // prepares the quantization function TransformPixelFunction changeFormat = (sourcePixel, targetPixel) => { // if both source and target formats are deep color formats, copies a value directly if (isSourceDeepColor && isTargetDeepColor) { //UInt64 value = sourcePixel.Value; //targetPixel.SetValue(value); } else { // retrieves a source image color Color color = GetColorFromPixel(sourcePixel); // if alpha is not present in the source image, but is present in the target, make one up if (!hasSourceAlpha && hasTargetAlpha) { Int32 argb = 255 << 24 | color.R << 16 | color.G << 8 | color.B; color = Color.FromArgb(argb); } // sets the color to a target pixel SetColorToPixel(targetPixel, color, quantizer); } // allows to write (obviously) the transformed pixel return true; }; // step 5 - generates the target image IList<Point> standardPath = new StandardPathProvider().GetPointPath(Width, Height); TransformPerPixel(target, standardPath, changeFormat, parallelTaskCount); }
public static List<Color> SynthetizeImagePalette(Image sourceImage, IColorQuantizer quantizer, Int32 colorCount, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(sourceImage, "sourceImage"); // wraps source image to a buffer using (ImageBuffer source = new ImageBuffer(sourceImage, ImageLockMode.ReadOnly)) { return source.SynthetizePalette(quantizer, colorCount, parallelTaskCount); } }
private void ChangeQuantizer() { activeQuantizer = quantizerList[listMethod.SelectedIndex]; // turns off the color option for the uniform quantizer, as it doesn't make sense listColors.Enabled = listMethod.SelectedIndex != 1 && listMethod.SelectedIndex != 6 && listMethod.SelectedIndex != 7; // enables the color cache option; where available listColorCache.Enabled = activeQuantizer is BaseColorCacheQuantizer; // listColorModel.Enabled = listColorCache.Enabled && turnOnEvents && activeColorCache is BaseColorCache && ((BaseColorCache)activeColorCache).IsColorModelSupported; // enables dithering when applicable listDitherer.Enabled = listMethod.SelectedIndex != 5; // enabled parallelism when supported listParallel.Enabled = activeQuantizer.AllowParallel; // applies current UI selection if (activeQuantizer is BaseColorCacheQuantizer) { System.Diagnostics.Debug.WriteLine(activeQuantizer.ToString() + " is a BaseColorCacheQuantizer"); BaseColorCacheQuantizer quantizer = (BaseColorCacheQuantizer) activeQuantizer; quantizer.ChangeCacheProvider(activeColorCache); } if (listMethod.SelectedIndex == 1 || listMethod.SelectedIndex == 6 || listMethod.SelectedIndex == 7) { turnOnEvents = false; listColors.SelectedIndex = 7; turnOnEvents = true; } }
public void Prepare(IColorQuantizer quantizer, int width, int height) { _quantizer = quantizer; _width = width; }
private Graphics(Image bitmap) { _bitmap = bitmap; _quantizer = new DistinctSelectionQuantizer(); }
//============================================================ // <T>序列化位图数据。</T> // // @params output 输出流 // @params colorCount 调色板颜色数量 // @params pixelCount 分块的像素个数 //============================================================ public bool SerializeUnpackIndexed(IOutput output, int colorCount, int pixelCount) { // 若不支持半透明,去掉一个颜色,添加一个透明色 SIntRectangle rect = new SIntRectangle(); rect.Left = 0; rect.Top = 0; rect.Width = _native.Width; rect.Height = _native.Height; // 计算分割信息 int width = rect.Width; int height = rect.Height; int totalPixel = width * height; int splitWidth = width; int splitCount = totalPixel / pixelCount; int splitHeight = height; if (0 == splitCount) { splitHeight = height; splitCount = 1; } else { splitHeight = height / splitCount; splitCount = height / splitHeight; if (0 != (height % splitHeight)) { splitCount++; } } // 写入头信息 ushort option = 0; if (_optionAlpha) { option |= (ushort)EBitmapOption.Alpha; } output.WriteUint16(option); output.WriteUint16((ushort)width); output.WriteUint16((ushort)height); output.WriteUint16((ushort)splitCount); // 要序列化的源矩形区域 SIntRectangle subrect = new SIntRectangle(); subrect.Left = rect.Left; subrect.Top = rect.Top; subrect.Width = splitWidth; subrect.Height = splitHeight; // 源矩形数据 FByteStream bs = new FByteStream(); for (int n = 0; n < splitCount; n++) { bs.Clear(); subrect.Bottom = Math.Min(subrect.Top + splitHeight, rect.Top + height); // 创建图片优化器 FPictureQuantizer pictureQuantizer = null; IColorQuantizer colorQuantizer = null; if (_optionAlpha) { pictureQuantizer = new FPictureQuantizer(EColorQuantizer.Octree); colorQuantizer = pictureQuantizer.LoadQuantizerColors(_native, subrect, FPictureQuantizer.EQuantizedMode.Rgb); } else { pictureQuantizer = new FPictureQuantizer(EColorQuantizer.Octree16); colorQuantizer = pictureQuantizer.LoadQuantizerColors(_native, subrect, FPictureQuantizer.EQuantizedMode.Color); } // 存储图片优化数据 if (SerializeUnpackBlock(bs, colorQuantizer, subrect, colorCount)) { output.WriteUint32((uint)bs.Length); output.WriteBytes(bs.Memory, 0, bs.Length); // _logger.Debug(this, "SerializeIndexed", "index={0}/{1}, rect={2}, size={3}", n, splitCount, rect.ToString(), bs.Length); subrect.Top += splitHeight; } else { RMoCore.TrackConsole.Write(this, "SerializeIndexed", "Picture is all transparent."); return(false); } } return(true); }
public void FromBytes(byte[] bytes) { using (MemoryStream stream = new MemoryStream(bytes)) { BinaryReader reader = new BinaryReader(stream); byte version = reader.ReadByte(); if (version == 0x00) { var t = (DesignPattern.TypeEnum)reader.ReadByte(); if (this._Type == DesignPattern.TypeEnum.SimplePattern && t != DesignPattern.TypeEnum.SimplePattern) { throw new ArgumentException("Simple design spot can't hold pro design.", "project"); } if (this._Type != DesignPattern.TypeEnum.SimplePattern && t == DesignPattern.TypeEnum.SimplePattern) { throw new ArgumentException("Pro design spot can't hold simple design.", "project"); } this._Type = t; Quantizer = Quantizers[reader.ReadByte()]; ColorCache = ColorCaches[reader.ReadByte()]; var info = DesignPatternInformation.Types[this._Type]; this.SubPatterns = new List <SubPattern>(); for (int i = 0; i < info.Parts.Count; i++) { var subPattern = new SubPattern(this, info.Parts[i], true); this.SubPatterns.Add(subPattern); int layerCount = reader.ReadByte(); for (int j = 0; j < layerCount; j++) { var layerType = reader.ReadByte(); if (layerType == 0x01) { int objectX = reader.ReadInt32(); int objectY = reader.ReadInt32(); int objectW = reader.ReadInt32(); int objectH = reader.ReadInt32(); byte crop = reader.ReadByte(); byte resampling = reader.ReadByte(); int nameLength = reader.ReadInt32(); string name = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(nameLength)); int bitmapWidth = reader.ReadInt32(); int bitmapHeight = reader.ReadInt32(); byte[] bitmapPixels = reader.ReadBytes(bitmapWidth * bitmapHeight * 4); var bitmap = new System.Drawing.Bitmap(bitmapWidth, bitmapHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb); bitmap.FromBytes(bitmapPixels); SmartObjectLayer layer = new SmartObjectLayer(subPattern, name, bitmap, objectX, objectY, objectW, objectH); subPattern.Layers.Add(layer); layer.Crop = SmartObjectLayer.Crops[crop]; layer.Resampler = SmartObjectLayer.Resamplers[resampling]; layer.Colors = new UnityEngine.Color[layer.Width * layer.Height]; layer.UpdateColors(); layer.UpdateTexture(); } else if (layerType == 0x00) { int nameLength = reader.ReadInt32(); string name = System.Text.Encoding.UTF8.GetString(reader.ReadBytes(nameLength)); RasterLayer layer = new RasterLayer(subPattern, name); layer.Colors = new UnityEngine.Color[layer.Width * layer.Height]; for (int y = 0; y < layer.Height; y++) { for (int x = 0; x < layer.Width; x++) { layer.Colors[x + y * layer.Width] = new UnityEngine.Color(reader.ReadByte() / 255f, reader.ReadByte() / 255f, reader.ReadByte() / 255f, reader.ReadByte() / 255f); } } layer.UpdateTexture(); subPattern.Layers.Add(layer); } } } } } _CurrentSubPattern = 0; Editor.SetSize(CurrentSubPattern.Width, CurrentSubPattern.Height); Editor.LayersChanged(); Editor.SubPatternChanged(CurrentSubPattern.Part); Editor.SetType(this._Type); Editor.Show(null, null, null); Editor.OnImageUpdated(); Editor.Tools.HistoryChanged(CurrentSubPattern.History); for (int i = 0; i < SubPatterns.Count; i++) { SubPatterns[i].UpdateImage(false); } this.RegeneratePreview(); }
private void UpdateQuantizer() { if (!_pixelFormat.IsIndexed() || _quantizer != null) return; _quantizer = new DistinctSelectionQuantizer(); _quantizer.Prepare(this); // Pass: scan ImageBuffer.ProcessPerPixel(this, null, ParallelTaskCount, (passIndex, pixel) => { var color = pixel.GetColor(); _quantizer.AddColor(color, pixel.X, pixel.Y); return true; }); }
/// <summary> /// Initializes a new instance of the <see cref="ColorImageQuantizer"/> class. /// </summary> /// /// <param name="quantizer">Color quantization algorithm to use for processing images.</param> /// public ColorImageQuantizer(IColorQuantizer quantizer) { this.quantizer = quantizer; }
private void ResetPalette() { _palette = _pixelFormat.IsIndexed() ? new ColorPalette(new Color[_pixelFormat.GetColorCount()]) : null; _quantizer = null; }
public static Image QuantizeImage(ImageBuffer source, IColorQuantizer quantizer, IColorDitherer ditherer, Int32 colorCount, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(source, "source"); // creates a target bitmap in an appropriate format PixelFormat targetPixelFormat = Extend.GetFormatByColorCount(colorCount); Image result = new Bitmap(source.Width, source.Height, targetPixelFormat); // lock mode ImageLockMode lockMode = ditherer == null ? ImageLockMode.WriteOnly : ImageLockMode.ReadWrite; // wraps target image to a buffer using (ImageBuffer target = new ImageBuffer(result, lockMode)) { source.Quantize(target, quantizer, ditherer, colorCount, parallelTaskCount); return result; } }
public static Image QuantizeImage(Image sourceImage, IColorQuantizer quantizer, IColorDitherer ditherer, Int32 colorCount, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(sourceImage, "sourceImage"); // lock mode ImageLockMode lockMode = ditherer == null ? ImageLockMode.ReadOnly : ImageLockMode.ReadWrite; // wraps source image to a buffer using (ImageBuffer source = new ImageBuffer(sourceImage, lockMode)) { return QuantizeImage(source, quantizer, ditherer, colorCount, parallelTaskCount); } }
public void ChangeQuantizer(int num) { Quantizer = Quantizers[num]; RegeneratePreview(); }
public static void ChangeFormat(ImageBuffer source, PixelFormat targetFormat, IColorQuantizer quantizer, out Image targetImage, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(source, "source"); // creates a target bitmap in an appropriate format targetImage = new Bitmap(source.Width, source.Height, targetFormat); // wraps target image to a buffer using (ImageBuffer target = new ImageBuffer(targetImage, ImageLockMode.WriteOnly)) { source.ChangeFormat(target, quantizer, parallelTaskCount); } }
public void WriteColorUsingPixelAt(Pixel pixel, Int32 x, Int32 y, Color color, IColorQuantizer quantizer, Byte[] buffer = null) { // redirects pixel -> [x, y] pixel.Update(x, y); // writes color to bitmap/buffer using pixel WriteColorUsingPixel(pixel, color, quantizer, buffer); }
public void SetColor(Color color, IColorQuantizer quantizer) { // determines whether the format is indexed if (IsIndexed) { // last chance if quantizer is provided, use it if (quantizer != null) { Byte index = (Byte) quantizer.GetPaletteIndex(color, X, Y); ((IIndexedPixel) pixelData).SetIndex(bitOffset, index); } else // cannot write color to an index format { String message = string.Format("Cannot retrieve color for an indexed format. Use GetPixelIndex() instead."); throw new NotSupportedException(message); } } else // sets color to a non-indexed format { ((INonIndexedPixel) pixelData).SetColor(color); } }
static Bitmap() { Quantizer = new DistinctSelectionQuantizer(); }
private Bitmap(Bitmap source) { this._width = source._width; this._height = source._height; this._stride = source._stride; this._pixelFormat = source._pixelFormat; var size = source._height * source._stride; var bytes = new byte[size]; Marshal.Copy(source._scan0, bytes, 0, size); this._scan0 = Marshal.AllocHGlobal(size); Marshal.Copy(bytes, 0, this._scan0, size); this._freeScan0 = true; if (this._pixelFormat.IsIndexed()) { this.SetPalette(new ColorPalette(source._palette.Entries)); } else { this._quantizer = null; this._palette = null; } }
public List<Color> SynthetizePalette(IColorQuantizer quantizer, Int32 colorCount, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(quantizer, "quantizer"); // Step 1 - prepares quantizer for another round quantizer.Prepare(this); // Step 2 - scans the source image for the colors ScanColors(quantizer, parallelTaskCount); // Step 3 - synthetises the palette, and returns the result return quantizer.GetPalette(colorCount); }
public void Quantize(ImageBuffer target, IColorQuantizer quantizer, IColorDitherer ditherer, Int32 colorCount, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(target, "target"); Guard.CheckNull(quantizer, "quantizer"); // initializes quantization parameters Boolean isTargetIndexed = target.PixelFormat.IsIndexed(); // step 1 - prepares the palettes List<Color> targetPalette = isTargetIndexed ? SynthetizePalette(quantizer, colorCount, parallelTaskCount) : null; // step 2 - updates the bitmap palette target.bitmap.SetPalette(targetPalette); target.UpdatePalette(true); // step 3 - prepares ditherer (optional) if (ditherer != null) ditherer.Prepare(quantizer, colorCount, this, target); // step 4 - prepares the quantization function TransformPixelFunction quantize = (sourcePixel, targetPixel) => { // reads the pixel color Color color = GetColorFromPixel(sourcePixel); // converts alpha to solid color color = QuantizationHelper.ConvertAlpha(color); // quantizes the pixel SetColorToPixel(targetPixel, color, quantizer); // marks pixel as processed by default Boolean result = true; // preforms inplace dithering (optional) if (ditherer != null && ditherer.IsInplace) { result = ditherer.ProcessPixel(sourcePixel, targetPixel); } // returns the result return result; }; // step 5 - generates the target image IList<Point> path = quantizer.GetPointPath(Width, Height); TransformPerPixel(target, path, quantize, parallelTaskCount); // step 6 - preforms non-inplace dithering (optional) if (ditherer != null && !ditherer.IsInplace) { Dither(target, ditherer, quantizer, colorCount, 1); } // step 7 - finishes the dithering (optional) if (ditherer != null) ditherer.Finish(); // step 8 - clean-up quantizer.Finish(); }
public void WriteColorUsingPixel(Pixel pixel, Color color, IColorQuantizer quantizer, Byte[] buffer = null) { // sets color to pixel (pixel is updated with color) SetColorToPixel(pixel, color, quantizer); // writes pixel to a bitmap/buffer WritePixel(pixel, buffer); }
/// <summary> /// Initializes a new instance of the <see cref="ColorImageQuantizer"/> class. /// </summary> /// /// <param name="quantizer">Color quantization algorithm to use for processing images.</param> /// public ColorImageQuantizer( IColorQuantizer quantizer ) { this.quantizer = quantizer; }
public void ScanColors(IColorQuantizer quantizer, Int32 parallelTaskCount = 4) { // checks parameters Guard.CheckNull(quantizer, "quantizer"); // determines which method of color retrieval to use IList<Point> path = quantizer.GetPointPath(Width, Height); // use different scanning method depending whether the image format is indexed ProcessPixelFunction scanColors = pixel => { quantizer.AddColor(GetColorFromPixel(pixel), pixel.X, pixel.Y); return false; }; // performs the image scan, using a chosen method ProcessPerPixel(path, scanColors, parallelTaskCount); }