首页> 博客> java图像合并之身份证正反面合成图片
已注销用户的gravatar头像
已注销用户 2018-04-25 10:07:20
java图像合并之身份证正反面合成图片

背景

上个项目,看见有个需求:需要把身份证的正面和反面合成一张图片,以便相关人员的审核,这里就分享对应的代码。

 

操作步骤

先从百度图片里面,下载两张图片,一张身份证正面,一张身份证反面

 

然后运行代码,即可获得一张正反面的身份证图片

 

举个栗子:

这是 正面

java图像合并之身份证正反面合成图片

 

这是反面

java图像合并之身份证正反面合成图片

 

合成的结果图:

java图像合并之身份证正反面合成图片

 

目的 简单明了,不用多说了,接下来看代码

package com.essence.util;

import org.apache.commons.codec.binary.Base64;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.*;

/**
 * 图像合并
 */
public class ImageMergeUtil {

	private static Logger LOGGER = LogManager.getLogger(ImageMergeUtil.class);


	/**
	 * 图像合并bytes [图片类型]
	 * @param prosPath 第一张图片路径
	 * @param consPath 第二张图片路径
	 * @return
	 */
	public static byte[] imageMergeToBytes(String prosPath, String consPath) {
		LOGGER.info("prosFile:" + prosPath + ";consFile:" + consPath);
		byte[] bytes;
		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);
			throw new BizException(e.getMessage(),e);
		}
		return bytes;
	}

	/**
	 * 图像合并bytes [.dat类型]
	 * @param prosPath 第一张图片路径
	 * @param consPath 第二张图片路径
	 * @return
	 */
	public static byte[] imageMergeToBytes2(String prosPath, String consPath)
			throws EsServiceException {
		LOGGER.info("prosPath:" + prosPath + ";consPath:" + consPath);
		// 读取待合并的文件
		BufferedImage bi1 = null;
		BufferedImage bi2 = null;
		// 调用mergeImage方法获得合并后的图像
		BufferedImage destImg = null;
		String imgStr = "";
		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);
			throw new BizException(e.getMessage(),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) {
			throw new BizException(e.getMessage(),e);
		} catch (IOException e) {
			throw new BizException(e.getMessage(),e);
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					throw new BizException(e.getMessage(),e);
				}
			}
			if (writer != null) {
				try {
					writer.close();
				} catch (IOException e) {
					throw new BizException(e.getMessage(),e);
				}
			}
		}
		if (writer != null) {
			return writer.toString();
		} else {
			return null;
		}
	}

	/**
	 * 免冠照
	 * @return
	 */
	public static byte[] mgImage(String path) {
		LOGGER.info("path:" + path);
		byte[] bytes;
		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);
			throw new BizException(e.getMessage(),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;
		try {
			bytes = imageMergeToBytes2(prosPath, consPath);
		} catch (EsServiceException e) {
			LOGGER.error("[imageMergeToString2]异常", e);
			throw new BizException(e.getMessage(),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 {
		byte[] imgStr = ImageMergeUtil.imageMergeToBytes("E:\\1.png", "E:\\2.png");
		ImageUploadUtil.buff2Image(imgStr,"E:\\sfz.jpg");

		System.out.println("成功..........................");
	}
}

 

就这个工具类,有需要的直接就 copy 即可,里面有异常语句直接去掉,类似这样的 

throw new BizException(e.getMessage(),e);

 

有需要的自行研究吧! 

工作中的代码记录...


打赏

已有4人打赏

LH8826的gravatar头像 shadow小影的gravatar头像 故事_sun的gravatar头像 最代码官方的gravatar头像
最代码博客评论总数 16个评论
最近浏览
reginx100  LV1 2022年2月28日
星星
LikL9420  LV12 2021年7月23日
月亮 月亮 月亮
1910034830 2021年7月6日
暂无贡献等级
潜水D猴子  LV2 2021年5月20日
星星 星星
AAA153759  LV4 2020年7月16日
月亮
wkc  LV21 2020年6月28日
太阳 月亮 星星
Tomcat80  LV5 2020年3月6日
月亮 星星
有人说我公主有病 2020年1月18日
暂无贡献等级
java学者wz 2019年11月30日
暂无贡献等级
栗劲松  LV2 2019年11月26日
星星 星星
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友

国外留学毕业证书制作公司长春办理国外留学生学位证南昌国外博士毕业证代办贵阳海外文凭毕业证定做大连代办海外学位南京海外文凭毕业证定制南京办海外文凭证书代做大连做国外学历证补办办理国外毕业证代做上海国外留学文凭定做兰州代办海外证件代做太原办理国外文凭办理南宁补办海外留学文凭制作石家庄办理海外留学文凭济南做国外学历文凭办理贵阳做国外学位证书代做哈尔滨定做海外学历定制天津补办海外学位制作武汉制作国外学历文凭制作珠海定做海外文凭证书定制上海定做海外证件代做北京国外留学文凭代做福州代做国外学位证制作广州补办国外文凭证书代做福州做国外学历文凭代办兰州做国外留学学位证办理成都定做海外留学毕业证制作广州代办国外学位定做重庆办理海外学位证书西宁定做海外文凭哈尔滨代做国外本科毕业证办理淀粉肠小王子日销售额涨超10倍罗斯否认插足凯特王妃婚姻让美丽中国“从细节出发”清明节放假3天调休1天男孩疑遭霸凌 家长讨说法被踢出群国产伟哥去年销售近13亿网友建议重庆地铁不准乘客携带菜筐雅江山火三名扑火人员牺牲系谣言代拍被何赛飞拿着魔杖追着打月嫂回应掌掴婴儿是在赶虫子山西高速一大巴发生事故 已致13死高中生被打伤下体休学 邯郸通报李梦为奥运任务婉拒WNBA邀请19岁小伙救下5人后溺亡 多方发声王树国3次鞠躬告别西交大师生单亲妈妈陷入热恋 14岁儿子报警315晚会后胖东来又人满为患了倪萍分享减重40斤方法王楚钦登顶三项第一今日春分两大学生合买彩票中奖一人不认账张家界的山上“长”满了韩国人?周杰伦一审败诉网易房客欠租失踪 房东直发愁男子持台球杆殴打2名女店员被抓男子被猫抓伤后确诊“猫抓病”“重生之我在北大当嫡校长”槽头肉企业被曝光前生意红火男孩8年未见母亲被告知被遗忘恒大被罚41.75亿到底怎么缴网友洛杉矶偶遇贾玲杨倩无缘巴黎奥运张立群任西安交通大学校长黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发妈妈回应孩子在校撞护栏坠楼考生莫言也上北大硕士复试名单了韩国首次吊销离岗医生执照奥巴马现身唐宁街 黑色着装引猜测沈阳一轿车冲入人行道致3死2伤阿根廷将发行1万与2万面值的纸币外国人感慨凌晨的中国很安全男子被流浪猫绊倒 投喂者赔24万手机成瘾是影响睡眠质量重要因素春分“立蛋”成功率更高?胖东来员工每周单休无小长假“开封王婆”爆火:促成四五十对专家建议不必谈骨泥色变浙江一高校内汽车冲撞行人 多人受伤许家印被限制高消费

国外留学毕业证书制作公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化