java 图片处理-水印,透明图等

核能气质少年 提交于 2020-04-15 17:39:50

【推荐阅读】微服务还能火多久?>>>

这里 使用的是 thumbnailator , 我看了一下,目前作者又去维护了,而且start 数那么多,肯定比较稳定了,

网上的demo的也不少,一般的需求需求也满足了。

 <!--图片处理工具-->
        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.11</version>
        </dependency>

主要是最近 有一个业务需求,就是需要生成 海报或者说 生成对应的图片。

仿照  http://p0.prodapi.cn/#/  这里的功能一样。

其实也就是 通过 一层图层一层 图层的水印 盖上去,生成 最终的海报或者 对应的图片。

工具类型:

package com.newpearl.o2o.biz.utils;

import com.newpearl.utils.Preconditions;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Position;
import org.apache.commons.lang3.StringUtils;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
 * @version 1.0
 * @Description: 图片处理工具
 * @Author: oumin
 * @Date: 2020-04-15 10:54
 */
public class ImgMakerUtil {


    /**
     * 缩小图片
     * @param fileImg 原图
     * @param scale 缩小倍数
     */
    public static BufferedImage scaleImg(File fileImg, double scale) throws IOException {

        return Thumbnails.of(fileImg)
                .scale(scale).asBufferedImage();

    }

    /**
     * 将图片 生成对应尺寸的新图片
     * @param sourceImg
     * @param width
     * @param height
     * @return
     * @throws IOException
     */
    public  static  BufferedImage imgChangeSize(File sourceImg,int width, int height)throws IOException {

        return Thumbnails.of(sourceImg)
                .size(width,height)
                .asBufferedImage();
    }


    /**
     * 生成一张包含文字的图片(或者是透明的文字图片)
     * @param text 文字内容
     * @param img_width 生成新图的图片宽度
     * @param img_height 生成新图的图片高度
     * @param img_bg_color 生成新图的图片背景颜色(如果为空,代表是一张透明的图片) 比如 #FFFFFF 白色
     * @param fontColor 文字颜色(黑色) 比如 #FFFFFF 白色
     * @param fontName  字体(默认黑体)
     * @param fontSize  字体大小
     * @param fontXPoint 文字在图片的X位置(默认 0 )
     * @param fontYPoint 文字在图片的Y位置 (默认 等于 fontSize)
     */
    public   static BufferedImage  createTextImg(String text,
                      int img_width, int img_height, String img_bg_color,
                 String fontColor,String fontName,int fontSize,
                   Integer fontXPoint,Integer fontYPoint){
        Preconditions.checkArgument(StringUtils.isBlank(text),"文字不能为空");
        //是否透明背景图片
        boolean transparent =false;
        if (StringUtils.isBlank(img_bg_color)){
            transparent=true;
        }

        Color java_fontColor=null;
        if (StringUtils.isBlank(fontColor)){
            java_fontColor=Color.BLACK;
        }else{
            java_fontColor=Color.decode(fontColor);
        }
        if (StringUtils.isBlank(fontName)){
            fontName="黑体";
        }
        if (fontXPoint==null){
            fontXPoint=0;
        }
        if (fontYPoint == null) {
            fontYPoint=fontSize;
        }




        // 获取图片的缓冲区,也就是所谓的画布
        BufferedImage bufferedImage = new BufferedImage(img_width, img_height, BufferedImage.TYPE_INT_RGB);



        //获取画笔,画笔用于在画布上进行绘制
        Graphics2D paint = (Graphics2D) bufferedImage.getGraphics();

        if (transparent){
            //背景透明
            bufferedImage = paint.getDeviceConfiguration().
                    createCompatibleImage(img_width,img_height, Transparency.TRANSLUCENT);
            paint = (Graphics2D) bufferedImage.getGraphics();
        }else{
            //设置背景色
              paint.setColor(Color.decode(img_bg_color));
            //绘制画布的背景色,范围, 这里是全部
             paint.fillRect(0, 0, img_width,img_height);
        }


        //设置画笔的颜色,字体颜色
        paint.setColor(java_fontColor);
        //字体 "Avenir,Helvetica,Arial,sans-serif"
        paint.setFont(new Font(fontName, Font.PLAIN, fontSize));
        //绘制显示的具体内容
        paint.drawString(text,fontXPoint,fontYPoint);//如果 y 轴大小和 字体大小一样,就不用担心文字显示不全


        return  bufferedImage;

    }


