原来用java也可以做海报图!

 

其实做开发这么久以来,我接触到的东西都不算全面,甚至知识面还是比较窄的!今天接到了一个比较有意思的项目,用后端代码画图,在我的印象中,后端的图片来源应该都是前端,或者UI,再不济,后端动态取值,给前端来排版展示!

但是今天,我的这个功能结束了,我做到了后端取值,自己排版!生成图片!

当然,其实这个其实并不复杂,而且大多数人都在用!下面就看要做哪些准备工作吧!

public InputStream shareQdlPoster(String headImg, String share_txt,
			String qrcode, int hasSign,String brandName,String backGround,Map<String,Object> param){
		ByteArrayOutputStream os = null;
		InputStream is = null;
		InputStream result = null;
		try {
			BufferedImage buffImg=null;
			result = getURLInputStream(backGround);
			buffImg = Thumbnails.of(result).scale(0.5f).outputQuality(1f).asBufferedImage();
			Graphics g = buffImg.getGraphics();// 得到画笔对象
			if(headImg!=null&&!"".equals(headImg)){
				//用户头像
				BufferedImage img = roundImg(headImg, 160, 160);
				g.drawImage(img,737,142,398,398,null);
			}
			//商品图
			if(param!=null&&!param.isEmpty()){
				BufferedImage imgCover = ImageIO.read(getURLInputStream(Tools.toString(param.get("goodsImage"))));
				g.drawImage(imgCover,395,1080,1100,1100,null);
			}
			//赞助商名称
			g.setColor(Color.GRAY);
			g.setFont(new Font("苹方-简", Font.BOLD, 60));
			g.drawString(brandName+"赞助", 830, 2280);
			//连续签到天数
			g.setColor(Color.RED);
			g.setFont(new Font("Arial", Font.PLAIN, 250));
			g.drawString(Tools.toString(hasSign), 1150,830);
			//仍缺天数
			g.setColor(Color.WHITE);
			g.setFont(new Font("苹方-简", Font.BOLD,75));
			g.drawString(share_txt, 400, 980);
			//活动时间
			if(param!=null&&!param.isEmpty()){
			g.setColor(Color.WHITE);
			g.setFont(new Font("苹方-简", Font.BOLD, 50));
			g.drawString("活动时间:"+Tools.toString(param.get("getTime")), 300, 2480);
			}
			//领取地址
			if(param!=null&&!param.isEmpty()){
				g.setColor(Color.WHITE);
				g.setFont(new Font("苹方-简", Font.BOLD, 50));
				String addr=Tools.toString(param.get("getAddr"));
				if(addr.length()>18){
					String firstRow=addr.substring(0,18);
					String secondRow=addr.substring(18);
					g.drawString("领取地址:"+firstRow, 300, 2550);
					g.drawString(secondRow, 500, 2610);
				}else {
					g.drawString("领取地址:"+addr,300, 2550);
				}
			}
			// 小程序二维码
			BufferedImage imgQrcode = new ImageUtil().roundImg(qrcode, 160, 160);
			g.drawImage(imgQrcode,1250,2800,400,400, null);
			
			g.dispose();
			os = new ByteArrayOutputStream();
			ImageIO.write(buffImg, "jpg", os);			
			is = new ByteArrayInputStream(os.toByteArray());
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			IOUtils.closeQuietly(os);
			IOUtils.closeQuietly(result);
		}
		return is;
	}

很明显,这个类返回的是一个inputStream的流!在类里面,我们既能对文字进行排版操作,也能对图片进行排版操作。

比如:Thumbnails这个方法是处理图片综合比例和大小的

           roundImg 是对图像进行圆角处理,其原理就是透明化周边角

            getURLInputStream 是对传进来的url参数进行读取,所以从这里我们知道,图片必须是能读取出来的url。

等等还有很多,可以自己追寻源码或者百度!这里我还可以提供一个头像圆角处理的方法

 /**
     * 把头像裁剪成圆形
     * @param headImg doamin + path
     * @return
     */
    public  BufferedImage roundImg(String headImg,int width, int height) {
        if (StringUtils.isBlank(headImg)) {
            return null;
        }
        InputStream result = null;
        try {
        	result = getURLInputStream(headImg);
        	BufferedImage bi1 = ImageIO.read(result);
            BufferedImage bi2 = new BufferedImage(bi1.getWidth(), bi1.getHeight(),
                    BufferedImage.TYPE_4BYTE_ABGR);
            Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, bi1.getWidth(), bi1
                    .getHeight());
            Graphics2D g2 = bi2.createGraphics();
//            g2.setBackground(Color.WHITE);
            g2.setColor(new Color(0,0,0,0));
            g2.fill(new Rectangle(bi2.getWidth(), bi2.getHeight()));
            g2.setClip(shape);
            // 使用 setRenderingHint 设置抗锯齿
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            
            g2.drawImage(bi1, 0, 0, null);
            g2.dispose();
            ByteArrayOutputStream bs = new ByteArrayOutputStream();
            ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
            ImageIO.write(bi2, "png", imOut);
            InputStream is = new ByteArrayInputStream(bs.toByteArray());
            BufferedImage buffImg = ImageIO.read(is);
            
            return zoomInImage(buffImg,width,height);        
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
			e.printStackTrace();
		} finally{
			IOUtils.closeQuietly(result);
		}
        return null;
    }

