点阵图更改背景文字

前言

在开发中,点阵图有时候需要更改北京图片,比如白底黑字,或者黑底白字,这个时候,只需要把点阵图所有字节取反,就可以更改背景颜色

更改背景颜色

以行列式为标准,然后生成的字节取反

ini 复制代码
package cn.com.ut.oct.pic;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;



public class EInkDisplaySDK {

    // 支持的字体样式
    public enum FontStyle {
        PLAIN, BOLD, ITALIC
    }

    /**
     * 将文本转换为点阵数据
     *
     * @param text      要转换的文本
     * @param fontSize  字体大小
     * @param fontStyle 字体样式
     * @param width     显示区域宽度
     * @param height    显示区域高度
     * @return 点阵数据字节数组
     */
    public static byte[][] textToDotMatrix(String text, int fontSize, FontStyle fontStyle,
                                           int width, int height) {
        // 创建字体
        Font font = new Font("宋体", getAwtFontStyle(fontStyle), fontSize);

        // 创建临时图像进行渲染
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
        Graphics2D g2d = image.createGraphics();

        // 设置渲染参数
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, width, height);
        g2d.setColor(Color.BLACK);
        g2d.setFont(font);

        // 计算文本位置(居中)
        String[] data = text.split(",");
        int margin = 10;
        int high = 30;
        int count = 0;
        double angleInRadians = Math.toRadians(90);
//        g2d.rotate(angleInRadians, image.getWidth() / 2, image.getHeight() / 2);
        for (String str : data) {
            count++;
            // 绘制文本
//            g2d.scale(-1.0, 1.0);
            FontMetrics metrics = g2d.getFontMetrics();
            int x = (width - metrics.stringWidth(str)) / 2;
            int y = ((height - metrics.getHeight()) / 2) + metrics.getAscent();
            g2d.drawString(str, x, high);
            if (count > 0) {
                high = high + 30;
            }
        }
        g2d.dispose();
        // 创建一个新的BufferedImage对象,用于存储旋转后的图片


