cleanup Quantizer.cs

This commit is contained in:
adelikat 2019-12-31 10:24:57 -06:00
parent 64ea9afee5
commit 0082de7c0a
3 changed files with 48 additions and 71 deletions

View File

@ -14,11 +14,12 @@
// Based on: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/colorquant.asp // Based on: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/colorquant.asp
//Bizhawk says: adapted from https://github.com/inexorabletash/PcxFileType/blob/master/Quantize //BizHawk says: adapted from https://github.com/inexorabletash/PcxFileType/blob/master/Quantize
using System; using System;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using BizHawk.Common.NumberExtensions;
namespace BizHawk.Client.EmuHawk namespace BizHawk.Client.EmuHawk
{ {
@ -27,35 +28,9 @@ namespace BizHawk.Client.EmuHawk
/// <summary> /// <summary>
/// Flag used to indicate whether a single pass or two passes are needed for quantization. /// Flag used to indicate whether a single pass or two passes are needed for quantization.
/// </summary> /// </summary>
private bool _singlePass; private readonly bool _singlePass;
protected bool highquality; protected int DitherLevel;
public bool HighQuality
{
get
{
return highquality;
}
set
{
highquality = value;
}
}
protected int ditherLevel;
public int DitherLevel
{
get
{
return ditherLevel;
}
set
{
ditherLevel = value;
}
}
/// <summary> /// <summary>
/// Construct the quantizer /// Construct the quantizer
@ -66,7 +41,7 @@ namespace BizHawk.Client.EmuHawk
/// only call the 'QuantizeImage' function. If two passes are required, the code will call 'InitialQuantizeImage' /// only call the 'QuantizeImage' function. If two passes are required, the code will call 'InitialQuantizeImage'
/// and then 'QuantizeImage'. /// and then 'QuantizeImage'.
/// </remarks> /// </remarks>
public Quantizer(bool singlePass) protected Quantizer(bool singlePass)
{ {
_singlePass = singlePass; _singlePass = singlePass;
} }
@ -83,32 +58,30 @@ namespace BizHawk.Client.EmuHawk
int width = source.Width; int width = source.Width;
// And construct a rectangle from these dimensions // And construct a rectangle from these dimensions
Rectangle bounds = new Rectangle(0, 0, width, height); var bounds = new Rectangle(0, 0, width, height);
// First off take a 32bpp copy of the image // First off take a 32bpp copy of the image
Bitmap copy; Bitmap copy;
if (source is Bitmap && source.PixelFormat == PixelFormat.Format32bppArgb) if (source is Bitmap bitmap && bitmap.PixelFormat == PixelFormat.Format32bppArgb)
{ {
copy = (Bitmap)source; copy = bitmap;
} }
else else
{ {
copy = new Bitmap(width, height, PixelFormat.Format32bppArgb); copy = new Bitmap(width, height, PixelFormat.Format32bppArgb);
// Now lock the bitmap into memory // Now lock the bitmap into memory
using (Graphics g = Graphics.FromImage(copy)) using Graphics g = Graphics.FromImage(copy);
{ g.PageUnit = GraphicsUnit.Pixel;
g.PageUnit = GraphicsUnit.Pixel;
// Draw the source image onto the copy bitmap, // Draw the source image onto the copy bitmap,
// which will effect a widening as appropriate. // which will effect a widening as appropriate.
g.DrawImage(source, 0, 0, bounds.Width, bounds.Height); g.DrawImage(source, 0, 0, bounds.Width, bounds.Height);
}
} }
// And construct an 8bpp version // And construct an 8bpp version
Bitmap output = new Bitmap(width, height, PixelFormat.Format8bppIndexed); var output = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
// Define a pointer to the bitmap data // Define a pointer to the bitmap data
BitmapData sourceData = null; BitmapData sourceData = null;
@ -128,7 +101,7 @@ namespace BizHawk.Client.EmuHawk
// Then set the color palette on the output bitmap. I'm passing in the current palette // Then set the color palette on the output bitmap. I'm passing in the current palette
// as there's no way to construct a new, empty palette. // as there's no way to construct a new, empty palette.
output.Palette = this.GetPalette(output.Palette); output.Palette = GetPalette(output.Palette);
// Then call the second pass which actually does the conversion // Then call the second pass which actually does the conversion
SecondPass(sourceData, output, width, height, bounds); SecondPass(sourceData, output, width, height, bounds);
@ -160,13 +133,12 @@ namespace BizHawk.Client.EmuHawk
// Define the source data pointers. The source row is a byte to // Define the source data pointers. The source row is a byte to
// keep addition of the stride value easier (as this is in bytes) // keep addition of the stride value easier (as this is in bytes)
byte* pSourceRow = (byte*)sourceData.Scan0.ToPointer(); byte* pSourceRow = (byte*)sourceData.Scan0.ToPointer();
int* pSourcePixel;
// Loop through each row // Loop through each row
for (int row = 0; row < height; row++) for (int row = 0; row < height; row++)
{ {
// Set the source pixel to the first pixel in this row // Set the source pixel to the first pixel in this row
pSourcePixel = (Int32*)pSourceRow; var pSourcePixel = (int*)pSourceRow;
// And loop through each column // And loop through each column
for (int col = 0; col < width; col++, pSourcePixel++) for (int col = 0; col < width; col++, pSourcePixel++)
@ -176,15 +148,22 @@ namespace BizHawk.Client.EmuHawk
// Add the stride to the source row // Add the stride to the source row
pSourceRow += sourceData.Stride; pSourceRow += sourceData.Stride;
} }
} }
int ClampToByte(int val) private int ClampToByte(int val)
{ {
if (val < 0) return 0; if (val < 0)
else if (val > 255) return 255; {
else return val; return 0;
}
if (val > 255)
{
return 255;
}
return val;
} }
/// <summary> /// <summary>
@ -198,8 +177,8 @@ namespace BizHawk.Client.EmuHawk
protected virtual void SecondPass(BitmapData sourceData, Bitmap output, int width, int height, Rectangle bounds) protected virtual void SecondPass(BitmapData sourceData, Bitmap output, int width, int height, Rectangle bounds)
{ {
BitmapData outputData = null; BitmapData outputData = null;
Color[] pallete = output.Palette.Entries; Color[] palettes = output.Palette.Entries;
int weight = ditherLevel; int weight = DitherLevel;
try try
{ {
@ -209,7 +188,7 @@ namespace BizHawk.Client.EmuHawk
// Define the source data pointers. The source row is a byte to // Define the source data pointers. The source row is a byte to
// keep addition of the stride value easier (as this is in bytes) // keep addition of the stride value easier (as this is in bytes)
byte* pSourceRow = (byte*)sourceData.Scan0.ToPointer(); byte* pSourceRow = (byte*)sourceData.Scan0.ToPointer();
Int32* pSourcePixel = (Int32*)pSourceRow; int* pSourcePixel = (int*)pSourceRow;
// Now define the destination data pointers // Now define the destination data pointers
byte* pDestinationRow = (byte*)outputData.Scan0.ToPointer(); byte* pDestinationRow = (byte*)outputData.Scan0.ToPointer();
@ -229,13 +208,13 @@ namespace BizHawk.Client.EmuHawk
if ((row & 1) == 0) if ((row & 1) == 0)
{ {
pSourcePixel = (Int32*)pSourceRow; pSourcePixel = (int*)pSourceRow;
pDestinationPixel = pDestinationRow; pDestinationPixel = pDestinationRow;
ptrInc = +1; ptrInc = +1;
} }
else else
{ {
pSourcePixel = (Int32*)pSourceRow + width - 1; pSourcePixel = (int*)pSourceRow + width - 1;
pDestinationPixel = pDestinationRow + width - 1; pDestinationPixel = pDestinationRow + width - 1;
ptrInc = -1; ptrInc = -1;
} }
@ -261,7 +240,7 @@ namespace BizHawk.Client.EmuHawk
byte pixelValue = QuantizePixel(target); byte pixelValue = QuantizePixel(target);
*pDestinationPixel = pixelValue; *pDestinationPixel = pixelValue;
int actual = pallete[pixelValue].ToArgb(); int actual = palettes[pixelValue].ToArgb();
int actualR = actual & 0xFF; int actualR = actual & 0xFF;
int actualG = (actual >> 8) & 0xFF; int actualG = (actual >> 8) & 0xFF;
@ -314,11 +293,8 @@ namespace BizHawk.Client.EmuHawk
errorNextRowG[width - (col + 1)] += errorGd; errorNextRowG[width - (col + 1)] += errorGd;
errorNextRowB[width - (col + 1)] += errorBd; errorNextRowB[width - (col + 1)] += errorBd;
unchecked pSourcePixel += ptrInc;
{ pDestinationPixel += ptrInc;
pSourcePixel += ptrInc;
pDestinationPixel += ptrInc;
}
} }
// Add the stride to the source row // Add the stride to the source row
@ -362,7 +338,7 @@ namespace BizHawk.Client.EmuHawk
/// <summary> /// <summary>
/// Retrieve the palette for the quantized image /// Retrieve the palette for the quantized image
/// </summary> /// </summary>
/// <param name="original">Any old palette, this is overrwritten</param> /// <param name="original">Any old palette, this is overwritten</param>
/// <returns>The new color palette</returns> /// <returns>The new color palette</returns>
protected abstract ColorPalette GetPalette(ColorPalette original); protected abstract ColorPalette GetPalette(ColorPalette original);
} }

