积跬步,聚小流------java信息生成图片

需求:

是在做证书的时候碰到的这个问题。

当时需求是可以进行在线打印证书,第一次进行的操作是直接打印html,并且已经排好版(用jqprint插件)进行打印,在打印时碰到了兼容的问题,另外由于背景图片加载较文字加载的慢,则出现先加载文字后出现图片的现象,则显的很不专业,遂采用了将信息转化为图片,然后直接打印图片,不论怎么样进行打印,都不会改变,而且可以导出图片,对图片进行更为精细的操作。

代码编写:

先不多说 先上代码:

package com.jzba.utils;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class ImgUtils {	

	private static int newWidth=0,newHeight=0,newX=0,newY=0;

	public static void main(String[] args) throws Exception{--1、本地测试
		String over="D:/zz/1/over.png";
		Color color = new Color(100,100,100);
		ImageUtil iu=new ImageUtil();
		Map map=iu.getImageSizeByBufferedImage("D:/zz/ceshi.png");--备注:见代码下方
		int width=(Integer)map.get("width");
		int height=(Integer)map.get("height");
		float bili=width/height;
		if (width>height) {
			newWidth=660;
			newHeight=height*660/width;
			newX=600;
			newY=1160+330-newHeight/2;
		}else{
			newHeight=660;
			newWidth=width*660/height;
			newY=1160;
			newX=600+330-newWidth/2;
		}
		//String temp1=createCard("D:/zz/1/background.png","D:/zz/1/ceshi.png","D:/zz/1/code.bmp","D:/zz/1/temp1.png",newX,newY,600,1210,newWidth,newHeight,250,250);
		String temp1=createCard("D:/zz/1/background.png","D:/zz/1/ceshi2.jpg","D:/zz/1/code.bmp","D:/zz/1/temp1.png",100,100,600,1210,newWidth,newHeight,250,250);
		ImageIcon imgIcon = new ImageIcon(temp1);
   		Image theImg = imgIcon.getImage();
   		int w = theImg.getWidth(null);
   		int h = theImg.getHeight(null);
   		BufferedImage bufImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
   		// 获取Graphics2D
   		Graphics2D g = bufImg.createGraphics();
   		g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
   		// 画图
   		bufImg = g.getDeviceConfiguration().createCompatibleImage(w, h, Transparency.TRANSLUCENT);
   		g.dispose();
   		g = bufImg.createGraphics();
   		g.setStroke(new BasicStroke(1));
   		g.drawImage(theImg, 0, 0, w, h, null);//背景图起始位置
   		g.setColor(color);
   		Font nf = loadFont("D:/zz/simhei.ttf",60);
   		Font nf2 = loadFont("D:/zz/simhei.ttf",50);
   	    g.setFont(nf);
   		g.drawString("秘  密",2500,1040);//
   		g.setFont(nf2);
   		g.drawString("秘  密",1920,1190);//
   		g.drawString("秘  密", 1920, 1290);//
   		g.drawString("秘  密", 1920, 1390);//
   		g.drawString("秘  密", 1920, 1490);//
   		g.drawString("秘  密 ", 1920, 1590);//
   		g.drawString("秘  密", 1920, 1700);//
   		g.drawString("秘  密", 1920, 1800);//
   		//释放对象
   		File tofile=new File(over);
   		ImageIO.write(bufImg, "png", tofile);
   		g.dispose();
	}
	/**
	 *
	 * 将所要添加的图片整合在一起进行添加
	 * @param backsPath 背景图片的路径
	 * @param titleImgPath 缩略图图片的路径
	 * ...
	 *
	 * @return toPath 合成后图片的路径
         *
         * */

	public static String createCard(String backsPath,String titleImgPath,String codeImgPath,String toPath,int x,int y,int newx,int newy,int widthTitle,int heightTitle,int codeWidth,int codeHeight){
		 try {
			InputStream imageBack=new FileInputStream(backsPath);//背景图
		        InputStream imageTitle=new FileInputStream(titleImgPath);//缩略图图片
		        InputStream imageCode=new FileInputStream(codeImgPath);//二维码图片
		        BufferedImage backImg=ImageIO.read(imageBack);
		        BufferedImage titleImg=ImageIO.read(imageTitle);
		        BufferedImage codeImg=ImageIO.read(imageCode);
		        System.out.println("*****Graphics****"+backsPath);
		        Graphics g=backImg.getGraphics();
		        System.out.println("*****Graphics****1");
		        g.drawImage(titleImg,x,y,widthTitle,heightTitle,null);
		        System.out.println("*****Graphics****2");
		        g.drawImage(codeImg,newx,newy,codeWidth,codeHeight,null);
		        System.out.println("*****Graphics****3");
		        OutputStream outImage=new FileOutputStream(toPath);
		        System.out.println("*****Graphics****4");
//		        JPEGImageEncoder enc=JPEGCodec.createJPEGEncoder(outImage);--这里存在问题
//		        System.out.println("*****Graphics****5");--在window下可以,在linux下无法进行
//				enc.encode(backImg);
		        File tofile=new File(toPath);
		        ImageIO.write(backImg, "png", tofile);
//				System.out.println("*****"+backsPath);
		        imageBack.close();//关闭输出端口
		        imageTitle.close();
		        imageCode.close();
		        outImage.close();
		} catch (Exception e) {
				e.printStackTrace();
		}
		return toPath;
	}
	/**
	 * 将所要添加的文本信息整合在一起进行添加
	 *
	 *
	 * **/
	public static String addCardWord(String filePath,String toPath,int fontsize, Color markContentColor,String fontPath,String code,String type,String artist,
			String artname,String description,String material,String artisttype,String recordescription,String releaseDate,int codex,int codey,int typex,int typey,
			int artistx,int artisty,int artnamex,int artnamey,int descriptionx,int descriptiony,int materialx,int materialy,int artisttypex,int artisttypey,
			int recordescriptionx,int recordescriptiony)throws Exception{
		ImageIcon imgIcon = new ImageIcon(filePath);
   		Image theImg = imgIcon.getImage();
   		int w = theImg.getWidth(null);
   		int h = theImg.getHeight(null);
   		BufferedImage bufImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
   		// 获取Graphics2D
   		Graphics2D g = bufImg.createGraphics();
   		g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
   		// 画图
   		bufImg = g.getDeviceConfiguration().createCompatibleImage(w, h, Transparency.TRANSLUCENT);
   		g.dispose();
   		g = bufImg.createGraphics();
   		g.setStroke(new BasicStroke(1));
   		g.drawImage(theImg, 0, 0, w, h, null);//背景图起始位置
   		g.setColor(markContentColor);
   		Font nf = loadFont(fontPath,fontsize);
   	    g.setFont(nf);
   		g.drawString(code, codex, codey);
   		g.drawString(type, typex, typey);
   		g.drawString(artist, artistx, artisty);
   		g.drawString(artname, artnamex, artnamey);
   		g.drawString(description, descriptionx, descriptiony);
   		g.drawString(material, materialx, materialy);
   		g.drawString(artisttype, artisttypex, artisttypey);
   		g.drawString(recordescription, recordescriptionx, recordescriptiony);
   		//释放对象
   		File tofile=new File(toPath);
   		ImageIO.write(bufImg, "png", tofile);
   		g.dispose();
   		return toPath;
	}

	/**
	 * 向图片里面添加图片
	 * @param backsPath 背景图片路径
	 * @param upPath 添加图片路径
	 * @param toPath 生成图片路径
	 * @param x 所添加图片在背景图片上的横向位移,以左上角为标准
	 * @param y 所添加图片在背景图片上的竖向位移,以左上角为标准
	 * @param width 所添加图片的宽度
	 * @param height 所添加图片的高度
	 * @return toPath String 返回生成图片的路径
	 *
	 * **/
    public static String addImg2Img(String backsPath,String upPath,String toPath,int x,int y,int width,int height){
        	   try {
	               InputStream imagein=new FileInputStream(backsPath);
	               InputStream imagein2=new FileInputStream(upPath);
	               BufferedImage image=ImageIO.read(imagein);//读取背景图片
	               BufferedImage image2=ImageIO.read(imagein2);//读取要添加的图片
	               Graphics g=image.getGraphics();//将背景图片作为画图面板
	               g.drawImage(image2,x,y,width,height,null);//在背景图片的基础上进行画图,将待添加图片加入
	               OutputStream outImage=new FileOutputStream(toPath);//打开导出图片路径
	               JPEGImageEncoder enc=JPEGCodec.createJPEGEncoder(outImage);
	               enc.encode(image);//将生成的图片输出
	               imagein.close();//关闭打开的导入、导出通道
	               imagein2.close();
	               outImage.close();
			   } catch (Exception e) {
			       e.printStackTrace();
			   }
        	   return toPath;
    }
    /**
	 * 向图片里面添加文字
	 * @param filePath 背景图片路径
	 * @param toPath 生成图片路径
	 * @param markContent 添加的文本内容
	 * @param fontsize 添加文本的字体大小
	 * @param markContentColor 添加文本的颜色
	 * @param fontPath 添加文本的字体
	 * @param x 所添加图片在背景图片上的横向位移,以左上角为标准
	 * @param y 所添加图片在背景图片上的竖向位移,以左上角为标准
	 * @return toPath String 返回生成图片的路径
	 *
	 * **/
    public static String addWord2Img(String filePath,String toPath, String markContent,int fontsize, Color markContentColor,String fontPath,int x,int y) throws Exception {
	   		ImageIcon imgIcon = new ImageIcon(filePath);
	   		Image theImg = imgIcon.getImage();
	   		int w = theImg.getWidth(null);
	   		int h = theImg.getHeight(null);
	   		BufferedImage bufImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
	   		// 获取Graphics2D
	   		Graphics2D g = bufImg.createGraphics();
	   		g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
	   		// 画图
	   		bufImg = g.getDeviceConfiguration().createCompatibleImage(w, h, Transparency.TRANSLUCENT);
	   		g.dispose();
	   		g = bufImg.createGraphics();
	   		g.setStroke(new BasicStroke(1));
	   		g.drawImage(theImg, 0, 0, w, h, null);//背景图起始位置
	   		g.setColor(markContentColor);//给添加的文本进行颜色设置
	   		Font nf = loadFont(fontPath,fontsize);
	   	    g.setFont(nf);//对添加的文本进行字体和字体大小设置
	   		g.drawString(markContent, x, y);//将文本添加到图片指定的位置
	   		//释放对象
	   		File tofile=new File(toPath);//打开导出通道
	   		ImageIO.write(bufImg, "png", tofile);//进行画图
	   		g.dispose();
	   		return toPath;
  	}
    /**
	 * 对添加文本的字体和字体大小进行设置
	 * @param fontFileName 外部字体名
	 * @param fontsize 添加文本的字体大小
	 * @param markContentColor 添加文本的颜色
	 * @return dynamicFontPt Font 对文本的相应设置
	 *
	 * **/
	public static Font loadFont(String fontFileName, float fontSize) throws Exception  //第一个参数是外部字体名,第二个是字体大小
	{
			File file = new File(fontFileName);
			FileInputStream aixing = new FileInputStream(file);
			Font dynamicFont = Font.createFont(Font.TRUETYPE_FONT, aixing);
			Font dynamicFontPt = dynamicFont.deriveFont(fontSize);
			aixing.close();
			return dynamicFontPt;
	}

}

