利用Java实现了任意两张图片的垂直方向拼接,不限制大小类型,可直接用于生产。
实现任意两张图片的垂直方向拼接,对于过小图片实现了放大,保证了图片拼接后的清晰度。
对于高度大于宽度的图片,进行了-90度旋转。
java
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
//垂直方向合并图片
public class ImageMerge {
/**
* 1比较2张图片的大小,以2张图片的最大边长为宽,以第二边长为高,构造2张空图片
* 2选择第一张图片,若宽小于于高,旋转-90度,粘贴到第一张空图片上
* 3选择第二张图片,若宽小于于高,旋转-90度,粘贴到第二张空图片上
*
* @param img1 待合并的第一张图
* @param img2 带合并的第二张图
* @return 返回合并后的BufferedImage对象
* @throws IOException
*/
public static BufferedImage mergeImage(BufferedImage img1, BufferedImage img2) throws IOException {
//判断是否需要放大图片
if (Math.max(img1.getWidth(), img1.getHeight()) > Math.max(img2.getWidth(), img2.getHeight())) {
img2 = judgeIfNeedChangeImageSize(img1, img2);
} else {
img1 = judgeIfNeedChangeImageSize(img1, img2);
}
//获取背景图片宽高
int w1 = img1.getWidth();
int h1 = img1.getHeight();
int w2 = img2.getWidth();
int h2 = img2.getHeight();
List<Integer> list = Arrays.asList(w1, w2, h1, h2);
list.sort((v1, v2) -> v2 - v1);
int maxWidth = list.get(0);
int maxHeight = list.get(1);
int[] backgroundImage = new int[maxWidth * maxHeight];
//设置背景图片数据
for (int i = 0; i < backgroundImage.length; i++) {
backgroundImage[i] = -1;
}
//绘制背景图片
BufferedImage createImage = new BufferedImage(maxWidth, maxHeight << 1, BufferedImage.TYPE_INT_RGB);
createImage.setRGB(0, 0, maxWidth, maxHeight, backgroundImage, 0, maxWidth);
createImage.setRGB(0, maxHeight, maxWidth, maxHeight, backgroundImage, 0, maxWidth);
//准备图片一绘制数据
int[] imageArrayOne = new int[w1 * h1];
imageArrayOne = img1.getRGB(0, 0, w1, h1, imageArrayOne, 0, w1);
if (w1 < h1) {
rotateImage(w1, h1, imageArrayOne);
int temp = w1;
w1 = h1;
h1 = temp;
}
//计算绘图位置,尽量居中
int startX;
int startY;
startX = (maxWidth - w1) >> 1;
startY = (maxHeight - h1) >> 1;
//在背景图片上绘制图片
createImage.setRGB(startX, startY, w1, h1, imageArrayOne, 0, w1);
//准备图片一绘制数据
int[] imageArrayTwo = new int[w2 * h2];
imageArrayTwo = img2.getRGB(0, 0, w2, h2, imageArrayTwo, 0, w2);
if (w2 < h2) {
rotateImage(w2, h2, imageArrayTwo);
int temp = w2;
w2 = h2;
h2 = temp;
}
//计算绘图位置,尽量居中
startX = (maxWidth - w2) >> 1;
startY = (maxHeight - h2) >> 1;
//准备图片二绘制数据
createImage.setRGB(startX, maxHeight + startY, w2, h2, imageArrayTwo, 0, w2);
return createImage;
}
private static BufferedImage judgeIfNeedChangeImageSize(BufferedImage img1, BufferedImage img2) {
int w1 = img1.getWidth();
int h1 = img1.getHeight();
int w2 = img2.getWidth();
int h2 = img2.getHeight();
int max1 = Math.max(w1, h1);
int max2 = Math.max(w2, h2);
if (max1 < max2) {
return enlargementImage(img1, w1, h1, max1, max2);
} else {
return enlargementImage(img2, w2, h2, max2, max1);
}
}
private static BufferedImage enlargementImage(BufferedImage srcImg, int w1, int h1, int max1, int max2) {
while (max2 / max1 >= 2) {
max1 *= 2;
w1 *= 2;
h1 *= 2;
}
// 放大边长
BufferedImage resultImg = new BufferedImage(w1, h1, BufferedImage.TYPE_INT_RGB);
//绘制放大后的图片
resultImg.getGraphics().drawImage(srcImg, 0, 0, w1, h1, null);
return resultImg;
}
/**
* 旋转图片-90度
*
* @param width 目标图像宽度
* @param height 目标图像高度
* @return
*/
public static void rotateImage(int width, int height, int[] imageArray) {
int[][] arr = new int[height][width];
int x = 0;
int y = 0;
for (int i = 0; i < imageArray.length; i++) {
arr[y][x++] = imageArray[i];
if (x % width == 0) {
x = 0;
y++;
}
}
//旋转-90度
int index = 0;
for (int j = width - 1; j >= 0; j--) {
for (int i = 0; i < arr.length; i++) {
imageArray[index++] = arr[i][j];
}
}
}
private static final String SOURCE_FILE_PATH = "C:\\Users\\Administrator\\Pictures\\fee.jpg";
private static final String WATER_FILE_PATH = "C:\\Users\\Administrator\\Pictures\\invoiceH.png";
private static final String SAVE_FILE_PATH = "C:\\Users\\Administrator\\Pictures\\overlyingImageNew.jpg";
/**
* @param fileUrl 文件绝对路径或相对路径
* @return 读取到的缓存图像
* @throws IOException 路径错误或者不存在该文件时抛出IO异常
*/
public static BufferedImage getBufferedImage(String fileUrl)
throws IOException {
File f = new File(fileUrl);
return ImageIO.read(f);
}
/**
* 输出图片
*
* @param buffImg 图像拼接叠加之后的BufferedImage对象
* @param savePath 图像拼接叠加之后的保存路径
*/
public static void generateSaveFile(BufferedImage buffImg, String savePath) {
int temp = savePath.lastIndexOf(".") + 1;
try {
File outFile = new File(savePath);
if (!outFile.exists()) {
outFile.createNewFile();
}
ImageIO.write(buffImg, savePath.substring(temp), outFile);
System.out.println("ImageIO write...");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Java 测试图片合并方法
*/
public static void imageMargeTest() {
// 读取待合并的文件
BufferedImage bi1 = null;
BufferedImage bi2 = null;
// 调用mergeImage方法获得合并后的图像
BufferedImage destImg = null;
System.out.println("下面是垂直合并的情况:");
String saveFilePath = WATER_FILE_PATH;
String divingPath = SOURCE_FILE_PATH;
String margeImagePath = SAVE_FILE_PATH;
try {
bi1 = getBufferedImage(saveFilePath);
bi2 = getBufferedImage(divingPath);
// 调用mergeImage方法获得合并后的图像
destImg = mergeImage(bi1, bi2);
} catch (IOException e) {
e.printStackTrace();
}
// 保存图像
generateSaveFile(destImg, margeImagePath);
System.out.println("垂直合并完毕!");
}
public static void main(String[] args) {
// 测试图片的垂直合并
imageMargeTest();
}
}