View File

@ -5,24 +5,24 @@ namespace BizHawk.Common.NumberExtensions
{ {
public static class NumberExtensions public static class NumberExtensions
{ {
public static string ToHexString(this int n, int numdigits) public static string ToHexString(this int n, int numDigits)
{ {
return string.Format($"{{0:X{numdigits}}}", n); return string.Format($"{{0:X{numDigits}}}", n);
} }
public static string ToHexString(this uint n, int numdigits) public static string ToHexString(this uint n, int numDigits)
{ {
return string.Format($"{{0:X{numdigits}}}", n); return string.Format($"{{0:X{numDigits}}}", n);
} }
public static string ToHexString(this long n, int numdigits) public static string ToHexString(this long n, int numDigits)
{ {
return string.Format($"{{0:X{numdigits}}}", n); return string.Format($"{{0:X{numDigits}}}", n);
} }
public static string ToHexString(this ulong n, int numdigits) public static string ToHexString(this ulong n, int numDigits)
{ {
return string.Format($"{{0:X{numdigits}}}", n); return string.Format($"{{0:X{numDigits}}}", n);
} }
public static bool Bit(this byte b, int index) public static bool Bit(this byte b, int index)
@ -61,7 +61,7 @@ namespace BizHawk.Common.NumberExtensions
/// </summary> /// </summary>
public static int NumHexDigits(this long i) public static int NumHexDigits(this long i)
{ {
// now this is a bit of a trick. if it was less than 0, it mustve been >= 0x80000000 and so takes all 8 digits // now this is a bit of a trick. if it was less than 0, it must have been >= 0x80000000 and so takes all 8 digits
if (i < 0) if (i < 0)
{ {
return 8; return 8;
@ -99,7 +99,7 @@ namespace BizHawk.Common.NumberExtensions
} }
/// <summary> /// <summary>
/// Force the value to be strictly between min and max (both exclued) /// Force the value to be strictly between min and max (both excluded)
/// </summary> /// </summary>
/// <typeparam name="T">Anything that implements <see cref="IComparable{T}"/></typeparam> /// <typeparam name="T">Anything that implements <see cref="IComparable{T}"/></typeparam>
/// <param name="val">Value that will be clamped</param> /// <param name="val">Value that will be clamped</param>

View File

@ -320,6 +320,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Prereqs/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Prereqs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=prescale/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=prescale/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Quantizer/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Quantizer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=quantizing/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=quickload/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=quickload/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=quicknes/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=quicknes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=quicksave/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=quicksave/@EntryIndexedValue">True</s:Boolean>