备注:在代码中调用到了上一篇文章中获取图片尺寸的相应类,用在这里的目的是,针对不同的作品,可能是横向图片,也可能是竖条图片,为了保证图片不会变形失真,则将图片显示在固定的一个区域内,像这里:

默认了一段660*660的区域,首先进行判定要添加图片是横条还是竖条,如果是横条,则宽度是大于高度的,则设置大的宽度为660,相应的根据比例:660/宽度=要求的高度/实际高度,则可以得到相应的高度值,而且此高度值肯定是小于660的,因为是横条,所以宽度的位移就是指定区域的相应位移,这里为600px,而高度位移,则应该是添加图片的左上角的位移,为背景图片的高度一半减去图片当前高度的一半;同理如果是竖条,则高度是大于宽度的,则设置大的高度为660,以此类推,得到相应的位移和尺寸。从而实现的效果是什么样子呢,我们来简单看下:

(这是高度大于宽度)

(这是宽度大于高度)

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 00:39:38

积跬步,聚小流------java信息生成图片的相关文章

积跬步,聚小流------java获取图片的尺寸

在一篇文章中获取到通过例如以下两种方式进行获取: 1.使用ImageReader进行获取: 2.使用BufferedImage进行获取: 而且经过验证ImageReader进行操作的耗时远远低于BufferedImage操作的耗时,详情可查看链接查看原文 然后依据应用我自己在项目中略做修改,在这里记录下: <span style="font-size:14px;">package com.jzba.utils; import java.awt.image.BufferedI

