Linux环境下BufferedImage Graphics drawString 中文乱码解决方法

在linux环境下的,生成的带文字的图片在前台一直显示为方框乱码,windows环境正常。

img.setFont(new Font("宋体", Font.BOLD, 20));

写中文进入图片之前必须设置字体,而且这个字体必须支持中文,否则就会出现乱码或者方框、问号等等。

BufferedImage在内存创建的图像调用的是服务器端的字体,所以在img.drawString(str, x, y);时,如果服务器端找不到对应的中文字体,那么它就识别不了,最后写入图片的中文就变成了乱码、方框、问号等等了。

在这里可以有两种方法添加服务器端的中文支持:

第一种方法,添加系统中文字体(宋体):
root@dragon-virtual-machine:~# cd /usr/share/fonts
root@dragon-virtual-machine:/usr/share/fonts# mkdir winFonts
root@dragon-virtual-machine:/usr/share/fonts# cp /home/dragon/Desktop/simsun.ttc winFonts
root@dragon-virtual-machine:/usr/share/fonts# cd winFonts
root@dragon-virtual-machine:/usr/share/fonts/winFonts# mkfontdir
root@dragon-virtual-machine:/usr/share/fonts/winFonts# mkfontscale
第二种方法,添加jre中文字体(宋体):
root@dragon-virtual-machine:~# cd /usr/lib/jvm/java-6-sun/jre/lib/fonts
root@dragon-virtual-machine:/usr/lib/jvm/java-6-sun/jre/lib/fonts# cp /home/dragon/Desktop/simsun.ttc .

修改完必须重启服务器才有效。


好的,我来回答你的问题。 首先,你可以使用zxing库中的MultiFormatWriter类来生成二维码,该类的write方法可以将二维码内容生成为一个BitMatrix对象,然后再将其转换为BufferedImage对象。 要在二维码上面生成可换行标题,你可以先将标题按照指定的宽度进行分行处理,然后使用Graphics2D类中的drawString方法逐行绘制标题,最后将绘制好的BufferedImage对象和生成的二维码合并即可。 至于内容乱码问题,可能是由于字符编码不统一所致,你可以将生成二维码的方法中指定字符编码为UTF-8,这样可以避免乱码问题的出现。 下面是一个示例代码,供你参考: ``` import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import javax.imageio.ImageIO; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; public class QRCodeUtil { private static final int WIDTH = 400; // 二维码宽度 private static final int HEIGHT = 400; // 二维码高度 private static final int TITLE_WIDTH = 300; // 标题宽度 private static final Font TITLE_FONT = new Font("微软雅黑", Font.PLAIN, 20); // 标题字体 /** * 生成二维码图片 * * @param content 二维码内容 * @param title 标题 * @param out 输出流 * @throws WriterException * @throws IOException */ public static void generateQRCode(String content, String title, OutputStream out) throws WriterException, IOException { // 设置二维码参数 MultiFormatWriter multiFormatWriter = new MultiFormatWriter(); // 设置二维码纠错级别 ErrorCorrectionLevel level = ErrorCorrectionLevel.H; // 设置编码字符集 String charset = StandardCharsets.UTF_8.name(); // 设置二维码内容及参数 BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, WIDTH, HEIGHT, QRCodeUtil.getDecodeHintType(charset, level)); // 生成二维码图片 BufferedImage image = QRCodeUtil.toBufferedImage(bitMatrix); // 绘制标题 Graphics2D g2 = image.createGraphics(); g2.setColor(Color.BLACK); g2.setFont(TITLE_FONT); int y = 50; // 标题起始y坐标 for (String line : splitTitle(title, TITLE_FONT, TITLE_WIDTH)) { g2.drawString(line, (WIDTH - g2.getFontMetrics().stringWidth(line)) / 2, y); y += g2.getFontMetrics().getHeight(); } // 输出图片 ImageIO.write(image, "png", out); } /** * 将BitMatrix对象转换为BufferedImage对象 * * @param matrix BitMatrix对象 * @return BufferedImage对象 */ private static BufferedImage toBufferedImage(BitMatrix matrix) { int width = matrix.getWidth(); int height = matrix.getHeight(); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { image.setRGB(x, y, matrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); } } return image; } /** * 分行处理标题 * * @param title 标题 * @param font 字体 * @param width 宽度 * @return 分行后的标题 */ private static String[] splitTitle(String title, Font font, int width) { StringBuilder sb = new StringBuilder(); for (char c : title.toCharArray()) { sb.append(c); if (font.getStringBounds(sb.toString(), null).getWidth() > width) { sb.deleteCharAt(sb.length() - 1); sb.append("\n"); } } return sb.toString().split("\n"); } /** * 获取解码参数 * * @param charset 编码字符集 * @param level 纠错级别 * @return 解码参数 */ private static java.util.Map<EncodeHintType, Object> getDecodeHintType(String charset, ErrorCorrectionLevel level) { java.util.Map<EncodeHintType, Object> hints = new java.util.HashMap<>(); hints.put(EncodeHintType.CHARACTER_SET, charset); hints.put(EncodeHintType.ERROR_CORRECTION, level); hints.put(EncodeHintType.MARGIN, 1); return hints; } } ``` 使用方法: ``` String content = "http://www.example.com"; String title = "这是一个可换行的标题"; OutputStream out = new FileOutputStream("qrcode.png"); QRCodeUtil.generateQRCode(content, title, out); out.close(); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值