You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:Eclipse控制台Unicode盲文艺术无法复制及文件写入失败

Java盲文字符画程序问题修复方案

核心问题定位

你的程序存在四个关键问题,导致尺寸调整后输出异常、文件写入失败:

  • 循环遍历边界错误,遗漏部分像素组
  • 文件写入流未关闭,缓冲区内容未刷入磁盘
  • 8点盲文点位与Unicode字符的映射逻辑完全错误
  • 未做目标尺寸的图片缩放处理,无法直接生成136*100的盲文输出

具体修复点

1. 修正循环遍历边界

原代码中i < height-4和j < width-4的条件会漏掉最后一组4行2列的像素,导致输出不完整。应修改为:

for (int i = 0; i <= height - 4; i += 4) {
    for (int j = 0; j <= width - 2; j += 2) {
        // 子像素赋值逻辑不变
    }
}

2. 确保文件流正确关闭

使用try-with-resources语法自动管理FileWriter,避免缓冲区内容未写入文件:

try (FileWriter writer = new FileWriter(homeAdress + "output.txt")) {
    for (int i = 0; i < outputChar.length; i++) {
        for (int j = 0; j < outputChar[i].length; j++) {
            writer.write(outputChar[i][j]);
        }
        writer.write('\n');
    }
} // 代码块结束自动关闭流

3. 修复盲文点位映射逻辑

8点盲文的Unicode编码从U+2800开始,点位布局与二进制权重对应关系如下:

1 4
2 5
3 6
7 8

其中点位1对应2⁰、点位2对应2¹、点位3对应2²、点位7对应2³;点位4对应2⁴、点位5对应2⁵、点位6对应2⁶、点位8对应2⁷。修正后的映射方法:

public static char TurnTo8DotsBraille(int[][] subPixle) {
    int decimal = 0;
    // 左列点位映射
    if (subPixle[0][0] == 1) decimal += 1 << 0;
    if (subPixle[1][0] == 1) decimal += 1 << 1;
    if (subPixle[2][0] == 1) decimal += 1 << 2;
    if (subPixle[3][0] == 1) decimal += 1 << 3;
    // 右列点位映射
    if (subPixle[0][1] == 1) decimal += 1 << 4;
    if (subPixle[1][1] == 1) decimal += 1 << 5;
    if (subPixle[2][1] == 1) decimal += 1 << 6;
    if (subPixle[3][1] == 1) decimal += 1 << 7;
    return (char) (0x2800 + decimal); // U+2800为盲文空白字符
}

4. 添加目标尺寸缩放逻辑

要生成136列×100行的盲文输出,需先将原图缩放到272像素宽(136×2)、400像素高(100×4),因为每个盲文字符对应2列4行像素:

// 目标盲文尺寸:136列,100行 → 对应图片尺寸272×400
int targetBrailleWidth = 136;
int targetBrailleHeight = 100;
int targetImgWidth = targetBrailleWidth * 2;
int targetImgHeight = targetBrailleHeight * 4;

