Skip to content

Commit

Permalink
add: 字体取模预览和导出数据
Browse files Browse the repository at this point in the history
  • Loading branch information
chenxuuu committed Nov 15, 2024
1 parent 12c209b commit e19c3e6
Show file tree
Hide file tree
Showing 7 changed files with 532 additions and 32 deletions.
Binary file added Assets/font.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions Image2Display/Image2Display/Assets/Languages/en-US.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@
<system:String x:Key="CopyToClipboardText">Copy to Clipboard</system:String>
<system:String x:Key="ExportFileText">Export File</system:String>
<system:String x:Key="TotalCharacters">Total Characters</system:String>
<system:String x:Key="LoadFontFileFail">Fail to load font file, format error.</system:String>

<system:String x:Key="Settings">Settings</system:String>
<system:String x:Key="General">General</system:String>
Expand Down
3 changes: 2 additions & 1 deletion Image2Display/Image2Display/Assets/Languages/zh-CN.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@
<system:String x:Key="LSB">最低有效位(LSB)</system:String>
<system:String x:Key="SuccessTitle">成功</system:String>
<system:String x:Key="SuccessMessage">数据已导出。</system:String>
<system:String x:Key="FailTitle">导出失败</system:String>
<system:String x:Key="FailTitle">失败</system:String>
<system:String x:Key="ExportPalette">导出调色板</system:String>
<system:String x:Key="ExportPaletteDescription">导出当前图片所使用的所有颜色</system:String>
<system:String x:Key="ExportData">导出数据</system:String>
Expand Down Expand Up @@ -196,6 +196,7 @@
<system:String x:Key="CopyToClipboardText">复制到剪贴板</system:String>
<system:String x:Key="ExportFileText">导出文件</system:String>
<system:String x:Key="TotalCharacters">总字符数量</system:String>
<system:String x:Key="LoadFontFileFail">字体文件加载失败,文件格式不正确。</system:String>

<!-- 设置页 -->
<system:String x:Key="Settings">设置</system:String>
Expand Down
4 changes: 4 additions & 0 deletions Image2Display/Image2Display/Helpers/DemoFontData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ namespace Image2Display.Helpers;

