Java合成图片及文字--Graphics2D

         

版权声明 :

本文为博主原创文章,如需转载,请注明出处(https://blog.csdn.net/F1004145107/article/details/84317601)

          本文包含俩部分,使用的是 java.awt.Graphics2D 

          1.生成二维码(彩色二维码,去白边)

          2.将二维码、文字合成到图片上面

          代码的逻辑都在注释里面了,如果有不懂的可以私信我,代码中的图片可以做测试,链接均可用

    public static void main(String[] args) {
        java.awt.Font font = new java.awt.Font("宋体", java.awt.Font.BOLD, 36);// 添加字体的属性设置
        InputStream is = null;
        try {
            // 图片1
            BufferedImage backImg = ImageIO.read(new URL("http://wisezhe.oss-cn-beijing.aliyuncs.com/18-11-21/87298612.jpg"));
            // 图片2
            String urlStr = "http://wisezhe.oss-cn-beijing.aliyuncs.com/18-11-21/59672258.jpg";
            URL url = new URL(urlStr);
            // 打开连接
            URLConnection con = url.openConnection();
            // 设置请求超时为5s
            con.setConnectTimeout(5 * 1000);
            // 输入流
            is = con.getInputStream();
            BufferedImage imageLocal = ImageIO.read(is);
            // 加载用户的二维码
            BufferedImage imageCode = ImageIO.read(new URL(getQrCode()));
            // 创建模板
            Graphics2D g = imageLocal.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            // 在模板上添加用户二维码(地址,左边距,上边距,图片宽度,图片高度),值都为像素
            g.drawImage(imageCode, 474, 42, 170, 170, null);
            g.setFont(font);
            // 设置刷子颜色
            g.setColor(new java.awt.Color(148, 134, 118));
            // 添加文字
            g.drawString("我是wise", 60, 129);
            // 完成模板修改
            g.dispose();
            // 合成图片
            imageLocal = PictureUtils.mergeImage(backImg, imageLocal, false, 0, 0);
            // 将图片直接生成到桌面
            File file = new File("C:\\Users\\Administrator\\Desktop\\test.jpg");
            ImageIO.write(imageLocal, "jpg", file);
            // 如果图片需要返回使用下列代码即可,上传图片并且返回图片url
//            ByteArrayOutputStream outPutStream =3 new ByteArrayOutputStream();
//            ImageIO.write(imageLocal, "jpg", outPutStream);
//            String s = UploadUtils.submitImage(id + ".jpg", outPutStream.toByteArray());
//            String key = "";
//            BaseUpImageEntity baseUpImageEntity = JacksonUtil.readValue(s, BaseUpImageEntity.class);
//            if (baseUpImageEntity != null && "0".equals(baseUpImageEntity.getHead().getRspStatusCode())) {
//                key = baseUpImageEntity.getBody().getUrl();
//            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 生成用户二维码
     *
     * @author wise
     * @return java.lang.String
     */
    private static String getQrCode() {
        // 跳转链接
        String content = "https://www.google.com/";
        ByteArrayOutputStream baos = null;
        String url = "";
        try {
            baos = new ByteArrayOutputStream();
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            Map hints = new HashMap();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, 400, 400, hints);
            // 去掉二维码的白边
            bitMatrix = updateBit(bitMatrix, 0);
            // 生成彩色二维码
            BufferedImage bufferedImage = toBufferedImage(bitMatrix);
            ByteArrayOutputStream outPutStream = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "jpg", outPutStream);
            String json = UploadUtils.submitImage("xxxxxx.jpg", outPutStream.toByteArray());
            // 如不需生成彩色二维码直接使用下面被注释掉的代码即可
//          MatrixToImageWriter.writeToStream(bitMatrix, "jpg", baos);
//          String json = UploadUtils.submitImage(id + uid + ".jpg", baos.toByteArray());
            BaseUpImageEntity baseUpImageEntity = JacksonUtil.readValue(json, BaseUpImageEntity.class);
            if (baseUpImageEntity != null && "0".equals(baseUpImageEntity.getHead().getRspStatusCode())) {
                url = baseUpImageEntity.getBody().getUrl();
            }
            return url;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (baos != null) {
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 去掉二维码的白边
     * 
     * @author wise
     * @param matrix
     * @return com.google.zxing.common.BitMatrix
     */
    public static BitMatrix updateBit(BitMatrix matrix, int margin) {
        int tempM = margin * 2;
        // 获取二维码图案的属性
        int[] rec = matrix.getEnclosingRectangle();
        int resWidth = rec[2] + tempM;
        int resHeight = rec[3] + tempM;
        // 按照自定义边框生成新的BitMatrix
        BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
        resMatrix.clear();
        // 循环,将二维码图案绘制到新的bitMatrix中
        for (int i = margin; i < resWidth - margin; i++) {
            for (int j = margin; j < resHeight - margin; j++) {
                if (matrix.get(i - margin + rec[0], j - margin + rec[1])) {
                    resMatrix.set(i, j);
                }
            }
        }
        return resMatrix;
    }

    /**  
     * 生成彩色二维码
     * 
     * @author  wise
     * @param matrix
     * @return  java.awt.image.BufferedImage
     */
    public static BufferedImage toBufferedImage(BitMatrix matrix) {
        // 背景颜色 RGB:242,241,236
        Integer backColor = 0xF2F1EC;//十六进制
        // 二维码颜色 RGB:148,134,118
        Integer qrCodeColor = 0x948676;//
        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) ? qrCodeColor : backColor);
            }
        }
        return image;
    }

         俩张图片进行合成的工具类源码

