Fixed dithering for images with 8-bit alph-channel (closes #8), applied dithering on images loading step to generate previews using dithered image

fonts_experiment 1.0.2.4
Valeriy Mironov 2017-12-14 23:16:29 +02:00
parent b5916ab5ba
commit 128a3fa33e
3 changed files with 36 additions and 24 deletions

View File

@ -4,42 +4,50 @@ namespace Resources.Image
{ {
public class ColorError public class ColorError
{ {
public const int LowLevel = 0x00; public const byte LowLevel = 0x00;
public const int HighLevel = 0xff; public const byte HighLevel = 0xff;
public const int Treshold = 0x80; public const byte Treshold = 0x80;
public ColorError(Color original) public ColorError(Color original)
{ {
var r = original.R < Treshold ? LowLevel : HighLevel; var a = NewValue(original.A);
var g = original.G < Treshold ? LowLevel : HighLevel; var r = NewValue(original.R);
var b = original.B < Treshold ? LowLevel : HighLevel; var g = NewValue(original.G);
var b = NewValue(original.B);
NewColor = Color.FromArgb(original.A, r, g, b); NewColor = Color.FromArgb(a, r, g, b);
ErrorA = original.A - a;
ErrorR = original.R - r; ErrorR = original.R - r;
ErrorG = original.G - g; ErrorG = original.G - g;
ErrorB = original.B - b; ErrorB = original.B - b;
} }
public Color NewColor { get; } public Color NewColor { get; }
public int ErrorA { get; }
public int ErrorR { get; } public int ErrorR { get; }
public int ErrorG { get; } public int ErrorG { get; }
public int ErrorB { get; } public int ErrorB { get; }
public bool IsZero => ErrorR == 0 && ErrorG == 0 && ErrorB == 0; public bool IsZero => ErrorA == 0 && ErrorR == 0 && ErrorG == 0 && ErrorB == 0;
public Color ApplyError(Color color, int part, int total) public Color ApplyError(Color color, int part, int total)
{ {
return Color.FromArgb( return Color.FromArgb(
NewColor.A, CheckBounds(color.A + ErrorA * part / total),
CheckBounds(color.R + ErrorR * part / total), CheckBounds(color.R + ErrorR * part / total),
CheckBounds(color.G + ErrorG * part / total), CheckBounds(color.G + ErrorG * part / total),
CheckBounds(color.B + ErrorB * part / total) CheckBounds(color.B + ErrorB * part / total)
); );
} }
private byte CheckBounds(int value) private static byte NewValue(byte value)
{ {
return (byte) (value < 0 ? 0 : (value > 255 ? 255 : value)); return value < Treshold ? LowLevel : HighLevel;
}
private static byte CheckBounds(int value)
{
return (byte) (value < LowLevel ? LowLevel : (value > HighLevel ? HighLevel : value));
} }
} }
} }

View File

@ -37,7 +37,6 @@ namespace Resources.Image
_width = (ushort) image.Width; _width = (ushort) image.Width;
_height = (ushort) image.Height; _height = (ushort) image.Height;
ApplyDithering();
ExtractPalette(); ExtractPalette();
if (_bitsPerPixel == 3) _bitsPerPixel = 4; if (_bitsPerPixel == 3) _bitsPerPixel = 4;
@ -57,17 +56,6 @@ namespace Resources.Image
WriteImage(); WriteImage();
} }
private void ApplyDithering()
{
var clone = new Bitmap(_image.Width, _image.Height, PixelFormat.Format32bppArgb);
using (var gr = Graphics.FromImage(clone))
{
gr.DrawImage(_image, new Rectangle(0, 0, clone.Width, clone.Height));
}
FloydSteinbergDitherer.Process(clone);
_image = clone;
}
private void ExtractPalette() private void ExtractPalette()
{ {
Logger.Trace("Extracting palette..."); Logger.Trace("Extracting palette...");

View File

@ -1,7 +1,9 @@
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using NLog; using NLog;
using Resources.Image;
namespace Resources namespace Resources
{ {
@ -27,11 +29,25 @@ namespace Resources
continue; continue;
} }
var image = (Bitmap) System.Drawing.Image.FromFile(fullFileName);
Logger.Trace("Image was loaded from file {0}", fullFileName); Logger.Trace("Image was loaded from file {0}", fullFileName);
return (Bitmap) System.Drawing.Image.FromFile(fullFileName); return ApplyDithering(image);
} }
throw new FileNotFoundException($"File referenced by index {index} not found."); throw new FileNotFoundException($"File referenced by index {index} not found.");
} }
private static Bitmap ApplyDithering(Bitmap image)
{
var clone = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb);
using (var gr = Graphics.FromImage(clone))
{
gr.DrawImage(image, new Rectangle(0, 0, clone.Width, clone.Height));
}
FloydSteinbergDitherer.Process(clone);
clone.Save("tmp.png");
return clone;
}
} }
} }