diff --git a/src/ImageProcessor.Playground/ImageProcessor.Playground.csproj b/src/ImageProcessor.Playground/ImageProcessor.Playground.csproj
index 22044e950..44d73c00b 100644
--- a/src/ImageProcessor.Playground/ImageProcessor.Playground.csproj
+++ b/src/ImageProcessor.Playground/ImageProcessor.Playground.csproj
@@ -34,6 +34,9 @@
prompt
4
+
+
+
diff --git a/src/ImageProcessor.Playground/Program.cs b/src/ImageProcessor.Playground/Program.cs
index 2bfd70ff8..bb6344a36 100644
--- a/src/ImageProcessor.Playground/Program.cs
+++ b/src/ImageProcessor.Playground/Program.cs
@@ -50,12 +50,12 @@ namespace ImageProcessor.PlayGround
}
// Image mask = Image.FromFile(Path.Combine(resolvedPath, "mask2.png"));
- //FileInfo fileInfo = new FileInfo(Path.Combine(resolvedPath, "rgba.png"));
- IEnumerable files = GetFilesByExtensions(di, ".png");
+ FileInfo fileInfo = new FileInfo(Path.Combine(resolvedPath, "rgba.png"));
+ //IEnumerable files = GetFilesByExtensions(di, ".png");
//IEnumerable files = GetFilesByExtensions(di, ".gif", ".webp", ".bmp", ".jpg", ".png", ".tif");
- foreach (FileInfo fileInfo in files)
- {
+ //foreach (FileInfo fileInfo in files)
+ //{
byte[] photoBytes = File.ReadAllBytes(fileInfo.FullName);
Console.WriteLine("Processing: " + fileInfo.Name);
@@ -109,7 +109,7 @@ namespace ImageProcessor.PlayGround
Console.WriteLine(@"Completed {0} in {1:s\.fff} secs with peak memory usage of {2}.", fileInfo.Name, stopwatch.Elapsed, Process.GetCurrentProcess().PeakWorkingSet64.ToString("#,#"));
//Console.WriteLine("Processed: " + fileInfo.Name + " in " + stopwatch.ElapsedMilliseconds + "ms");
- }
+ //}
Console.ReadLine();
}
diff --git a/src/ImageProcessor/Imaging/FastBitmap.cs b/src/ImageProcessor/Imaging/FastBitmap.cs
index 120286709..5b6fcb818 100644
--- a/src/ImageProcessor/Imaging/FastBitmap.cs
+++ b/src/ImageProcessor/Imaging/FastBitmap.cs
@@ -52,9 +52,9 @@ namespace ImageProcessor.Imaging
private BitmapData bitmapData;
///
- /// The pixel buffer for holding pixel data.
+ /// The position of the first pixel in the bitmap.
///
- private byte* pixelBuffer;
+ private byte* pixelBase;
///
/// A value indicating whether this instance of the given entity has been disposed.
@@ -117,7 +117,7 @@ namespace ImageProcessor.Imaging
///
private Color32* this[int x, int y]
{
- get { return (Color32*)(this.pixelBuffer + (y * this.bytesInARow) + (x * this.color32Size)); }
+ get { return (Color32*)(this.pixelBase + (y * this.bytesInARow) + (x * this.color32Size)); }
}
///
@@ -210,7 +210,7 @@ namespace ImageProcessor.Imaging
this.Dispose(true);
// This object will be cleaned up by the Dispose method.
- // Therefore, you should call GC.SupressFinalize to
+ // Therefore, you should call GC.SuppressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
@@ -290,8 +290,8 @@ namespace ImageProcessor.Imaging
// Lock the bitmap
this.bitmapData = this.bitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
- // Copy the bitmap data across to the array for manipulation.
- this.pixelBuffer = (byte*)this.bitmapData.Scan0.ToPointer();
+ // Set the value to the first scan line
+ this.pixelBase = (byte*)this.bitmapData.Scan0.ToPointer();
}
///
@@ -302,7 +302,7 @@ namespace ImageProcessor.Imaging
// Copy the RGB values back to the bitmap and unlock the bitmap.
this.bitmap.UnlockBits(this.bitmapData);
this.bitmapData = null;
- this.pixelBuffer = null;
+ this.pixelBase = null;
}
}
}
diff --git a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs
index 91e5c975b..a0ee180f4 100644
--- a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs
+++ b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs
@@ -14,7 +14,6 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
using System;
using System.Collections.Generic;
using System.Drawing;
- using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
@@ -43,7 +42,7 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
public Bitmap Image { get; private set; }
///
- /// Gets the pixel lines.
+ /// Gets the enumerable pixel array representing each row of pixels.
///
///
/// Thrown if the given image is not a 32 bit per pixel image.
@@ -64,39 +63,20 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
int width = this.Image.Width;
int height = this.Image.Height;
- int[] buffer = new int[width];
Pixel[] pixels = new Pixel[width];
- //using (FastBitmap bitmap = new FastBitmap(this.Image))
- //{
- // for (int y = 0; y < height; y++)
- // {
- // for (int x = 0; x < width; x++)
- // {
- // Color color = bitmap.GetPixel(x, y);
- // pixels[x] = new Pixel(color.A, color.R, color.G, color.B);
- // }
- // yield return pixels;
- // }
- //}
-
- for (int rowIndex = 0; rowIndex < height; rowIndex++)
+ using (FastBitmap bitmap = new FastBitmap(this.Image))
{
- BitmapData data = this.Image.LockBits(Rectangle.FromLTRB(0, rowIndex, width, rowIndex + 1), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
- try
+ for (int y = 0; y < height; y++)
{
- Marshal.Copy(data.Scan0, buffer, 0, width);
- for (int pixelIndex = 0; pixelIndex < buffer.Length; pixelIndex++)
+ for (int x = 0; x < width; x++)
{
- pixels[pixelIndex] = new Pixel(buffer[pixelIndex]);
+ Color color = bitmap.GetPixel(x, y);
+ pixels[x] = new Pixel(color.A, color.R, color.G, color.B);
}
- }
- finally
- {
- this.Image.UnlockBits(data);
- }
- yield return pixels;
+ yield return pixels;
+ }
}
}
}
@@ -105,31 +85,34 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
/// Updates the pixel indexes.
///
///
- /// The line indexes.
+ /// The enumerable byte array representing each row of pixels.
///
public void UpdatePixelIndexes(IEnumerable lineIndexes)
{
int width = this.Image.Width;
int height = this.Image.Height;
+ int rowIndex = 0;
- IEnumerator indexesIterator = lineIndexes.GetEnumerator();
-
- for (int rowIndex = 0; rowIndex < height; rowIndex++)
+ BitmapData data = this.Image.LockBits(Rectangle.FromLTRB(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
+ try
{
- indexesIterator.MoveNext();
-
-
- BitmapData data = this.Image.LockBits(Rectangle.FromLTRB(0, rowIndex, width, rowIndex + 1), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
-
- try
+ IntPtr pixelBase = data.Scan0;
+ int scanWidth = data.Stride;
+ foreach (byte[] scanLine in lineIndexes)
{
- Marshal.Copy(indexesIterator.Current, 0, data.Scan0, width);
- }
- finally
- {
- this.Image.UnlockBits(data);
+ // TODO: Use unsafe code
+ Marshal.Copy(scanLine, 0, IntPtr.Add(pixelBase, scanWidth * rowIndex), width);
+
+ if (++rowIndex >= height)
+ {
+ break;
+ }
}
}
+ finally
+ {
+ this.Image.UnlockBits(data);
+ }
}
}
}
diff --git a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs
index d22486a6d..31b747ed6 100644
--- a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs
+++ b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs
@@ -82,11 +82,11 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
int bestDistance = int.MaxValue;
byte bestMatch = 0;
- foreach (var lookup in bucket)
+ foreach (LookupNode lookup in bucket)
{
- var lookupPixel = lookup.Pixel;
+ Pixel lookupPixel = lookup.Pixel;
- var deltaAlpha = pixel.Alpha - lookupPixel.Alpha;
+ int deltaAlpha = pixel.Alpha - lookupPixel.Alpha;
int distance = deltaAlpha * deltaAlpha;
var deltaRed = pixel.Red - lookupPixel.Red;
diff --git a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizer.cs b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizer.cs
index 39fc8c65c..038e2de3f 100644
--- a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizer.cs
+++ b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizer.cs
@@ -1,16 +1,95 @@
-using System.Collections.Generic;
-using System.Drawing;
-using System.Drawing.Imaging;
+// --------------------------------------------------------------------------------------------------------------------
+//
+// Copyright (c) James South.
+// Licensed under the Apache License, Version 2.0.
+//
+// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
{
+ using System.Collections.Generic;
+ using System.Drawing;
+ using System.Drawing.Imaging;
+
+ ///
+ /// The wu quantizer.
+ ///
public class WuQuantizer : WuQuantizerBase, IWuQuantizer
{
+ ///
+ /// The get quantized image.
+ ///
+ ///
+ /// The image.
+ ///
+ ///
+ /// The color count.
+ ///
+ ///
+ /// The lookups.
+ ///
+ ///
+ /// The alpha threshold.
+ ///
+ ///
+ /// The .
+ ///
+ internal override Image GetQuantizedImage(ImageBuffer image, int colorCount, Pixel[] lookups, int alphaThreshold)
+ {
+ Bitmap result = new Bitmap(image.Image.Width, image.Image.Height, PixelFormat.Format8bppIndexed);
+ result.SetResolution(image.Image.HorizontalResolution, image.Image.VerticalResolution);
+ ImageBuffer resultBuffer = new ImageBuffer(result);
+ PaletteColorHistory[] paletteHistogram = new PaletteColorHistory[colorCount + 1];
+ resultBuffer.UpdatePixelIndexes(IndexedPixels(image, lookups, alphaThreshold, paletteHistogram));
+ result.Palette = BuildPalette(result.Palette, paletteHistogram);
+ return result;
+ }
+
+ ///
+ /// The build palette.
+ ///
+ ///
+ /// The palette.
+ ///
+ ///
+ /// The palette histogram.
+ ///
+ ///
+ /// The .
+ ///
+ private static ColorPalette BuildPalette(ColorPalette palette, PaletteColorHistory[] paletteHistogram)
+ {
+ for (int paletteColorIndex = 0; paletteColorIndex < paletteHistogram.Length; paletteColorIndex++)
+ {
+ palette.Entries[paletteColorIndex] = paletteHistogram[paletteColorIndex].ToNormalizedColor();
+ }
+
+ return palette;
+ }
+
+ ///
+ /// The indexed pixels.
+ ///
+ ///
+ /// The image.
+ ///
+ ///
+ /// The lookups.
+ ///
+ ///
+ /// The alpha threshold.
+ ///
+ ///
+ /// The palette histogram.
+ ///
+ ///
+ /// The .
+ ///
private static IEnumerable IndexedPixels(ImageBuffer image, Pixel[] lookups, int alphaThreshold, PaletteColorHistory[] paletteHistogram)
{
byte[] lineIndexes = new byte[image.Image.Width];
PaletteLookup lookup = new PaletteLookup(lookups);
- foreach (var pixelLine in image.PixelLines)
+ foreach (Pixel[] pixelLine in image.PixelLines)
{
for (int pixelIndex = 0; pixelIndex < pixelLine.Length; pixelIndex++)
{
@@ -28,25 +107,5 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
yield return lineIndexes;
}
}
-
- internal override Image GetQuantizedImage(ImageBuffer image, int colorCount, Pixel[] lookups, int alphaThreshold)
- {
- var result = new Bitmap(image.Image.Width, image.Image.Height, PixelFormat.Format8bppIndexed);
- var resultBuffer = new ImageBuffer(result);
- var paletteHistogram = new PaletteColorHistory[colorCount + 1];
- resultBuffer.UpdatePixelIndexes(IndexedPixels(image, lookups, alphaThreshold, paletteHistogram));
- result.Palette = BuildPalette(result.Palette, paletteHistogram);
- return result;
- }
-
- private static ColorPalette BuildPalette(ColorPalette palette, PaletteColorHistory[] paletteHistogram)
- {
- for (int paletteColorIndex = 0; paletteColorIndex < paletteHistogram.Length; paletteColorIndex++)
- {
- palette.Entries[paletteColorIndex] = paletteHistogram[paletteColorIndex].ToNormalizedColor();
- }
-
- return palette;
- }
}
-}
+}
\ No newline at end of file