C# 转换TTF为GB2312点阵字库

xiaoxiao2021-02-28  90

C# 转换TTF为GB2312点阵字库

前段时间碰到的一个项目要求在LCD上显示收到的短信,需要12×12的GB2312点阵字库。因为板子上已经放了块W25Q64了,就想着找个字库烧进去。最后虽然是用HZK12,但是总感觉不能释然,于是打算写个用系统字体库来生成点阵字库的工具。 网上有很多有这类的代码,不过我好像没找到我需要的。 思路是这样

遍历GB2312将汉字绘制到Bitmap按取模形式提取Bitmap上的数据(我只用列行式)按字库烧入方案输出到文件

首先为了遍历GB2312,要能用区码和位码生成汉字

//用GB2312区码和位码获取字符 public static string GetGB2312CH(byte areaCode, byte bitCode) { return Encoding.GetEncoding("gb2312").GetString(new byte[2]{areaCode, bitCode}); }

然后把汉字绘制到Bitmap

//获取字符串图片 public static Bitmap GetStrImage(string hz, Font font) { Bitmap bmp = new Bitmap(1, 1); Graphics g = Graphics.FromImage(bmp); SizeF sizeF = g.MeasureString(hz, font); //重设位图大小 bmp = new Bitmap(Convert.ToInt32(sizeF.Width), Convert.ToInt32(sizeF.Height)); g = Graphics.FromImage(bmp); //背景色黑色 g.Clear(Color.Black); g.DrawString(hz, font, new SolidBrush(Color.White), new PointF(0, 0)); return bmp; }

再按点阵字库的要求提取Bitmap上的像素点数据,我只用到了列行式顺向的点阵

//检查Bitmap的一行有没有有效数据 public static bool CheckBitmapRow(Bitmap src, int row) { for (int i=0; i<src.Width; i++) { if (src.GetPixel(i, row).ToArgb() != Color.Black.ToArgb()) { return true; } } return false; } //检查Bitmap的一列有没有有效数据 public static bool CheckBitmapCol(Bitmap src, int col) { for (int i=0; i<src.Height; i++) { if (src.GetPixel(col, i).ToArgb() != Color.Black.ToArgb()) { return true; } } return false; } //获取点阵字模从Bitmap 列行式顺向 //modWidth-字模宽 modHeight-字模高 public static byte[] GetCodeTabFromBitmap_ColRowMode(Bitmap src, int modWidth, int modHeight) { byte[] result = new byte[((modHeight+7)/8) * modWidth]; int colOffset=0, rowOffset=0; //这里做了一点取模的偏移 if (src.Height > modHeight) { for (rowOffset = 0; rowOffset < src.Height; rowOffset++) { if ((src.Height - rowOffset) <= modHeight) { break; } if (CheckBitmapRow(src, rowOffset)) { break; } } } if (src.Width > modWidth) { for (colOffset = 0; colOffset < src.Width; colOffset++) { if ((src.Width - colOffset) <= modWidth) { break; } if (CheckBitmapCol(src, colOffset)) { break; } } } //取模 for (int page = 0; page < (((modHeight+7)/8)); page ++) { for (int col = 0; col < modWidth; col++) { byte temp = 0; for (int row = 0; row < 8; row ++) { temp = (byte)(temp >> 1); if ((col + colOffset < src.Width) && (row + rowOffset + page * 8 < src.Height)) { if (src.GetPixel(col + colOffset, row + rowOffset + page * 8).ToArgb() != Color.Black.ToArgb()) { temp |= 0x80; } } } result[col + page*modWidth] = temp; } } return result; }

有了上面这几个程序就能输出点阵字库到文件了,这里是导出C语言格式

//导出点阵字库 //fileName-文件名, font-所用字体, modWidth-字模宽度, modeHeight-字模高度 public static void ExportCodeTab(string fileName, Font font, int modWidth, int modHeight) { FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate); //遍历GB2312的87个区 for (int i = 0; i < 87; i++) { //这里的预处理指令和字库烧入方案有关 string strAreaStart = "#ifdef GB2312_AREA_" + (i + 1); byte[] tempAreaStart = System.Text.Encoding.Default.GetBytes(strAreaStart); fs.Write(tempAreaStart, 0, tempAreaStart.Length); //遍历每个区的94个字符 for (int j = 0; j < 94; j++) { //根据区码位码生成字符 string hz = GetGB2312CH((byte)(i + 0xA1), (byte)(j + 0xA0)); //获取字符Bitmap Bitmap bmp = GetStrImage(hz, font); //取模 byte[] temp = GetCodeTabFromBitmap_ColRowMode(bmp, modWidth, modHeight); string str = "//第" + (i + 1) + "区 " + "第" + (j + 1) + "位" + " " + hz + "\r\n" + BytesToStringC(temp); //转换取模数据 byte[] temp2 = System.Text.Encoding.Default.GetBytes(str); fs.Write(temp2, 0, temp2.Length); } string strAreaEnd = "#endif //GB2312_AREA_" + (i + 1) + "\r\n"; byte[] tempAreaEnd = System.Text.Encoding.Default.GetBytes(strAreaEnd); fs.Write(tempAreaEnd, 0, tempAreaEnd.Length); } for (int i = 0; i < 87; i++) { string strAreaDefine = "//#define GB2312_AREA_" + (i + 1) + "\r\n"; byte[] tempAreaDefine = System.Text.Encoding.Default.GetBytes(strAreaDefine); fs.Write(tempAreaDefine, 0, tempAreaDefine.Length); } fs.Close(); } //转换Byte数组为 C语言格式的十六进制字符串 public static string BytesToStringC(byte[] InBytes) { string StringOut = ""; int i = 0; int len = InBytes.Length; foreach (byte InByte in InBytes) { if (i % 16 == 0) { StringOut += " "; } StringOut = StringOut + "0x" + String.Format("{0:X2}", InByte); if (i < (len - 1)) { StringOut += ", "; } else { StringOut += ",\r\n"; } if (i % 16 == 15) { StringOut += "\r\n"; } i++; } return StringOut; }

用起来是这样

ExportCodeTab(@"D:\codetab.h", new Font("宋体", 10), 16, 16);

导出效果

转载请注明原文地址: https://www.6miu.com/read-69972.html

最新回复(0)