java图片合成

 以下代码是java合成图片的工具类,只需要将图片名称以注释中的格式命名,然后将两个常量路径改成自己的本地路径即可。

package com.util;

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Set;

import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageOutputStream;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;

/**
 * 身份证正反面照片合成到一张图片上,正面上反面下<BR>
 *
 * 图片命名有规范,具体要求如下:<BR>
 * 1.正面:姓名-身份证号-身份证正面.png,如:曾**-3603************409x-身份证正面.png<BR>
 * 2.反面:姓名-身份证号-身份证背面.png,如:曾**-3603************409x-身份证背面.png<BR>
 *
 * 所有需要合成的源图片放在SOURCE目录下,SOURCE可自定义<BR>
 * 所有合成后的图片放在TARGET目录下,TARGET可自定义<BR>
 *
 * @title PictureSynthesisUtil
 * @author lvgb
 * @date 2019年7月4日
 */
public class PictureSynthesisUtil {

    private static Logger LOGGER = LogManager.getLogger(PictureSynthesisUtil.class);
    /**
     * 合成前图片存放目录
     */
    private static final String SOURCE = "D:\\test\\身份证\\";
    /**
     * 合成后图片存放目录
     */
    private static final String TARGET = "D:\\test\\合成\\";

    /**
     *
     * 图像合并bytes [图片类型]
     *
     * @param prosPath
     *            第一张图片路径
     *
     * @param consPath
     *            第二张图片路径
     *
     * @return
     *
     */
    public static byte[] imageMergeToBytes(String prosPath, String consPath) {

        LOGGER.info("prosFile:" + prosPath + ";consFile:" + consPath);

        byte[] bytes = null;

        try {

            // 读取待合并的文件

            BufferedImage prosImg = ImageIO.read(new File(prosPath));

            BufferedImage consImg = ImageIO.read(new File(consPath));

            // 图像压缩

            prosImg = resize(prosImg, 1000, 1000, true);

            consImg = resize(consImg, 1000, 1000, true);

            // 合并后图像

            BufferedImage mergeImg = mergeImage(prosImg, consImg, false);

            // 压缩 后大概100K-300K

            mergeImg = resize(mergeImg, 1000, 1000, false);

            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            ImageIO.write(mergeImg, "jpg", baos);

            bytes = baos.toByteArray();

            baos.close();

        } catch (IOException e) {

            LOGGER.error("[图像合并bytes]异常", e);

            //

        }

        return bytes;

    }

    /**
     *
     * 图像合并bytes [.dat类型]
     *
     * @param prosPath
     *            第一张图片路径
     *
     * @param consPath
     *            第二张图片路径
     *
     * @return
     *
     */

    public static byte[] imageMergeToBytes2(String prosPath, String consPath)

            throws Exception {

        LOGGER.info("prosPath:" + prosPath + ";consPath:" + consPath);

        // 读取待合并的文件

        BufferedImage bi1 = null;

        BufferedImage bi2 = null;

        // 调用mergeImage方法获得合并后的图像

        BufferedImage destImg = null;

        byte[] bytes = null;

        try {

            // 读取图片的base64String

            String prosString = readFile2String(prosPath, "");

            String consString = readFile2String(consPath, "");

            bi1 = getBufferedImage(prosString);

            bi1 = resize(bi1, 1000, 1000, true);

            bi2 = getBufferedImage(consString);

            bi2 = resize(bi2, 1000, 1000, true);

            // 合成

            destImg = mergeImage(bi1, bi2, false);

            // 压缩 后大概100K-300K

            destImg = resize(destImg, 1000, 1000, false);

            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            ImageIO.write(destImg, "jpg", baos);

            bytes = baos.toByteArray();

        } catch (IOException e) {

            LOGGER.error("[图像合并bytes2]异常", e);

        }

        return bytes;

    }

    /**
     *
     * @param base64string
     *
     *            图片base64编码
     *
     * @return 读取到的缓存图像
     *
     * @throws IOException
     *
     *             路径错误或者不存在该文件时抛出IO异常
     *
     */