package com.shengya.service.utils;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

/**
 * @author wise
 */
public class PictureUtils {

    /**
     * @param fileUrl 文件绝对路径或相对路径
     * @return 读取到的缓存图像
     * @throws IOException 路径错误或者不存在该文件时抛出IO异常
     */
    public static BufferedImage getBufferedImage(String fileUrl) throws IOException {
        File f = new File(fileUrl);
        return ImageIO.read(f);
    }

    /**
     * @param savedImg 待保存的图像
     * @param saveDir  保存的目录
     * @param fileName 保存的文件名,必须带后缀,比如 "beauty.jpg"
     * @param format   文件格式:jpg、png或者bmp
     * @return
     */
    public static boolean saveImage(BufferedImage savedImg, String saveDir, String fileName, String format) {
        boolean flag = false;
        // 先检查保存的图片格式是否正确
        String[] legalFormats = {"jpg", "JPG", "png", "PNG", "bmp", "BMP"};
        int i = 0;
        for (i = 0; i < legalFormats.length; i++) {
            if (format.equals(legalFormats[i])) {
                break;
            }
        }
        if (i == legalFormats.length) { // 图片格式不支持
            System.out.println("不是保存所支持的图片格式!");
            return false;
        }

        // 再检查文件后缀和保存的格式是否一致
        String postfix = fileName.substring(fileName.lastIndexOf('.') + 1);
        if (!postfix.equalsIgnoreCase(format)) {
            System.out.println("待保存文件后缀和保存的格式不一致!");
            return false;
        }

        String fileUrl = saveDir + fileName;
        File file = new File(fileUrl);
        try {
            flag = ImageIO.write(savedImg, format, file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 待合并的两张图必须满足这样的前提,如果水平方向合并,则高度必须相等;如果是垂直方向合并,宽度必须相等。
     * mergeImage方法不做判断,自己判断。
     *
     * @param img1         待合并的第一张图
     * @param img2         带合并的第二张图
     * @param isHorizontal 为true时表示水平方向合并,为false时表示垂直方向合并
     * @return 返回合并后的BufferedImage对象
     * @throws IOException
     */
    public static BufferedImage mergeImage(BufferedImage img1, BufferedImage img2, boolean isHorizontal, int startX, int startY) throws IOException {
        int w1 = img1.getWidth();
        int h1 = img1.getHeight();
        int w2 = img2.getWidth();
        int h2 = img2.getHeight();

        // 从图片中读取RGB
        int[] ImageArrayOne = new int[w1 * h1];
        ImageArrayOne = img1.getRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 逐行扫描图像中各个像素的RGB到数组中
        int[] ImageArrayTwo = new int[w2 * h2];
        ImageArrayTwo = img2.getRGB(0, 0, w2, h2, ImageArrayTwo, 0, w2);

        // 生成新图片
        BufferedImage DestImage = null;
        if (isHorizontal) { // 水平方向合并
            DestImage = new BufferedImage(w1, h1, BufferedImage.TYPE_INT_RGB);
            DestImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
            DestImage.setRGB(startX, startY, w2, h2, ImageArrayTwo, 0, w2); // 设置下半部分的RGB
        } else { // 垂直方向合并
            DestImage = new BufferedImage(w1, h1 + h2, BufferedImage.TYPE_INT_RGB);
            DestImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
            DestImage.setRGB(0, h1, w2, h2, ImageArrayTwo, 0, w2); // 设置下半部分的RGB
        }
        return DestImage;
    }

}

   在只用工具类时可能会报java.lang.ArrayIndexOutOfBoundsException: Coordinate out of bounds!异常,原因是俩张图片的尺寸问题,如果进行垂直合成就必须保证俩张图片的宽度像素是一样,水平合成需保证高度像素是一样

你可能感兴趣的:(图片合成,工具)