Search code examples
c#fontsbitmapvector-graphicsled

Small pixel font


I'm trying to display pixels on a monitor, in preparation for when I display on a set of LEDs. I'm doing this using a font to draw onto a bitmap, and then reading off the bitmap, whether the pixel is lighter or darker, and putting this into a 2 dimensional array of booleans. This array is then passed into my interface-specific display method, for displaying. As this set is only going to be 6 pixels high, I'm using a font made for a six pixel resolution from www.dafont.com/6px.font Currently this system doesn't display that well - some characters are not really readable.

Is this even the right way to be doing this? What should I be doing? Thanks!

Pixel map file:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.Linq;
using System.Text;

namespace Phidgets
{
    public class StringDrawer
    {
        internal int height, width;
        internal bool[][] mapData;
        GraphicalInterface MyGraphicalInterface;
        Bitmap canvas;
        int MaxPixelLength;
        Graphics canvasGraphics;
        Brush brush = new SolidBrush(Color.Black);
        Font font;
        public StringDrawer(int width, int height, GraphicalInterface myInterface)
        {
            InitFont();
            this.height = height;
            this.width = width;
            MaxPixelLength = 2048 + width;//2048 pixels, plus the amount of empty pixels at the end.
            mapData = new bool[height][];
            for (int i = 0; i < height; i++)
            {
                mapData[i] = new bool[width];
            }
            MyGraphicalInterface = myInterface;
            canvas = new Bitmap(MaxPixelLength, height);
            canvasGraphics = Graphics.FromImage(canvas);
        }
        void DrawPoint(int x, int y)
        {
            mapData[x][y] = true;
        }
        void Clear()
        {
            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    mapData[i][j] = false;
                }
            }
        }
        public void DrawString(String input)
        {
            input = input.ToUpper();
            Clear();
            PaintCanvas(input);
            UpdateDataFromCanvas();
            MyGraphicalInterface.Update(mapData);
        }
        public void UpdateDataFromCanvas()
        {
            for (int y = 0; y < mapData.Count(); y++)
            {
                for (int x = 0; x < mapData[0].Length; x++)
                {
                    bool b = canvas.GetPixel(x, y).R < 128;//r g or b is equivalent here, half way between light and dark.
                    mapData[y][x] = b;
                }
            }
        }
        Bitmap GetCurrentFrame(int startX)
        {
            return null;
        }
        void PaintCanvas(String input)
        {
            canvasGraphics.Clear(Color.White);
            canvasGraphics.DrawString(input, regFont, solidBrush, 0, 0);
        }
        SolidBrush solidBrush;
        Font regFont;
        void InitFont()
        {
            System.Drawing.Text.PrivateFontCollection privateFontCollection = new System.Drawing.Text.PrivateFontCollection();
            privateFontCollection.AddFontFile("../../6px-Normal.ttf");
            solidBrush = new SolidBrush(Color.Black);
            FontFamily[] fontFamilies = privateFontCollection.Families;
            string familyName = fontFamilies[0].Name;
            regFont = new Font(familyName, 6,FontStyle.Regular, GraphicsUnit.Pixel);
        }
    }
    public abstract class GraphicalInterface
    {
        public abstract void Update(bool[][] mapData);
    }
    public class ScreenInterface : GraphicalInterface
    {
        //int xStart = 350;
        //int yStart = 23;
        int xStart, yStart;
        Graphics g;
        Brush brush = new SolidBrush(Color.Black);
        public ScreenInterface(int xStart, int yStart, Form1 f)
        {
            g = f.CreateGraphics();
            this.xStart = xStart;
            this.yStart = yStart;
        }
        public override void Update(bool[][] mapData)
        {
            const int scale = 4;
            for (int y = 0; y < mapData.Count(); y++)
            {
                for (int x = 0; x < mapData[0].Length; x++)
                {
                    if (mapData[y][x])
                        g.FillRectangle(brush, xStart + (x * scale), yStart + (y * scale), scale, scale);
                }
            }
        }
    }
    public class LedInterface : GraphicalInterface
    {
        public override void Update(bool[][] mapData)
        {
            for (int y = 0; y < mapData.Count(); y++)
            {
                for (int x = 0; x < mapData[0].Length; x++)
                {
                    //not implemented
                }
            }
        }
    }
}

Form1 file:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Phidgets
{
    public partial class Form1 : Form
    {
        StringDrawer testDrawer, LedDrawer;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            const int width = 24;
            const int height = 6;
            ScreenInterface screen = new ScreenInterface(450, 23, this);
            testDrawer = new StringDrawer(width, height, screen);
            LedDrawer = new StringDrawer(width, height, new LedInterface());
        }

        private void closeButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void GoButton_Click(object sender, EventArgs e)
        {
            testDrawer.DrawString("a b c");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Thanks to defont.com/6px for the font used, and as always, much wow to stackoverflow.");
        }
    }
}

Any help is much appreciated - thanks!


Solution

  • Figured out the problem - the font wasn't even assigning!

    When I called: regFont = new Font(familyName, 6,FontStyle.Regular, GraphicsUnit.Pixel);

    It didn't change! Like, if you went through in the debugger, the value didn't change after the assignment. So weird. but when I changed the InitFont method to say:

        void InitFont()
        {
            System.Drawing.Text.PrivateFontCollection privateFontCollection =
               new System.Drawing.Text.PrivateFontCollection();
            privateFontCollection.AddFontFile("../../6px-Normal.ttf");
            solidBrush = new SolidBrush(Color.Black);
            FontFamily[] fontFamilies = privateFontCollection.Families;
            regFont = new Font(fontFamilies[0], 6);
        }
    

    the assignment worked. So a little anti-climactic, but thanks guys for your help.