两张图片合并生成

Posted cl-rr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了两张图片合并生成相关的知识,希望对你有一定的参考价值。

java中偶尔会出现需要将一张小图片嵌入大图中或带二维码的海报图片,那么本文就是奔着这个目的来的,直接上腊肉!

zxing是生成1D和2D条形或二维码的工具类库,java图形库Graphics2D进行图片的合成。

依赖:

<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.3.3</version>
</dependency>

 

代码:
以下为合成图片和二维码,合成2张图片参看第一个方法注释掉的代码
 

/*
 * overlapImage
 * @description:合成二维码和图片为文件
 * @author 李阳
 * @date 2018/12/13
 * @params [backPicPath, code]
 * @return void
 */
public static final void combineCodeAndPicToFile(String backPicPath, BufferedImage code/*String fillPicPath*/) {
    try {
        BufferedImage big = ImageIO.read(new File(backPicPath));
        BufferedImage small = code;
        /*//合成两个文件时使用
        BufferedImage small = ImageIO.read(new File(fillPicPath));*/
        Graphics2D g = big.createGraphics();

        //二维码或小图在大图的左上角坐标
        int x = (big.getWidth() - small.getWidth()) / 2;
        // int y = (big.getHeight() - small.getHeight()) / 2;
        int y = (big.getHeight() - small.getHeight() - 100);
        g.drawImage(small, x, y, small.getWidth(), small.getHeight(), null);
        g.dispose();
        //为了保证大图背景不变色,formatName必须为"png"
        ImageIO.write(big, "png", new File("C:/Users/kevin/Desktop/combinePic.jpg"));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/* 
 * combineCodeAndPicToInputstream
 * @description:合成二维码和图片为输出流,可用于下载或直接展示
 * @author 李阳
 * @date 2018/12/13
 * @params [backPicPath, code]
 * @return java.io.InputStream
 */
public static final void combineCodeAndPicToInputstream(String backPicPath, BufferedImage code, HttpServletResponse resp) {
    try {
        BufferedImage big = ImageIO.read(new File(backPicPath));
        // BufferedImage small = ImageIO.read(new File(fillPicPath));
        BufferedImage small = code;
        Graphics2D g = big.createGraphics();

        //二维码或小图在大图的左上角坐标
        int x = (big.getWidth() - small.getWidth()) / 2;
        int y = (big.getHeight() - small.getHeight() - 100);   //二维码距大图下边距100
        g.drawImage(small, x, y, small.getWidth(), small.getHeight(), null);
        g.dispose();
        resp.addHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode("lia阿里.png","UTF-8") );//去掉这行设置header的代码,前端访问可以直接展示
        //为了保证大图背景不变色,formatName必须为"png"
        ImageIO.write(big, "png", resp.getOutputStream());
    } catch (Exception e) {
        e.printStackTrace();
    }
}
/* 
 * combineCodeAndPicToBase64 
 * @description:合成二维码和图片为Base64,同样可用于直接展示
 * @author 李阳
 * @date 2018/12/14
 * @params [backPicPath, code]
 * @return java.lang.String
 */
public static final String combineCodeAndPicToBase64(String backPicPath, BufferedImage code) {
    ImageOutputStream imOut = null;
    try {
        BufferedImage big = ImageIO.read(new File(backPicPath));
        // BufferedImage small = ImageIO.read(new File(fillPicPath));
        BufferedImage small = code;
        Graphics2D g = big.createGraphics();

        //二维码或小图在大图的左上角坐标
        int x = (big.getWidth() - small.getWidth()) / 2;
        int y = (big.getHeight() - small.getHeight() - 100);
        g.drawImage(small, x, y, small.getWidth(), small.getHeight(), null);
        g.dispose();
        //为了保证大图背景不变色,formatName必须为"png"

        ByteArrayOutputStream bs = new ByteArrayOutputStream();
        imOut = ImageIO.createImageOutputStream(bs);
        ImageIO.write(big, "png", imOut);
        InputStream in = new ByteArrayInputStream(bs.toByteArray());

        byte[] bytes = new byte[in.available()];
        in.read(bytes);
        String base64 = Base64.getEncoder().encodeToString(bytes);
        System.out.println(base64);

        return "data:image/jpeg;base64," + base64;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

/* 
 * createImage 
 * @description:生成二维码
 * @author 李阳
 * @date 2018/12/13
 * @params [content 二维码内容, logoImgPath 中间logo, needCompress 是否压缩]
 * @return java.awt.image.BufferedImage
 */
private static BufferedImage createImage(String content, String logoImgPath, boolean needCompress) throws IOException, WriterException {
    Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
    hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
    hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
    hints.put(EncodeHintType.MARGIN, 1);
    //200是定义的二维码或小图片的大小
    BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, 200, 200, hints);
    int width = bitMatrix.getWidth();
    int height = bitMatrix.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, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
        }
    }
    // 没有logo
    if (logoImgPath == null || "".equals(logoImgPath)) {
        return image;
    }

    // 插入logo
    insertImage(image, logoImgPath, needCompress);
    return image;
}

