using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;
namespace _20180227_単純減色にパターンディザ
{
public partial class MainWindow : Window
{
BitmapSource OriginBitmap;
string ImageFileFullPath;
public MainWindow()
{
InitializeComponent();
this.Title = this.ToString();
this.AllowDrop = true;
this.Drop += MainWindow_Drop;
ButtonConvert.Click += ButtonConvert_Click;
ButtonConvertWith1x1Dither.Click += ButtonConvertWith1x1Dither_Click;
ButtonConvertWith2x2Dither.Click += ButtonConvertWith2x2Dither_Click;
ButtonConvertWith4x4Dither.Click += ButtonConvertWith4x4Dither_Click;
ButtonOrigin.Click += ButtonOrigin_Click;
NumericScrollBar.ValueChanged += NumericScrollBar_ValueChanged;
NumericScrollBar.MouseWheel += NumericScrollBar_MouseWheel;
NumericTextBox.MouseWheel += NumericTextBox_MouseWheel;
NumericTextBox.GotFocus += NumericTextBox_GotFocus;
NumericTextBox.TextChanged += NumericTextBox_TextChanged;
}
private float[][] Get2x2ditherMatrix()
{
return new float[][]
{
new float[]{ 1f / 5f, 3f / 5f },
new float[]{ 4f / 5f, 2f / 5f }
};
}
private float[][] Get1x1ditherMatrix()
{
return new float[][] { new float[] { 1f / 2f } };
}
private float[][] Get4x4ditherMatrix()
{
return new float[][] {
new float[] { 1f / 17f, 13f / 17f, 4f / 17f, 16f / 17f },
new float[] { 9f / 17f, 5f / 17f, 12f / 17f, 8f / 17f },
new float[] { 3f / 17f, 15f / 17f, 2f / 17f, 14f / 17f },
new float[] { 11f / 17f, 7f / 17f, 10f / 17f, 6f / 17f }
};
}
<summary>
</summary>
<param name="ditherMatrix"></param>
<param name="source"></param>
<param name="division"></param>
private BitmapSource SimpleGensyokuWithPatternDither(float[][] ditherMatrix, BitmapSource source, int division)
{
byte[][][] converter = GetConverterArray4(division, ditherMatrix);
var wb = new WriteableBitmap(source);
int h = wb.PixelHeight;
int w = wb.PixelWidth;
int stride = wb.BackBufferStride;
byte[] pixles = new byte[h * stride];
wb.CopyPixels(pixles, stride, 0);
long p = 0;
for (int y = 0; y < h; ++y)
{
for (int x = 0; x < w; ++x)
{
p = y * stride + (x * 4);
for (int i = 0; i < 3; ++i)
{
pixles[p + i] = converter[y % converter.Length][x % converter[0].Length][pixles[p + i]];
}
}
}
wb.WritePixels(new Int32Rect(0, 0, w, h), pixles, stride, 0);
return wb;
}
<summary>
</summary>
<param name="division"></param>
<param name="threshold"></param>
<returns></returns>
private byte[] GetConverterArray3_2(int division, float threshold)
{
float[] range = new float[division + 1];
float threshold最初 = (float)(255f / division / 0.5 * threshold);
range[0] = threshold最初;
for (int i = 1; i < range.Length; ++i)
{
range[i] = threshold最初 + (255f / division * i);
}
float colorFrequency = 255f / (division - 1f);
byte[] color = new byte[division + 1];
for (int i = 0; i < color.Length; ++i)
{
if (i * colorFrequency >= 255)
{
color[i] = 255;
}
else
{
color[i] = (byte)Math.Round(
(i * colorFrequency), MidpointRounding.AwayFromZero);
}
}
byte[] neko = new byte[256];
int thresholdIndex = 0;
for (int i = 0; i < neko.Length; ++i)
{
if (i > range[thresholdIndex])
{
thresholdIndex++;
}
neko[i] = color[thresholdIndex];
}
return neko;
}
private byte[][][] GetConverterArray4(int division, float[][] ditherMatrix)
{
byte[][][] converterArray = new byte[ditherMatrix.Length][][];
for (int i = 0; i < ditherMatrix.Length; ++i)
{
converterArray[i] = new byte[ditherMatrix[i].Length][];
for (int j = 0; j < ditherMatrix[i].Length; ++j)
{
converterArray[i][j] = GetConverterArray3_2(division, ditherMatrix[i][j]);
}
}
return converterArray;
}
<summary>
</summary>
<param name="division"></param>
<returns></returns>
private byte[] GetConverterArray(int division)
{
float frequency = 256f / division;
float[] range = new float[division + 1];
for (int i = 0; i < range.Length; ++i)
{
range[i] = i * frequency;
}
frequency = 255f / (division - 1);
byte[] color = new byte[division];
for (int i = 0; i < color.Length; ++i)
{
color[i] = (byte)(i * frequency);
}
byte[] converter = new byte[256];
int j = 0;
for (int i = 0; i < 256; ++i)
{
if (i >= range[j + 1])
{
j++;
}
converter[i] = color[j];
}
return converter;
}
private void GensyokuNumeric2Table()
{
int division = (int)NumericScrollBar.Value;
byte[] converter = GetConverterArray(division);
var wb = new WriteableBitmap(OriginBitmap);
int h = wb.PixelHeight;
int w = wb.PixelWidth;
int stride = wb.BackBufferStride;
byte[] pixles = new byte[h * stride];
wb.CopyPixels(pixles, stride, 0);
long p = 0;
for (int y = 0; y < h; ++y)
{
for (int x = 0; x < w; ++x)
{
p = y * stride + (x * 4);
pixles[p + 2] = converter[pixles[p + 2]];
pixles[p + 1] = converter[pixles[p + 1]];
pixles[p + 0] = converter[pixles[p + 0]];
}
}
wb.WritePixels(new Int32Rect(0, 0, w, h), pixles, stride, 0);
MyImage.Source = wb;
TextBlockColorCount.Text = Math.Pow(division, 3).ToString();
}
#region イベント
private void ButtonConvertWith4x4Dither_Click(object sender, RoutedEventArgs e)
{
if (OriginBitmap == null) { return; }
MyImage.Source = SimpleGensyokuWithPatternDither(Get4x4ditherMatrix(), OriginBitmap, (int)NumericScrollBar.Value);
}
private void ButtonConvertWith2x2Dither_Click(object sender, RoutedEventArgs e)
{
if (OriginBitmap == null) { return; }
MyImage.Source = SimpleGensyokuWithPatternDither(Get2x2ditherMatrix(), OriginBitmap, (int)NumericScrollBar.Value);
}
private void ButtonConvertWith1x1Dither_Click(object sender, RoutedEventArgs e)
{
if (OriginBitmap == null) { return; }
MyImage.Source = SimpleGensyokuWithPatternDither(Get1x1ditherMatrix(), OriginBitmap, (int)NumericScrollBar.Value);
}
private void NumericTextBox_GotFocus(object sender, RoutedEventArgs e)
{
TextBox box = (TextBox)sender;
this.Dispatcher.InvokeAsync(() => { Task.Delay(10); box.SelectAll(); });
}
private void NumericScrollBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
TextBlockColorCount.Text = Math.Pow(NumericScrollBar.Value, 3).ToString();
}
private void ButtonConvert_Click(object sender, RoutedEventArgs e)
{
if (OriginBitmap == null) { return; }
GensyokuNumeric2Table();
}
private void NumericTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox textBox = (TextBox)sender;
double d;
if (!double.TryParse(textBox.Text, out d))
{
textBox.Text = System.Text.RegularExpressions.Regex.Replace(textBox.Text, "[^0-9]", "");
}
}
private void NumericTextBox_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (e.Delta > 0) { NumericScrollBar.Value++; }
else { NumericScrollBar.Value--; }
}
private void NumericScrollBar_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (e.Delta > 0) { NumericScrollBar.Value++; }
else { NumericScrollBar.Value--; }
}
private void ButtonOrigin_Click(object sender, RoutedEventArgs e)
{
if (OriginBitmap == null) { return; }
MyImage.Source = OriginBitmap;
}
private void MainWindow_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop) == false) { return; }
string[] filePath = (string[])e.Data.GetData(DataFormats.FileDrop);
OriginBitmap = GetBitmapSourceWithChangePixelFormat2(filePath[0], PixelFormats.Pbgra32, 96, 96);
if (OriginBitmap == null)
{
MessageBox.Show("not Image");
}
else
{
MyImage.Source = OriginBitmap;
ImageFileFullPath = filePath[0];
}
}
#endregion
private BitmapSource GetBitmapSourceWithChangePixelFormat2(
string filePath, PixelFormat pixelFormat, double dpiX = 0, double dpiY = 0)
{
BitmapSource source = null;
try
{
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
var bf = BitmapFrame.Create(fs);
var convertedBitmap = new FormatConvertedBitmap(bf, pixelFormat, null, 0);
int w = convertedBitmap.PixelWidth;
int h = convertedBitmap.PixelHeight;
int stride = (w * pixelFormat.BitsPerPixel + 7) / 8;
byte[] pixels = new byte[h * stride];
convertedBitmap.CopyPixels(pixels, stride, 0);
if (dpiX == 0) { dpiX = bf.DpiX; }
if (dpiY == 0) { dpiY = bf.DpiY; }
source = BitmapSource.Create(
w, h, dpiX, dpiY,
convertedBitmap.Format,
convertedBitmap.Palette, pixels, stride);
};
}
catch (Exception)
{
}
return source;
}
}
}