java 水印

package com.xiaoai.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

@Slf4j
public class SysUtils {
    /**
     * 验证手机号
     *
     * @param str
     * @return
     * @throws PatternSyntaxException
     */
    public static boolean checkChinaPhoneLegal(String str) throws PatternSyntaxException {
        // ^ 匹配输入字符串开始的位置
        // \d 匹配一个或多个数字,其中 \ 要转义,所以是 \\d
        // $ 匹配输入字符串结尾的位置
        String regExp = "(^1[3|4|5|6|7|8|9]\\d{9}$)|(^09\\d{8}$)";
        Pattern p = Pattern.compile(regExp);
        Matcher m = p.matcher(str);
        return m.matches();
    }

    public static boolean checkEmail(String email) {// 验证邮箱的正则表达式
        String format = "\\p{Alpha}\\w{2,15}[@][a-z0-9]{3,}[.]\\p{Lower}{2,}";
        //p{Alpha}:内容是必选的,和字母字符[\p{Lower}\p{Upper}]等价。如:200896@163.com不是合法的。
        //w{2,15}: 2~15个[a-zA-Z_0-9]字符;w{}内容是必选的。 如:dyh@152.com是合法的。
        //[a-z0-9]{3,}:至少三个[a-z0-9]字符,[]内的是必选的;如:dyh200896@16.com是不合法的。
        //[.]:'.'号时必选的; 如:dyh200896@163com是不合法的。
        //p{Lower}{2,}小写字母,两个以上。如:dyh200896@163.c是不合法的。
        return email.matches(format);
    }

    public static String getUUID() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    public static Date getDate(Date date) {
        return dateAddDay(date, 1);
    }

