java 生成分享图片(二维码,图片拼接,文字编辑)

您所在的位置:网站首页 java二维码图片生成方法有哪些软件可以用的 java 生成分享图片(二维码,图片拼接,文字编辑)

java 生成分享图片(二维码,图片拼接,文字编辑)

2024-07-15 14:48:26| 来源: 网络整理| 查看: 265

需求背景

之前遇到过需要后端,根据每个用户生成带背景宣传图带二维码带用户图片带文字的合成图片的需求,自己当时花了半天的时间整理了资料,今天把自己写的代码分享出来,如果有同样需求的人,希望能给个好评,有其他建议的童鞋,可以一起讨论交流。

文章下面贴有项目地址,感谢star 项目整合了二维码和日志,有需要的童鞋也可以做参考

图片缓冲类 BufferedImage

BufferedImage类是Image的实现类,是可以把图片加载到内存的缓冲类,我写的代码中就基本上都是基于该类实现对图片的操作。

图片加载 Thumbnails

Thumbnails是谷歌开源的一套图片工具类 当我需要把本地图片加载进来得到BufferedImage对象的时候,我们可以通过

Thumbnails.of(filePath) .scale(1) .asBufferedImage();

如果是远程图片

Thumbnails.of(new URL(filePath)) .scale(1) .asBufferedImage(); 添加文本 /** * 修改图片,返回修改后的图片缓冲区(只输出一行文本) */ public BufferedImage modifyImage(BufferedImage img, Object content, int x, int y) { try { int w = img.getWidth(); int h = img.getHeight(); g = img.createGraphics(); g.setBackground(Color.WHITE); g.setColor(Color.BLACK);//设置字体颜色 if (this.font != null) { g.setFont(this.font); } // 验证输出位置的纵坐标和横坐标 if (x >= h || y >= w) { this.x = h - this.fontsize + 2; this.y = w; } else { this.x = x; this.y = y; } g.setFont( new Font("微软雅黑", Font.BOLD, 22)); if (content != null) { g.drawString(content.toString(), this.x, this.y); } g.setBackground(Color.WHITE); g.dispose(); } catch (Exception e) { System.out.println(e.getMessage()); } return img; } 生成图片到本地

ImageIO提供了write的方法,将图片文件打印到本地

/** * 生成新图片到本地 */ public boolean writeImageLocal(String newImage, BufferedImage img) { boolean isok = false; if (newImage != null && img != null) { try { File outputfile = new File(newImage); isok = ImageIO.write(img, "jpg", outputfile); } catch (IOException e) { System.out.println(e.getMessage()); } } return isok; } 工具类代码

有了上面四个点,我们基本上就可以图片为所欲为了

package com.xwn.utils; import javax.imageio.ImageIO; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.io.File; import java.io.IOException; import java.net.URL; import java.awt.Rectangle; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.InputStream; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.imageio.ImageReadParam; import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; import com.xwn.constant.Constant; import com.xwn.constant.PicConstant; import com.xwn.model.UserInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.Assert; import net.coobird.thumbnailator.Thumbnails; import java.awt.RenderingHints; import java.awt.geom.Ellipse2D; /** * 服务端画图 * 绘制,拼接,修改图片 * @author xwn */ public class PictureUtils { private static final Logger log = LoggerFactory.getLogger(PictureUtils.class); private Font font = new Font("微软雅黑", Font.BOLD, 70);// 添加字体的属性设置 private Graphics2D g = null; private int fontsize = 0; private int x = 0; private int y = 0; /** * 导入本地图片到缓冲区 */ public BufferedImage loadImageLocal(String imgName) { try { return ImageIO.read(new File(imgName)); } catch (IOException e) { System.out.println(e.getMessage()); } return null; } /** * 导入网络图片到缓冲区 */ public BufferedImage loadImageUrl(String imgName) { try { URL url = new URL(imgName); return ImageIO.read(url); } catch (IOException e) { System.out.println(e.getMessage()); } return null; } /** * 生成新图片到本地 */ public boolean writeImageLocal(String newImage, BufferedImage img) { boolean isok = false; if (newImage != null && img != null) { try { File outputfile = new File(newImage); isok = ImageIO.write(img, "jpg", outputfile); } catch (IOException e) { System.out.println(e.getMessage()); } } return isok; } /** * 将{@link BufferedImage}生成formatName指定格式的图像数据 * @param source * @param formatName 图像格式名,图像格式名错误则抛出异常 * @return */ public static void wirteBytes(BufferedImage source,String formatName,String newImage){ Assert.notNull(source, "source"); ByteArrayOutputStream output = new ByteArrayOutputStream(); Graphics2D g = null; try { for(BufferedImage s=source;!ImageIO.write(s, formatName, output);){ if(null!=g) { throw new IllegalArgumentException(String.format("not found writer for '%s'",formatName)); } s = new BufferedImage(source.getWidth(),source.getHeight(), BufferedImage.TYPE_INT_RGB); g = s.createGraphics(); g.drawImage(source, 0, 0,null); } } catch (IOException e) { throw new RuntimeException(e); } finally { if (null != g) { g.dispose(); } } } /** * 将指定颜色变透明 只能保存 png jpg * @param imageSrc 图片 * @param mask 颜色 * @return */ public static BufferedImage createImageByMaskColorEx(BufferedImage imageSrc, Color mask) { int x, y; x = imageSrc.getWidth(null); y = imageSrc.getHeight(null); BufferedImage imageDes = new BufferedImage(x, y, BufferedImage.TYPE_4BYTE_ABGR); WritableRaster rasterDes = imageDes.getRaster(); int[] des = new int[4]; while (--x >= 0) { for (int j = 0; j des[3] = 0; } else { des[0] = sr; des[1] = sg; des[2] = sb; des[3] = 255; } rasterDes.setPixel(x, j, des); } } return imageDes; } /** * 设置颜色 * @param img 图片 * @return */ public BufferedImage setColor(BufferedImage img){ //定义一个数组,存放RGB值 int[] rgb = new int[3]; int width = img.getWidth(); int height = img.getHeight(); int minx = img.getMinTileX(); int miny = img.getMinTileY(); //遍历像素点,判断是否更换颜色 for (int i = minx; i //换色 int pixel = img.getRGB(i, j); rgb[0] = (pixel & 0xff0000) >>16; rgb[1] = (pixel & 0xff00) >>8; rgb[2] = (pixel & 0xff) ; if (rgb[0]100&& rgb[1]100 && rgb[2]100) { img.setRGB(i, j, 0xffffff); } } } return img; } /** * 设定文字的字体等 * @param fontStyle 文字字体 * @param fontSize 大小 */ public void setFont(String fontStyle, int fontSize) { this.fontsize = fontSize; this.font = new Font(fontStyle, Font.PLAIN, fontSize); } /** * 修改图片,返回修改后的图片缓冲区(只输出一行文本) */ public BufferedImage modifyImage(BufferedImage img, Object content, int x, int y) { try { int w = img.getWidth(); int h = img.getHeight(); g = img.createGraphics(); g.setBackground(Color.WHITE); g.setColor(Color.BLACK);//设置字体颜色 if (this.font != null) { g.setFont(this.font); } // 验证输出位置的纵坐标和横坐标 if (x >= h || y >= w) { this.x = h - this.fontsize + 2; this.y = w; } else { this.x = x; this.y = y; } g.setFont( new Font("微软雅黑", Font.BOLD, 22)); if (content != null) { g.drawString(content.toString(), this.x, this.y); } g.setBackground(Color.WHITE); g.dispose(); } catch (Exception e) { System.out.println(e.getMessage()); } return img; } /** * 修改图片,返回修改后的图片缓冲区(只输出一行文本) * @param img 图片 * @return */ public BufferedImage modifyImageYe(BufferedImage img) { try { int w = img.getWidth(); int h = img.getHeight(); g = img.createGraphics(); g.setBackground(Color.WHITE); g.setColor(Color.blue);//设置字体颜色 if (this.font != null) g.setFont(this.font); g.drawString("reyo.cn", w - 85, h - 5); g.dispose(); } catch (Exception e) { System.out.println(e.getMessage()); } return img; } /** * 合成图片 * @param b 图片b * @param d 图片d * @param x x坐标 * @param y y坐标 * @param height 高度 * @param weight 宽度 * @return */ public BufferedImage modifyImagetogeter(BufferedImage b, BufferedImage d,int x,int y,int height ,int weight) { try { g = d.createGraphics(); g.drawImage(b, x, y, weight, height, null); g.dispose(); } catch (Exception e) { System.out.println(e.getMessage()); } return d; } /** * 对图片进行剪裁 返回字节数组 * @param is 图片输入流 * @param width 裁剪图片的宽 * @param height 裁剪图片的高 * @param imageFormat 输出图片的格式 "jpeg jpg等" * @return */ public static byte[] clipImage(InputStream is,int width, int height, String imageFormat){ ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { // 构造Image对象 BufferedImage src = javax.imageio.ImageIO.read(is); // 缩小边长 BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 绘制 缩小 后的图片 tag.getGraphics().drawImage(src, 0, 0, width, height, null); ImageIO.write(tag, imageFormat, bos); } catch (IOException e) { e.printStackTrace(); } return bos.toByteArray(); } /** * 对图片裁剪,并把裁剪新图片保存 * @param srcPath 读取源图片路径 * @param toPath 写入图片路径 * @param x 剪切起始点x坐标 * @param y 剪切起始点y坐标 * @param width 剪切宽度 * @param height 剪切高度 * @param readImageFormat 读取图片格式 * @param writeImageFormat 写入图片格式 */ public static void cropImage(String srcPath, String toPath, int x,int y,int width,int height, String readImageFormat,String writeImageFormat){ FileInputStream fis = null ; ImageInputStream iis =null ; try{ //读取图片文件 fis = new FileInputStream(srcPath); Iterator readers = ImageIO.getImageReadersByFormatName(readImageFormat); ImageReader reader = readers.next(); //获取图片流 iis = ImageIO.createImageInputStream(fis); reader.setInput(iis, true); ImageReadParam param = reader.getDefaultReadParam(); //定义一个矩形 Rectangle rect = new Rectangle(x, y, width, height); //提供一个 BufferedImage,将其用作解码像素数据的目标。 param.setSourceRegion(rect); BufferedImage bi = reader.read(0, param); //保存新图片 ImageIO.write(bi, writeImageFormat, new File(toPath)); }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(fis!=null){ fis.close(); } if(iis!=null){ iis.close(); } }catch(Exception e){ e.printStackTrace(); } } } /** * 传入的图像必须是正方形的 才会 圆形 如果是长方形的比例则会变成椭圆的 * @param bi1 图片 * @return * @throws IOException */ public static BufferedImage convertCircular(BufferedImage bi1) throws IOException { // 透明底的图片 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.setClip(shape); // 使用 setRenderingHint 设置抗锯齿 g2.drawImage(bi1, 0, 0, null); // 设置颜色 g2.setBackground(Color.green); g2.dispose(); return bi2; } /** * 缩小Image,此方法返回源图像按给定宽度、高度限制下缩放后的图像 * @param inputImage * @param newWidth:压缩后宽度 * @param newHeight:压缩后高度 * @param beijing:背景图片 * @throws java.io.IOException */ public static BufferedImage scaleByPercentage(BufferedImage inputImage, int newWidth, int newHeight,BufferedImage beijing) throws Exception { // 获取原始图像透明度类型 int type = inputImage.getColorModel().getTransparency(); int width = inputImage.getWidth(); int height = inputImage.getHeight(); // 开启抗锯齿 RenderingHints renderingHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 使用高质量压缩 renderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); BufferedImage img = new BufferedImage(newWidth, newHeight, type); Graphics2D graphics2d = img.createGraphics(); graphics2d.setRenderingHints(renderingHints); graphics2d.drawImage(inputImage, 0, 0, newWidth, newHeight, 0, 0, width, height, null); graphics2d.dispose(); return img; } /** * 头像缩放 四舍五入 double转int * @param beijing_ * @return */ public static Integer doubleToInt(BufferedImage beijing_,double d){ return (new Double((d*beijing_.getHeight()))).intValue(); } /** * 让字符串隔开展现 * @param code * @return */ public static String getCode(String code){ StringBuilder sb = new StringBuilder(); for (int i = 0; i sb.append(code.charAt(i)).append(" "); }else{ sb.append(code.charAt(i)); } } return sb.toString(); } /** * 网络图片输出到BufferedImage * @throws IOException */ private BufferedImage getBufferedImageForURL(String filePath) throws IOException { //asBufferedImage() 返回BufferedImage BufferedImage thumbnail = Thumbnails.of(new URL(filePath)) .scale(1) .asBufferedImage(); return thumbnail; } /** * 本地图片输出到BufferedImage * @throws IOException */ private BufferedImage getBufferedImageForLocal(String filePath) throws IOException { /** * asBufferedImage() 返回BufferedImage */ BufferedImage thumbnail = Thumbnails.of(filePath) .scale(1) .asBufferedImage(); return thumbnail; } /** * 合成图片 * @param user 用户 * @throws IOException */ public static void initImage(UserInfo user) throws IOException { Map map = new HashMap(); PictureUtils tt = new PictureUtils(); String baseUrl = Constant.BASE_URL; String beijing = PicConstant.yaoqingbeijing128; String dibian = PicConstant.yaoqingdibian128; //底边合成背景 String newPicUrl = new StringBuffer(baseUrl).append("ok/").append(user.getUserId()).append(".jpg").toString(); if(!new File(newPicUrl).exists()){ //获取绑定二维码图片 Map qrCodeMap = QrCodeUtil.getUserQrImgURL(user); if(qrCodeMap != null){ String qrCodeImgURL = qrCodeMap.get("qrPath"); String qrCode = qrCodeMap.get("qrCode"); boolean isOk = true; try { BufferedImage head_ = tt.getBufferedImageForURL(user.getHeadImgUrl()); BufferedImage qrCodeImg = tt.getBufferedImageForLocal(qrCodeImgURL); BufferedImage beijing_ = tt.getBufferedImageForURL(beijing); BufferedImage dibian_ = tt.getBufferedImageForURL(dibian); head_ = convertCircular(head_); head_ = scaleByPercentage(head_, doubleToInt(dibian_,PicConstant.DOUBLE_TO_INT_HEAD), doubleToInt(dibian_,PicConstant.DOUBLE_TO_INT_HEAD),beijing_); isOk = tt.writeImageLocal(new StringBuilder(baseUrl).append("head.jpg").toString(),head_); //合成头像 int x = 30; int y = 75; int weight1 = head_.getWidth(); int height1 = head_.getHeight(); tt.modifyImagetogeter(head_, dibian_,x,y,height1,weight1); isOk = tt.writeImageLocal(new StringBuilder(baseUrl).append("dibian.jpg").toString(), tt.modifyImagetogeter(head_, dibian_,x,y,height1,weight1)); //添加文字 x = 100; y = 135; tt.modifyImage(dibian_,getCode(user.getInviteCode()),x,y); isOk = tt.writeImageLocal(new StringBuilder(baseUrl).append("xiabufen1.jpg").toString(),tt.modifyImage(dibian_,getCode(user.getInviteCode()),x,y)); //合成二维码 x = 325; y = 12; int weight3 = doubleToInt(qrCodeImg,PicConstant.DOUBLE_TO_INT_QR); int height3 = doubleToInt(qrCodeImg,PicConstant.DOUBLE_TO_INT_QR); tt.modifyImagetogeter(qrCodeImg, dibian_,x,y,doubleToInt(qrCodeImg,PicConstant.DOUBLE_TO_INT_QR),doubleToInt(qrCodeImg,PicConstant.DOUBLE_TO_INT_QR)); isOk = tt.writeImageLocal(new StringBuilder(baseUrl).append("xiabufen2.jpg").toString(), tt.modifyImagetogeter(qrCodeImg, dibian_,x,y,height3,weight3)); x = 0; y = beijing_.getHeight()-dibian_.getHeight(); int weight = dibian_.getWidth(); int height = dibian_.getHeight(); isOk = tt.writeImageLocal(newPicUrl, tt.modifyImagetogeter(dibian_, beijing_,x,y,height,weight)); } catch (Exception e) { log.error("合成"+ e.getMessage()); } if(!isOk){ log.error("生成图片失败!"); } map.put("qrCode", qrCode); map.put("newPicUrl", newPicUrl); } }else{ map.put("qrCode", new StringBuffer(Constant.DEFAULT_IMG_BASEURL).append(user.getUserId()).toString()); map.put("newPicUrl", newPicUrl); } log.info(map.toString()); } public static void main(String[] args) throws IOException { UserInfo user = new UserInfo(); user.setUserId(1); user.setHeadImgUrl(PicConstant.Head_Test); user.setInviteCode("123456"); initImage(user); } }

这里我只放主工具类的代码,想要全部代码可以点击文章下面的码云地址下载项目。

效果图片

示例样本用到了我的对象存储,有兴趣的童鞋可以点击 阿里云COS

附带图片部分图片 完成的图片在这里插入图片描述

码云地址

https://gitee.com/love_xwn/csdn-space.git



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