From 6f2475936100056b9fb5a03249d50f5ea319e857 Mon Sep 17 00:00:00 2001 From: daiyongfei <974332738@qq.com> Date: Tue, 15 Jul 2025 15:58:12 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=8F=91=E9=80=81=E6=8C=87=E4=BB=A4?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../utils/c/ChineseDotMatrixExtractor.java | 111 +++++++ .../utils/c/ChineseDotMatrixToC.java | 193 ++++++++++++ .../equipment/utils/c/DotMatrixGenerator.java | 277 ++++++++++++++++++ .../utils/c/ImprovedTextToBitmap.java | 163 +++++++++++ .../utils/c/TextToBitmapConverter.java | 128 ++++++++ 5 files changed, 872 insertions(+) create mode 100644 fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixExtractor.java create mode 100644 fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixToC.java create mode 100644 fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/DotMatrixGenerator.java create mode 100644 fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ImprovedTextToBitmap.java create mode 100644 fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/TextToBitmapConverter.java diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixExtractor.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixExtractor.java new file mode 100644 index 0000000..b0cd04f --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixExtractor.java @@ -0,0 +1,111 @@ +package com.fuyuanshen.equipment.utils.c; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.List; + +/** + * @author: 默苍璃 + * @date: 2025-07-1508:52 + */ + +public class ChineseDotMatrixExtractor { + + public static void main(String[] args) { + String chineseChar = "汉"; // 要提取的汉字 + int size = 12; // 点阵尺寸 + + // 生成点阵数据 + int[][] dotMatrix = generateDotMatrix(chineseChar, size); + + // 打印点阵 + printDotMatrix(dotMatrix); + + // 获取二进制数据(可选) + List binaryData = convertToBinary(dotMatrix); + System.out.println("\nBinary data: " + binaryData); + } + + /** + * 生成汉字点阵 + * @param character 单个汉字字符 + * @param size 点阵尺寸 + * @return 二维点阵数组(1表示点亮,0表示熄灭) + */ + public static int[][] generateDotMatrix(String character, int size) { + // 创建12x12灰度图像 + BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_BYTE_GRAY); + Graphics2D g = image.createGraphics(); + + try { + // 设置白色背景 + g.setColor(Color.RED); + g.fillRect(0, 0, size, size); + + // 设置黑色字体(使用支持中文的字体) + g.setColor(java.awt.Color.BLACK); + g.setFont(new Font("宋体", Font.PLAIN, size)); + + // 居中绘制文字(调整y坐标使字符垂直居中) + g.drawString(character, 0, size - 2); + } finally { + g.dispose(); + } + + // 分析像素生成点阵 + int[][] dotMatrix = new int[size][size]; + for (int y = 0; y < size; y++) { + for (int x = 0; x < size; x++) { + // 获取像素灰度值(0-255) + int rgb = image.getRGB(x, y) & 0xFF; + // 灰度小于128视为有效像素(黑色区域) + dotMatrix[y][x] = (rgb < 128) ? 1 : 0; + } + } + return dotMatrix; + } + + /** + * 打印点阵到控制台 + * @param dotMatrix 点阵数据 + */ + public static void printDotMatrix(int[][] dotMatrix) { + for (int[] row : dotMatrix) { + for (int pixel : row) { + System.out.print(pixel == 1 ? "■ " : "□ "); + } + System.out.println(); + } + } + + /** + * 将点阵转换为二进制数据(每行两个字节) + * @param dotMatrix 点阵数据 + * @return 二进制数据列表(每个元素代表一行) + */ + public static List convertToBinary(int[][] dotMatrix) { + List binaryData = new ArrayList<>(); + for (int[] row : dotMatrix) { + byte highByte = 0; + byte lowByte = 0; + + // 处理每行前8位 + for (int i = 0; i < 8; i++) { + if (i < row.length && row[i] == 1) { + highByte |= (1 << (7 - i)); + } + } + + // 处理每行后4位(12x12点阵的特殊处理) + for (int i = 8; i < 12; i++) { + if (i < row.length && row[i] == 1) { + lowByte |= (1 << (15 - i)); // 放在第二个字节的高4位 + } + } + binaryData.add(highByte); + binaryData.add(lowByte); + } + return binaryData; + } +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixToC.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixToC.java new file mode 100644 index 0000000..d1e5508 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixToC.java @@ -0,0 +1,193 @@ +package com.fuyuanshen.equipment.utils.c; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * @author: 默苍璃 + * @date: 2025-07-1509:06 + */ +public class ChineseDotMatrixToC { + + public static void main(String[] args) { + // 要转换的汉字列表 + String[] characters = {"汉", "字", "点", "阵", "显", "示", "屏", "登", "记", "信", "息"}; + + // 输出C文件名 + String outputFileName = "chinese_font_12x12.c"; + + // 生成C文件 + generateCFontFile(characters, 12, outputFileName); + + System.out.println("C文件已生成: " + outputFileName); + } + + /** + * 生成C字体文件 + * @param characters 汉字数组 + * @param size 点阵尺寸 + * @param fileName 输出文件名 + */ + public static void generateCFontFile(String[] characters, int size, String fileName) { + try (FileWriter writer = new FileWriter(fileName)) { + // 写入文件头部 + writer.write("/*\n"); + writer.write(" * 12×12 汉字点阵数据(高位在前)\n"); + writer.write(" * 格式:每行16位(2字节),实际使用前12位\n"); + writer.write(" * 存储:每个汉字24字节(12行×2字节)\n"); + writer.write(" * 生成时间: " + new java.util.Date() + "\n"); + writer.write(" */\n\n"); + + writer.write("#include \n\n"); + + // 主数组声明 + writer.write("const uint8_t FONT_12X12[] = {\n"); + + // 存储所有汉字的数据 + for (int i = 0; i < characters.length; i++) { + String character = characters[i]; + int unicode = (int)character.charAt(0); + + // 生成点阵数据 + int[][] dotMatrix = generateDotMatrix(character, size); + + // 转换为十六进制数组 + List hexData = convertToHex(dotMatrix); + + // 写入注释(汉字和Unicode) + writer.write(String.format(" /* '%s' (U+%04X) */\n", character, unicode)); + + // 写入数据(每8个字节一行) + for (int j = 0; j < hexData.size(); j += 8) { + writer.write(" "); + for (int k = j; k < Math.min(j + 8, hexData.size()); k++) { + writer.write(hexData.get(k)); + if (k < hexData.size() - 1) { + writer.write(", "); + } + } + writer.write("\n"); + } + + // 最后一个汉字后不加逗号 + if (i < characters.length - 1) { + writer.write(",\n"); + } + } + + writer.write("};\n\n"); + + // 添加获取点阵的函数 + writer.write("// 获取汉字点阵数据\n"); + writer.write("const uint8_t* get_font_data(uint16_t unicode) {\n"); + writer.write(" switch(unicode) {\n"); + + int offset = 0; + for (String character : characters) { + int unicode = (int)character.charAt(0); + writer.write(String.format(" case 0x%04X: // '%s'\n", unicode, character)); + writer.write(String.format(" return &FONT_12X12[%d];\n", offset)); + offset += 24; // 每个汉字24字节 + } + + writer.write(" default:\n"); + writer.write(" return NULL;\n"); + writer.write(" }\n"); + writer.write("}\n"); + + System.out.println("成功生成 " + characters.length + " 个汉字的点阵数据"); + } catch (IOException e) { + System.err.println("文件写入错误: " + e.getMessage()); + } + } + + /** + * 生成汉字点阵 + * @param character 单个汉字字符 + * @param size 点阵尺寸 + * @return 二维点阵数组(1表示点亮,0表示熄灭) + */ + private static int[][] generateDotMatrix(String character, int size) { + // 创建12x12灰度图像 + BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_BYTE_GRAY); + Graphics2D g = image.createGraphics(); + + try { + // 设置白色背景 + g.setColor(Color.WHITE); + g.fillRect(0, 0, size, size); + + // 设置黑色字体(使用支持中文的字体) + g.setColor(Color.BLACK); + + // 尝试加载系统字体(优先使用宋体) + Font font; + try { + font = new Font("宋体", Font.PLAIN, size); + } catch (Exception e) { + font = new Font(Font.SANS_SERIF, Font.PLAIN, size); + } + g.setFont(font); + + // 调整绘制位置(居中显示) + FontMetrics metrics = g.getFontMetrics(); + int x = (size - metrics.charWidth(character.charAt(0))) / 2; + int y = ((size - metrics.getHeight()) / 2) + metrics.getAscent(); + + // 绘制文字 + g.drawString(character, x, y); + } finally { + g.dispose(); + } + + // 分析像素生成点阵 + int[][] dotMatrix = new int[size][size]; + for (int y = 0; y < size; y++) { + for (int x = 0; x < size; x++) { + // 获取像素灰度值(0-255) + int rgb = image.getRGB(x, y) & 0xFF; + // 灰度小于128视为有效像素(黑色区域) + dotMatrix[y][x] = (rgb < 180) ? 1 : 0; // 使用稍高阈值确保清晰度 + } + } + return dotMatrix; + } + + /** + * 将点阵转换为十六进制字符串(高位在前) + * @param dotMatrix 点阵数据 + * @return 十六进制字符串列表(每个元素是一个字节的十六进制表示) + */ + private static List convertToHex(int[][] dotMatrix) { + List hexData = new ArrayList<>(); + + for (int[] row : dotMatrix) { + int highByte = 0; + int lowByte = 0; + + // 处理前8位(高位在前) + for (int i = 0; i < 8; i++) { + if (i < row.length && row[i] == 1) { + highByte |= (1 << (7 - i)); + } + } + + // 处理后4位(放在第二个字节的高4位) + for (int i = 8; i < 12; i++) { + if (i < row.length && row[i] == 1) { + lowByte |= (1 << (15 - i)); + } + } + + // 添加到结果列表 + hexData.add(String.format("0X%02X", highByte)); + hexData.add(String.format("0X%02X", lowByte)); + } + + return hexData; + } +} \ No newline at end of file diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/DotMatrixGenerator.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/DotMatrixGenerator.java new file mode 100644 index 0000000..7ba70bd --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/DotMatrixGenerator.java @@ -0,0 +1,277 @@ +package com.fuyuanshen.equipment.utils.c; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class DotMatrixGenerator { + + public static void main(String[] args) { + // 要转换的字符列表(汉字+字母+数字) + String[] characters = { + "登", "记", "信", "息", + "A", "B", "C", + "0", "1", "2" + }; + + // 输出C文件名 + String outputFileName = "display_fonts.c"; + + // 生成C文件 + generateCFontFile(characters, outputFileName); + + System.out.println("C字体文件已生成: " + outputFileName); + } + + /** + * 生成C字体文件 + * @param characters 字符数组 + * @param fileName 输出文件名 + */ + public static void generateCFontFile(String[] characters, String fileName) { + try (FileWriter writer = new FileWriter(fileName)) { + // 写入文件头部 + writer.write("/*\n"); + writer.write(" * 显示屏点阵数据\n"); + writer.write(" * 生成时间: " + new java.util.Date() + "\n"); + writer.write(" * 格式说明:\n"); + writer.write(" * - 汉字: 12×12点阵 (24字节/字符)\n"); + writer.write(" * - 字母数字: 8×12点阵 (12字节/字符)\n"); + writer.write(" * 所有数据均采用高位在前(MSB first)格式\n"); + writer.write(" */\n\n"); + + writer.write("#include \n\n"); + + // 存储所有汉字的数据 + List hanziMatrices = new ArrayList<>(); + List hanziCharacters = new ArrayList<>(); + + // 存储所有ASCII字符的数据 + List asciiMatrices = new ArrayList<>(); + List asciiCharacters = new ArrayList<>(); + + // 分离汉字和ASCII字符 + for (String character : characters) { + char c = character.charAt(0); + if (isHanzi(c)) { + hanziMatrices.add(generateDotMatrix(character, 12)); + hanziCharacters.add(character); + } else if (isAscii(c)) { + asciiMatrices.add(generateDotMatrix(character, 8)); + asciiCharacters.add(character); + } + } + + // 汉字点阵数组 + if (!hanziMatrices.isEmpty()) { + writer.write("/* 12×12 汉字点阵数据 */\n"); + writer.write("const uint8_t HANZI_FONT_12X12[] = {\n"); + + for (int i = 0; i < hanziMatrices.size(); i++) { + String character = hanziCharacters.get(i); + int[][] dotMatrix = hanziMatrices.get(i); + List hexData = convertToHex(dotMatrix, 12); + + // 写入注释(汉字和Unicode) + writer.write(String.format(" /* '%s' (U+%04X) */\n", + character, (int)character.charAt(0))); + + // 写入数据(每8个字节一行) + for (int j = 0; j < hexData.size(); j += 8) { + writer.write(" "); + for (int k = j; k < Math.min(j + 8, hexData.size()); k++) { + writer.write(hexData.get(k)); + if (k < hexData.size() - 1) { + writer.write(", "); + } + } + writer.write("\n"); + } + + // 最后一个汉字后不加逗号 + if (i < hanziMatrices.size() - 1) { + writer.write(",\n"); + } + } + writer.write("};\n\n"); + } + + // ASCII点阵数组 + if (!asciiMatrices.isEmpty()) { + writer.write("/* 8×12 字母数字点阵数据 */\n"); + writer.write("const uint8_t ASCII_FONT_8X12[] = {\n"); + + for (int i = 0; i < asciiMatrices.size(); i++) { + String character = asciiCharacters.get(i); + int[][] dotMatrix = asciiMatrices.get(i); + List hexData = convertToHex(dotMatrix, 8); + + // 写入注释(字符和ASCII码) + writer.write(String.format(" /* '%c' (0x%02X) */ ", + character.charAt(0), (int)character.charAt(0))); + + // 写入数据(每行12字节) + for (int j = 0; j < hexData.size(); j++) { + writer.write(hexData.get(j)); + if (j < hexData.size() - 1) { + writer.write(", "); + } + } + writer.write("\n"); + } + writer.write("};\n\n"); + } + + // 添加获取点阵的函数 + writer.write("/* 获取点阵数据函数 */\n"); + writer.write("const uint8_t* get_font_data(uint16_t code) {\n"); + + // 汉字处理 + if (!hanziCharacters.isEmpty()) { + writer.write(" // 汉字处理\n"); + writer.write(" switch(code) {\n"); + + int offset = 0; + for (int i = 0; i < hanziCharacters.size(); i++) { + String character = hanziCharacters.get(i); + writer.write(String.format(" case 0x%04X: // '%s'\n", + (int)character.charAt(0), character)); + writer.write(String.format(" return &HANZI_FONT_12X12[%d];\n", offset)); + offset += 24; // 每个汉字24字节 + } + + writer.write(" }\n"); + } + + // ASCII字符处理 + if (!asciiCharacters.isEmpty()) { + writer.write(" // ASCII字符处理\n"); + writer.write(" switch(code) {\n"); + + int offset = 0; + for (int i = 0; i < asciiCharacters.size(); i++) { + String character = asciiCharacters.get(i); + writer.write(String.format(" case 0x%02X: // '%c'\n", + (int)character.charAt(0), character.charAt(0))); + writer.write(String.format(" return &ASCII_FONT_8X12[%d];\n", offset)); + offset += 12; // 每个ASCII字符12字节 + } + + writer.write(" }\n"); + } + + writer.write(" return NULL; // 未找到对应字符\n"); + writer.write("}\n"); + + System.out.println("成功生成字符点阵数据"); + System.out.println(" - 汉字: " + hanziCharacters.size() + " 个"); + System.out.println(" - 字母数字: " + asciiCharacters.size() + " 个"); + + } catch (IOException e) { + System.err.println("文件写入错误: " + e.getMessage()); + } + } + + /** + * 判断是否是汉字 + */ + private static boolean isHanzi(char c) { + // 基本汉字Unicode范围: 4E00-9FFF + return c >= 0x4E00 && c <= 0x9FFF; + } + + /** + * 判断是否是ASCII字符 + */ + private static boolean isAscii(char c) { + return c < 128; + } + + /** + * 生成点阵 + * @param character 字符 + * @param size 点阵尺寸 + * @return 二维点阵数组 + */ + private static int[][] generateDotMatrix(String character, int size) { + // 创建图像 + BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_BYTE_GRAY); + Graphics2D g = image.createGraphics(); + + try { + // 设置白色背景 + g.setColor(Color.WHITE); + g.fillRect(0, 0, size, size); + + // 设置黑色字体 + g.setColor(Color.BLACK); + + // 选择合适的字体 + Font font; + if (isHanzi(character.charAt(0))) { + font = new Font("宋体", Font.PLAIN, size); + } else { + font = new Font("Courier New", Font.PLAIN, size); + } + g.setFont(font); + + // 调整绘制位置(居中显示) + FontMetrics metrics = g.getFontMetrics(); + int x = (size - metrics.charWidth(character.charAt(0))) / 2; + int y = ((size - metrics.getHeight()) / 2) + metrics.getAscent(); + + // 绘制文字 + g.drawString(character, x, y); + } finally { + g.dispose(); + } + + // 分析像素生成点阵 + int[][] dotMatrix = new int[size][size]; + for (int y = 0; y < size; y++) { + for (int x = 0; x < size; x++) { + // 获取像素灰度值 + int rgb = image.getRGB(x, y) & 0xFF; + // 灰度小于180视为有效像素 + dotMatrix[y][x] = (rgb < 180) ? 1 : 0; + } + } + return dotMatrix; + } + + /** + * 将点阵转换为十六进制字符串 + * @param dotMatrix 点阵数据 + * @param size 点阵尺寸 + * @return 十六进制字符串列表 + */ + private static List convertToHex(int[][] dotMatrix, int size) { + List hexData = new ArrayList<>(); + + for (int[] row : dotMatrix) { + int value = 0; + + // 高位在前处理 + for (int i = 0; i < size; i++) { + if (i < row.length && row[i] == 1) { + value |= (1 << (size - 1 - i)); + } + } + + // 根据尺寸拆分字节 + if (size == 12) { + // 12×12点阵:每行拆分为2字节 + hexData.add(String.format("0X%02X", (value >> 8) & 0xFF)); + hexData.add(String.format("0X%02X", value & 0xFF)); + } else { + // 8×12点阵:每行1字节 + hexData.add(String.format("0X%02X", value & 0xFF)); + } + } + + return hexData; + } +} \ No newline at end of file diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ImprovedTextToBitmap.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ImprovedTextToBitmap.java new file mode 100644 index 0000000..08ec8e9 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ImprovedTextToBitmap.java @@ -0,0 +1,163 @@ +package com.fuyuanshen.equipment.utils.c; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * 发送指令显示工具 + * + * @author: 默苍璃 + * @date: 2025-07-1515:35 + */ +public class ImprovedTextToBitmap { + + public static void main(String[] args) throws IOException { + String unit = "中国电子集团"; + String department = "人工智能研发中心"; + String name = "张三"; + + byte[] unitBytes = textToBitmapBytes(unit); + byte[] deptBytes = textToBitmapBytes(department); + byte[] nameBytes = textToBitmapBytes(name); + + generateCFile(unitBytes, deptBytes, nameBytes, "display_data.c"); + } + + public static byte[] textToBitmapBytes(String text) { + if (text == null || text.isEmpty()) { + return new byte[0]; + } + + // 使用更清晰的黑体字体 + Font font = new Font("黑体", Font.PLAIN, 12); + + // 创建临时图像获取字体度量 + BufferedImage tempImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); + Graphics2D tempG = tempImage.createGraphics(); + tempG.setFont(font); + FontMetrics metrics = tempG.getFontMetrics(); + + // 添加字符间距(防止汉字粘连) + int charSpacing = 1; + int totalWidth = 0; + for (char c : text.toCharArray()) { + totalWidth += metrics.charWidth(c) + charSpacing; + } + + // 宽度对齐到8的倍数 + int width = (int) Math.ceil(totalWidth / 8.0) * 8; + int height = 12; + + // 创建图像 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = image.createGraphics(); + g.setFont(font); + + // 设置渲染参数 - 关闭抗锯齿(提高小字清晰度) + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_OFF); + + // 透明背景 + g.setComposite(AlphaComposite.Clear); + g.fillRect(0, 0, width, height); + g.setComposite(AlphaComposite.Src); + g.setColor(Color.BLACK); + + // 绘制文本(优化垂直对齐) + int y = (height - metrics.getHeight()) / 2 + metrics.getAscent() - 1; + int x = 0; + for (char c : text.toCharArray()) { + g.drawString(String.valueOf(c), x, y); + x += metrics.charWidth(c) + charSpacing; + } + g.dispose(); + tempG.dispose(); + + // 扫描像素并打包数据 + List byteList = new ArrayList<>(); + int currentByte = 0; + int bitCount = 0; + + for (int yPos = 0; yPos < height; yPos++) { + for (int xPos = 0; xPos < width; xPos++) { + int pixel = image.getRGB(xPos, yPos); + int alpha = (pixel >> 24) & 0xFF; + + // 使用阈值处理(提高清晰度) + boolean isOpaque = alpha > 64; // 阈值可调整 + + currentByte = (currentByte << 1) | (isOpaque ? 1 : 0); + bitCount++; + + if (bitCount == 8) { + byteList.add((byte) currentByte); + currentByte = 0; + bitCount = 0; + } + } + } + + // 处理最后不满8位的部分 + if (bitCount > 0) { + currentByte <<= (8 - bitCount); // 左移到高位 + byteList.add((byte) currentByte); + } + + // 转换结果 + byte[] result = new byte[byteList.size()]; + for (int i = 0; i < byteList.size(); i++) { + result[i] = byteList.get(i); + } + return result; + } + + public static void generateCFile(byte[] unit, byte[] department, byte[] name, String filename) throws IOException { + try (FileWriter writer = new FileWriter(filename)) { + writer.write("/**\n"); + writer.write(" * 点阵显示数据 - 自动生成\n"); + writer.write(" * 宽度计算公式: width = (数组长度 * 8) / 12\n"); + writer.write(" */\n\n"); + writer.write("#include \n\n"); + + // 单位数据 + writer.write(String.format("// 单位: %d 字节, 宽度: %d 像素\n", + unit.length, (unit.length * 8) / 12)); + writer.write("const uint8_t unit[] = {\n "); + writeByteArray(writer, unit); + writer.write("\n};\n\n"); + + // 部门数据 + writer.write(String.format("// 部门: %d 字节, 宽度: %d 像素\n", + department.length, (department.length * 8) / 12)); + writer.write("const uint8_t department[] = {\n "); + writeByteArray(writer, department); + writer.write("\n};\n\n"); + + // 姓名数据 + writer.write(String.format("// 姓名: %d 字节, 宽度: %d 像素\n", + name.length, (name.length * 8) / 12)); + writer.write("const uint8_t name[] = {\n "); + writeByteArray(writer, name); + writer.write("\n};\n"); + } + } + + private static void writeByteArray(FileWriter writer, byte[] data) throws IOException { + for (int i = 0; i < data.length; i++) { + int value = data[i] & 0xFF; + writer.write(String.format("0x%02X", value)); + + if (i < data.length - 1) { + writer.write(", "); + if ((i + 1) % 12 == 0) writer.write("\n "); + } + } + } +} \ No newline at end of file diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/TextToBitmapConverter.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/TextToBitmapConverter.java new file mode 100644 index 0000000..f5dfba9 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/TextToBitmapConverter.java @@ -0,0 +1,128 @@ +package com.fuyuanshen.equipment.utils.c; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * @author: 默苍璃 + * @date: 2025-07-1515:14 + */ +public class TextToBitmapConverter { + // 主函数:输入文字并生成C文件 + public static void main(String[] args) throws IOException { + String unit = "单位名称"; + String department = "部门名称"; + String name = "姓名"; + + byte[] unitBytes = textToBitmapBytes(unit); + byte[] deptBytes = textToBitmapBytes(department); + byte[] nameBytes = textToBitmapBytes(name); + + generateCFile(unitBytes, deptBytes, nameBytes, "output.c"); + } + + // 将文本转换为点阵字节数组 + public static byte[] textToBitmapBytes(String text) { + // 1. 创建虚拟画布 + Font font = new Font("SansSerif", Font.PLAIN, 12); + FontMetrics metrics = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB) + .getGraphics().getFontMetrics(font); + + // 计算文本宽度并调整为8的倍数 + int textWidth = metrics.stringWidth(text); + int width = (int) Math.ceil(textWidth / 8.0) * 8; + int height = 12; + + // 创建带透明通道的图像 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = image.createGraphics(); + g.setFont(font); + + // 设置渲染参数 + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g.setComposite(AlphaComposite.Clear); + g.fillRect(0, 0, width, height); + g.setComposite(AlphaComposite.Src); + g.setColor(Color.BLACK); + + // 绘制文本(垂直居中) + int y = (height - metrics.getHeight()) / 2 + metrics.getAscent(); + g.drawString(text, 0, y); + g.dispose(); + + // 2. 扫描像素并打包数据 + List byteList = new ArrayList<>(); + int currentByte = 0; + int bitCount = 0; + + for (int yPos = 0; yPos < height; yPos++) { + for (int xPos = 0; xPos < width; xPos++) { + // 检查像素透明度 + int pixel = image.getRGB(xPos, yPos); + boolean isOpaque = ((pixel >> 24) & 0xFF) > 0; + + // 打包位数据(高位在前) + currentByte = (currentByte << 1) | (isOpaque ? 1 : 0); + bitCount++; + + // 每8位打包为一个字节 + if (bitCount == 8) { + byteList.add((byte) currentByte); + currentByte = 0; + bitCount = 0; + } + } + } + + // 转换结果 + byte[] result = new byte[byteList.size()]; + for (int i = 0; i < byteList.size(); i++) { + result[i] = byteList.get(i); + } + return result; + } + + // 生成C文件 + public static void generateCFile(byte[] unit, byte[] department, byte[] name, String filename) throws IOException { + try (FileWriter writer = new FileWriter(filename)) { + // 写入文件头 + writer.write("#include \n\n"); + + // 写入单位数据 + writer.write("const uint8_t unit[] = {\n "); + writeByteArray(writer, unit); + writer.write("\n};\n\n"); + + // 写入部门数据 + writer.write("const uint8_t department[] = {\n "); + writeByteArray(writer, department); + writer.write("\n};\n\n"); + + // 写入姓名数据 + writer.write("const uint8_t name[] = {\n "); + writeByteArray(writer, name); + writer.write("\n};\n"); + } + } + + // 辅助方法:格式化字节数组输出 + private static void writeByteArray(FileWriter writer, byte[] data) throws IOException { + for (int i = 0; i < data.length; i++) { + // 将字节转换为无符号整数 + int value = data[i] & 0xFF; + writer.write(String.format("0x%02X", value)); + + // 添加逗号(最后一个元素除外) + if (i < data.length - 1) { + writer.write(", "); + // 每16个元素换行 + if ((i + 1) % 16 == 0) writer.write("\n "); + } + } + } +} From 04df7e3ec7aaadf2a430ed8022bb92871274898b Mon Sep 17 00:00:00 2001 From: daiyongfei <974332738@qq.com> Date: Wed, 16 Jul 2025 08:46:21 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=8F=AF=E9=9D=A0=E7=82=B9=E9=98=B5?= =?UTF-8?q?=E7=94=9F=E6=88=90=E5=B7=A5=E5=85=B7=20-=20=E7=BB=88=E6=9E=81?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../utils/c/ChineseDotMatrixExtractor.java | 111 ------- .../utils/c/ChineseDotMatrixToC.java | 193 ------------ .../equipment/utils/c/DotMatrixGenerator.java | 277 ------------------ ...oBitmap.java => ReliableTextToBitmap.java} | 162 +++++++--- .../utils/c/TextToBitmapConverter.java | 128 -------- 5 files changed, 119 insertions(+), 752 deletions(-) delete mode 100644 fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixExtractor.java delete mode 100644 fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixToC.java delete mode 100644 fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/DotMatrixGenerator.java rename fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/{ImprovedTextToBitmap.java => ReliableTextToBitmap.java} (50%) delete mode 100644 fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/TextToBitmapConverter.java diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixExtractor.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixExtractor.java deleted file mode 100644 index b0cd04f..0000000 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixExtractor.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.fuyuanshen.equipment.utils.c; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.List; - -/** - * @author: 默苍璃 - * @date: 2025-07-1508:52 - */ - -public class ChineseDotMatrixExtractor { - - public static void main(String[] args) { - String chineseChar = "汉"; // 要提取的汉字 - int size = 12; // 点阵尺寸 - - // 生成点阵数据 - int[][] dotMatrix = generateDotMatrix(chineseChar, size); - - // 打印点阵 - printDotMatrix(dotMatrix); - - // 获取二进制数据(可选) - List binaryData = convertToBinary(dotMatrix); - System.out.println("\nBinary data: " + binaryData); - } - - /** - * 生成汉字点阵 - * @param character 单个汉字字符 - * @param size 点阵尺寸 - * @return 二维点阵数组(1表示点亮,0表示熄灭) - */ - public static int[][] generateDotMatrix(String character, int size) { - // 创建12x12灰度图像 - BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_BYTE_GRAY); - Graphics2D g = image.createGraphics(); - - try { - // 设置白色背景 - g.setColor(Color.RED); - g.fillRect(0, 0, size, size); - - // 设置黑色字体(使用支持中文的字体) - g.setColor(java.awt.Color.BLACK); - g.setFont(new Font("宋体", Font.PLAIN, size)); - - // 居中绘制文字(调整y坐标使字符垂直居中) - g.drawString(character, 0, size - 2); - } finally { - g.dispose(); - } - - // 分析像素生成点阵 - int[][] dotMatrix = new int[size][size]; - for (int y = 0; y < size; y++) { - for (int x = 0; x < size; x++) { - // 获取像素灰度值(0-255) - int rgb = image.getRGB(x, y) & 0xFF; - // 灰度小于128视为有效像素(黑色区域) - dotMatrix[y][x] = (rgb < 128) ? 1 : 0; - } - } - return dotMatrix; - } - - /** - * 打印点阵到控制台 - * @param dotMatrix 点阵数据 - */ - public static void printDotMatrix(int[][] dotMatrix) { - for (int[] row : dotMatrix) { - for (int pixel : row) { - System.out.print(pixel == 1 ? "■ " : "□ "); - } - System.out.println(); - } - } - - /** - * 将点阵转换为二进制数据(每行两个字节) - * @param dotMatrix 点阵数据 - * @return 二进制数据列表(每个元素代表一行) - */ - public static List convertToBinary(int[][] dotMatrix) { - List binaryData = new ArrayList<>(); - for (int[] row : dotMatrix) { - byte highByte = 0; - byte lowByte = 0; - - // 处理每行前8位 - for (int i = 0; i < 8; i++) { - if (i < row.length && row[i] == 1) { - highByte |= (1 << (7 - i)); - } - } - - // 处理每行后4位(12x12点阵的特殊处理) - for (int i = 8; i < 12; i++) { - if (i < row.length && row[i] == 1) { - lowByte |= (1 << (15 - i)); // 放在第二个字节的高4位 - } - } - binaryData.add(highByte); - binaryData.add(lowByte); - } - return binaryData; - } -} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixToC.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixToC.java deleted file mode 100644 index d1e5508..0000000 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ChineseDotMatrixToC.java +++ /dev/null @@ -1,193 +0,0 @@ -package com.fuyuanshen.equipment.utils.c; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * @author: 默苍璃 - * @date: 2025-07-1509:06 - */ -public class ChineseDotMatrixToC { - - public static void main(String[] args) { - // 要转换的汉字列表 - String[] characters = {"汉", "字", "点", "阵", "显", "示", "屏", "登", "记", "信", "息"}; - - // 输出C文件名 - String outputFileName = "chinese_font_12x12.c"; - - // 生成C文件 - generateCFontFile(characters, 12, outputFileName); - - System.out.println("C文件已生成: " + outputFileName); - } - - /** - * 生成C字体文件 - * @param characters 汉字数组 - * @param size 点阵尺寸 - * @param fileName 输出文件名 - */ - public static void generateCFontFile(String[] characters, int size, String fileName) { - try (FileWriter writer = new FileWriter(fileName)) { - // 写入文件头部 - writer.write("/*\n"); - writer.write(" * 12×12 汉字点阵数据(高位在前)\n"); - writer.write(" * 格式:每行16位(2字节),实际使用前12位\n"); - writer.write(" * 存储:每个汉字24字节(12行×2字节)\n"); - writer.write(" * 生成时间: " + new java.util.Date() + "\n"); - writer.write(" */\n\n"); - - writer.write("#include \n\n"); - - // 主数组声明 - writer.write("const uint8_t FONT_12X12[] = {\n"); - - // 存储所有汉字的数据 - for (int i = 0; i < characters.length; i++) { - String character = characters[i]; - int unicode = (int)character.charAt(0); - - // 生成点阵数据 - int[][] dotMatrix = generateDotMatrix(character, size); - - // 转换为十六进制数组 - List hexData = convertToHex(dotMatrix); - - // 写入注释(汉字和Unicode) - writer.write(String.format(" /* '%s' (U+%04X) */\n", character, unicode)); - - // 写入数据(每8个字节一行) - for (int j = 0; j < hexData.size(); j += 8) { - writer.write(" "); - for (int k = j; k < Math.min(j + 8, hexData.size()); k++) { - writer.write(hexData.get(k)); - if (k < hexData.size() - 1) { - writer.write(", "); - } - } - writer.write("\n"); - } - - // 最后一个汉字后不加逗号 - if (i < characters.length - 1) { - writer.write(",\n"); - } - } - - writer.write("};\n\n"); - - // 添加获取点阵的函数 - writer.write("// 获取汉字点阵数据\n"); - writer.write("const uint8_t* get_font_data(uint16_t unicode) {\n"); - writer.write(" switch(unicode) {\n"); - - int offset = 0; - for (String character : characters) { - int unicode = (int)character.charAt(0); - writer.write(String.format(" case 0x%04X: // '%s'\n", unicode, character)); - writer.write(String.format(" return &FONT_12X12[%d];\n", offset)); - offset += 24; // 每个汉字24字节 - } - - writer.write(" default:\n"); - writer.write(" return NULL;\n"); - writer.write(" }\n"); - writer.write("}\n"); - - System.out.println("成功生成 " + characters.length + " 个汉字的点阵数据"); - } catch (IOException e) { - System.err.println("文件写入错误: " + e.getMessage()); - } - } - - /** - * 生成汉字点阵 - * @param character 单个汉字字符 - * @param size 点阵尺寸 - * @return 二维点阵数组(1表示点亮,0表示熄灭) - */ - private static int[][] generateDotMatrix(String character, int size) { - // 创建12x12灰度图像 - BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_BYTE_GRAY); - Graphics2D g = image.createGraphics(); - - try { - // 设置白色背景 - g.setColor(Color.WHITE); - g.fillRect(0, 0, size, size); - - // 设置黑色字体(使用支持中文的字体) - g.setColor(Color.BLACK); - - // 尝试加载系统字体(优先使用宋体) - Font font; - try { - font = new Font("宋体", Font.PLAIN, size); - } catch (Exception e) { - font = new Font(Font.SANS_SERIF, Font.PLAIN, size); - } - g.setFont(font); - - // 调整绘制位置(居中显示) - FontMetrics metrics = g.getFontMetrics(); - int x = (size - metrics.charWidth(character.charAt(0))) / 2; - int y = ((size - metrics.getHeight()) / 2) + metrics.getAscent(); - - // 绘制文字 - g.drawString(character, x, y); - } finally { - g.dispose(); - } - - // 分析像素生成点阵 - int[][] dotMatrix = new int[size][size]; - for (int y = 0; y < size; y++) { - for (int x = 0; x < size; x++) { - // 获取像素灰度值(0-255) - int rgb = image.getRGB(x, y) & 0xFF; - // 灰度小于128视为有效像素(黑色区域) - dotMatrix[y][x] = (rgb < 180) ? 1 : 0; // 使用稍高阈值确保清晰度 - } - } - return dotMatrix; - } - - /** - * 将点阵转换为十六进制字符串(高位在前) - * @param dotMatrix 点阵数据 - * @return 十六进制字符串列表(每个元素是一个字节的十六进制表示) - */ - private static List convertToHex(int[][] dotMatrix) { - List hexData = new ArrayList<>(); - - for (int[] row : dotMatrix) { - int highByte = 0; - int lowByte = 0; - - // 处理前8位(高位在前) - for (int i = 0; i < 8; i++) { - if (i < row.length && row[i] == 1) { - highByte |= (1 << (7 - i)); - } - } - - // 处理后4位(放在第二个字节的高4位) - for (int i = 8; i < 12; i++) { - if (i < row.length && row[i] == 1) { - lowByte |= (1 << (15 - i)); - } - } - - // 添加到结果列表 - hexData.add(String.format("0X%02X", highByte)); - hexData.add(String.format("0X%02X", lowByte)); - } - - return hexData; - } -} \ No newline at end of file diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/DotMatrixGenerator.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/DotMatrixGenerator.java deleted file mode 100644 index 7ba70bd..0000000 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/DotMatrixGenerator.java +++ /dev/null @@ -1,277 +0,0 @@ -package com.fuyuanshen.equipment.utils.c; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class DotMatrixGenerator { - - public static void main(String[] args) { - // 要转换的字符列表(汉字+字母+数字) - String[] characters = { - "登", "记", "信", "息", - "A", "B", "C", - "0", "1", "2" - }; - - // 输出C文件名 - String outputFileName = "display_fonts.c"; - - // 生成C文件 - generateCFontFile(characters, outputFileName); - - System.out.println("C字体文件已生成: " + outputFileName); - } - - /** - * 生成C字体文件 - * @param characters 字符数组 - * @param fileName 输出文件名 - */ - public static void generateCFontFile(String[] characters, String fileName) { - try (FileWriter writer = new FileWriter(fileName)) { - // 写入文件头部 - writer.write("/*\n"); - writer.write(" * 显示屏点阵数据\n"); - writer.write(" * 生成时间: " + new java.util.Date() + "\n"); - writer.write(" * 格式说明:\n"); - writer.write(" * - 汉字: 12×12点阵 (24字节/字符)\n"); - writer.write(" * - 字母数字: 8×12点阵 (12字节/字符)\n"); - writer.write(" * 所有数据均采用高位在前(MSB first)格式\n"); - writer.write(" */\n\n"); - - writer.write("#include \n\n"); - - // 存储所有汉字的数据 - List hanziMatrices = new ArrayList<>(); - List hanziCharacters = new ArrayList<>(); - - // 存储所有ASCII字符的数据 - List asciiMatrices = new ArrayList<>(); - List asciiCharacters = new ArrayList<>(); - - // 分离汉字和ASCII字符 - for (String character : characters) { - char c = character.charAt(0); - if (isHanzi(c)) { - hanziMatrices.add(generateDotMatrix(character, 12)); - hanziCharacters.add(character); - } else if (isAscii(c)) { - asciiMatrices.add(generateDotMatrix(character, 8)); - asciiCharacters.add(character); - } - } - - // 汉字点阵数组 - if (!hanziMatrices.isEmpty()) { - writer.write("/* 12×12 汉字点阵数据 */\n"); - writer.write("const uint8_t HANZI_FONT_12X12[] = {\n"); - - for (int i = 0; i < hanziMatrices.size(); i++) { - String character = hanziCharacters.get(i); - int[][] dotMatrix = hanziMatrices.get(i); - List hexData = convertToHex(dotMatrix, 12); - - // 写入注释(汉字和Unicode) - writer.write(String.format(" /* '%s' (U+%04X) */\n", - character, (int)character.charAt(0))); - - // 写入数据(每8个字节一行) - for (int j = 0; j < hexData.size(); j += 8) { - writer.write(" "); - for (int k = j; k < Math.min(j + 8, hexData.size()); k++) { - writer.write(hexData.get(k)); - if (k < hexData.size() - 1) { - writer.write(", "); - } - } - writer.write("\n"); - } - - // 最后一个汉字后不加逗号 - if (i < hanziMatrices.size() - 1) { - writer.write(",\n"); - } - } - writer.write("};\n\n"); - } - - // ASCII点阵数组 - if (!asciiMatrices.isEmpty()) { - writer.write("/* 8×12 字母数字点阵数据 */\n"); - writer.write("const uint8_t ASCII_FONT_8X12[] = {\n"); - - for (int i = 0; i < asciiMatrices.size(); i++) { - String character = asciiCharacters.get(i); - int[][] dotMatrix = asciiMatrices.get(i); - List hexData = convertToHex(dotMatrix, 8); - - // 写入注释(字符和ASCII码) - writer.write(String.format(" /* '%c' (0x%02X) */ ", - character.charAt(0), (int)character.charAt(0))); - - // 写入数据(每行12字节) - for (int j = 0; j < hexData.size(); j++) { - writer.write(hexData.get(j)); - if (j < hexData.size() - 1) { - writer.write(", "); - } - } - writer.write("\n"); - } - writer.write("};\n\n"); - } - - // 添加获取点阵的函数 - writer.write("/* 获取点阵数据函数 */\n"); - writer.write("const uint8_t* get_font_data(uint16_t code) {\n"); - - // 汉字处理 - if (!hanziCharacters.isEmpty()) { - writer.write(" // 汉字处理\n"); - writer.write(" switch(code) {\n"); - - int offset = 0; - for (int i = 0; i < hanziCharacters.size(); i++) { - String character = hanziCharacters.get(i); - writer.write(String.format(" case 0x%04X: // '%s'\n", - (int)character.charAt(0), character)); - writer.write(String.format(" return &HANZI_FONT_12X12[%d];\n", offset)); - offset += 24; // 每个汉字24字节 - } - - writer.write(" }\n"); - } - - // ASCII字符处理 - if (!asciiCharacters.isEmpty()) { - writer.write(" // ASCII字符处理\n"); - writer.write(" switch(code) {\n"); - - int offset = 0; - for (int i = 0; i < asciiCharacters.size(); i++) { - String character = asciiCharacters.get(i); - writer.write(String.format(" case 0x%02X: // '%c'\n", - (int)character.charAt(0), character.charAt(0))); - writer.write(String.format(" return &ASCII_FONT_8X12[%d];\n", offset)); - offset += 12; // 每个ASCII字符12字节 - } - - writer.write(" }\n"); - } - - writer.write(" return NULL; // 未找到对应字符\n"); - writer.write("}\n"); - - System.out.println("成功生成字符点阵数据"); - System.out.println(" - 汉字: " + hanziCharacters.size() + " 个"); - System.out.println(" - 字母数字: " + asciiCharacters.size() + " 个"); - - } catch (IOException e) { - System.err.println("文件写入错误: " + e.getMessage()); - } - } - - /** - * 判断是否是汉字 - */ - private static boolean isHanzi(char c) { - // 基本汉字Unicode范围: 4E00-9FFF - return c >= 0x4E00 && c <= 0x9FFF; - } - - /** - * 判断是否是ASCII字符 - */ - private static boolean isAscii(char c) { - return c < 128; - } - - /** - * 生成点阵 - * @param character 字符 - * @param size 点阵尺寸 - * @return 二维点阵数组 - */ - private static int[][] generateDotMatrix(String character, int size) { - // 创建图像 - BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_BYTE_GRAY); - Graphics2D g = image.createGraphics(); - - try { - // 设置白色背景 - g.setColor(Color.WHITE); - g.fillRect(0, 0, size, size); - - // 设置黑色字体 - g.setColor(Color.BLACK); - - // 选择合适的字体 - Font font; - if (isHanzi(character.charAt(0))) { - font = new Font("宋体", Font.PLAIN, size); - } else { - font = new Font("Courier New", Font.PLAIN, size); - } - g.setFont(font); - - // 调整绘制位置(居中显示) - FontMetrics metrics = g.getFontMetrics(); - int x = (size - metrics.charWidth(character.charAt(0))) / 2; - int y = ((size - metrics.getHeight()) / 2) + metrics.getAscent(); - - // 绘制文字 - g.drawString(character, x, y); - } finally { - g.dispose(); - } - - // 分析像素生成点阵 - int[][] dotMatrix = new int[size][size]; - for (int y = 0; y < size; y++) { - for (int x = 0; x < size; x++) { - // 获取像素灰度值 - int rgb = image.getRGB(x, y) & 0xFF; - // 灰度小于180视为有效像素 - dotMatrix[y][x] = (rgb < 180) ? 1 : 0; - } - } - return dotMatrix; - } - - /** - * 将点阵转换为十六进制字符串 - * @param dotMatrix 点阵数据 - * @param size 点阵尺寸 - * @return 十六进制字符串列表 - */ - private static List convertToHex(int[][] dotMatrix, int size) { - List hexData = new ArrayList<>(); - - for (int[] row : dotMatrix) { - int value = 0; - - // 高位在前处理 - for (int i = 0; i < size; i++) { - if (i < row.length && row[i] == 1) { - value |= (1 << (size - 1 - i)); - } - } - - // 根据尺寸拆分字节 - if (size == 12) { - // 12×12点阵:每行拆分为2字节 - hexData.add(String.format("0X%02X", (value >> 8) & 0xFF)); - hexData.add(String.format("0X%02X", value & 0xFF)); - } else { - // 8×12点阵:每行1字节 - hexData.add(String.format("0X%02X", value & 0xFF)); - } - } - - return hexData; - } -} \ No newline at end of file diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ImprovedTextToBitmap.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ReliableTextToBitmap.java similarity index 50% rename from fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ImprovedTextToBitmap.java rename to fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ReliableTextToBitmap.java index 08ec8e9..bde75c7 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ImprovedTextToBitmap.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ReliableTextToBitmap.java @@ -3,97 +3,170 @@ package com.fuyuanshen.equipment.utils.c; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; +import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** - * 发送指令显示工具 + * 可靠点阵生成工具 - 终极版 * * @author: 默苍璃 - * @date: 2025-07-1515:35 + * @date: 2025-07-15 */ -public class ImprovedTextToBitmap { +public class ReliableTextToBitmap { public static void main(String[] args) throws IOException { - String unit = "中国电子集团"; - String department = "人工智能研发中心"; - String name = "张三"; + String unit = "繁體繁體繁體"; + String department = "A研B发C"; + String name = "12李34四56"; byte[] unitBytes = textToBitmapBytes(unit); byte[] deptBytes = textToBitmapBytes(department); byte[] nameBytes = textToBitmapBytes(name); generateCFile(unitBytes, deptBytes, nameBytes, "display_data.c"); + + // 生成预览图片 + generatePreviewImage(unitBytes, "unit_image.png"); + generatePreviewImage(deptBytes, "department_image.png"); + generatePreviewImage(nameBytes, "name_image.png"); } + // 专门生成预览图片的方法 + private static void generatePreviewImage(byte[] data, String filename) { + try { + BufferedImage image = convertByteArrayToImage(data, 12); + ImageIO.write(image, "PNG", new File(filename)); + System.out.println("成功生成预览图片: " + filename); + } catch (IOException e) { + System.err.println("图片生成失败: " + e.getMessage()); + } + } + + /** + * 可靠的字节数组转图像方法 + */ + public static BufferedImage convertByteArrayToImage(byte[] data, int height) { + if (data == null || data.length == 0) { + return new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); + } + + // 计算宽度 + int width = (data.length * 8) / height; + + // 创建RGB图像 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + + // 设置白色背景 + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + image.setRGB(x, y, Color.WHITE.getRGB()); + } + } + + // 直接设置像素点 + int bitIndex = 0; + for (int i = 0; i < data.length; i++) { + int value = data[i] & 0xFF; + for (int bit = 7; bit >= 0; bit--) { // 高位在前 + boolean isBlack = ((value >> bit) & 1) == 1; + if (isBlack) { + int x = bitIndex % width; + int y = bitIndex / width; + if (y < height) { // 确保不越界 + image.setRGB(x, y, Color.BLACK.getRGB()); + } + } + bitIndex++; + } + } + + return image; + } + + /** + * 可靠的点阵生成方法 + */ public static byte[] textToBitmapBytes(String text) { if (text == null || text.isEmpty()) { return new byte[0]; } - // 使用更清晰的黑体字体 - Font font = new Font("黑体", Font.PLAIN, 12); + // 1. 创建画布 - 使用RGB类型避免问题 + Font font = new Font("宋体", Font.PLAIN, 12); + BufferedImage image = createTextImage(text, font); + // 2. 直接提取点阵数据 + return extractBitmapData(image); + } + + /** + * 创建文本图像 - 最可靠的方法 + */ + private static BufferedImage createTextImage(String text, Font font) { // 创建临时图像获取字体度量 - BufferedImage tempImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); + BufferedImage tempImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); Graphics2D tempG = tempImage.createGraphics(); tempG.setFont(font); FontMetrics metrics = tempG.getFontMetrics(); - // 添加字符间距(防止汉字粘连) - int charSpacing = 1; - int totalWidth = 0; - for (char c : text.toCharArray()) { - totalWidth += metrics.charWidth(c) + charSpacing; - } + // 计算文本宽度 + int totalWidth = metrics.stringWidth(text); // 宽度对齐到8的倍数 int width = (int) Math.ceil(totalWidth / 8.0) * 8; int height = 12; - // 创建图像 - BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + // 创建RGB图像 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = image.createGraphics(); + + // 设置白色背景 + g.setColor(Color.WHITE); + g.fillRect(0, 0, width, height); + + // 设置黑色文本 + g.setColor(Color.BLACK); g.setFont(font); - // 设置渲染参数 - 关闭抗锯齿(提高小字清晰度) + // 关闭抗锯齿 - 确保清晰度 g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_OFF); - // 透明背景 - g.setComposite(AlphaComposite.Clear); - g.fillRect(0, 0, width, height); - g.setComposite(AlphaComposite.Src); - g.setColor(Color.BLACK); + // 绘制文本 - 精确居中 + int y = (height - metrics.getHeight()) / 2 + metrics.getAscent(); + g.drawString(text, 0, y); - // 绘制文本(优化垂直对齐) - int y = (height - metrics.getHeight()) / 2 + metrics.getAscent() - 1; - int x = 0; - for (char c : text.toCharArray()) { - g.drawString(String.valueOf(c), x, y); - x += metrics.charWidth(c) + charSpacing; - } g.dispose(); tempG.dispose(); - // 扫描像素并打包数据 + return image; + } + + /** + * 提取点阵数据 - 简单可靠的方法 + */ + private static byte[] extractBitmapData(BufferedImage image) { + int width = image.getWidth(); + int height = image.getHeight(); + List byteList = new ArrayList<>(); int currentByte = 0; int bitCount = 0; - for (int yPos = 0; yPos < height; yPos++) { - for (int xPos = 0; xPos < width; xPos++) { - int pixel = image.getRGB(xPos, yPos); - int alpha = (pixel >> 24) & 0xFF; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + // 获取像素颜色 + Color color = new Color(image.getRGB(x, y)); - // 使用阈值处理(提高清晰度) - boolean isOpaque = alpha > 64; // 阈值可调整 + // 简单阈值判断 - 灰度小于128为黑色 + int gray = (color.getRed() + color.getGreen() + color.getBlue()) / 3; + boolean isBlack = gray < 128; - currentByte = (currentByte << 1) | (isOpaque ? 1 : 0); + // 高位优先打包 + currentByte = (currentByte << 1) | (isBlack ? 1 : 0); bitCount++; if (bitCount == 8) { @@ -106,11 +179,14 @@ public class ImprovedTextToBitmap { // 处理最后不满8位的部分 if (bitCount > 0) { - currentByte <<= (8 - bitCount); // 左移到高位 + currentByte <<= (8 - bitCount); byteList.add((byte) currentByte); } - // 转换结果 + return byteListToArray(byteList); + } + + private static byte[] byteListToArray(List byteList) { byte[] result = new byte[byteList.size()]; for (int i = 0; i < byteList.size(); i++) { result[i] = byteList.get(i); @@ -121,7 +197,7 @@ public class ImprovedTextToBitmap { public static void generateCFile(byte[] unit, byte[] department, byte[] name, String filename) throws IOException { try (FileWriter writer = new FileWriter(filename)) { writer.write("/**\n"); - writer.write(" * 点阵显示数据 - 自动生成\n"); + writer.write(" * 点阵显示数据 - 可靠生成\n"); writer.write(" * 宽度计算公式: width = (数组长度 * 8) / 12\n"); writer.write(" */\n\n"); writer.write("#include \n\n"); diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/TextToBitmapConverter.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/TextToBitmapConverter.java deleted file mode 100644 index f5dfba9..0000000 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/TextToBitmapConverter.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.fuyuanshen.equipment.utils.c; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * @author: 默苍璃 - * @date: 2025-07-1515:14 - */ -public class TextToBitmapConverter { - // 主函数:输入文字并生成C文件 - public static void main(String[] args) throws IOException { - String unit = "单位名称"; - String department = "部门名称"; - String name = "姓名"; - - byte[] unitBytes = textToBitmapBytes(unit); - byte[] deptBytes = textToBitmapBytes(department); - byte[] nameBytes = textToBitmapBytes(name); - - generateCFile(unitBytes, deptBytes, nameBytes, "output.c"); - } - - // 将文本转换为点阵字节数组 - public static byte[] textToBitmapBytes(String text) { - // 1. 创建虚拟画布 - Font font = new Font("SansSerif", Font.PLAIN, 12); - FontMetrics metrics = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB) - .getGraphics().getFontMetrics(font); - - // 计算文本宽度并调整为8的倍数 - int textWidth = metrics.stringWidth(text); - int width = (int) Math.ceil(textWidth / 8.0) * 8; - int height = 12; - - // 创建带透明通道的图像 - BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = image.createGraphics(); - g.setFont(font); - - // 设置渲染参数 - g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, - RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - g.setComposite(AlphaComposite.Clear); - g.fillRect(0, 0, width, height); - g.setComposite(AlphaComposite.Src); - g.setColor(Color.BLACK); - - // 绘制文本(垂直居中) - int y = (height - metrics.getHeight()) / 2 + metrics.getAscent(); - g.drawString(text, 0, y); - g.dispose(); - - // 2. 扫描像素并打包数据 - List byteList = new ArrayList<>(); - int currentByte = 0; - int bitCount = 0; - - for (int yPos = 0; yPos < height; yPos++) { - for (int xPos = 0; xPos < width; xPos++) { - // 检查像素透明度 - int pixel = image.getRGB(xPos, yPos); - boolean isOpaque = ((pixel >> 24) & 0xFF) > 0; - - // 打包位数据(高位在前) - currentByte = (currentByte << 1) | (isOpaque ? 1 : 0); - bitCount++; - - // 每8位打包为一个字节 - if (bitCount == 8) { - byteList.add((byte) currentByte); - currentByte = 0; - bitCount = 0; - } - } - } - - // 转换结果 - byte[] result = new byte[byteList.size()]; - for (int i = 0; i < byteList.size(); i++) { - result[i] = byteList.get(i); - } - return result; - } - - // 生成C文件 - public static void generateCFile(byte[] unit, byte[] department, byte[] name, String filename) throws IOException { - try (FileWriter writer = new FileWriter(filename)) { - // 写入文件头 - writer.write("#include \n\n"); - - // 写入单位数据 - writer.write("const uint8_t unit[] = {\n "); - writeByteArray(writer, unit); - writer.write("\n};\n\n"); - - // 写入部门数据 - writer.write("const uint8_t department[] = {\n "); - writeByteArray(writer, department); - writer.write("\n};\n\n"); - - // 写入姓名数据 - writer.write("const uint8_t name[] = {\n "); - writeByteArray(writer, name); - writer.write("\n};\n"); - } - } - - // 辅助方法:格式化字节数组输出 - private static void writeByteArray(FileWriter writer, byte[] data) throws IOException { - for (int i = 0; i < data.length; i++) { - // 将字节转换为无符号整数 - int value = data[i] & 0xFF; - writer.write(String.format("0x%02X", value)); - - // 添加逗号(最后一个元素除外) - if (i < data.length - 1) { - writer.write(", "); - // 每16个元素换行 - if ((i + 1) % 16 == 0) writer.write("\n "); - } - } - } -} From cc776300ecf5fbeb0dfb7c48be49f98f3413fa1d Mon Sep 17 00:00:00 2001 From: daiyongfei <974332738@qq.com> Date: Thu, 17 Jul 2025 09:23:11 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=88=A0=E9=99=A4=E8=AE=BE=E5=A4=87=20?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/log/enums/BusinessType.java | 2 +- .../controller/DeviceAPPController.java | 8 ++--- .../service/impl/DeviceServiceImpl.java | 34 +++++++++++-------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/fys-common/fys-common-log/src/main/java/com/fuyuanshen/common/log/enums/BusinessType.java b/fys-common/fys-common-log/src/main/java/com/fuyuanshen/common/log/enums/BusinessType.java index bcd0100..65963be 100644 --- a/fys-common/fys-common-log/src/main/java/com/fuyuanshen/common/log/enums/BusinessType.java +++ b/fys-common/fys-common-log/src/main/java/com/fuyuanshen/common/log/enums/BusinessType.java @@ -37,7 +37,7 @@ public enum BusinessType { EXPORT, /** - * 导入 + * */ IMPORT, diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceAPPController.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceAPPController.java index bf01dd8..e99b139 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceAPPController.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceAPPController.java @@ -6,17 +6,17 @@ import com.fuyuanshen.common.core.validate.EditGroup; import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit; import com.fuyuanshen.common.log.annotation.Log; import com.fuyuanshen.common.log.enums.BusinessType; -import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; import com.fuyuanshen.common.web.core.BaseController; import com.fuyuanshen.equipment.domain.bo.UserAppBo; -import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria; import com.fuyuanshen.equipment.service.AppUserService; -import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; /** * @Description: diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java index 37177d4..1045f26 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceServiceImpl.java @@ -10,6 +10,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fuyuanshen.common.core.domain.model.LoginUser; +import com.fuyuanshen.common.core.exception.BadRequestException; +import com.fuyuanshen.common.core.utils.StringUtils; import com.fuyuanshen.common.mybatis.core.page.PageQuery; import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; import com.fuyuanshen.common.satoken.utils.AppLoginHelper; @@ -42,6 +44,7 @@ import com.fuyuanshen.system.domain.vo.SysOssVo; import com.fuyuanshen.system.service.ISysOssService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.formula.functions.T; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -54,6 +57,7 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Objects; /** * @Description: @@ -272,20 +276,23 @@ public class DeviceServiceImpl extends ServiceImpl impleme public void deleteAll(List ids) { List invalidIds = new ArrayList<>(); + for (Long id : ids) { + DeviceAssignments deviceAssignment = deviceAssignmentsMapper.selectById(id); + Device deviceType = deviceMapper.selectById(deviceAssignment.getDeviceId()); + + if (StringUtils.isNotEmpty(deviceAssignment.getAssigneeName())) { + throw new BadRequestException(deviceType.getDeviceName() + ":设备已分配,请先解绑设备!!!"); + } + + // 接收者 + if (Objects.equals(deviceAssignment.getAssigneeId(), deviceType.getOriginalOwnerId())) { + invalidIds.add(deviceAssignment.getDeviceId()); + } + + } + deviceAssignmentsMapper.deleteByIds(ids); - // - // for (Long id : ids) { - // - // Device deviceType = deviceMapper.selectById(id); - // if (deviceType == null || !Objects.equals(deviceType.getCurrentOwnerId(), LoginHelper.getUserId())) { - // invalidIds.add(id); - // } - // } - // if (!invalidIds.isEmpty()) { - // throw new RuntimeException("以下设备无法删除(ID 不存在或无权限): " + invalidIds); - // } - // - // deviceMapper.deleteByIds(ids); + deviceMapper.deleteByIds(invalidIds); } @@ -570,7 +577,6 @@ public class DeviceServiceImpl extends ServiceImpl impleme } - /** * 查询设备MAC号 *