• 图片转字符图片(一)


    序言

    这个是从抖音上学来的,一开始刷抖音,遇到不少字符串跳舞的视频,因此来实践一下

    主要分为三个部分

    1. 静态图片转静态图片
    2. gif转gif
    3. 视频转视频

    静态图片转静态图片

    其实原理很简单,读取图片的像素,新建一张大小一样的图片,根据原图像素的灰度,决定是不是要显示出来,并在新图相应的位置添加字符,这样就完成了

    先来看下效果图,如下

    原图

    字符串后

    代码实现

    借助前辈写的工具,主要包含一下四个类:

    1. AnimatedGifEncoder
    2. GifDecoder
    3. LZWEncoder
    4. NeuQuant

    源地址:https://github.com/rtyley/animated-gif-lib-for-java

    ps: 网上各种版本的太多,不清楚这个是不是原作者,github上搜GifDecoder

    环境:

    JDK 1.8

    注:Java原生代码实现使用jdk内部的GIFImageReader、GIFImageWriter等类,maven在编译的时候会提示这是sun公司的私有API,在1.7、1.8版的JDK中已经删除,所以是有风险的。在此使用ImageIO这个类来进行图片的操作。

    测试代码:

        @Test
        public static void imgTest() 
            String inputFile = "F:/123/head.png";
            String outputFile = "F:/123/head_copy.png";
            // String base = "01"; // 替换的字符串
            String base = "@#&$%*o!;.";// 字符串由复杂到简单
            int threshold = 8;// 阈值
            ImgUtil.toTextImg(inputFile, outputFile, base, threshold);
        }
    

    参数调整

    具体参数调整如下图所示:

    代码

    1. 调整字符大小,颜色
    2. 调整字符间距
    3. 调整字符的区域 (index数值越小,灰度越大)

    完整代码如下所示:

    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    
    import javax.imageio.ImageIO;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * @ClassName: ImgUtil
     * @Description: TODO
     * @author jiang
     * @date 2018年8月14日 下午10:15:56
     * 
     */
    public class ImgUtil {
    
        static Logger logger = LoggerFactory.getLogger(ImgUtil.class);
    
        public static boolean toTextImg(String inputFile, String outputFile, final String base, int threshold) {
    
    //        String blackFile = "F:/123/head_black.png";
            BufferedImage src = null;
            BufferedImage tag = null;
            boolean res = false;
            try {
                src = ImageIO.read(new FileInputStream(inputFile));
                int[] rgb = new int[3];
                int width = src.getWidth();
                int height = src.getHeight();
                int minx = src.getMinX();
                int miny = src.getMinY();
                // 黑白化
    /*-                        
                src = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null).filter(src, null);
                res = ImageIO.write(src, blackFile.substring(blackFile.lastIndexOf(".") + 1), new File(blackFile));
                src = ImageIO.read(new FileInputStream(blackFile));*/
    
                tag = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
                Graphics g = tag.getGraphics();
                g.setFont(new Font("微软雅黑", Font.PLAIN, 10));// 设置字体
                g.setColor(Color.BLUE);// 设置颜色
                for (int x = minx; x < width; x += 6) {
                    for (int y = miny; y < height; y += 6) {
                        int pixel = src.getRGB(x, y); // 下面三行代码将一个数字转换为RGB数字
                        rgb[0] = (pixel & 0xff0000) >> 16;// red
                        rgb[1] = (pixel & 0xff00) >> 8;// green
                        rgb[2] = (pixel & 0xff);// blue
                        final float gray = 0.299f * rgb[0] + 0.578f * rgb[1] + 0.114f * rgb[2];
                        final int index = Math.round(gray * (base.length() + 1) / 255);
    //                    logger.debug("{},{}",index,base.length() / threshold);
                        if (index <= threshold) {
                            g.drawString(String.valueOf(base.charAt(index % base.length())), x, y);// 文字的编写及位置
                        }
    
                        /*-
                        if (rgb[0] + rgb[1] + rgb[2] <= 500) {
                            System.out.println("i=" + i + ",j=" + j + ":(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")");
                            g.drawString("v", i, j);// 文字的编写及位置
                        }*/
                    }
                }
                g.dispose();
    
                // 输出图片
                res = ImageIO.write(tag, outputFile.substring(outputFile.lastIndexOf(".") + 1),
                        new File(outputFile));
                logger.debug("字符化结果:{}", res);
            } catch (IOException e) {
                logger.error("err", e);
                return false;
            }
            return true;
        }
    
    }
    

    代码的思路很简单,src.getRGB(x, y)获取具体像素点的颜色值,共六位,每两位一个颜色值,依次是red、green、blue,类似的使用

    (pixel & 0xff0000) >> 16
    

    获取第一位的红色等,根据灰度公式

    Gray = R/*0.299 + G/*0.587 + B/*0.114
    

    计算灰度(百度颜色灰度公式,有很多来计算心理灰度的解决方案),选择合适的灰度替换上合适的字符即可

    源码地址:

    1. https://github.com/Ruffianjiang/java4fun/tree/master/img2text

    参考:

    1. https://blog.csdn.net/chwshuang/article/details/64923345
  • 相关阅读:
    屏幕截图(带光标)
    warning LNK4070的解决办法
    2015-08-10
    wmic的用法
    2015-03-12
    MFC Button控件自绘
    MFC窗口创建、销毁消息流程
    DDX_Control、SubclassWindow和SubclassDlgItem
    css animation fade in
    kohana reading session data error(session_start)引起的错误
  • 原文地址:https://www.cnblogs.com/lossingdawn/p/9508942.html
Copyright © 2020-2023  润新知