求助: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,提问作者محمد حسین رحیمی
相关产品推荐
相关产品推荐