    private static BufferedImage getBufferedImage(String base64string)

            throws IOException {

        InputStream stream = BaseToInputStream(base64string);

        return ImageIO.read(stream);

    }

    private static InputStream BaseToInputStream(String base64string)

            throws IOException {

        ByteArrayInputStream stream = null;

        byte[] bytes1 = Base64.decodeBase64(base64string.getBytes());

        stream = new ByteArrayInputStream(bytes1);

        return stream;

    }

    /**
     *
     * @param fileName
     *
     * @param encoding
     *
     *            编码类型
     *
     * @return 转换后的字符串
     *
     */

    public static String readFile2String(String fileName, String encoding) {

        InputStreamReader reader = null;

        StringWriter writer = new StringWriter();

        try {

            File file = new File(fileName);

            if (encoding != null && !"".equals(encoding.trim())) {

                reader = new InputStreamReader(new FileInputStream(file),

                        encoding);

            } else {

                reader = new InputStreamReader(new FileInputStream(file));

            }

            char[] buffer = new char[8 * 1024];

            int n = 0;

            while (-1 != (n = reader.read(buffer))) {

                writer.write(buffer, 0, n);

            }

            reader.close();

            writer.close();

        } catch (FileNotFoundException e) {

        } catch (IOException e) {

        } finally {

            if (reader != null) {

                try {

                    reader.close();

                } catch (IOException e) {

                }

            }

            if (writer != null) {

                try {

                    writer.close();

                } catch (IOException e) {

                }

            }

        }

        if (writer != null) {

            return writer.toString();

        } else {

            return null;

        }

    }

    /**
     *
     * 免冠照
     *
     * @return
     *
     */

    public static byte[] mgImage(String path) {

        LOGGER.info("path:" + path);

        byte[] bytes = null;

        try {

            // 读取待合并的文件

            BufferedImage mgImg = ImageIO.read(new File(path));

            // 图像压缩

            mgImg = resize(mgImg, 1000, 1000, true);

            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            ImageIO.write(mgImg, "jpg", baos);

            bytes = baos.toByteArray();

            baos.close();

        } catch (IOException e) {

            LOGGER.error("[获取免冠照bytes]异常", e);

        }

        return bytes;

    }

    /**
     *
     * 获取免冠照
     *
     * @param mgImage
     *
     * @return
     *
     */

    public static String mgImageToString(String mgImage) {

        byte[] bytes = mgImage(mgImage);

        return Base64.encodeBase64String(bytes);

    }

    /**
     *
     * 图像合并String [图片类型]
     *
     * @param prosPath
     *            第一张图片路径
     *
     * @param consPath
     *            第二张图片路径
     *
     * @return
     *
     */

    public static String imageMergeToString(String prosPath, String consPath) {

        byte[] bytes = imageMergeToBytes(prosPath, consPath);

        return Base64.encodeBase64String(bytes);

    }

    /**
     *
     * 图像合并String [.dat类型]
     *
     * @param prosPath
     *            第一张图片路径
     *
     * @param consPath
     *            第二张图片路径
     *
     * @return
     *
     */

    public static String imageMergeToString2(String prosPath, String consPath) {

        byte[] bytes = null;

        try {

            bytes = imageMergeToBytes2(prosPath, consPath);

        } catch (Exception e) {

            LOGGER.error("[imageMergeToString2]异常", e);

        }

        return Base64.encodeBase64String(bytes);

    }

    /**
     *
     * 压缩图片
     *
     */

