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 const int LowLevel = 0x00;
public const int HighLevel = 0xff;
public const int Treshold = 0x80;
public const byte LowLevel = 0x00;
public const byte HighLevel = 0xff;
public const byte Treshold = 0x80;
public ColorError(Color original)
{
var r = original.R < Treshold ? LowLevel : HighLevel;
var g = original.G < Treshold ? LowLevel : HighLevel;
var b = original.B < Treshold ? LowLevel : HighLevel;
var a = NewValue(original.A);
var r = NewValue(original.R);
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;
ErrorG = original.G - g;
ErrorB = original.B - b;
}
public Color NewColor { get; }
public int ErrorA { get; }
public int ErrorR { get; }
public int ErrorG { 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)
{
return Color.FromArgb(
NewColor.A,
CheckBounds(color.A + ErrorA * part / total),
CheckBounds(color.R + ErrorR * part / total),
CheckBounds(color.G + ErrorG * 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;
_height = (ushort) image.Height;
ApplyDithering();
ExtractPalette();
if (_bitsPerPixel == 3) _bitsPerPixel = 4;
@ -57,17 +56,6 @@ namespace Resources.Image
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()
{
Logger.Trace("Extracting palette...");

View File

@ -1,7 +1,9 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using NLog;
using Resources.Image;
namespace Resources
{
@ -27,11 +29,25 @@ namespace Resources
continue;
}
var image = (Bitmap) System.Drawing.Image.FromFile(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.");
}
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;
}
}
}