多张图片拼接成长图

今天做小程序时遇到一个问题,分享长图。由于某些原因,前端做不了,于是我在后台提供了一个接口来生成长图。 主要用到的类java.awt.image.BufferedImage。在拼接图片过程中需要考虑的问题:

1.图片张数的不同,对拼接后图片的影响
2.图片大小尺寸的不同,造成拼接后的图片参差不齐的问题

第一个问题,需要循环增加拼接图片的长度(一般做纵向拼接)。针对第二个问题,使用了Thumbnails来解决,将所有图片压缩成同等大小尺寸的图片,这样拼接后图片就不会参差不齐,但是还是有失真的风险,自己把握好尺寸大小和压缩比例。Thumbnails是由谷歌提供的图片处理包,目前版本0.4.8。 可以简洁的实现图片的缩放、压缩、旋转、水印、格式转换等操作。 使用Thumbnails很简单,项目中引入maven依赖

<dependency>

    <groupId>net.coobird</groupId>

    <artifactId>thumbnailator</artifactId>

    <version>0.4.8</version>

</dependency>

以下是一个测试类

public class MergedImages {

    /**
     * 将多张图片拼接成一张长图
     *
     * @param strings 原图文件地址或url地址
     * @param type    类型,1-文件地址;2-url地址
     * @return 拼接后的图片BufferedImage
     */
    public static BufferedImage moreToOne(String[] strings, Integer type) {
        //传入图片少于1张直接返回
        int len = strings.length;
        if (len < 1) {
            return null;
        }
        //使用一个数组将图片装起来
        BufferedImage[] bufferedImages = new BufferedImage[len];
        int[][] imageArrays = new int[len][];
        for (int i = 0; i < len; i++) {
            try {
                if (type == 1) {
                    //文件地址,可直接转换
                    bufferedImages[i] = Thumbnails.of(strings[i])
                            .size(400, 600)
                            .outputQuality(0.8f)
                            .asBufferedImage();
                }
                if (type == 2) {
                    //url地址,需要先将图片获取
                    URL url = new URL(strings[i]);
                    //openStream通过url地址获取图片流
                    BufferedInputStream in = new BufferedInputStream(url.openStream());
                    bufferedImages[i] = Thumbnails.of(in)
                            .size(400, 600)
                            .outputQuality(0.8f)
                            .asBufferedImage();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //获取图片宽高
            int width = bufferedImages[i].getWidth();
            int height = bufferedImages[i].getHeight();
            // 从图片中读取RGB
            imageArrays[i] = new int[width * height];
            imageArrays[i] = bufferedImages[i].getRGB(0, 0, width, height,
                    imageArrays[i], 0, width);
        }
        //拼接图片的宽高
        int dstHeight = 0;
        int dstWidth = bufferedImages[0].getWidth();
        for (BufferedImage bufferedImage : bufferedImages) {
            dstWidth = Math.max(dstWidth, bufferedImage.getWidth());
            dstHeight += bufferedImage.getHeight();
        }
        // 生成新图片
        BufferedImage imageNew = null;
        try {
            imageNew = new BufferedImage(dstWidth, dstHeight, BufferedImage.TYPE_INT_RGB);
            int newHeight = 0;
            for (int i = 0; i < bufferedImages.length; i++) {
                imageNew.setRGB(0, newHeight, dstWidth, bufferedImages[i].getHeight(), imageArrays[i], 0, dstWidth);
                newHeight += bufferedImages[i].getHeight();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return imageNew;
    }

    /**
     * 将图片转为base64输出
     *
     * @param strings 原图文件地址或url地址
     * @param type    类型,1-文件地址;2-url地址
     * @return 图片的base64编码
     */
    public static String outBase64(String[] strings, Integer type) {
        BufferedImage bufferedImage = moreToOne(strings, type);
        //输出流
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        String base64 = null;
        try {
            if (bufferedImage == null) {
                return null;
            }
            ImageIO.write(bufferedImage, "jpg", stream);
            base64 = Base64.getEncoder().encodeToString(stream.toByteArray());
            stream.flush();
            stream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "data:image/jpg;base64," + base64;
    }

    /**
     * 将图片保存到指定目录地址
     *
     * @param strings  原图文件地址或url地址
     * @param type     类型,1-文件地址;2-url地址
     * @param savePath 文件保存地址
     */
    public static void saveFile(String[] strings, Integer type, String savePath) {
        BufferedImage bufferedImage = moreToOne(strings, type);
        int temp = savePath.lastIndexOf(".") + 1;
        try {
            File outFile = new File(savePath);
            if (!outFile.exists()) {
                boolean newFile = outFile.createNewFile();
                if (newFile && bufferedImage != null) {
                    ImageIO.write(bufferedImage, savePath.substring(temp), outFile);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        String s1 = "http://127.0.0.1/2/20210906115946680612W1jqbAI263038f250a2e940dd0abd0559ac4badde.jpg";
        String s2 = "http://127.0.0.1/5/20210907094432105txYYoNmBefR20e33abc8e586913615d4de6fe7f1b219.jpg";
        String s3 = "http://127.0.0.1/5/20210907094551897QOYKyB55Kufq646356585f44a0158db1e117289a71c4.jpg";
        String s11 = "C:\\Users\\Administrator\\Pictures\\1.jpg";
        String s22 = "C:\\Users\\Administrator\\Pictures\\2.jpg";
        String s33 = "C:\\Users\\Administrator\\Pictures\\3.jpg";
        String saveFilePath = "C:\\Users\\Administrator\\Pictures\\overlyingImageNew.jpg";

        //输出base64
        String[] strings = {s1, s2, s3};
        System.out.println(outBase64(strings, 2));
        //写文件到指定目录
        String[] string2 = {s11, s22, s33};
        saveFile(string2, 1, saveFilePath);
    }
}

简单记录一下,方便后续自己使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值