    public static Date dateAddDay(Date date, int day) {
        Date date1 = nowDate(date);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date1);//设置起时间
        cal.add(Calendar.DATE, day);//增加一天
        Date date2 = cal.getTime();
        return date2;
    }


    public static Date nowDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String time = sdf.format(date);
        Date date1 = null;
        try {
            date1 = sdf.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date1;
    }

    /**
     * 描述:获取下一个月的第一天.
     *
     * @return
     */
    public static Date getPerFirstDayOfMonth() {
        SimpleDateFormat dft = new SimpleDateFormat("yyyyMMdd");
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, 1);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
        Date date = calendar.getTime();
        String format = dft.format(date);
        try {
            return dft.parse(format);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取月份最后一天
     *
     * @param
     * @return
     * @throws ParseException
     */
    public static Date getMaxMonthDate(Date date) {
        SimpleDateFormat dft = new SimpleDateFormat("yyyyMMdd");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        String dateStr = dft.format(calendar.getTime());
        dateStr = dateStr + "235959";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        try {
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取当年的最后一天
     *
     * @param
     * @return
     */
    public static Date getCurrYearLast() {
        Calendar currCal = Calendar.getInstance();
        int currentYear = currCal.get(Calendar.YEAR);
        Date date = getYearLast(currentYear);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String format = sdf.format(date);
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmmss");
        format = format + "235959";
        try {
            return sdf1.parse(format);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取某年最后一天日期
     *
     * @param year 年份
     * @return Date
     */
    public static Date getYearLast(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        return calendar.getTime();
    }

    public static JSONObject sendPost(String url, Map<String, Object> map, RestTemplate restTemplate) {
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        String jsonParam = JSON.toJSONString(map);
        HttpEntity<String> formEntity = new HttpEntity<>(jsonParam, headers);
        JSONObject result = restTemplate.postForEntity(url, formEntity, JSONObject.class).getBody();
        assert result != null;
        log.info(result.toString());
        return result;
    }

//    public static InputStream sendBufferPost(String url, Map<String, Object> map, RestTemplate restTemplate) {
//        HttpHeaders headers = new HttpHeaders();
//        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
//        headers.setContentType(type);
//        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
//        String jsonParam = JSON.toJSONString(map);
//        HttpEntity<String> formEntity = new HttpEntity<>(jsonParam, headers);
//        ResponseEntity<byte[]> entity =
//                restTemplate.exchange(url, HttpMethod.POST,formEntity, byte[].class);
//        byte[] result = entity.getBody();
//        return new ByteArrayInputStream(result);
//    }

    public static byte[] sendBufferPost(String url, Map<String, Object> map, RestTemplate restTemplate) {
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        String jsonParam = JSON.toJSONString(map);
        HttpEntity<String> formEntity = new HttpEntity<>(jsonParam, headers);
        ResponseEntity<byte[]> entity =
                restTemplate.exchange(url, HttpMethod.POST, formEntity, byte[].class);
        return entity.getBody();
    }

    /**
     * 计算地球上任意两点(经纬度)距离
     *
     * @param long1 第一点经度
     * @param lat1  第一点纬度
     * @param long2 第二点经度
     * @param lat2  第二点纬度
     * @return 返回距离 单位:米
     */
    public static double distanceByLongNLat(double long1, double lat1, double long2, double lat2) {
        double a, b, R;
        R = 6378137;//地球半径
        lat1 = lat1 * Math.PI / 180.0;
        lat2 = lat2 * Math.PI / 180.0;
        a = lat1 - lat2;
        b = (long1 - long2) * Math.PI / 180.0;
        double d;
        double sa2, sb2;
        sa2 = Math.sin(a / 2.0);
        sb2 = Math.sin(b / 2.0);
        d = 2 * R * Math.asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1) * Math.cos(lat2) * sb2 * sb2));
        return d;
    }


    /**
     * 添加水印
     * @param inputStream
     * @param mark
     * @return
     */
    public static InputStream addMark(InputStream inputStream, String mark,Integer rgb,Float alpha,Integer fontSize,Integer degree) {

        if(Objects.isNull(rgb)){
            rgb = 0xffffff;
        }
        if(Objects.isNull(alpha)){
            alpha = 1F;
        }
        if(Objects.isNull(fontSize)){
            fontSize = 60;
        }

        String[] waterMarkContents = mark.split("\\|\\|");
        // 用来调整水印的间距
        int space = 20;
        //将读取流转化为图片对象
        Image srcImg = null;
        try {
            srcImg = ImageIO.read(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //获取图片的宽
        int srcImgWidth = srcImg.getWidth(null);
        //获取图片的高
        int srcImgHeight = srcImg.getHeight(null);
        System.out.println("图片的宽:" + srcImgWidth);
        System.out.println("图片的高:" + srcImgHeight);

        BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
        // 加水印
        //创建画笔
        Graphics2D g = bufImg.createGraphics();
        //设置对线段的锯齿状边缘处理
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        //srcImg 为上面获取到的原始图片的图片对象
        g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);

        //设置水印旋转
        if (null != degree) {
            g.rotate(Math.toRadians(degree),
                    (double) bufImg.getWidth() / 2,
                    (double) bufImg.getHeight() / 2);
        }

        //根据图片的背景设置水印颜色

        g.setColor(new Color(rgb));
        g.setComposite(AlphaComposite
                .getInstance(AlphaComposite.SRC_OVER, alpha));
        //设置字体  画笔字体样式为微软雅黑,加粗,文字大小为60pt
        g.setFont(new Font("微软雅黑", Font.BOLD, fontSize));



        java.util.List<String> waterMarkContentList = new ArrayList<>();
// 将换行后的文字放入新的集合
        for (String markContent : waterMarkContents) {
            // 单字符长度
            int tempCharLen = 0;
            // 单行字符总长度临时计算
            int tempLineLen = 0;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < markContent.length(); i++) {
                char tempChar = markContent.charAt(i);
                tempCharLen = getCharLen(tempChar, g);
                tempLineLen += tempCharLen;
                // 文字长度大于图片宽度-2*间距-字体大小
                if (tempLineLen > srcImgWidth - space * 2 - tempCharLen) {
                    // 长度已经满一行
                    waterMarkContentList.add(sb.toString());
                    // 清空内容,重新追加
                    sb.delete(0, sb.length());
                    tempLineLen = 0;
                }
                // 追加字符
                sb.append(tempChar);
            }
            waterMarkContentList.add(sb.toString());
        }

        // 绘制水印
        int tempY = fontSize + space;
        for (int i = 0; i < waterMarkContentList.size(); i++) {
            String s = waterMarkContentList.get(i);
            //左上角
//                g.drawString(s, space, i * tempY + 3 * space);
            //右下角
            g.drawString(s, space, srcImgHeight - (waterMarkContentList.size() - i) * tempY + space);

//            g.drawString(s, space, (srcImgHeight - (waterMarkContentList.size() - i) * (tempY*2))/2 + space);

            //设置水印的坐标
//            int x = (srcImgWidth - getWatermarkLength(mark, g)) / 2;
//            int y = srcImgHeight / 2;
            //画出水印 第一个参数是水印内容,第二个参数是x轴坐标,第三个参数是y轴坐标
//            g.drawString(s, x, y);
        }
        g.dispose();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write(bufImg,"jpg",baos);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return new ByteArrayInputStream(baos.toByteArray());
    }



    /**
     * 添加水印 并且等比缩(等比压缩图片)
     * @param inputStream
     * @param mark
     * @return
     */
    public static InputStream addMarkValue(InputStream inputStream, String mark,Integer rgb,Float alpha,Integer fontSize,Integer degree) {

        if(Objects.isNull(rgb)){
            rgb = 0xffffff;
        }
        if(Objects.isNull(alpha)){
            alpha = 1F;
        }
//        if(Objects.isNull(fontSize)){
//            fontSize = 60;
//        }
        if(Objects.isNull(fontSize)){
            fontSize = 30;
        }

        String[] waterMarkContents = mark.split("\\|\\|");
        // 用来调整水印的间距
        int space = 20;
        //将读取流转化为图片对象
        Image srcImg = null;
        try {
            srcImg = ImageIO.read(inputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }


        // 等比缩
        int srcImgWidth = srcImg.getWidth(null);;
        int srcImgHeight = srcImg.getHeight(null);

        //如果图片本身的宽和高均小于要压缩到的宽和高,则不压缩直接返回
        if(800>srcImg.getWidth(null)&&800>srcImg.getHeight(null)){
            srcImgWidth =800;
            srcImgHeight =800;
        }else{
            //宽和高等比缩放的率
            double rate1=(double)srcImg.getWidth(null)/(double)800;
            double rate2=(double)srcImg.getHeight(null)/(double)800;
            //控制缩放大小
            double rate=rate1<rate2 ? rate1:rate2;
            srcImgWidth=(int) (srcImg.getWidth(null)/rate);
            srcImgHeight=(int) (srcImg.getHeight(null)/rate);
        }







        //获取图片的宽
//        int srcImgWidth = srcImg.getWidth(null);
//        //获取图片的高
//        int srcImgHeight = srcImg.getHeight(null);

        // 设置图片固定大小
//        int srcImgWidth = 1080; // 目标宽度
//        int srcImgHeight = 2400; // 目标高度
        System.out.println("图片的宽:" + srcImgWidth);
        System.out.println("图片的高:" + srcImgHeight);

        BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);

        //===============图片开始压缩=======================

        //通过比例压缩
        float scale = 0.6f;
        //压缩之后的长度和宽度
        int doWithHeight = (int) (scale * srcImgHeight);
        int dowithWidth = (int) (scale * srcImgWidth);
        // 图片压缩
        bufImg.getGraphics().drawImage(bufImg.getScaledInstance(dowithWidth, doWithHeight, java.awt.Image.SCALE_SMOOTH), 0, 0, null);

        //===============图片结束压缩=======================



        // 加水印
        //创建画笔
        Graphics2D g = bufImg.createGraphics();
        //设置对线段的锯齿状边缘处理
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        //srcImg 为上面获取到的原始图片的图片对象
        g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);

        //设置水印旋转
        if (null != degree) {
            g.rotate(Math.toRadians(degree),
                    (double) bufImg.getWidth() / 2,
                    (double) bufImg.getHeight() / 2);
        }

        //根据图片的背景设置水印颜色

        g.setColor(new Color(rgb));
        g.setComposite(AlphaComposite
                .getInstance(AlphaComposite.SRC_OVER, alpha));
        //设置字体  画笔字体样式为微软雅黑,加粗,文字大小为60pt
        g.setFont(new Font("微软雅黑", Font.BOLD, fontSize));



        java.util.List<String> waterMarkContentList = new ArrayList<>();
// 将换行后的文字放入新的集合
        for (String markContent : waterMarkContents) {
            // 单字符长度
            int tempCharLen = 0;
            // 单行字符总长度临时计算
            int tempLineLen = 0;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < markContent.length(); i++) {
                char tempChar = markContent.charAt(i);
                tempCharLen = getCharLen(tempChar, g);
                tempLineLen += tempCharLen;
                // 文字长度大于图片宽度-2*间距-字体大小
                if (tempLineLen > srcImgWidth - space * 2 - tempCharLen) {
                    // 长度已经满一行
                    waterMarkContentList.add(sb.toString());
                    // 清空内容,重新追加
                    sb.delete(0, sb.length());
                    tempLineLen = 0;
                }
                // 追加字符
                sb.append(tempChar);
            }
            waterMarkContentList.add(sb.toString());
        }

        // 绘制水印
        int tempY = fontSize + space;
        for (int i = 0; i < waterMarkContentList.size(); i++) {
            String s = waterMarkContentList.get(i);
            //左上角
//                g.drawString(s, space, i * tempY + 3 * space);
            //右下角
            g.drawString(s, space, srcImgHeight - (waterMarkContentList.size() - i) * tempY + space);

//            g.drawString(s, space, (srcImgHeight - (waterMarkContentList.size() - i) * (tempY*2))/2 + space);

            //设置水印的坐标
//            int x = (srcImgWidth - getWatermarkLength(mark, g)) / 2;
//            int y = srcImgHeight / 2;
            //画出水印 第一个参数是水印内容,第二个参数是x轴坐标,第三个参数是y轴坐标
//            g.drawString(s, x, y);
        }


        // 设置透明度,0.5 表示半透明
        AlphaComposite alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f);
        g.setComposite(alphaComposite);

        String text ="现场拍照";

        g.setStroke(new BasicStroke(10));