public class DemoFontData
{
public static byte[] Default
{
get => ZiSymbol;
}
public static readonly byte[] ZiSymbol = [
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x4B,0x48,0x06,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0xFF,0xA2,0x00,
Expand Down
224 changes: 223 additions & 1 deletion Image2Display/Image2Display/Helpers/FontConvert.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using Image2Display.Models;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
Expand All @@ -18,7 +21,7 @@ public class FontConvert
/// <param name="height">像素宽度</param>
/// <param name="image">图片缓冲区,没给的话会新建一个</param>
/// <returns>图片缓冲</returns>
public static ImageData GetImage(byte[] data, int width, int height,ImageData? image = null)
public static ImageData GetImage(byte[] data, int width, int height, ImageData? image = null)
{
//像素尺寸
var pixelSize = 8;
Expand Down Expand Up @@ -65,5 +68,224 @@ public static ImageData GetImage(byte[] data, int width, int height,ImageData? i
return image;
}

public static byte[] GetData(SKTypeface font, int size, char c, int width, int height, int offsetx, int offsety)
{
//创建画布
using var surface = SKSurface.Create(new SKImageInfo(width, height));
//创建画笔
using var paint = new SKPaint
{
Color = SKColors.White,
TextSize = size,
Typeface = font,
TextAlign = SKTextAlign.Center,
IsAntialias = true,
};
//画布上画字
surface.Canvas.DrawText(c.ToString(), width/2 + offsetx, height - offsety, paint);
//获取像素数据
IntPtr data = surface.PeekPixels().GetPixels();
var result = new byte[width * height];

// 获取像素数据
using var pixmap = surface.PeekPixels();
if (pixmap != null)
{
// 遍历像素数据
for (int y = 0; y < pixmap.Height; y++)
{
for (int x = 0; x < pixmap.Width; x++)
{
IntPtr pixel = pixmap.GetPixels(x, y);
var buff = new byte[pixmap.BytesPerPixel];
System.Runtime.InteropServices.Marshal.Copy(pixel, buff, 0, buff.Length);
result[x + y * width] = buff[0];
}
}
}

return result;
}

/// <summary>
/// 数据二值化处理(仅用于预览)
/// </summary>
public static void ThresholdImage(byte[] data, byte threshold)
{
for (int i = 0; i < data.Length; i++)
{
data[i] = data[i] > threshold ? (byte)255 : (byte)0;
}
}

/// <summary>
/// 图片转换为特定灰度的图片(仅用于预览)
/// </summary>
public static void GrayScaleImage(byte[] data, int bit)
{
for (int i = 0; i < data.Length; i++)
{
//这个灰度位数,有多少种颜色
var number = 1 << bit;
//每个颜色的间隔
var interval = 255 / (number - 1);
//把每个格子的灰度对齐到最近的颜色
data[i] = (byte)((data[i] / interval) * interval);
}
}

/// <summary>
/// 反转图像颜色(仅用于预览)
/// </summary>
public static void InvertImage(byte[] data)
{
for (int i = 0; i < data.Length; i++)
{
data[i] = (byte)(255 - data[i]);
}
}

private static void IteratePixel(byte[] data, int rotate, int width, int height, Action<byte> action)
{
//主要开始1 主要结束1 次要开始2 次要结束2 是否先x后y
var (m1, m2, p1, p2, xFirst) = rotate switch
{
0 => (0, width - 1, 0, height - 1, true),
1 => (width - 1, 0, 0, height - 1, true),
2 => (0, width - 1, height - 1, 0, true),
3 => (width - 1, 0, height - 1, 0, true),
4 => (0, height - 1, 0, width - 1, false),
5 => (height - 1, 0, 0, width - 1, false),
6 => (0, height - 1, width - 1, 0, false),
7 => (height - 1, 0, width - 1, 0, false),
_ => throw new NotImplementedException(),
};

var mStep = m1 < m2 ? 1 : -1;
var pStep = p1 < p2 ? 1 : -1;
if (xFirst)
{
for (var y = p1; y != p2 + pStep; y += pStep)
{
for (var x = m1; x != m2 + mStep; x += mStep)
{
action(data[x + y * width]);
}
}
}
else
{
for (var x = p1; x != p2 + pStep; x += pStep)
{
for (var y = m1; y != m2 + mStep; y += mStep)
{
action(data[x + y * width]);
}
}
}
}

/// <summary>
/// 获取处理后的数据
/// </summary>
/// <returns></returns>
public static List<byte> GetResultData(
byte[] raw, int width, int height,
bool isGray, int bit, byte threshold,
bool isInvert, int byteOrder, bool bitOrderMSB)
{
//先取反
if(isInvert)
InvertImage(raw);

var bitLength = 1;
if (isGray)
bitLength = bit;

var result = new List<byte>();
int bitIndex = 0;
byte lastByte = 0;
//按像素顺序遍历
IteratePixel(raw, byteOrder, width, height, (b) =>
{
if(isGray)
{
//灰度处理
b = (byte)(b >> (8 - bitLength));
}
else
{
//二值化处理
b = b > threshold ? (byte)1 : (byte)0;
}
//反向数据
if (!bitOrderMSB)
{
var temp = (byte)0;
for (int i = 0; i < bitLength; i++)
{
temp <<= 1;
temp |= (byte)(b & 1);
b >>= 1;
}
b = temp;
}
//添加到结果
lastByte <<= bitLength;
lastByte |= b;
bitIndex += bitLength;
if (bitIndex >= 8)
{
result.Add(lastByte);
lastByte = 0;
bitIndex = 0;
}
});
//最后一个字节
if (bitIndex > 0)
{
lastByte <<= 8 - bitIndex;
result.Add(lastByte);
}
return result;
}


/// <summary>
/// 将字体数据转换为C数组
/// </summary>
/// <param name="data">数据,每个字一个数组</param>
/// <param name="width">字库宽度</param>
/// <param name="height">字库高度</param>
/// <param name="charset">实际用的字符集</param>
/// <returns></returns>
public static string ByteListToCArray(List<List<byte>> data, int width, int height, IList<char> charset)
{
var sb = new StringBuilder();
if (Utils.Settings.Language.Contains("ZH", StringComparison.CurrentCultureIgnoreCase))
sb.Append("/*@注意:此文件由Image2Display生成 */\n");
else
sb.Append("/*@Notice: This file is generated by Image2Display */\n");
if (data.Count == 0 || data[0].Count == 0 || charset.Count == 0)
sb.Append("/* no data */\n");
else
{
sb.Append($"/*@Size: {width}x{height}, " +
$"Char: {charset.Count}," +
$"Data per char: {data[0].Count} */\n");
}
sb.Append("const uint8_t fonts[] = {\n");
//每行一个字
for (int i = 0; i < charset.Count; i++)
{
sb.Append($"/* {charset[i]} */\n");
foreach (var b in data[i])
{
sb.Append($"0x{b:X2},");
}
sb.Append("\n\n");
}
sb.Append("};\n");
return sb.ToString();
}
}
Loading

0 comments on commit e19c3e6

Please sign in to comment.