怎么获取https或者http中的url数据,方法咱们也有参考:

/**
	 * 获取https或http的URL数据
	 * @param u
	 * @return
	 * @throws Exception
	 */
	public static InputStream getURLInputStream(String u) throws Exception{
		URL url = new URL(u);
		String host = url.getProtocol() + "://" + url.getHost();
		String path = u.replaceAll(host,"");
		HttpResponse resp = HttpUtils.doGet(host, path, "GET", new HashMap<String, String>(), new HashMap<String, String>());
		InputStream result = resp.getEntity().getContent();
		return result;
	}

其实我们再对图片进行处理的过程中,还会涉及到图片的尺寸问题,在这里,我也只封装了一个改变图片high,width的方法:

/**
     * 改变图片尺寸
     *
     * @param imgUrl 图片的路径 domail + path
     * @param width  修改后的宽度
     * @param height 修改后的高度
     * @return BufferedImage对象
     */
    public  BufferedImage getBufferedImage(String imgUrl, int width, int height) {
        if (StringUtils.isBlank(imgUrl)) {
            return null;
        }
        InputStream result = null;
        try {
        	result = getURLInputStream(imgUrl);
            BufferedImage bi = ImageIO.read(result);
            BufferedImage tag = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
            tag.getGraphics().drawImage(bi, 0, 0, bi.getWidth(), bi.getHeight(), null);
            ByteArrayOutputStream bs = new ByteArrayOutputStream();
            ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
            ImageIO.write(tag, "jpg", imOut);
            InputStream is = new ByteArrayInputStream(bs.toByteArray());
            BufferedImage buffImg = ImageIO.read(is);
            return zoomInImage(buffImg,width,height);
 
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
        	e.printStackTrace();
		} finally{
			IOUtils.closeQuietly(result);
		}
        return null;
    }

当然,在这里,能操作的前提肯定是图片已经存到服务器中,再不济也应该是我们自己的tomcat服务器中。下面还会解释一下,怎么拼接域名,怎么存储图片!

InputStream ips=null;
//开始生成海报--------------------------------------------------------------------------------------
	if (goods!=null&&!goods.isEmpty()) {
	//输出海报图片
	ips = new ImageUtil().shareQdlPoster(headImg,share_txt,qrPath,has_sign,brandName,backGroundImage,goods);
					}
	if(ips!=null){
	filePath = FileUtil.saveFile(ips, getProperties("file.root"), "share", "share.jpg");
	}
	IOUtils.closeQuietly(ips);

这里可以再详细的介绍一下saveFile这个具体的存储方法

/**
	 * 上传文件
	 * @param excelFile 文件
	 * @param fileRootPath ROOT_PATH路径
	 * @param fileBusiType 文件业务类型
	 * @param fileName 文件名
	 * @return
	 * @throws Exception
	 */
	public static String saveFile(InputStream in,String fileRootPath,String fileBusiType,String fileName) throws Exception {
		String uploadFileName = Tools.replaceLine(Tools.uuid()) + fileName.substring(fileName.lastIndexOf(".")); // UUID生成文件名
		String location = FileStore.saveFile(in, fileBusiType,fileRootPath,uploadFileName);
		return location;
	}

这里中间过渡一段,saveFile的具体实现内容在下面

/**
	 * 保存文件至文件服务器
	 * @param in 数据输入流
	 * @param fileName 文件名
	 * @return 文件相对路径
	 * @throws SQLException
	 * @throws IOException
	 */
	public static String saveFile(InputStream in,String fileCategory,String fileRootPath, String fileName) throws Exception{

		//创建目录
		String relaPath = getRelaPath(fileCategory);
		File path = new File(fileRootPath, relaPath);
		if (!path.exists() || !path.isDirectory()){
			path.mkdirs();
		}
		
		//创建文件
		String location = relaPath + fileName;
		File file = new File(fileRootPath, location);
//		File file = MyFile.newInstance(fileRootPath,location);
		FileOutputStream out = new FileOutputStream(file);
		try{
			rw(in, out);
		}finally{
			try{
				out.close();
			}catch(Exception ex){
			}
		}
		return location;
	}

这也是一个通过文件流来新建文件夹,或者寻找文件夹。

以上不进详细,仅供参考,也作为我个人的一个线上笔记!

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值