java生成群头像_TCH987551623的博客-程序员宅基地

技术标签: java  其它  数据库  

 

参考:http://www.2cto.com/weixin/201503/382943.html

 

通过java生成类似微信的群头像:

 

package com.tch.test.common.image;
 
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
 
/**
 * 图片处理类
 */
public final class ImageUtil {
	
    /** 图片格式:JPG */
    private static final String PICTRUE_FORMATE_JPG = "JPG";
    private static final int PIC_WIDTH = 400; // 这是画板的宽高
    private static final int PIC_HEIGHT = 400; // 这是画板的高度
 
    private ImageUtil() {
    }
    
    public static void main(String[] args) throws IOException {
    	String destPath = "/media/tch/disk1/study/temp/folder/";
    	List<String> sourcePics = new ArrayList<>();
    	sourcePics.add("http://h.hiphotos.baidu.com/zhidao/pic/item/eac4b74543a9822628850ccc8c82b9014b90eb91.jpg");
    	sourcePics.add("http://h.hiphotos.baidu.com/zhidao/pic/item/3812b31bb051f81991b9d8dbdcb44aed2f73e787.jpg");
    	sourcePics.add("http://cdn.duitang.com/uploads/item/201412/19/20141219154459_3P4G2.jpeg");
    	sourcePics.add("http://img4.duitang.com/uploads/item/201603/12/20160312211255_nB5mQ.thumb.700_0.jpeg");
    	sourcePics.add("http://h.hiphotos.baidu.com/zhidao/pic/item/c8177f3e6709c93d0f5f00e79b3df8dcd1005474.jpg");
    	sourcePics.add("http://ww1.sinaimg.cn/crop.7.22.1192.1192.1024/5c6defebjw8epti0r9noaj20xc0y1n0x.jpg");
    	sourcePics.add("http://ww1.sinaimg.cn/crop.0.0.800.800.1024/735510dbjw8eoo1nn6h22j20m80m8t9t.jpg");
    	sourcePics.add("http://ww2.sinaimg.cn/crop.0.0.1242.1242.1024/005EWUXPjw8eto7cdd42wj30yi0yiabz.jpg");
    	sourcePics.add("http://ww2.sinaimg.cn/crop.0.0.1080.1080.1024/d773ebfajw8eum57eobkwj20u00u075w.jpg");
    	for(int i = 1; i <= sourcePics.size(); i++){
    		getGroupAvatar(sourcePics.subList(0, i), destPath + "out" + i + ".jpg");
    	}
	}
    
    /**
     * 生成群头像
     * @param userAvatars 用户头像
     * @throws IOException
     */
    public static void getGroupAvatar(List<String> userAvatars, String destPath) throws IOException {
    	int totalPicNum = userAvatars.size();
    	PicInfo picInfo = getPicInfo(totalPicNum);
        List<BufferedImage> bufferedImages = new ArrayList<BufferedImage>();
        // 压缩图片所有的图片生成尺寸
        for (int i = 0; i < totalPicNum; i++) {
            bufferedImages.add(resizeNetWorkImage(userAvatars.get(i), picInfo.getPerPicWith(), picInfo.getPerPicHeight(), true));
        }
        BufferedImage outImage = new BufferedImage(PIC_WIDTH, PIC_HEIGHT, BufferedImage.TYPE_INT_RGB);
        // 生成画布
        Graphics graphics = outImage.getGraphics();
        Graphics2D graphics2d = (Graphics2D) graphics;
        graphics2d.setBackground(new Color(231,231,231));
        graphics2d.clearRect(0, 0, PIC_WIDTH, PIC_HEIGHT);
        //开始将单个图片逐个画到画布上
        for (int picIndex = 0; picIndex < bufferedImages.size(); picIndex++) {
        	if(totalPicNum == 2 || totalPicNum == 5 || totalPicNum == 6){
        		//需要特殊处理,来让图片垂直居中
        		specialDraw(bufferedImages.get(picIndex), picIndex, picInfo, graphics2d, totalPicNum);
        	}else{
        		//不需要特殊处理,按照正常的处理逻辑
        		normalDraw(bufferedImages.get(picIndex), picIndex, picInfo, graphics2d);
        	}
        }
        //将最终结果图片输出到指定文件
        ImageIO.write(outImage, PICTRUE_FORMATE_JPG, new File(destPath));
    }

