美文网首页
中文乱码 java绘制文字图片

中文乱码 java绘制文字图片

作者: 小强不可爱 | 来源:发表于2018-08-11 13:12 被阅读0次
    近期项目中客户有个需求,就是将默认头像要进行动态的将用户的姓名的一部分也显示在头像中, 效果图.png

    这个需求很简单,也很容易就搞定了,我的测试代码:

    String name = new String(request.getParameter("name").getBytes("ISO-8859-1"),"UTF-8");;
            System.out.println(name);
            String path = getServletContext().getRealPath("/WEB-INF/image/6.jpeg");
            File theImgFile = new File(path);
            int x = 20;
            int y = 60;
            if(name != null && name.length() > 0){
                InputStream imageIn = new FileInputStream(theImgFile);
                // JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(imageIn);
                // BufferedImage image = decoder.decodeAsBufferedImage();
                // ImageInputStream createStream = ImageIO.createImageInputStream(imageIn);
                BufferedImage image = ImageIO.read(imageIn);
                Graphics g=image.getGraphics();
                //设置颜色
                g.setColor(new Color(Integer.parseInt("ffffff",16)));
                //设置字体
                Font mFont = new Font("微软雅黑",Font.BOLD,22);//默认字体
                g.setFont(mFont);
                FontMetrics fm = g.getFontMetrics();
                int width = fm.stringWidth(name);
                System.out.println("字体宽度:"+width+"  显示文字:"+name);
                if(width > 0 && width < 30) {
                    x = 33;
                }else if(width < 35 && width >= 30) {
                    x = 30;
                }else if(width < 40 && width >= 35) {
                    x = 27;
                }else if(width < 50 && width >= 40) {
                    x = 25;
                }else if(width < 60 && width >= 50) {
                    x = 18;
                }else if(width < 70 && width >= 60) {
                    x = 15;
                }
                //输出文字
                g.drawString(name,x,y);
                //输出数据流
                response.setContentType("image/jpeg"); 
                ServletOutputStream out = response.getOutputStream();
                ImageIO.write(image, "jpeg", out);
                out.close();
            }
    

    当然,这代码主要还得感谢度娘,具体时哪位哥们还是小姐姐的就忘了。
    正题:需求中遇到两个大问题和一个小问题
    1,我在windows下开发并且一切正常,如果拿我本机当服务器,全剧终!
    当我将这个功能放到linux服务器下时出现中文乱码,这种情况按常理想到的就是编码转换的问题,但这个思路去解决这个问题并没能够解决中文乱码的问题,最后是公司技术大佬发现了是linux中jdk文字目录问题,在jre/fonts文字目录下加上我们需要的文字文件就能够正常显示中文。我们可以通过遍历检测文字目录:

    GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
            String[] fontName = e.getAvailableFontFamilyNames();
            for (int i = 0; i < fontName.length; i++) {
                if("微软雅黑".equalsIgnoreCase(fontName[i])){
                    isWryh = true;  //系统更有微软雅黑字体
                }
            }
    

    这样就可以在没有我没想要的文字文件时,将最终数据的图片中乱码给去掉不现实字体。
    2,这些代码我是在家中进行重新编写的,我将小工程放到虚拟机centos中运行提示:

    java.lang.ClassNotFoundException: com.sun.image.codec.jpeg.JPEGCodec
    

    这是为什么呢?这些类都时在jdk中的,为什么没有这个类呢?我将这个类所在包找到jre/lib/rt.jar放到工程lib下重新打包并部署,依然出现没有找到这个类,终于找到了原因

    java.lang.ClassNotFoundException的原因:
    The basic explanation is that com.sun.image.codec.jpeg.JPEGCodec 
    and related libraries have long been marked as depreciated, 
    and you should use the [ImageIO]
    (http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html) 
    library instead.
    

    原来,在jdk1.7版本后,这jpeg包下的类已经不推荐,所以,果断用ImageIO替换这两个类,在最上面的代码中使用

    BufferedImage image = ImageIO.read(imageIn);
    

    3,第三个问题我只能归结问算术问题了,解决这个需求我使用的是一张带底色的图片,之后在上面动态的绘制文字,这里就要注意这个“动态”俩字。绘制的文字是取用户姓名的后两位,用户姓名后两位我们不能不怀疑有奇葩的组合:“Aa”,“AA”,“tt”,“Tt”,“WW”,“ww”,“Ww”,“测试”,“测测”,“测a”,“测t”,“测T”,“测W”.......这些组合都是有可能的,刚开始我在想是否可以通过字节数来给文字定位,最后发现这个字节数并不能很好的把文字的物理长度“诠释”出来。最后找到了这个可以计算字体宽度的API

    FontMetrics fm = g.getFontMetrics();
    int width = fm.stringWidth(name);
    

    通过这字体宽度进行文字定位就很容易了。

    相关文章

      网友评论

          本文标题:中文乱码 java绘制文字图片

          本文链接:https://www.haomeiwen.com/subject/wfqdbftx.html