    private static BufferedImage resize(BufferedImage source, int targetW, int targetH, boolean isRotate) {

        // targetW,targetH分别表示目标长和宽

        int type = source.getType();

        BufferedImage target = null;

        int width = source.getWidth();

        int height = source.getHeight();

        // 图片宽度小于高度 需要 则调整 宽高 值

        if (width < height && isRotate) {

            width = height;

            height = source.getWidth();

        }

        double sx = (double) targetW / width;

        double sy = (double) targetH / height;

        // 这里想实现在targetW,targetH范围内实现等比缩放

        if (sx > sy) {

            sx = sy;

            targetW = (int) (sx * source.getWidth());

        } else {

            sy = sx;

            targetH = (int) (sy * source.getHeight());

        }

        if (type == BufferedImage.TYPE_CUSTOM) {

            ColorModel cm = source.getColorModel();

            WritableRaster raster = cm.createCompatibleWritableRaster(targetW,

                    targetH);

            boolean alphaPremultiplied = cm.isAlphaPremultiplied();

            target = new BufferedImage(cm, raster, alphaPremultiplied, null);

        } else {

            target = new BufferedImage(targetW, targetH, type);

        }

        Graphics2D g = target.createGraphics();

        // smoother than exlax:

        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

        g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));

        g.dispose();

        return target;

    }

    /**
     *
     * 待合并的两张图必须满足这样的前提,如果水平方向合并,则高度必须相等;如果是垂直方向合并,宽度必须相等。
     *
     * mergeImage方法不做判断,自己判断。
     *
     *
     *
     * @param img1
     *
     *            待合并的第一张图
     *
     * @param img2
     *
     *            带合并的第二张图
     *
     * @param isHorizontal
     *
     *            为true时表示水平方向合并,为false时表示垂直方向合并
     *
     * @return 返回合并后的BufferedImage对象
     *
     * @throws IOException
     *
     */

    private static BufferedImage mergeImage(BufferedImage img1, BufferedImage img2, boolean isHorizontal)
            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];

        // 逐行扫描图像中各个像素的RGB到数组中

        ImageArrayOne = img1.getRGB(0, 0, w1, h1, ImageArrayOne, 0, w1);

        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 + w2, h1, BufferedImage.TYPE_INT_RGB);

            // 设置上半部分或左半部分的RGB

            destImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1);

            destImage.setRGB(w1, 0, w2, h2, ImageArrayTwo, 0, w2);

        } else { // 垂直方向合并

            destImage = new BufferedImage(w1, h1 + h2, BufferedImage.TYPE_INT_RGB);

            // 设置上半部分或左半部分的RGB

            destImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1);

            // 设置下半部分的RGB

            destImage.setRGB(0, h1, w2, h2, ImageArrayTwo, 0, w2);

        }

        return destImage;

    }

    public static void main(String[] args) throws Exception {
        File[] files = new File(SOURCE).listFiles();
        Set<String> successSet = new HashSet<String>();
        Set<String> failSet = new HashSet<String>();
        // 先清空目标文件夹里面的内容
        FileUtils.cleanDirectory(new File(TARGET));
        // 合成图片到目标文件夹
        for (File file : files) {
            String fileName = file.getName();
            String name = fileName.substring(0, fileName.lastIndexOf("-"));
            if (successSet.add(name)) {
                System.out.println(name);
                try {
                    byte[] imgStr = imageMergeToBytes(SOURCE + name + "-身份证正面.png", SOURCE + name + "-身份证背面.png");

                    byte2image(imgStr, TARGET + name + ".png");
                } catch (Exception e) {
                    failSet.add(name);
                }
            }
        }
        System.out.println();
        if (successSet.size() * 2 == files.length) {
            System.out.println("全部处理成功..........................");
        } else {
            System.out.println("部分失败,失败名单如下:");
            JSON.toJSONString(failSet);
            System.out.println("失败原因大部分是命名不够规范,仔细核对一下即可");
        }
    }

    // byte数组到图片
    public static void byte2image(byte[] data, String path) {
        if (data.length < 3 || path.equals(""))
            return;
        try {
            FileImageOutputStream imageOutput = new FileImageOutputStream(new File(path));
            imageOutput.write(data, 0, data.length);
            imageOutput.close();
            System.out.println("Make Picture success,Please find image in " + path);
        } catch (Exception ex) {
            System.out.println("Exception: " + ex);
            ex.printStackTrace();
        }
    }

}


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值