/* 
 * insertImage 
 * @description:二维码插入logo
 * @author 李阳
 * @date 2018/12/13
 * @params [source, logoImgPath, needCompress]
 * @return void
 */
private static void insertImage(BufferedImage source, String logoImgPath, boolean needCompress) throws IOException {
    File file = new File(logoImgPath);
    if (!file.exists()) {
        return;
    }

    Image src = ImageIO.read(new File(logoImgPath));
    int width = src.getWidth(null);
    int height = src.getHeight(null);
    //处理logo
    if (needCompress) {
        if (width > WIDTH) {
            width = WIDTH;
        }

        if (height > HEIGHT) {
            height = HEIGHT;
        }

        Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
        BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics gMaker = tag.getGraphics();
        gMaker.drawImage(image, 0, 0, null); // 绘制缩小后的图
        gMaker.dispose();
        src = image;
    }

    // 在中心位置插入logo
    Graphics2D graph = source.createGraphics();
    int x = (200 - width) / 2;
    int y = (200 - height) / 2;
    graph.drawImage(src, x, y, width, height, null);
    Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
    graph.setStroke(new BasicStroke(3f));
    graph.draw(shape);
    graph.dispose();
}

public static final void main(String[] args) throws IOException, WriterException {
    BufferedImage code = createImage("https://my.oschina.net/kevin2kelly", null, false);
    combineCodeAndPicToFile("C:/Users/kevin/Desktop/无标题.png", code);
    combineCodeAndPicToBase64("C:/Users/kevin/Desktop/无标题.png", code);
}

 

自己的代码:

技术图片
package com.lingouu.tools.picutre;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.lingouu.exception.NormalException;
import com.lingouu.tools.oss.iossService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Hashtable;

import static org.apache.catalina.manager.Constants.CHARSET;

@Component
@Slf4j
public class PictureUtils {

    public static void combineCodeAndPic(String backPicPath, String codePath, HttpServletResponse resp) {
        BufferedImage backPic = null;
        BufferedImage code = null;
        try {
            code = ImageIO.read(new URL(codePath));
            backPic = ImageIO.read(new URL(backPicPath));
        } catch (IOException e) {
            log.error("分享图生成失败", e);
        }
        combineCodeAndPic(backPic, code, resp);
    }

    public static void generateCodeAndPic(String backPicPath, String pathUrl, HttpServletResponse resp){
        BufferedImage backPic = null;
        BufferedImage code = null;
        try {
            backPic = ImageIO.read(new URL(backPicPath));
            code = createCode(pathUrl);
        } catch (Exception e) {
            log.error("分享图生成失败", e);
        }
        combineCodeAndPic(backPic, code, resp);
    }

    private static void combineCodeAndPic(BufferedImage backPic, BufferedImage code, HttpServletResponse resp) {
        try {
            Graphics2D g = backPic.createGraphics();
            //二维码或小图在大图的左上角坐标
            int x = (backPic.getWidth() - code.getWidth() / 2) / 2;
            int y = (backPic.getHeight() - code.getHeight() / 2 - 100);   //二维码距大图下边距100
            g.drawImage(code, x, y, code.getWidth() / 2, code.getHeight() / 2, null);
            g.dispose();
            resp.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("back.png", "UTF-8"));//去掉这行设置header的代码,前端访问可以直接展示
            ImageIO.write(backPic, "png", resp.getOutputStream());
        } catch (Exception e) {
            log.error("分享图生成失败", e);
        }
    }

    /*
     * @description:生成二维码
     * @params [content 二维码内容, needCompress 是否压缩]
     * @return java.awt.image.BufferedImage
     */
    private static BufferedImage createCode(String content) throws IOException, WriterException {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        hints.put(EncodeHintType.MARGIN, 1);
        //200是定义的二维码或小图片的大小
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, 430, 430, hints);
        int width = bitMatrix.getWidth();
        int height = bitMatrix.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, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        return image;
    }
}
View Code

 

填充图片:
技术图片

背景图和合成图片:
图一为原始背景图,第二图为base64在浏览器访问效果,三为2张图合成,四图为图片和二维码合成。
技术图片

 

参考:
http://www.zhaochengquan.com/2018/03/29/%E5%9F%BA%E4%BA%8EZXing%E7%9A%84%E4%BA%8C%E7%BB%B4%E7%A0%81%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90%E4%B8%8E%E5%9B%BE%E7%89%87%E5%90%88%E6%88%90/

https://blog.csdn.net/qq_35971258/article/details/80593500

以上是关于两张图片合并生成的主要内容,如果未能解决你的问题,请参考以下文章

图片怎么合并在一起 怎么将两张图片合并在一起

//--合并两张图片 BITMAP

opencv 怎么把两张图片合并到一起?

合并两张图片模拟服装店

WPF 通过位处理合并图片

UESTC - 1599