不积跬步无以至千里----高度自适应的textarea

在某个项目里面,有这样的一个小需求. textarea的高度自适应,当高度高于300px之后,textarea高度不再增高,出滚动条.当高度小于某个高度例如80px的时候,高度不再变小. 其实这个需求在很多地方都有出现过,例如微博的评论框,还有各种评论框. 谈不上什么有难度的技术,写下来当一个小插件积累. <!doctype html> <html> <head> <meta charset="utf-8"> <title>高

技术成长-不积跬步无以至千里

走在开发的道路上,你会发现越走路越长,越走路上的坑越多.本人是想在成长的道路上多踩一些坑的,踩的坑越多,遇到问题解决速度越快.坑多了,可能自己都记不住了,就需要记一记,有些时候你遇到的坑采用的解决办法并不是最优解,所有需要拿出来跟小伙伴一起分享分享你的经验. 记录到比如印象笔记或者有道云笔记里,或者自己的一个文件夹里,不过,个人经验,记在文件夹后很少有人再去看,还是记在印象笔记或者有道云笔记里,可以帮助自己随时翻看.现在的流程是重要的时候记录在有道云笔记上,做个索引,然后印象笔记记录的是我再找对

积跬步,聚小流------关于手机号,前端应该注意哪些

现代的网上商城中越来越多的开始使用手机注册,方便,快捷,然后作为前端,也就不可避免的要在界面上碰到关于手机号的问题,今天小小总结一下该注意哪些问题,又该来如何实现呢? 1.实现效果 先把自己当前做出来的效果传上来看下: (备注:这里的手机号码是我随便输了一个,如果真有这个号码受到了骚扰,别怪我啊,噗噗...) 2.需要注意的问题 这里我们来简单罗列下需要注意的问题吧: * input输入框,只能输入数字: * 输入过程中下方同步显示所输入的内容: * 判断输入手机号是否格式正确: * 判断手机归