//        g.setFont(new Font("微软雅黑", Font.BOLD, 300));
//        没有压缩图片设置现场拍照大小
//        g.setFont(new Font("方正粗黑宋简体", Font.PLAIN, 120));
        // 压缩后设置现场拍照大小
        g.setFont(new Font("方正粗黑宋简体", Font.PLAIN, 150));


        int x =  (srcImgWidth - getWatermarkLength(text, g)) / 2;
        int y = srcImgHeight/2;

        g.setColor(new Color(0x80000000));
        g.drawString(text, x, y);

        /* 添加水印的文字和设置水印文字出现的内容 ----位置 */
//        g.drawString(iter, width - w, height - h);
//        g.setFont(new Font(Font.DIALOG_INPUT,Font.BOLD+Font.PLAIN, 200));

        g.dispose();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write(bufImg,"jpg",baos);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return new ByteArrayInputStream(baos.toByteArray());
    }
    /**
     * 获取水印文字的长度
     * @param waterMarkContent
     * @param g
     * @return
     */
    private static int getWatermarkLength(String waterMarkContent, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
    }
    private static int getCharLen(char c, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charWidth(c);
    }
    //河北省  红色:0xff0000

    public static void main(String[] args) {
        try {
//            IMG_20231122_114353
            InputStream inputStream = new FileInputStream("D:\\IMG_20231123_115406.jpg");
            InputStream inputStream1 = addMarkValue(inputStream, "经度:114.498895||" +
                            "纬度:38.001944||" +
                            "地址:石家庄市新华区 赵陵铺街道||"+
                    "时间:2022/10/6 14:26:01 ||" +
                    "海拔:0.0米 ||" +
//                    "天气:17-24C 北风  ||" +
                    "备注:爱巢建通区域养老服务中备餐区"
                    ,null,0.6F,null,null);
            String tarImgPath="D:\\tool2.jpg";
            FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
            byte[] buf = new byte[1024];
            int le = -1;
            while (( le = inputStream1.read(buf))!=-1){
                outImgStream.write(buf,0,le);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

//    public static void main(String[] args) {
//        try {
//            InputStream inputStream = new FileInputStream("C:\\Users\\Administrator\\Downloads\\2e54e20843bd4a2d9c6fb83bbbee4766.png");
//            InputStream inputStream1 = addMark(inputStream, "经度:114.498895||"+
//                    "纬度:38.001944||"
//                    +"位同社区12-4-2301" +
//                    "||" +
//                    "2023-07-18 11:14:00",0xff0000,0.6F,60,null);
//            String tarImgPath="D:\\测试.jpg";
//            FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
//            byte[] buf = new byte[1024];
//            int le = -1;
//            while (( le = inputStream1.read(buf))!=-1){
//                outImgStream.write(buf,0,le);
//            }
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }
//
//    }

}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值