236 lines
8.8 KiB
C#
236 lines
8.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.ComponentModel.DataAnnotations;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
|
|
namespace McBitFont {
|
|
public partial class ImageImporter : Form {
|
|
|
|
private int fw, fh, pixelization, threshold;
|
|
private Color[] colorPool = [Color.Black, Color.White];
|
|
private Bitmap bmpOriginal, bmpProcessed;
|
|
public Bitmap bmpScaled;
|
|
|
|
public ImageImporter(int width, int height) {
|
|
InitializeComponent();
|
|
fw = width;
|
|
fh = height;
|
|
}
|
|
|
|
private void UpdateControls(byte level) {
|
|
switch (level) {
|
|
case 1:
|
|
bmpProcessed = null;
|
|
bmpScaled = null;
|
|
pbProcessed.Image = null;
|
|
pbScaled.Image = null;
|
|
lblProcessedSize.Text = "0 x 0";
|
|
lblScaledSize.Text = "0 x 0";
|
|
btnResize.Enabled = false;
|
|
btnOK.Enabled = false;
|
|
btnConvert.Enabled = true;
|
|
break;
|
|
case 2:
|
|
bmpScaled = null;
|
|
pbScaled.Image = null;
|
|
lblScaledSize.Text = "0 x 0";
|
|
btnOK.Enabled = false;
|
|
btnResize.Enabled = true;
|
|
break;
|
|
case 3:
|
|
btnOK.Enabled = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void btnOK_Click(object sender, EventArgs e) {
|
|
DialogResult = DialogResult.OK;
|
|
}
|
|
|
|
private void btnCancel_Click(object sender, EventArgs e) {
|
|
DialogResult = DialogResult.Cancel;
|
|
}
|
|
|
|
// Pick a color from color pool that is closest to an average of given colors
|
|
private Color PickColor(Color[] colors) {
|
|
int i;
|
|
int r = 0; int g = 0; int b = 0;
|
|
|
|
// Calculating average color amongst givet color set
|
|
for (i = 0; i < colors.Length; i++) {
|
|
r += colors[i].R;
|
|
g += colors[i].G;
|
|
b += colors[i].B;
|
|
}
|
|
r /= colors.Length;
|
|
g /= colors.Length;
|
|
b /= colors.Length;
|
|
|
|
int near = 1000;
|
|
int ind = 0;
|
|
|
|
// Picking a closts color from color pool
|
|
for (i = 0; i < colorPool.Length; i++) {
|
|
int valR = colorPool[i].R - r + threshold;
|
|
int valG = colorPool[i].R - g + threshold;
|
|
int valB = colorPool[i].R - b + threshold;
|
|
if (valR < 0) valR = -valR;
|
|
if (valG < 0) valG = -valG;
|
|
if (valB < 0) valB = -valB;
|
|
|
|
threshold = tbThreshold.Value;
|
|
int total = valR + valG + valB;
|
|
|
|
if (total < near) {
|
|
ind = i;
|
|
near = total;
|
|
}
|
|
}
|
|
return colorPool[ind];
|
|
}
|
|
|
|
private static void DrawArrow(Graphics g, Point from, Point to, float thickness = 1, Color? color = null) {
|
|
if (color == null) color = Color.Black;
|
|
var pen = new Pen((Color)color, thickness) {
|
|
CustomEndCap = new AdjustableArrowCap(4, 5)
|
|
};
|
|
g.DrawLine(pen, from, to);
|
|
}
|
|
|
|
private void tbPixelization_ValueChanged(object sender, EventArgs e) {
|
|
lblPixelization.Text = "Pixelization: " + tbPixelization.Value.ToString();
|
|
}
|
|
|
|
private void tbThreshold_ValueChanged(object sender, EventArgs e) {
|
|
lblThreshold.Text = "Threshold: " + tbThreshold.Value.ToString();
|
|
}
|
|
|
|
private void btnLoadImage_Click(object sender, EventArgs e) {
|
|
if (dlgLoadImage.ShowDialog() == DialogResult.OK) {
|
|
bmpOriginal = new Bitmap(dlgLoadImage.FileName);
|
|
|
|
pbOriginal.Image = Draw200x200(bmpOriginal);
|
|
lblOrigSize.Text = bmpOriginal.Width.ToString() + " x " + bmpOriginal.Height.ToString()
|
|
+ " (" + pbOriginal.Image.Width.ToString() + " x " + pbOriginal.Image.Height.ToString() + ")";
|
|
|
|
// Clear other images
|
|
UpdateControls(1);
|
|
}
|
|
}
|
|
|
|
private void btnConvert_Click(object sender, EventArgs e) {
|
|
pixelization = tbPixelization.Value;
|
|
//Bitmap bmOrig = (Bitmap)pbOriginal.Image;
|
|
bmpProcessed = new Bitmap(bmpOriginal.Width, bmpOriginal.Height);
|
|
|
|
// Processing image
|
|
using (Graphics g = Graphics.FromImage(bmpProcessed)) {
|
|
List<Color> block;
|
|
Rectangle rect = new Rectangle();
|
|
SolidBrush sb = new SolidBrush(Color.Black);
|
|
Color final = Color.Black;
|
|
Color pixel;
|
|
|
|
// Going through original image with steps = pixelization
|
|
for (int x = 0; x < bmpOriginal.Width; x += pixelization) {
|
|
for (int y = 0; y < bmpOriginal.Height; y += pixelization) {
|
|
block = [];
|
|
|
|
// Going throug a block pixel by pixel to calculate its average color later
|
|
for (int v = 0; v < pixelization; v++) {
|
|
for (int c = 0; c < pixelization; c++) {
|
|
if (x + v < bmpOriginal.Width && y + c < bmpOriginal.Height) {
|
|
pixel = bmpOriginal.GetPixel(x + v, y + c);
|
|
if (pixel.A <= tbTransparency.Value) pixel = Color.White;
|
|
block.Add(pixel);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Getting a color from the color pool and painting the block
|
|
if (block.Count > 0) {
|
|
final = PickColor(block.ToArray());
|
|
sb.Color = final;
|
|
|
|
rect.X = x;
|
|
rect.Y = y;
|
|
rect.Width = pixelization;
|
|
rect.Height = pixelization;
|
|
|
|
g.FillRectangle(sb, rect);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pbProcessed.Image = Draw200x200(bmpProcessed);
|
|
lblProcessedSize.Text = bmpProcessed.Width.ToString() + " x " + bmpProcessed.Height.ToString()
|
|
+ " (" + pbProcessed.Image.Width.ToString() + " x " + pbProcessed.Image.Height.ToString() + ")";
|
|
|
|
UpdateControls(2);
|
|
}
|
|
|
|
private void btnResize_Click(object sender, EventArgs e) {
|
|
bmpScaled = DrawScaled(bmpProcessed, fw, fh);
|
|
|
|
pbScaled.Image = Draw200x200(bmpScaled);
|
|
lblScaledSize.Text = bmpScaled.Width.ToString() + " x " + bmpScaled.Height.ToString()
|
|
+ " (" + pbScaled.Image.Width.ToString() + " x " + pbScaled.Image.Height.ToString() + ")";
|
|
UpdateControls(3);
|
|
}
|
|
|
|
// Draw 200x200 bitmap for picturebox
|
|
private static Bitmap Draw200x200(Bitmap bmpRef) {
|
|
return DrawScaled(bmpRef, 200, 200);
|
|
}
|
|
|
|
// Draw scaled bitmap keeping aspect ratio
|
|
private static Bitmap DrawScaled(Bitmap bmpRef, int w, int h) {
|
|
var scale = Math.Min(w / (double)bmpRef.Width, h / (double)bmpRef.Height);
|
|
var bmpNew = new Bitmap((int)(bmpRef.Width * scale), (int)(bmpRef.Height * scale));
|
|
|
|
using (Graphics g = Graphics.FromImage(bmpNew)) {
|
|
g.InterpolationMode = InterpolationMode.NearestNeighbor;
|
|
g.PixelOffsetMode = PixelOffsetMode.Half;
|
|
g.DrawImage(bmpRef, 0, 0, bmpNew.Width, bmpNew.Height);
|
|
}
|
|
|
|
return bmpNew;
|
|
}
|
|
|
|
private void tbThreshold_KeyDown(object sender, KeyEventArgs e) {
|
|
if (e.KeyCode == Keys.C) {
|
|
tbThreshold.Value = 0;
|
|
}
|
|
}
|
|
|
|
private void tbPixelization_KeyDown(object sender, KeyEventArgs e) {
|
|
if (e.KeyCode == Keys.C) {
|
|
tbPixelization.Value = 1;
|
|
}
|
|
}
|
|
|
|
private void tbTransparency_ValueChanged(object sender, EventArgs e) {
|
|
lblTransparency.Text = "Transparency threshold: " + tbTransparency.Value.ToString();
|
|
}
|
|
|
|
private void tbTransparency_KeyDown(object sender, KeyEventArgs e) {
|
|
if (e.KeyCode == Keys.C) {
|
|
tbTransparency.Value = 32;
|
|
}
|
|
}
|
|
|
|
private void ImageImporter_Paint(object sender, PaintEventArgs e) {
|
|
DrawArrow(e.Graphics, new Point(175, 246), new Point(255, 246), 2, Color.SlateGray);
|
|
DrawArrow(e.Graphics, new Point(380, 246), new Point(455, 246), 2, Color.SlateGray);
|
|
}
|
|
}
|
|
}
|