java实现仿微信QQ群聊头像图片合成,根据群聊内的用户头像合成群聊头像,九宫格图;效果图如下:
代码实现:
/**
* 图片合成(仿微信群聊头像)
*
*/
public class ImageUtils {
/**
* 图片格式:JPG
*/
private static final String PICTURE_FORMAT_PNG = "jpg";
private ImageUtils() {
}
/**
* 画板的高
*/
private static final Integer PICTURE_HEIGHT = 112;
/**
* 画板的宽
*/
private static final Integer PICTURE_WIDTH = 112;
/**
* 生成组合头像
*
* @param paths
* 用户图像路径(绝对路径)
* @param outImgPath
* 新图片路径(绝对路径)
* @throws IOException
*/
public static String getCombinationOfhead(List<String> paths, String outImgPath) throws IOException {
if (CollectionUtils.isEmpty(paths)) {
return null;
}
List<BufferedImage> bufferedImages = new ArrayList<BufferedImage>();
// 压缩图片所有的图片生成尺寸
int imgH = 32;// 图片的高
int imgW = 32;// 图片的宽
if (paths.size() <= 4) {
imgH = imgW = 50;
}
boolean flag = false;
for (int i = 0; i < paths.size(); i++) {
if (StringUtils.isNotBlank(paths.get(i))) {
File imgFile = new File(paths.get(i));
// 判断文件是否存在
if (imgFile.exists()) {
flag = true;
bufferedImages.add(ImageUtils.resizeImage(paths.get(i), imgH, imgW, false));
}
}
}
if (!flag) {
return null;
}
// BufferedImage.TYPE_INT_RGB可以自己定义可查看API
BufferedImage outImage = new BufferedImage(PICTURE_WIDTH, PICTURE_HEIGHT, BufferedImage.TYPE_INT_RGB);
// 生成画布
Graphics g = outImage.getGraphics();
Graphics2D g2d = (Graphics2D) g;
// 设置背景色
g2d.setBackground(new Color(231, 231, 231));
// 通过使用当前绘图表面的背景色进行填充来清除指定的矩形。
g2d.clearRect(0, 0, PICTURE_WIDTH, PICTURE_HEIGHT);
// 开始拼凑 根据图片的数量判断该生成那种样式的组合头像
layoutImage(g2d, bufferedImages, imgW);
String imgName = new Date().getTime() + "_" + new Random().nextInt(120000) + "."
+ PICTURE_FORMAT_PNG.toLowerCase();
if (!outImgPath.endsWith("/") && !outImgPath.endsWith("\\")) {
outImgPath += "/";
}
File file = new File(outImgPath);
if (!file.exists()) {
file.mkdirs();
}
String dir = GlobalStatic.rootDir;
String imgPath = "";
if (outImgPath.indexOf(dir) >= 0) {
imgPath = outImgPath.substring(dir.length());
}
ImageIO.write(outImage, PICTURE_FORMAT_PNG, new File(outImgPath + imgName));
return imgPath + imgName;
}
/**
* 图片布局生成组合图片
* @param g2d 画布
* @param bufferedImages 图片
* @param imgW 图片的宽
*/
private static void layoutImage(Graphics2D g2d, List<BufferedImage> bufferedImages, int imgW) {
int j = 1;
int k = 1;
for (int i = 1; i <= bufferedImages.size(); i++) {
if (bufferedImages.size() == 9) {
if (i <= 3) {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (i - 1) + 4 * i, 4, null);
} else if (i >= 4 && i <= 6) {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (k - 1) + 4 * k, 4 * 2 + imgW, null);
++k;
} else {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (j - 1) + 4 * j, 4 * 3 + imgW * 2, null);
j++;
}
} else if (bufferedImages.size() == 8) {
if (i <= 2) {
g2d.drawImage(bufferedImages.get(i - 1), 18 + imgW * (i - 1) + 4 * i, 4, null);
} else if (i >= 3 && i <= 5) {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (k - 1) + 4 * k, 4 * 2 + imgW, null);
++k;
} else {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (j - 1) + 4 * j, 4 * 3 + imgW * 2, null);
j++;
}
} else if (bufferedImages.size() == 7) {
if (i <= 1) {
g2d.drawImage(bufferedImages.get(i - 1), 36 + imgW * (i - 1) + 4 * i, 4, null);
} else if (i >= 2 && i <= 4) {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (k - 1) + 4 * k, 4 * 2 + imgW, null);
++k;
} else {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (j - 1) + 4 * j, 4 * 3 + imgW * 2, null);
j++;
}
} else if (bufferedImages.size() == 6) {
if (i <= 3) {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (i - 1) + 4 * i, 22, null);
} else {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (j - 1) + 4 * j, 58, null);
j++;
}
} else if (bufferedImages.size() == 5) {
if (i <= 2) {
g2d.drawImage(bufferedImages.get(i - 1), 18 + imgW * (i - 1) + 4 * i, 22, null);
} else {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (j - 1) + 4 * j, 58, null);
j++;
}
} else if (bufferedImages.size() == 4) {
if (i <= 2) {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (i - 1) + 4 * i, 4, null);
} else {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (j - 1) + 4 * j, 58, null);
j++;
}
} else if (bufferedImages.size() == 3) {
if (i <= 1) {
g2d.drawImage(bufferedImages.get(i - 1), 31, 4, null);
} else {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (j - 1) + 4 * j, 58, null);
j++;
}
} else if (bufferedImages.size() == 2) {
g2d.drawImage(bufferedImages.get(i - 1), imgW * (i - 1) + 4 * i, 31, null);
} else if (bufferedImages.size() == 1) {
g2d.drawImage(bufferedImages.get(i - 1), 31, 31, null);
}
// 需要改变颜色的话在这里绘上颜色。可能会用到AlphaComposite类
}
}
/**
* 图片缩放
*
* @param filePath
* 图片路径
* @param height
* 高度
* @param width
* 宽度
* @param flag
* 比例不对时是否需要补白
*/
@SuppressWarnings("removal")
public static BufferedImage resizeImage(String filePath, int height, int width, boolean flag) {
try {
double ratio = 0; // 缩放比例
File f = new File(filePath);
BufferedImage bi = ImageIO.read(f);
Image itemp = bi.getScaledInstance(width, height, Image.SCALE_SMOOTH);
// 计算比例
if ((bi.getHeight() > height) || (bi.getWidth() > width)) {
if (bi.getHeight() > bi.getWidth()) {
ratio = (new Integer(height)).doubleValue() / bi.getHeight();
} else {
ratio = (new Integer(width)).doubleValue() / bi.getWidth();
}
AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
itemp = op.filter(bi, null);
}
if (flag) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, width, height);
if (width == itemp.getWidth(null))
g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2, itemp.getWidth(null),
itemp.getHeight(null), Color.white, null);
else
g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0, itemp.getWidth(null),
itemp.getHeight(null), Color.white, null);
g.dispose();
itemp = image;
}
return (BufferedImage) itemp;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 把图片剪切成圆形图片
* @param imgPath 原图路径
* @param outPath 处理后图片输出路径
* @return
* @throws IOException
*/
public static String cutoutRoundImage(String imgPath, String outPath) throws IOException {
BufferedImage bufferedImage = ImageIO.read(new File(imgPath));
// 根据需要是否使用 BufferedImage.TYPE_INT_ARGB
BufferedImage bufImg = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight());
Graphics2D g2 = bufImg.createGraphics();
g2.setBackground(Color.WHITE);
g2.fill(new Rectangle(bufImg.getWidth(), bufImg.getHeight()));
g2.setClip(shape);
// 使用 setRenderingHint 设置抗锯齿
g2.drawImage(bufferedImage, 0, 0, null);
g2.dispose();
String imgName = new Date().getTime() + "_" + new Random().nextInt(120000) + "."
+ PICTURE_FORMAT_PNG.toLowerCase();
if (!outPath.endsWith("/") && !outPath.endsWith("\\")) {
outPath += "/";
}
// 输出图片路径
String imgDir = outPath + imgName;
try {
ImageIO.write(bufImg, "jpg", new File(imgDir));
} catch (IOException e) {
e.printStackTrace();
}
return imgDir;
}
}