public void DitherPerformanceTest(bool errorDiffusion) { using var bmpRef = Icons.Information.ExtractBitmap(new Size(256, 256)); IQuantizer quantizer = PredefinedColorsQuantizer.SystemDefault8BppPalette(); IDitherer ditherer = errorDiffusion ? (IDitherer)ErrorDiffusionDitherer.FloydSteinberg : OrderedDitherer.Bayer8x8; new PerformanceTest { TestName = $"{bmpRef.Width}x{bmpRef.Height}@{bmpRef.GetColorCount()} {(errorDiffusion ? "Error Diffusion" : "Ordered")}", Iterations = 100, CpuAffinity = null } .AddCase(() => { using var result = bmpRef.CloneBitmap(); result.Dither(quantizer, ditherer); }, "BitmapExtensions.Dither") .AddCase(() => { using var result = bmpRef.CloneBitmap(); using (IBitmapDataInternal bitmapData = BitmapDataFactory.CreateBitmapData(result, ImageLockMode.ReadWrite)) using (IQuantizingSession quantizingSession = quantizer.Initialize(bitmapData)) using (IDitheringSession ditheringSession = ditherer.Initialize(bitmapData, quantizingSession)) { var row = bitmapData.DoGetRow(0); int width = bitmapData.Width; do { for (int x = 0; x < width; x++) { row.DoSetColor32(x, ditheringSession.GetDitheredColor(row.DoGetColor32(x), x, row.Index)); } } while (row.MoveNextRow()); } }, "Sequential dithering") .DoTest() .DumpResults(Console.Out); }
public void QuantizersPerformanceTest() { using var bmpRef = Icons.Information.ExtractBitmap(new Size(256, 256)); new PerformanceTest { TestName = $"{bmpRef.Width}x{bmpRef.Height}@{bmpRef.GetColorCount()}", Iterations = 25, CpuAffinity = null } .AddCase(() => { using var result = bmpRef.CloneBitmap(); result.Quantize(PredefinedColorsQuantizer.SystemDefault8BppPalette()); }, nameof(PredefinedColorsQuantizer.SystemDefault8BppPalette)) .AddCase(() => { using var result = bmpRef.CloneBitmap(); result.Quantize(OptimizedPaletteQuantizer.Octree()); }, nameof(OptimizedPaletteQuantizer.Octree)) .AddCase(() => { using var result = bmpRef.CloneBitmap(); result.Quantize(OptimizedPaletteQuantizer.MedianCut()); }, nameof(OptimizedPaletteQuantizer.MedianCut)) .AddCase(() => { using var result = bmpRef.CloneBitmap(); result.Quantize(OptimizedPaletteQuantizer.Wu()); }, nameof(OptimizedPaletteQuantizer.Wu)) .DoTest() .DumpResults(Console.Out); }
public void QuantizePerformanceTest() { //using var bmpRef = new Bitmap(@"D:\Letolt\MYSTY8RQER62.jpg"); using var bmpRef = Icons.Information.ExtractBitmap(new Size(256, 256)); IQuantizer quantizer = PredefinedColorsQuantizer.SystemDefault8BppPalette(); new PerformanceTest { TestName = $"{bmpRef.Width}x{bmpRef.Height}@{bmpRef.GetColorCount()}", Iterations = 100, CpuAffinity = null } .AddCase(() => { using var result = bmpRef.CloneBitmap(); result.Quantize(quantizer); }, "BitmapExtensions.Quantize") .AddCase(() => { using var result = bmpRef.CloneBitmap(); using (IBitmapDataInternal bitmapData = BitmapDataFactory.CreateBitmapData(result, ImageLockMode.ReadWrite)) using (IQuantizingSession session = quantizer.Initialize(bitmapData)) { var row = bitmapData.DoGetRow(0); int width = bitmapData.Width; do { for (int x = 0; x < width; x++) { row.DoSetColor32(x, session.GetQuantizedColor(row.DoGetColor32(x))); } } while (row.MoveNextRow()); } }, "Sequential quantization") .DoTest() .DumpResults(Console.Out); }
private static void AdjustQuantizerAndDitherer(IBitmapData target, ref IQuantizer quantizer, ref IDitherer ditherer) { if (quantizer != null || ditherer == null) { return; } if (target.PixelFormat.CanBeDithered()) { quantizer = PredefinedColorsQuantizer.FromBitmapData(target); } else { ditherer = null; } }
public void ClearWithDitheringTest(PixelFormat pixelFormat, uint argb, bool errorDiffusion) { const int size = 512; Color color = Color.FromArgb((int)argb); var ditherer = errorDiffusion ? (IDitherer)ErrorDiffusionDitherer.FloydSteinberg : OrderedDitherer.Bayer8x8; new PerformanceTest { TestName = $"{pixelFormat} {size}x{size} {(errorDiffusion ? "Error Diffusion" : "Ordered Dithering")}", Iterations = 10, CpuAffinity = null } .AddCase(() => { using var bmp = new Bitmap(size, size, pixelFormat); using IBitmapDataInternal acc = BitmapDataFactory.CreateBitmapData(bmp, ImageLockMode.ReadWrite); IQuantizer quantizer = PredefinedColorsQuantizer.FromBitmapData(acc); var c = new Color32(color); using (IQuantizingSession quantizingSession = quantizer.Initialize(acc)) using (IDitheringSession ditheringSession = ditherer.Initialize(acc, quantizingSession)) { IReadWriteBitmapDataRow row = acc.DoGetRow(0); do { for (int x = 0; x < acc.Width; x++) { row[x] = ditheringSession.GetDitheredColor(c, x, row.Index); } } while (row.MoveNextRow()); } }, "Sequential clear") .AddCase(() => { using var bmp = new Bitmap(size, size, pixelFormat); bmp.Clear(color, ditherer); }, "BitmapDataAccessor.Clear") .DoTest() .DumpResults(Console.Out); }
internal Image GetDisplayImage(bool generateSyncIfNull) { Image result = displayImage; if (result != null || !generateSyncIfNull) { return(result); } if (safeDefaultImage == null) { Image image = owner.image; Debug.Assert(image != null, "Image is not expected to be null here"); PixelFormat pixelFormat = image.PixelFormat; try { // Converting non supported or too slow pixel formats if (pixelFormat.In(convertedFormats)) { // Locking on display image so if it is the same as the original image, which is also locked when accessing its bitmap data // the "bitmap region is already locked" can be avoided. Important: this cannot be ensured without locking here internally because // OnPaint can occur any time after invalidating. isClonedSafeDefaultImage = true; lock (image) safeDefaultImage = pixelFormat == PixelFormat.Format16bppGrayScale ? image.ConvertPixelFormat(PixelFormat.Format8bppIndexed, PredefinedColorsQuantizer.Grayscale()) : image.ConvertPixelFormat(pixelFormat.HasAlpha() ? PixelFormat.Format32bppPArgb : PixelFormat.Format24bppRgb); } // Raw icons: converting because icons are handled oddly by GDI+, for example, the first column has half pixel width else if (image is Bitmap bmp && bmp.RawFormat.Guid == ImageFormat.Icon.Guid) { isClonedSafeDefaultImage = true; lock (image) safeDefaultImage = bmp.CloneCurrentFrame(); } else { safeDefaultImage = image; } }