    /**
     * 生成一张图片(或者透明的图片)
     * @param img_width 图片宽度
     * @param img_height 图片高度
     * @param img_bg_color 图片背景颜色(如果为空,代表是一张透明的图片) 比如 #FFFFFF 白色
     * @return
     */
    public   static BufferedImage createImg(
           int img_width, int img_height, String img_bg_color){

        //是否透明背景图片
        boolean transparent =false;
        if (StringUtils.isBlank(img_bg_color)){
            transparent=true;
        }

        // 获取图片的缓冲区,也就是所谓的画布
        BufferedImage bufferedImage = new BufferedImage(img_width, img_height, BufferedImage.TYPE_INT_RGB);



        //获取画笔,画笔用于在画布上进行绘制
        Graphics2D paint = (Graphics2D) bufferedImage.getGraphics();

        if (transparent){
            //背景透明
            bufferedImage = paint.getDeviceConfiguration().
                    createCompatibleImage(img_width,img_height, Transparency.TRANSLUCENT);
            paint = (Graphics2D) bufferedImage.getGraphics();
        }else{
            //设置背景色
            paint.setColor(Color.decode(img_bg_color));
            //绘制画布的背景色,范围, 这里是全部
            paint.fillRect(0, 0, img_width,img_height);
        }


        return  bufferedImage;

    }


    /**
     * 生成水印新图片
     * @param sourceImg 原图,即 需要加上水印的图片
     * @param waterImg  目标图,即 水印
     * @param img_width 生成新图的 宽
     * @param img_height 生成新图的 高
     * @param xPoint  打水印的X轴
     * @param yPoint 打水印的Y轴
     * @param opacity 透明度  0.0~1.0 : 0 代表 完全透明,  1 代表 完全不透明
     */
    public static  BufferedImage   watermarkImage(BufferedImage sourceImg,BufferedImage waterImg,
                                         int img_width, int img_height,
                                         int xPoint,int yPoint, float opacity) throws IOException {


        Position position=new Position() {
            // enclosingWidth 底图 宽,enclosingHeight 底图高,
            // width 水印图 宽,height 水印图 高
            public Point calculate(int enclosingWidth, int enclosingHeight, int width, int height,
                                   int insetLeft, int insetRight, int insetTop, int insetBottom) {
                return new Point(xPoint,yPoint);
            }
        };



        BufferedImage watermarkImage = waterImg;

       return Thumbnails.of(sourceImg)
                .size(img_width,img_height)//生成新图的 大小
                .watermark( position,watermarkImage,opacity)
                .asBufferedImage();

    }





}

表:

package com.newpearl.o2o.api.model.poster;

import java.util.*;
import javax.persistence.*;
import java.io.Serializable;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.hibernate.annotations.Proxy;
/**
 * 海报模板poster_template的JPA对象
 *
 * @author oumin
 * @version 1.0
 * @Date 2020年04月15日 09:41:12
 */
@Entity
@Proxy(lazy = false)
@Table(name = "poster_template")
public class PosterTemplate implements Serializable {

	public static final String TABLE_NAME = "poster_template";

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	/**
	 * 创建时间
	 */
	@Column(name = "create_time", nullable = true, length = 19)
	private Date createTime;

	/**
	 * 更新时间
	 */
	@Column(name = "modify_time", nullable = true, length = 19)
	private Date modifyTime;

	/**
	 * 是否删除
	 */
	@Column(name = "removed", nullable = true, length = 1)
	private Boolean removed;

	/**
	 * 模板名称
	 */
	@Column(name = "name", nullable = true, length = 100)
	private String name;

	/**
	 * 模板编码
	 */
	@Column(name = "code", nullable = true, length = 64)
	private String code;

	/**
	 * 宽度px
	 */
	@Column(name = "width", nullable = true, length = 10)
	private Integer width;

	/**
	 * 模板高度px
	 */
	@Column(name = "height", nullable = true, length = 10)
	private Integer height;

	/**
	 * 背景色
	 */
	@Column(name = "bg_color", nullable = true, length = 255)
	private String bgColor;

	/**
	 * 如果有背景图片,背景图片的URL
	 */
	@Column(name = "bg_img_url", nullable = true, length = 500)
	private String bgImgUrl;