        BufferedImage destImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());


        // 获取Graphics2D对象


        Graphics2D graphics2D = (Graphics2D) destImage.getGraphics();


        // 创建一个新的AffineTransform对象,并设置其为旋转变换


        AffineTransform transform = new AffineTransform();


        transform.rotate(Math.toRadians(90), image.getWidth() / 2, image.getHeight() / 2);


        // 使用Graphics2D对象的drawImage方法,将原始图片按照旋转变换绘制到新的BufferedImage对象上


        graphics2D.drawImage(image, transform, null);


        // 转换图像为点阵数据
        return convertImageToDotMatrix1(destImage, width, height);
    }

    /**
     * 将图像转换为点阵数据
     */
    private static byte[][] convertImageToDotMatrix(BufferedImage image, int width, int height) {
        // 计算每列需要的字节数(每8个像素用1字节表示)
        int bytesPerColumn = (int) Math.ceil(height / 8.0);
        int totalBytes = bytesPerColumn * width;

        try {
            ImageIO.write(image, "jpeg", new File("d:/hello/1.jpeg"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

//        BufferedImage image1 = getImage("d:/hello/1.jpeg");
//
//        try {
//            ImageIO.write(image1, "jpeg", new File("d:/hello/2.jpeg"));
//        } catch (IOException e) {
//            throw new RuntimeException(e);
//        }

        byte[][] dotMatrix = new byte[bytesPerColumn][width];

        ByteBuffer buffer = ByteBuffer.allocate(totalBytes);

        for (int x = 0; x < width; x++) {
            for (int byteIdx = 0; byteIdx < bytesPerColumn; byteIdx++) {
                byte b = 0;
                for (int bit = 0; bit < 8; bit++) {
                    int pixelY = byteIdx * 8 + bit;
                    if (pixelY < height) {
                        int rgb = image.getRGB(x, pixelY);
                        // 如果像素不是白色(即黑色文本),设置对应位
                        if (rgb != Color.WHITE.getRGB()) {
                            b |= (1 << bit); // 列主序时位顺序与行主序不同
                        }
                    }
                }
//                buffer.put(b);
                dotMatrix[byteIdx][x] = b;
            }
        }

        return dotMatrix;
    }

    /**
     * 将图像转换为点阵数据
     */
    private static byte[][] convertImageToDotMatrix1(BufferedImage image, int width, int height) {
        int bytesPerRow = (int) Math.ceil(width / 8.0);
        ; // 每行需要的字节数
//        byte[] dotMatrix = new byte[bytesPerRow * height];

        byte[][] dotMatrix = new byte[bytesPerRow][height];

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < bytesPerRow; x++) {
                byte b = 0;
                for (int bit = 0; bit < 8; bit++) {
                    int pixelX = x * 8 + bit;
                    if (pixelX < width) {
                        int rgb = image.getRGB(pixelX, y);
                        // 黑色像素设置对应位
                        if (rgb != Color.WHITE.getRGB()) {
                            int actualBit = 7 - bit;
                            b |= (1 << actualBit);
                        }
                    }
                }
                b = (byte) ~b;
                dotMatrix[x][y] = b;
            }
        }
        // 输出图像到文件
        File outputFile = new File("d:/hello/output.png");
        try {
            ImageIO.write(image, "png", outputFile);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return dotMatrix;
    }

    public static BufferedImage getImage(String srcFile) {
        // 读取原始图片


        BufferedImage srcImage = null;
        try {
            srcImage = ImageIO.read(new File(srcFile));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }


        // 创建一个新的BufferedImage对象,用于存储旋转后的图片


        BufferedImage destImage = new BufferedImage(srcImage.getWidth(), srcImage.getHeight(), srcImage.getType());


        // 获取Graphics2D对象


        Graphics2D graphics2D = (Graphics2D) destImage.getGraphics();


        // 创建一个新的AffineTransform对象,并设置其为旋转变换


        AffineTransform transform = new AffineTransform();


        transform.rotate(Math.toRadians(90), srcImage.getWidth() / 2, srcImage.getHeight() / 2);


        // 使用Graphics2D对象的drawImage方法,将原始图片按照旋转变换绘制到新的BufferedImage对象上


        graphics2D.drawImage(srcImage, transform, null);


//        // 将旋转后的图片保存到文件
//
//
//        ImageIO.write(destImage, "JPG", new File("d:/hello/dest.jpg"));
        return destImage;
    }

    /**
     * 字体样式转换
     */
    private static int getAwtFontStyle(FontStyle style) {
        switch (style) {
            case BOLD:
                return Font.BOLD;
            case ITALIC:
                return Font.ITALIC;
            default:
                return Font.PLAIN;
        }
    }

    /**
     * 多行文本转换(支持自动换行)
     */
    public static List<byte[][]> multiLineTextToDotMatrix(String text, int fontSize,
                                                          FontStyle fontStyle,
                                                          int width, int height,
                                                          int lineHeight) {
        List<String> lines = wrapText(text, width, fontSize, fontStyle);
        List<byte[][]> result = new ArrayList<>();

        for (String line : lines) {
            result.add(textToDotMatrix(line, fontSize, fontStyle, width, lineHeight));
        }

        return result;
    }

    /**
     * 文本自动换行处理
     */
    private static List<String> wrapText(String text, int maxWidth, int fontSize, FontStyle fontStyle) {
        // 简化的换行实现,实际应用中需要更复杂的逻辑
        List<String> lines = new ArrayList<>();
        Font font = new Font("SimSun", getAwtFontStyle(fontStyle), fontSize);

        // 这里应该使用FontMetrics计算文本宽度并进行换行
        // 简化实现:按字符数粗略分割
        int charsPerLine = maxWidth / fontSize * 2; // 粗略估算

        for (int i = 0; i < text.length(); i += charsPerLine) {
            int end = Math.min(i + charsPerLine, text.length());
            lines.add(text.substring(i, end));
        }

        return lines;
    }

    /**
     * 生成用于墨水屏刷新的压缩数据
     */
    public static byte[] generateCompressedData(byte[] dotMatrix, int width, int height) {
        // 简化的压缩实现,实际应根据墨水屏协议实现
        List<Byte> compressed = new ArrayList<>();
        byte currentByte = dotMatrix[0];
        int count = 1;

        for (int i = 1; i < dotMatrix.length; i++) {
            if (dotMatrix[i] == currentByte && count < 255) {
                count++;
            } else {
                compressed.add((byte) count);
                compressed.add(currentByte);
                currentByte = dotMatrix[i];
                count = 1;
            }
        }

        compressed.add((byte) count);
        compressed.add(currentByte);

        // 转换为字节数组
        byte[] result = new byte[compressed.size()];
        for (int i = 0; i < compressed.size(); i++) {
            result[i] = compressed.get(i);
        }

        return result;
    }
}

测试用例

ini 复制代码
public class EInkExample {
    static void main(String[] args) throws IOException {
        String str = "优秀";
        byte[][] dotMatrix = EInkDisplaySDK.textToDotMatrix(
                str,
                24,
                EInkDisplaySDK.FontStyle.PLAIN,
                152,
                152
        );


        List<Integer> list = new ArrayList<>(10);
        for (int i = 0; i < dotMatrix.length; i++) {
            for (int j = 0; j < dotMatrix[i].length; j++) {
                list.add((int) dotMatrix[i][j]);
                System.out.print(HexUtil.toHex((dotMatrix[i][j] & 0XFF)) + ",");
            }
            System.out.println();

        }
//        byte[] a = new byte[list.size()];
//        for (int i = 0; i < list.size(); i++) {
//            a[i] = list.get(i).byteValue();
//            System.out.print(a[i] + " ");
//            if ((i + 1) % 128 == 0) {
//                System.out.println();
//            }
//
//        }
//
//        System.out.println();
//        System.out.println("=================");
//
//        System.out.println();

    }
}

总结

可以使用点阵图去更改显示屏文字颜色

相关推荐
晴殇i2 小时前
千万级点赞系统架构演进:从单机数据库到分布式集群的完整解决方案
前端·后端·面试
ldmd2842 小时前
Go语言实战:入门篇-5:函数、服务接口和Swagger UI
开发语言·后端·golang
ZHE|张恒2 小时前
Spring Boot 3 + Flyway 全流程教程
java·spring boot·后端
Mintopia2 小时前
🧠 Next.js × GraphQL Yoga × GraphiQL:交互式智能之门
前端·后端·全栈
TDengine (老段)2 小时前
TDengine 数学函数 CRC32 用户手册
java·大数据·数据库·sql·时序数据库·tdengine·1024程序员节
林太白2 小时前
rust16-职位管理模块
后端·rust
心随雨下3 小时前
Tomcat日志配置与优化指南
java·服务器·tomcat
Kapaseker3 小时前
Java 25 中值得关注的新特性
java
wljt3 小时前
Linux 常用命令速查手册(Java开发版)
java·linux·python