积跬步,聚小流-------简单说配置环境变量

知其然,不如知其所以然,这个道理其实很多人都懂,只是得到鱼简单,而学会渔就要付出代价了,终究不是那么简单的,可能这就叫做成长吧. 看过很多关于java的培训书籍,像什么从入门到精通,像什么21天学会等等,事实上我也是从这个开始接触java的,就像开了一扇门,从此一发不可收拾的沦陷. 记得书中最开始都会讲JDK的安装和环境变量的配置,于是就会照搬书上的方法,安装,然后配置JAVA-HOME,CLASSPATH,PATH,然后我去编写自己的第一个"hello world",还能模糊想起最初

积跬步,聚小流-------几种方法实现分割线

其实这个问题想了实现了有一段时间了,只是单纯自己想了个办法简单实现了效果,没想出太多办法来,最关键的是,我也不知道这原来是叫"分割线",只知道是什么样,连搜都不着知道怎么搜,赶巧今天碰到了,就学习了下,先来描绘下要实现的"分割线"效果. 对,就是这个效果,记住了,这叫"分割线"... 最开始反应过来的是层叠起来实现效果,也是之前一直在用的方法 <hr width="80%"/> <div style=&quo

积跬步,聚小流------关于UML类图

UML的存在 类图是使用频率比較高的UML图,它用于描写叙述系统中所含的类以及它们之间的相互关系,帮助人们简化对系统的理解,也是系统分析和设计阶段的重要产物,也是系统编码和測试的重要类型根据. UML的表示方法 它的表示方法也比較简单,分成三层,第一层是类名.第二层是属性,第三层是方法. 而 属性和方法中用到的"+"表示public,"-"表示private,"#"表示protected.以及属性的写法:权限修饰符.属性名(方法名),然后是数据类

积跬步,聚小流------Bootstrap学习记录(3)

响应式作为Bootstrap的一大特色.栅格系统可谓是功不可没,既然如此,那我们就来看一下栅格系统是怎样帮助bootstrap实现响应式布局的呢? 1.什么是栅格系统 我们能够从Bootstrap的官网上找到比較官方的回答:Bootstrap提供了一套响应式.移动设备优先的流失栅格系统,随着屏幕或视口(viweport)的添加,系统会自己主动分为最多12列. 它包括了易于使用的提前定义类,还有强大的mixin用于生成更具语义的布局. 这样的说法是比較精准并且明了的.可是还能够更通俗一点的来解释:

积跬步,聚小流------oracle便捷修改整行数据

随着知识了解的越来越多,也越来越多的发现了自己的不足,简单记录下这次学到的知识吧. 尽管项目中都是用的oracle,但是实际上对于oracle的应用却不是很足,比方说,如果我查一个表中的数据,例: 这时候的这两条数据是我录入的测试数据,现在我想进行删除操作,可能我很快就能想到相应的sql语句: delete from arc_tobaccotechnician where name like '%是否%' 首先说这是对的,并且是非常快捷的,但是如果测试数据的共同点并不是那么好找呢,或者其它sql