Files
McBitFont/McBitFont/ImageImporter.cs
2025-05-23 16:41:38 +03:00

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);
}
}
}