// 缩放原图到目标尺寸
BufferedImage scaledImage = new BufferedImage(targetImgWidth, targetImgHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = scaledImage.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage(image, 0, 0, targetImgWidth, targetImgHeight, null);
g2d.dispose();

// 后续黑白转换使用缩放后的图片
BufferedImage result = new BufferedImage(targetImgWidth, targetImgHeight, BufferedImage.TYPE_BYTE_BINARY);
Graphics2D graphic = result.createGraphics();
graphic.drawImage(scaledImage, 0, 0, Color.WHITE, null);
graphic.dispose();

完整修复代码

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.FileWriter;

public class BlackAndWhitePrint {

    public static void main(String[] args) {
        try {
            String homeAdress = "C:\\Users\\taban\\eclipse-workspace\\BlackAndWhitePrint\\";
            String FileName = "C:\\Users\\taban\\eclipse-workspace\\BlackAndWhitePrint\\shakh.jpg";
            File input = new File(FileName);
            BufferedImage image = ImageIO.read(input);

            // 目标盲文尺寸:136列,100行 → 对应图片尺寸272×400
            int targetBrailleWidth = 136;
            int targetBrailleHeight = 100;
            int targetImgWidth = targetBrailleWidth * 2;
            int targetImgHeight = targetBrailleHeight * 4;

            // 缩放原图到目标尺寸
            BufferedImage scaledImage = new BufferedImage(targetImgWidth, targetImgHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = scaledImage.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.drawImage(image, 0, 0, targetImgWidth, targetImgHeight, null);
            g2d.dispose();

            // 转为黑白图像
            BufferedImage result = new BufferedImage(targetImgWidth, targetImgHeight, BufferedImage.TYPE_BYTE_BINARY);
            Graphics2D graphic = result.createGraphics();
            graphic.drawImage(scaledImage, 0, 0, Color.WHITE, null);
            graphic.dispose();

            File output = new File(homeAdress + "shakhEdit.jpg");
            ImageIO.write(result, "jpg", output);

            // 生成0-1位图
            int width = result.getWidth();
            int height = result.getHeight();
            int[][] bitmap = new int[height][width];
            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width; j++) {
                    int rgb = result.getRGB(j, i);
                    int r = (rgb >> 16) & 0xFF;
                    int g = (rgb >> 8) & 0xFF;
                    int b = (rgb & 0xFF);
                    int gray = (r + g + b) / 3;
                    bitmap[i][j] = (gray == 0) ? 1 : 0; // 黑色为1,白色为0
                }
            }

            // 转为盲文字符
            char[][] outputChar = new char[targetBrailleHeight][targetBrailleWidth];
            int[][] subpixle = new int[4][2];
            for (int i = 0; i <= height - 4; i += 4) {
                for (int j = 0; j <= width - 2; j += 2) {
                    subpixle[0][0] = bitmap[i][j];
                    subpixle[0][1] = bitmap[i][j + 1];
                    subpixle[1][0] = bitmap[i + 1][j];
                    subpixle[1][1] = bitmap[i + 1][j + 1];
                    subpixle[2][0] = bitmap[i + 2][j];
                    subpixle[2][1] = bitmap[i + 2][j + 1];
                    subpixle[3][0] = bitmap[i + 3][j];
                    subpixle[3][1] = bitmap[i + 3][j + 1];
                    outputChar[i / 4][j / 2] = TurnTo8DotsBraille(subpixle);
                }
            }

            // 控制台打印
            PrintTheChar(outputChar);

            // 文件写入(自动关闭流)
            try (FileWriter writer = new FileWriter(homeAdress + "output.txt")) {
                for (int i = 0; i < outputChar.length; i++) {
                    for (int j = 0; j < outputChar[i].length; j++) {
                        writer.write(outputChar[i][j]);
                    }
                    writer.write('\n');
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("失败");
        }
    }

    public static char TurnTo8DotsBraille(int[][] subPixle) {
        int decimal = 0;
        // 左列点位:1(2^0), 2(2^1), 3(2^2), 7(2^3)
        if (subPixle[0][0] == 1) decimal += 1 << 0;
        if (subPixle[1][0] == 1) decimal += 1 << 1;
        if (subPixle[2][0] == 1) decimal += 1 << 2;
        if (subPixle[3][0] == 1) decimal += 1 << 3;
        // 右列点位:4(2^4), 5(2^5), 6(2^6), 8(2^7)
        if (subPixle[0][1] == 1) decimal += 1 << 4;
        if (subPixle[1][1] == 1) decimal += 1 << 5;
        if (subPixle[2][1] == 1) decimal += 1 << 6;
        if (subPixle[3][1] == 1) decimal += 1 << 7;
        return (char) (0x2800 + decimal); // 盲文起始编码U+2800
    }

    public static void PrintTheChar(char[][] input) {
        for (int i = 0; i < input.length; i++) {
            for (int j = 0; j < input[i].length; j++) {
                System.out.print(input[i][j]);
            }
            System.out.println();
        }
    }
}

注意事项

  • 确保原图路径正确,若路径含中文需注意系统编码兼容性
  • 生成的output.txt需用支持Unicode的文本编辑器打开(如Notepad++)
  • 黑白转换阈值gray == 0可调整为gray < 128,适配更多灰度场景

内容的提问来源于stack exchange,提问作者محمد حسین رحیمی

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 18:24:58