最代码伊成的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);

 

有需要的自行研究吧! 

工作中的代码记录...


打赏

已有2人打赏

ldd888的gravatar头像最代码官方的gravatar头像

分享到:

最近浏览
chennan1 LV28月15日
星星星星
pridof8月9日
暂无贡献等级
GuangBiao LV88月9日
月亮月亮
b2code LV18月6日
星星
最代码-泽正 LV118月6日
月亮月亮星星星星星星
hankoufenxiao LV38月3日
星星星星星星
看看9855 LV28月2日
星星星星
S_Bility LV187月31日
太阳星星星星
zq671366 LV147月31日
月亮月亮月亮星星星星
空中飞尘 LV127月28日
月亮月亮月亮
顶部客服微信二维码底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友