    private static void specialDraw(BufferedImage bufferedImage, int picIndex, PicInfo picInfo, Graphics2D graphics2d, int totalPicNum) {
    	int xIndex = (picIndex % picInfo.getPicNumPerRow());
    	int y = 0;
    	if(totalPicNum == 2){
    		y = PIC_HEIGHT / 4;
    	}else if(totalPicNum == 5 || totalPicNum == 6){
    		if(picIndex < 3){
    			y = (PIC_HEIGHT / 2 - PIC_HEIGHT / 3);
    		}else{
    			y = PIC_HEIGHT / 2;
    		}
    	}
		graphics2d.drawImage(bufferedImage, xIndex * picInfo.getPerPicWith(), y, null);
	}

	private static void normalDraw(BufferedImage bufferedImage, int picIndex, PicInfo picInfo, Graphics2D graphics2d) {
    	int xIndex = (picIndex % picInfo.getPicNumPerRow());
		int yIndex = (picIndex / picInfo.getPicNumPerRow());
		graphics2d.drawImage(bufferedImage, xIndex * picInfo.getPerPicWith(), yIndex * picInfo.getPerPicHeight(), null);
	}

	/**
     * 图片缩放
     * @param filePath 图片路径
     * @param width 宽度
     * @param height 高度
     * @param fillWhite 比例不对时是否需要补白
     */
    public static BufferedImage resizeImage(BufferedImage bufferedImage, int width, int height, boolean fillWhite) {
        double ratio = 0; // 缩放比例
		Image newImage = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
		// 计算比例
		if ((bufferedImage.getHeight() > height) || (bufferedImage.getWidth() > width)) {
		    if (bufferedImage.getHeight() > bufferedImage.getWidth()) {
		        ratio = (new Integer(height)).doubleValue()/bufferedImage.getHeight();
		    } else {
		        ratio = (new Integer(width)).doubleValue()/bufferedImage.getWidth();
		    }
		    AffineTransformOp affineTransformOp = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
		    newImage = affineTransformOp.filter(bufferedImage, null);
		}
		if (fillWhite) {
		    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 == newImage.getWidth(null)){
		    	g.drawImage(newImage, 0, (height - newImage.getHeight(null))/2, newImage.getWidth(null), newImage.getHeight(null), Color.white, null);
		    }else{
		    	g.drawImage(newImage, (width - newImage.getWidth(null))/2, 0, newImage.getWidth(null), newImage.getHeight(null), Color.white, null);
		    }
		    g.dispose();
		    newImage = image;
		}
		return (BufferedImage) newImage;
    }
    
    /**
     * 缩放本地图片
     * @param file
     * @param width
     * @param height
     * @param fillWhite
     * @return
     */
    public static BufferedImage resizeLocalImage(File file, int width, int height, boolean fillWhite) {
        try {
        	//从本地加载图片
            BufferedImage bufferedImage = ImageIO.read(file);
            return resizeImage(bufferedImage, width, height, fillWhite);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 缩放网络图片
     * @param imageUrl
     * @param width
     * @param height
     * @param fillWhite
     * @return
     */
    public static BufferedImage resizeNetWorkImage(String imageUrl, int width, int height, boolean fillWhite) {
        try {
        	//从网络加载图片
            BufferedImage bufferedImage = ImageIO.read(new URL(imageUrl));
            return resizeImage(bufferedImage, width, height, fillWhite);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 获取群头像中每行/列显示的图片数
     * @param picNum 图片数量
     * @return
     */
    private static PicInfo getPicInfo(int totalPicNum){
    	//每行显示图片数
    	int picNumPerRow = 1;
    	//每列显示图片数
    	int picNumPerCol = 1;
    	switch (totalPicNum) {
		case 1:
			picNumPerRow = 1;
			picNumPerCol = 1;
			break;
		case 2:
			picNumPerRow = 2;
			picNumPerCol = 1;
			break;
		case 3:
		case 4:
			picNumPerRow = 2;
			picNumPerCol = 2;
			break;
		case 5:
		case 6:
			picNumPerRow = 3;
			picNumPerCol = 2;
			break;
		case 7:
		case 8:
		case 9:
			picNumPerRow = 3;
			picNumPerCol = 3;
			break;
		default:
			picNumPerRow = 1;
			picNumPerCol = 1;
			break;
		}
    	int perPicWith = PIC_WIDTH/picNumPerRow;
    	int perPicHeight = PIC_HEIGHT/picNumPerCol;
    	
    	//图片有效宽/高
    	int effectWithHeight = Math.min(perPicWith, perPicHeight);
    	
    	PicInfo picInfo = new PicInfo();
    	//图片的宽高统一
    	picInfo.setPerPicWith(effectWithHeight);
    	picInfo.setPerPicHeight(effectWithHeight);
    	picInfo.setPicNumPerRow(picNumPerRow);
    	picInfo.setPicNumPerCol(picNumPerCol);
    	return picInfo;
    }
    
    /**
     * 图片位置
     * @author tianchaohui
     */
    public static class PicLocation{
    	//横坐标
    	int xIndex = 0;
    	//纵坐标
        int yIndex = 0;
		public int getxIndex() {
			return xIndex;
		}
		public void setxIndex(int xIndex) {
			this.xIndex = xIndex;
		}
		public int getyIndex() {
			return yIndex;
		}
		public void setyIndex(int yIndex) {
			this.yIndex = yIndex;
		}
    }
    
    /**
     * 填充图片信息
     * @author tianchaohui
     */
    public static class PicInfo{
    	//每张图片宽度
    	private int perPicWith;
    	//每张图片高度
    	private int perPicHeight;
    	//每行显示图片数
    	int picNumPerRow;
    	//每列显示图片数
    	int picNumPerCol;
		public int getPerPicWith() {
			return perPicWith;
		}
		public void setPerPicWith(int perPicWith) {
			this.perPicWith = perPicWith;
		}
		public int getPerPicHeight() {
			return perPicHeight;
		}
		public void setPerPicHeight(int perPicHeight) {
			this.perPicHeight = perPicHeight;
		}
		public int getPicNumPerRow() {
			return picNumPerRow;
		}
		public void setPicNumPerRow(int picNumPerRow) {
			this.picNumPerRow = picNumPerRow;
		}
		public int getPicNumPerCol() {
			return picNumPerCol;
		}
		public void setPicNumPerCol(int picNumPerCol) {
			this.picNumPerCol = picNumPerCol;
		}
		@Override
		public String toString() {
			return "PicInfo [perPicWith=" + perPicWith + ", perPicHeight=" + perPicHeight + ", picNumPerRow="
					+ picNumPerRow + ", picNumPerCol=" + picNumPerCol + "]";
		}
    }
 
}

 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/TCH987551623/article/details/84817329

智能推荐

笔记_Emotional_gjx的博客-程序员宅基地

预备内容----软件安装筒1.记笔记工具—typroa文件名:基本文件名.扩展名2.截图工具的安装Greenshot3.sublimes—无需安装解压将解压后的文件复制到C:\programefiles\ 下选择sublimes.exe发送到桌面快捷方式HTML,主讲:刘晓勇一、HTML简介1.HTML是什么?HTML:Hyper Text Markup Language超...

beego框架代码分析_TIGERB_Blog的博客-程序员宅基地

前言也许beego框架在国内应该是众多PHPer转go的首选,因为beego的MVC、ORM、完善的中文文档让PHPer们得心应手,毫无疑问我也是。这种感觉就像当年入门PHP时使用Thi...

如何修复MacOS中的 SDK “iphoneos“ cannot be located‘ 错误_赵大仁的博客-程序员宅基地

如果你在执行 pod install 的时候碰到如下报错:其中报错主要位置信息为: error: SDK “iphoneos” cannot be located。请确保已安装Xcode,并尝试如下命令:sudo xcode-select --switch /Applications/Xcode.app即可正常执行 pod install 。...

最终一致性/BASE VS ACID_zhangxinrun_业余erlang的博客-程序员宅基地

学过数据库的人都会知道,ACID是关系型数据库的最基本原则。但是在遵守ACID原则规定的强一致性的同时,会对性能造成很大的影响。<br />对于大多数的互联网应用来讲,强一致性并不是非常重要的。和一致性比起来,可用性更加重要性一些。最终一致性简单的讲就是在某一个短暂的时间内数据可以不一致,但是在无限长的时间内,所有节点上的replica最终会达到完全一致。<br />BASE 策略是Eric A. Brewer 在 1988 年提出的。和ACID完全不同,BASE的基本思想就是牺牲强一致性,以便获得可用性或

python爬虫基础与实战_wangqianqianya的博客-程序员宅基地

爬虫爬虫的本质是模拟客户端(浏览器)向服务器发送请求。开始爬虫前可看看HTTP协议。工具:python自带的urllib模块,可以接受URL from urllib.request import urlopen #urllib.request即urllib2html=urlopen('https://www.baidu.com/') #urlopen()返回一个Respo...

明港镇计算机培训班,平桥区建筑工匠培训班在明港新集村开班_斜杆体制人吴聊先生的博客-程序员宅基地

明视界全镇居民都在关注明港广电中心新媒体官方平台为提高农村建筑工匠的从业水平,加强安全生产管理,引导和规范农民建房。近日,由区住建局牵头组织开展的农村建筑工匠培训班在明港新集村正式开班。区住建局副局长杨德云、明港镇产业集聚区副主任杨国军参加开班仪式。来自平桥区各乡镇负责农房抗震改造、农房品质提升的管理人员和现场作业技术人员共60余人参加培训。仪式上,区住建局副局长杨德云指出,建筑工匠是农村安全住房...

随便推点

LeetCode练习-简单 -70. 爬楼梯(动态规划)_Brain_河神的博客-程序员宅基地

LeetCode练习-简单 -70. 爬楼梯(动态规划)假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?注意:给定 n 是一个正整数。示例1:输入: 2输出: 2解释: 有两种方法可以爬到楼顶。1. 1 阶 + 1 阶2. 2 阶示例 2:输入: 3输出: 3解释: 有三种方法可以爬到楼顶。1. 1 阶 + 1 阶 + 1 阶2. 1 阶 + 2 阶3. 2 阶 + 1 阶分析: dp原理:

vs2015完全卸载_aaa1150322487的博客-程序员宅基地

请确保你是否完全卸载了VS2015, 你可以使用强制卸载指令来进行卸载。打开命令行窗口输入如下指令,其中D:\vssetup为vs安装包所在的文件夹。D:\vssetup\vs_ultimate.exe /uninstall /force如果你没有安装包,也可以在手动卸载后,清理跟VS相关的注册表相关设置。Amor转载于:https://www.cnblogs.com/l...

上半年营收256亿,转型的陆金所能否在纽交所站稳脚跟?_美股研究社的博客-程序员宅基地

继蚂蚁集团、京东数科之后,又一家金融科技独角兽——陆金所终于要上市。北京时间10月8日,陆金所控股正式向美国证券交易委员会(SEC)首次公开递交招股说明书。市场传闻此次IPO将募集20亿至30亿美元,若数据属实,这将成为美股历史上募资金额最高的金融科技IPO。金融科技行业不缺少神话,但同样险象环生。先有P2P的暴雷,后有全球“黑天鹅事件”导致的资金链断裂。即将赴美上市的陆金所,能否在这一条荆棘遍布的道路上走得稳当?借转型谋求营收增长,但营收结构丰富度不足从招股书公布的数据来看,2017年至2020年

SeniorUI31_手写CoordinatorLayout和Behavior_鱼包子Ray的博客-程序员宅基地

SeniorUI_高级UI汇总目录一 效果图二 需求组件: 标题+背景和滑动控件(显示内容)当向上滑动时,标题渐渐不透明,图片逐渐变小,直到标题完全显示,图片不显示当向下滑动时,显示背景图片并局域变大,标题变不透明,直到不能滑动,图片完全显示,标题完全不显示三 CoordinatorLayout分析CoordinatorLayout有两个主要的用法:作为顶层应用的装饰或者ch...

原子哥的按键扫描分析_qq_888192的博客-程序员宅基地

//返回值://0,没有任何按键按下//KEY0_PRES,KEY0按下//KEY1_PRES,KEY1按下//WKUP_PRES,WK_UP按下 //注意此函数有响应优先级,KEY0&amp;gt;KEY1&amp;gt;WK_UP!!u8 KEY_Scan(u8 mode) //mode:0,不支持连续按; 1,支持连续按;{                 static u8 key_up=1...

为啥我的sonarqube在linux服务器上已经跑起来,浏览器打不开_zhuqiaorjxy的博客-程序员宅基地

描述:我的sonarqube已经在linux 服务器上跑起来,并且没有报错,但是就是浏览器打不开。目前我已经试过如下方法:1.修改端口2.关闭防火墙3.重启服务以上三种都没有解决问题,求帮助!...

推荐文章

热门文章

相关标签