	/**
	 * 创建人ID
	 */
	@Column(name = "creator", nullable = true, length = 19)
	private Long creator;

	public Long getId() {
		return this.id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Date getCreateTime() {
		return this.createTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	public Date getModifyTime() {
		return this.modifyTime;
	}

	public void setModifyTime(Date modifyTime) {
		this.modifyTime = modifyTime;
	}

	public Boolean isRemoved() {
		return this.removed;
	}
	public Boolean getRemoved() {
		return this.removed;
	}

	public void setRemoved(Boolean removed) {
		this.removed = removed;
	}

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getCode() {
		return this.code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public Integer getWidth() {
		return this.width;
	}

	public void setWidth(Integer width) {
		this.width = width;
	}

	public Integer getHeight() {
		return this.height;
	}

	public void setHeight(Integer height) {
		this.height = height;
	}

	public String getBgColor() {
		return this.bgColor;
	}

	public void setBgColor(String bgColor) {
		this.bgColor = bgColor;
	}

	public String getBgImgUrl() {
		return this.bgImgUrl;
	}

	public void setBgImgUrl(String bgImgUrl) {
		this.bgImgUrl = bgImgUrl;
	}

	public Long getCreator() {
		return this.creator;
	}

	public void setCreator(Long creator) {
		this.creator = creator;
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}

}



子表
package com.newpearl.o2o.api.model.poster;

import com.newpearl.common.constant.poster.PosterLayerType;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.hibernate.annotations.Proxy;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
 * 海报模板图层poster_template_layer的JPA对象
 *
 * @author oumin
 * @version 1.0
 * @Date 2020年04月15日 09:43:22
 */
@Entity
@Proxy(lazy = false)
@Table(name = "poster_template_layer")
public class PosterTemplateLayer implements Serializable {

	public static final String TABLE_NAME = "poster_template_layer";

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	/**
	 * 排序,即图层的添加 顺序,越小越先添加
	 */
	@Column(name = "order_value", nullable = true, length = 19)
	private Long orderValue;

	/**
	 * 创建时间
	 */
	@Column(name = "create_time", nullable = true, length = 19)
	private Date createTime;

	/**
	 * 更新时间
	 */
	@Column(name = "modify_time", nullable = true, length = 19)
	private Date modifyTime;

	/**
	 * 是否删除
	 */
	@Column(name = "removed", nullable = true, length = 1)
	private Boolean removed;

	/**
	 * 图层名称
	 */
	@Column(name = "name", nullable = true, length = 100)
	private String name;

	/**
	 * 所属海报模板id
	 */
	@Column(name = "template_id", nullable = true, length = 19)
	private Long templateId;

	/**
	 * 动态参数编码
	 */
	@Column(name = "dynamic_parameter_code", nullable = true, length = 255)
	private String dynamicParameterCode;

	/**
	 * 默认参数值,即图层的值,图片就是url, 文字就是 文字内容
	 */
	@Column(name = "parameter_value", nullable = true, length = 255)
	private String parameterValue;

	/**
	 * 宽度px
	 */
	@Column(name = "width", nullable = true, length = 10)
	private Integer width;

	/**
	 * 高度px
	 */
	@Column(name = "height", nullable = true, length = 10)
	private Integer height;

	/**
	 * x轴坐标值
	 */
	@Column(name = "x_point", nullable = true, length = 10)
	private Integer xpoint;

	/**
	 * y轴坐标值
	 */
	@Column(name = "y_point", nullable = true, length = 10)
	private Integer ypoint;

	/**
	 * 图层类型: IMG 图片, TEXT 文字
	 */
	@Column(name = "type", nullable = true, length = 255)
	private String type= PosterLayerType.IMG.toString();

	/**
	 * 颜色: 图片就是图层背景颜色, 文字就是 文字的颜色
	 */
	@Column(name = "color", nullable = true, length = 255)
	private String color;

	/**
	 * 字体大小
	 */
	@Column(name = "font_size", nullable = true, length = 10)
	private Integer fontSize;

    /**
     * 字体名称: 比如 苹方字体
     */
    @Column(name = "font_name", nullable = true, length = 255)
	private  String fontName;

    public String getFontName() {
        return fontName;
    }

    public void setFontName(String fontName) {
        this.fontName = fontName;
    }

    public Long getId() {
		return this.id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Long getOrderValue() {
		return this.orderValue;
	}

	public void setOrderValue(Long orderValue) {
		this.orderValue = orderValue;
	}

	public Date getCreateTime() {
		return this.createTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	public Date getModifyTime() {
		return this.modifyTime;
	}

	public void setModifyTime(Date modifyTime) {
		this.modifyTime = modifyTime;
	}

	public Boolean isRemoved() {
		return this.removed;
	}
	public Boolean getRemoved() {
		return this.removed;
	}

	public void setRemoved(Boolean removed) {
		this.removed = removed;
	}

	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Long getTemplateId() {
		return this.templateId;
	}

	public void setTemplateId(Long templateId) {
		this.templateId = templateId;
	}

	public String getDynamicParameterCode() {
		return this.dynamicParameterCode;
	}

	public void setDynamicParameterCode(String dynamicParameterCode) {
		this.dynamicParameterCode = dynamicParameterCode;
	}

	public String getParameterValue() {
		return this.parameterValue;
	}

	public void setParameterValue(String parameterValue) {
		this.parameterValue = parameterValue;
	}

	public Integer getWidth() {
		return this.width;
	}

	public void setWidth(Integer width) {
		this.width = width;
	}

	public Integer getHeight() {
		return this.height;
	}

	public void setHeight(Integer height) {
		this.height = height;
	}

	public Integer getXpoint() {
		return this.xpoint;
	}

	public void setXpoint(Integer xpoint) {
		this.xpoint = xpoint;
	}

	public Integer getYpoint() {
		return this.ypoint;
	}

	public void setYpoint(Integer ypoint) {
		this.ypoint = ypoint;
	}

	public String getType() {
		return this.type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getColor() {
		return this.color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public Integer getFontSize() {
		return this.fontSize;
	}

	public void setFontSize(Integer fontSize) {
		this.fontSize = fontSize;
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
	}

}







 

生成 海报代码:

 @Override
    public String buildPoster(Long id, String dynamicParameterJson) throws IOException {
        JSONObject dynJson=new JSONObject();
        String http = "http";
        if (StringUtils.isNotBlank(dynamicParameterJson)){
            dynJson=JSONObject.parseObject(dynamicParameterJson);
        }

        PosterTemplate dbObj = this.getPosterTemplate(id);
        if (dbObj ==null || dbObj.isRemoved()){
            Preconditions.checkArgument(true,"海报不存在!");
        }
        List<PosterTemplateLayer> layers  =posterTemplateLayerDao.findByTemplateId(id);


        //模板图
        BufferedImage tempImg=null;
        if (StringUtils.isBlank(dbObj.getBgImgUrl())){
            // 生成 模板图
            tempImg= ImgMakerUtil.createImg(dbObj.getWidth(),dbObj.getHeight(),dbObj.getBgColor());

            //ImageIO.write(tempImg, "png", FileUtil.touch("C:\\Users\\sheji204\\Desktop\\test\\tempImg.png"));

        }else{


            if (dbObj.getBgImgUrl().contains(http)) {
                tempImg = ImageIO.read(new URL(dbObj.getBgImgUrl()));
            } else {
                tempImg = ImageIO.read(new URL("http:" + dbObj.getBgImgUrl()));
            }


        }

        //图层依次打水印
        BufferedImage beforeLayer=tempImg;//上一层 图片
        for (PosterTemplateLayer layer : layers) {
            //动态json 参数赋值
            if (!dynJson.isEmpty() && dynJson.containsKey(layer.getDynamicParameterCode())){
                String dynValue=dynJson.getString(layer.getDynamicParameterCode());
                layer.setParameterValue(dynValue);
            }

            if (layer.getType().equals(PosterLayerType.IMG.toString())){
                //纯图片层
                BufferedImage imgLayer=null;

//                if (layer.getName().equals("头像图层")){
//                    imgLayer=ImageIO.read(new File("C:\\Users\\sheji204\\Desktop\\thumbnail.thumbnail.分享名片.png"));
//                }else if(layer.getName().equals("二维码图层")){
//                    imgLayer=ImageIO.read(new File("C:\\Users\\sheji204\\Desktop\\缩小一半.名片底板.png"));
//                }

                if (layer.getParameterValue().contains(http)) {
                    imgLayer = ImageIO.read(new URL(layer.getParameterValue()));
                } else {
                    imgLayer = ImageIO.read(new URL("http:" + layer.getParameterValue()));
                }


                //打水印 生成图层
                beforeLayer =ImgMakerUtil.watermarkImage(beforeLayer,imgLayer,
                        dbObj.getWidth(),dbObj.getHeight(),
                        layer.getXpoint(),layer.getYpoint(),1.0f);

//                ImageIO.write(beforeLayer, "png",
//                        FileUtil.touch("C:\\Users\\sheji204\\Desktop\\test\\"+layer.getName()+".png"));


            }else if (layer.getType().equals(PosterLayerType.TEXT.toString())){
                //图片文字
                String fontName=layer.getFontName();
                if (StringUtils.isBlank(fontName)){
                    fontName="苹方字体";
                }
                BufferedImage textImg=ImgMakerUtil.createTextImg(layer.getParameterValue(),
                        layer.getWidth(),layer.getHeight(),null,layer.getColor(),
                        fontName,layer.getFontSize(),
                        null,null);

                beforeLayer =ImgMakerUtil.watermarkImage(beforeLayer,textImg,
                        dbObj.getWidth(),dbObj.getHeight(),
                        layer.getXpoint(),layer.getYpoint(),1.0f);


//                ImageIO.write(beforeLayer, "png",
//                        FileUtil.touch("C:\\Users\\sheji204\\Desktop\\test\\"+layer.getName()+".png"));


            }else if (layer.getType().equals(PosterLayerType.QR_CODE.toString())){
                //二维码 , 就根据 URL 生成二维码图片
                // 画二维码
                BitMatrix bitMatrix = QRCodeUtil.setBitMatrix(layer.getParameterValue(), layer.getWidth(), layer.getHeight());
                BufferedImage qrCode = QRCodeUtil.toBufferedImage(bitMatrix);

//                LoginUser loginUser= UserHandler.getLoginUser();
//                if (loginUser.getIcon() != null) {
//                    if (loginUser.getIcon().contains(http)) {
//                        QRCodeUtil.addLogo(qrCode, new URL(loginUser.getIcon()));
//                    } else {
//                        QRCodeUtil.addLogo(qrCode, new URL("http:" + loginUser.getIcon()));
//                    }
//                }

                //打水印 生成图层
                beforeLayer =ImgMakerUtil.watermarkImage(beforeLayer,qrCode,
                        dbObj.getWidth(),dbObj.getHeight(),
                        layer.getXpoint(),layer.getYpoint(),1.0f);


            }


        }


        //生成图片, 上传 阿里云,返回图片路径
       // ImageIO.write(beforeLayer, "png", FileUtil.touch("C:\\Users\\sheji204\\Desktop\\shareTest.png"));

        // 将图片上传至OSS
        InputStream inputStream;
        ByteArrayOutputStream bs = new ByteArrayOutputStream();
        ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
        ImageIO.write(beforeLayer, "png", imOut);
        inputStream = new ByteArrayInputStream(bs.toByteArray());
        AliyunOssHelper ossHelper = new AliyunOssHelper();
        String ossPath = AliyunOssPathUtils.getRandomFilePathByName("POSTER_PHOTO" + CommonUtils.getUUID() + ".jpg");
        OSSClient ossClient = ossHelper.getOssClient(AliyunOssPathUtils.getFileType());
        ossClient.putObject(
                ossHelper.getBucket(),
                ossPath,
                inputStream);
        if (!ossClient.doesObjectExist(ossHelper.getBucket(), ossPath)) {
            return null;
        }
        return ossHelper.getBucket_cname() + "/" + ossPath;
    }

 

供参考资源



hutool 的: https://www.hutool.cn/docs/#/core/%E5%9B%BE%E7%89%87/%E5%9B%BE%E7%89%87%E5%B7%A5%E5%85%B7-ImgUtil

https://gitee.com/biezhi/image-plugin?_from=gitee_search


https://github.com/m310851010/xice7-imageKit

https://www.jianshu.com/p/bf6a470aa7bf

https://blog.csdn.net/zixiaomuwu/article/details/51082056



这个google 的 更强感觉:

 https://github.com/coobird/thumbnailator

https://www.jb51.net/article/113461.htm

https://www.oschina.net/p/thumbnailator

 

 

 

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!