Java实现Gif图转字符动图

简介: 前面介绍了两篇基于jdk实现图片灰度处理、转字符图片的操作,接下来我们在将之前的能力扩展一下,支持将一个gif图灰度化或者转gif字符图本文的实现主要在前面两篇文章的基础上来实现,推荐没有看过的小伙伴也可以瞅一眼

前面介绍了两篇基于jdk实现图片灰度处理、转字符图片的操作,接下来我们在将之前的能力扩展一下,支持将一个gif图灰度化或者转gif字符图


本文的实现主要在前面两篇文章的基础上来实现,推荐没有看过的小伙伴也可以瞅一眼


  • Java实现图片灰度化
  • Java实现图片转字符图片示例demo


单张图的灰度化与转字符实现之后,gif图的实现就简单多了;gif图无非是多张图组合而成,将每一张图转换之后,再重新组装成gif图就完事了


这里我们使用的gif工具类来自于github.com/liuyueyi/qu…


核心关键类为GifEncodeGifDecode;借助它来实现gif图的加载与保存


首先我们将上篇博文中的转字符图的方法抽取一下


Color getAverage(BufferedImage image, int x, int y, int w, int h) {
    int red = 0;
    int green = 0;
    int blue = 0;
    int size = 0;
    for (int i = y; (i < h + y) && (i < image.getHeight()); i++) {
        for (int j = x; (j < w + x) && (j < image.getWidth()); j++) {
            int color = image.getRGB(j, i);
            red += ((color & 0xff0000) >> 16);
            green += ((color & 0xff00) >> 8);
            blue += (color & 0x0000ff);
            ++size;
        }
    }
    red = Math.round(red / (float) size);
    green = Math.round(green / (float) size);
    blue = Math.round(blue / (float) size);
    return new Color(red, green, blue);
}
private BufferedImage parseImg(BufferedImage img) {
    int w = img.getWidth(), h = img.getHeight();
    // 创建新的灰度图片画板
    BufferedImage out = new BufferedImage(w, h, img.getType());
    Graphics2D g2d = out.createGraphics();
    g2d.setColor(null);
    g2d.fillRect(0, 0, w, h);
    int size = 12;
    Font font = new Font("宋体", Font.BOLD, size);
    g2d.setFont(font);
    for (int x = 0; x < w; x += size) {
        for (int y = 0; y < h; y += size) {
            Color avgColor = getAverage(img, x, y, size, size);
            g2d.setColor(avgColor);
            g2d.drawString("灰", x, y);
        }
    }
    g2d.dispose();
    return out;
}
复制代码


接着就是Gif的操作了

@Test
public void testRender() throws IOException {
    String file = "https://c-ssl.duitang.com/uploads/item/201707/11/20170711194634_nTiK5.thumb.1000_0.gif";
    // 从网络上下载图片
    GifDecoder decoder = new GifDecoder();
    decoder.read(FileReadUtil.getStreamByFileName(file));
  // 这里是核心的转换逻辑
    List<ImmutablePair<BufferedImage, Integer>> frames = new ArrayList<>();
    for (int i = 0; i < decoder.getFrameCount(); i++) {
        BufferedImage img = decoder.getFrame(i);
        frames.add(ImmutablePair.of(parseImg(img), decoder.getDelay(i)));
    }
  // 下面是保存gif图
    File save = new File("/tmp/out2.gif");
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    GifHelper.saveGif(frames, outputStream);
    FileOutputStream out = new FileOutputStream(save);
    out.write(outputStream.toByteArray());
    out.flush();
    out.close();
    System.out.printf("渲染完成");
}
复制代码


上图转换成功之后,输出如下


image.png

如果希望输出图片更像原图,可以修改上面的fontSize,比如上面用的是12,可以调整成8,6等值,根据实际情况进行选择


有的小伙伴可能会说了,动漫的gif图转换之后相似度还可以,那么真实人物图转换之后呢?


接下来我们借助开源项目 github.com/liuyueyi/qu… 来迅速的实现一个gif图转换


下图来自网络,有兴趣的自己打开查看,就不贴上了😏)n.sinaimg.cn/sinacn/w390…

@Test
public void testGif() throws Exception {
    String img = "http://n.sinaimg.cn/sinacn/w390h219/20171231/0ac1-fyqefvw5238474.gif";
    ImgPixelWrapper.build().setSourceImg(img)
            .setBlockSize(7)
            .setPixelType(PixelStyleEnum.CHAR_COLOR)
            // 生成的gif图放大为原来的两倍
            .setRate(2d)
            // 支持设置字体
            .setFontStyle(Font.BOLD)
            // 这里设置生成字符图中的字符集
            .setChars("灰")
            .build()
            .asFile(prefix + "/out3.gif");
    System.out.println("--------");
}
复制代码

image.png

最后提个小问题,gif图都能生成字符图了,那么视频也可以生成字符视频么?



相关文章
|
1月前
|
人工智能 算法 Java
第十三届蓝桥杯B组Java(试题C:字符统计)
第十三届蓝桥杯B组Java(试题C:字符统计)
60 0
|
12天前
|
JavaScript Java Android开发
在cmd中运行javac编译java文件报错: 编码GBK的不可映射字符、 非法字符: \65279
在cmd中运行javac编译java文件报错: 编码GBK的不可映射字符、 非法字符: \65279
15 1
|
2天前
|
Java Serverless
Java字符个数统计代码
Java字符个数统计代码
20 6
|
27天前
|
存储 Java
java使用pdfbox 3.0版本删除pdf文件中指定字符所在行,生成新的pdf文件
【5月更文挑战第25天】java使用pdfbox 3.0版本删除pdf文件中指定字符所在行,生成新的pdf文件
62 1
|
30天前
|
Java
Java集合类ArrayList应用 | 如何在字符串s1中删除有在字符串s2出现的字符?
这是一个关于Java编程面试题的摘要,题目要求从字符串s1中删除s2中存在的字符。解题思路包括使用ArrayList或StringBuilder实现。ArrayList实现时,遍历s1,如果字符不在s2中,则添加到ArrayList;StringBuilder实现有两种方法,一是新建StringBuilder并追加s1,然后遍历删除s2中的字符,二是直接在原地修改s1的StringBuilder对象。代码示例中展示了这些方法。
34 3
|
1月前
|
存储 缓存 Java
|
1月前
|
Java
Java正则表达式去掉非汉字字符
【5月更文挑战第11天】Java正则表达式去掉非汉字字符
37 3
|
19天前
|
Java
JAVA读取EMF文件并转化为PNG,JPG,GIF格式
JAVA读取EMF文件并转化为PNG,JPG,GIF格式
15 0
|
1月前
|
存储 Java
JAVA中String长度限制解决超出字符长度
JAVA中String长度限制解决超出字符长度
27 1
|
1月前
|
存储 Java 数据库连接
java使用mp持久化框架,写入5000个字符,但是VARCHAR(255) 会报错
使用Java的MyBatis Plus框架时,如果尝试将超过VARCHAR(255)限制的字符串(如5000个字符)存入数据库,会抛出异常。解决方法是将列类型改为TEXT。可通过在实体类属性上添加`@TableField(typeHandler = JdbcType.CLOB)`注解,如`private String content;`,将属性映射到CLOB类型列,以存储更长字符串。
20 0