掘金的小伙伴们,大家好!本篇我们从0开始把Java学习环境搭建好,以方便后续的持续学习实践。我们将逐步的改进这个加水印的功能,最终以gradle插件的形式将其包装起来。
软件安装
软件的版本我们将追随后面要学习的spring boot3.0技术栈的脚步,都进行版本的升级。
JDK
我本地安装的版本:jdk-17.0.10_windows-x64_bin.exe,因为spring boot3.0最低支持jdk17,必须跟上脚步。安装过程基本都是下一步,最好指定下安装位置方便后面查找,我的安装路径:D:\Programs\Java\jdk-17
。
安装体验
因为我之前一直比较保守,装的jdk8,它还要单独安装jre。对比下来,高版本的jdk安装就很快,无需再装jre,很快就安装好了。
然后是配置环境变量,我在当前用户环境变量下,新增一个JAVA_HOME
环境变量指向jdk安装路径D:\Programs\Java\jdk-17
,然后在Path
环境变量下新增一项,指向jdk安装目录的bin
目录,值为%JAVA_HOME%\bin
。这样就可以在系统命令行的任何路径下调用bin
目录下的命令了。
idea
作为业界java开发的第一利器,我安装的版本是:ideaIU-2023.2.6。因为是收费的,个人学习的话总有一些办法的,这里就不多讨论了。
安装过程需要注意两点,首先安装位置,默认的磁盘空间不够的话,指定下安装位置:
然后执行后续安装步骤。第一次打开时,可以把之前备份的设置导入进来,一般新版本可以选择不导入,从头开始做设置:
创建项目
普通Java项目
在idea欢迎界面点New Project
,下一步的设置如下图,编辑完点创建:
打开的项目界面,idea会自动帮我们构建好,我们要做的就是直接运行main
方法看效果:
修改快捷键风格
小卷作为从eclipse用过来的老码农,还是更习惯eclipse的快捷键风格,因此做如下设置:
把自动补全组合键调整下,默认和舒服法有冲突:
设置自动导入类型
在我们粘贴外部文本代码时为了不一个个手动导入类型,可以设置idea自动导入:
File | Settings
最后点ok。
idea文档注释
为了保护个人代码的版权,可以增加自定义的文档注释,操作如下:
File | Settings | Editor | File and Code Templates
内容如下:
perl
/**
* 代码著作权归Java小卷所有。商业转载请联系Java小卷获得授权,非商业转载请注明出处。
* @Description TODO
* @Classname ${NAME}
* @Date ${DATE} ${TIME}
* @Created by Java小卷
*/
这样设置以后,在创建一个java文件时,就会包含这样的头部信息了。接下来设置生成自定义方法注释模板的方式
File | Settings | Editor | Live Templates
编辑模板变量
在这里要感谢大佬蜀山雪松的《Idea 设置类、方法注释模板(解决params和return显示问题)---不来虚的 实测有效》的这篇文章为小卷提供的groovy脚本,感谢大佬的指导!最后我们设置要应用的类型,这里只选择Java。
这样设置以后,在方法头部敲/juan
开头几个字符后,会有提示,回车就可以生成了。
第一版加水印源码
由于加水印的核心代码在网上有出现拷贝的多个版本,原作者已无法追溯,对此表示遗憾。
Main.java
java
package com.javaxiaojuan.java.tools.watermark;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
/**
* 代码著作权归Java小卷所有。商业转载请联系Java小卷获得授权,非商业转载请注明出处。
*
* @Description TODO
* @Classname Main
* @Date 2024/3/8 16:27
* @Created by Java小卷
*/
public class Main {
// ----------------- 水印设置 -----------------
/** 水印文字内容 */
private static final String WATER_MARK_CONTENT = "稀土掘金 - Java小卷";
/** 水印文字大小 */
private static int FONT_SIZE = 28;
/** 字体类型 */
private static final String FONT_TYPE = "微软雅黑";
/** 水印之间的间隔 */
private static int XMOVE = 180;
/** 水印之间的间隔 */
private static int YMOVE = 180;
/** 水印颜色 */
private static final Color MARK_CONTENT_COLOR = new Color(105,105,105);
/** 设置水印透明度 默认为1.0 值越小颜色越浅 */
private static final float ALPHA = 0.3f;
public static void main(String[] args) {
// 对工程中imgInput中的图片进行加水印操作
File file = new File("imgInput/test.png");
try ( OutputStream outImgStream = new FileOutputStream("imgOutput" + File.separator + file.getName())) {
Image srcImg = ImageIO.read(file);//文件转化为图片
// 加水印
BufferedImage bufImg = doWaterMark(srcImg);
ImageIO.write(bufImg, getFileExt(file.getName()), outImgStream);
outImgStream.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* description: 这是绘制水印的核心方法
* @since:
* @author: 作者已无法追溯
* @date:
* @Param srcImg:
* @return: java.awt.image.BufferedImage
*/
private static BufferedImage doWaterMark(Image srcImg) {
int srcImgWidth = srcImg.getWidth(null);//获取图片的宽
int srcImgHeight = srcImg.getHeight(null);//获取图片的高
if (srcImgWidth < srcImgHeight){
FONT_SIZE = 18;
XMOVE = 130;
YMOVE = 130;
}
// 加水印
BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
// 得到画笔对象
Graphics2D g = bufImg.createGraphics ();
// 设置对线段的锯齿状边缘处理
g.setRenderingHint (RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage (srcImg.getScaledInstance (srcImg.getWidth (null), srcImg.getHeight (null), Image.SCALE_SMOOTH),
0, 0, null);
// 设置水印旋转
int degree = -45;//设置水印文字的旋转角度
g.rotate (Math.toRadians (degree), (double) bufImg.getWidth () / 2, (double) bufImg.getHeight () / 2);
g.setColor(MARK_CONTENT_COLOR); //设置水印颜色
g.setFont(new Font(FONT_TYPE, Font.BOLD, FONT_SIZE)); //设置字体
// 设置水印文字透明度
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, ALPHA));
int x = -srcImgWidth / 2;
int y = -srcImgHeight / 2;
int markWidth = FONT_SIZE * getTextLength (WATER_MARK_CONTENT);// 字体长度
int markHeight = FONT_SIZE;// 字体高度
// 循环添加水印
while (x < srcImgWidth * 1.5) {
y = -srcImgHeight / 2;
while (y < srcImgHeight * 1.5) {
g.drawString (WATER_MARK_CONTENT, x, y);
y += markHeight + YMOVE;
}
x += markWidth + XMOVE;
}
// 释放资源
g.dispose ();
return bufImg;
}
/**
* 获取文本长度。汉字为1:1,英文和数字为2:1
* @since:
* @author: 作者已无法追溯
* @date:
* @Param text:
* @return: int
*/
private static int getTextLength (String text) {
int length = text.length ();
for (int i = 0; i < text.length (); i++) {
String s = String.valueOf (text.charAt (i));
if (s.getBytes ().length > 1) {
length++;
}
}
return length % 2 == 0 ? length / 2 : length / 2 + 1;
}
/**
* description: 获取文件扩展名
* @since: 1.0.0
* @author: Java小卷
* @date: 2024/3/8 17:12
* @Param filename:
* @return: java.lang.String
*/
private static String getFileExt(String filename) {
return filename.substring(filename.lastIndexOf(".") + 1);
}
}