方法一:
package com.ruoyi.common.utils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
/**
* <p class="detail">
* 描述:高斯模糊
* </p>
*
* @version V1.0
* @ClassName: GaussianBlurUtil
*/
public class GaussianBlurUtil {
public static void main(String[] args) throws IOException {
int radius = 15; //设置模糊权重
//获取当前jar所在路径
String img_root_path = "D:/Pictures/test-blur/";
System.out.println("current path:" + img_root_path);
//获取当前路径下的所有图片文件
java.util.List<String> images = listImgs(img_root_path);
//如果当前目录图片数量不为0,就循环处理图片
if (null != images && images.size() > 0) {
System.out.println("has images " + images.size());
for (String image : images) {
BufferedImage img = ImageIO.read(new File(img_root_path + image));
long start = System.currentTimeMillis();
img = blur(img, radius);
long end = System.currentTimeMillis();
ImageIO.write(img, "jpeg", new File(img_root_path + image));//覆盖源文件
System.out.println(image + ":花费时间:" + (end - start));
}
} else {
System.out.println("path is empty!");
}
}
/**
* <p class="detail">
* 功能:模糊执行方法
* </p>
*
* @param img 原图片
* @param radius 模糊权重
* @return 模糊后图片
* @throws IOException
* @date 2016年4月20日
*/
public static BufferedImage blur(BufferedImage img, int radius) throws IOException {
int height = img.getHeight();
int width = img.getWidth();
int[] values = getPixArray(img, width, height);
values = doBlur(values, width, height, radius);
img.setRGB(0, 0, width, height, values, 0, width);
return img;
}
/**
* <p class="detail">
* 功能:获取图像像素矩阵
* </p>
*
* @param im
* @param w
* @param h
* @return
* @date 2016年4月20日
*/
private static int[] getPixArray(Image im, int w, int h) {
int[] pix = new int[w * h];
PixelGrabber pg = null;
try {
pg = new PixelGrabber(im, 0, 0, w, h, pix, 0, w);
if (pg.grabPixels() != true)
try {
throw new java.awt.AWTException("pg error" + pg.status());
} catch (Exception eq) {
eq.printStackTrace();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return pix;
}
/**
* <p class="detail">
* 功能:高斯模糊算法。
* </p>
*
* @param pix
* @param w
* @param h
* @param radius
* @return
* @throws IOException
* @date 2016年4月20日
*/
public static int[] doBlur(int[] pix, int w, int h, int radius) throws IOException {
int wm = w - 1;
int hm = h - 1;
int wh = w * h;
int div = radius + radius + 1;
int[] r = new int[wh];
int[] g = new int[wh];
int[] b = new int[wh];
int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
int[] vmin = new int[Math.max(w, h)];
int divsum = (div + 1) >> 1;
divsum *= divsum;
int[] dv = new int[256 * divsum];
for (i = 0; i < 256 * divsum; i++) {
dv[i] = (i / divsum);
}
yw = yi = 0;
int[][] stack = new int[div][3];
int stackpointer;
int stackstart;
int[] sir;
int rbs;
int r1 = radius + 1;
int routsum, goutsum, boutsum;
int rinsum, ginsum, binsum;
for (y = 0; y < h; y++) {
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
for (i = -radius; i <= radius; i++) {
p = pix[yi + Math.min(wm, Math.max(i, 0))];
sir = stack[i + radius];
sir[0] = (p & 0xff0000) >> 16;
sir[1] = (p & 0x00ff00) >> 8;
sir[2] = (p & 0x0000ff);
rbs = r1 - Math.abs(i);
rsum += sir[0] * rbs;
gsum += sir[1] * rbs;
bsum += sir[2] * rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
}
}
stackpointer = radius;
for (x = 0; x < w; x++) {
r[yi] = dv[rsum];
g[yi] = dv[gsum];
b[yi] = dv[bsum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
if (y == 0) {
vmin[x] = Math.min(x + radius + 1, wm);
}
p = pix[yw + vmin[x]];
sir[0] = (p & 0xff0000) >> 16;
sir[1] = (p & 0x00ff00) >> 8;
sir[2] = (p & 0x0000ff);
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[(stackpointer) % div];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
yi++;
}
yw += w;
}
for (x = 0; x < w; x++) {
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
yp = -radius * w;
for (i = -radius; i <= radius; i++) {
yi = Math.max(0, yp) + x;
sir = stack[i + radius];
sir[0] = r[yi];
sir[1] = g[yi];
sir[2] = b[yi];
rbs = r1 - Math.abs(i);
rsum += r[yi] * rbs;
gsum += g[yi] * rbs;
bsum += b[yi] * rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
}
if (i < hm) {
yp += w;
}
}
yi = x;
stackpointer = radius;
for (y = 0; y < h; y++) {
// Preserve alpha channel: ( 0xff000000 & pix[yi] )
pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16)
| (dv[gsum] << 8) | dv[bsum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
stackstart = stackpointer - radius + div;
sir = stack[stackstart % div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
if (x == 0) {
vmin[y] = Math.min(y + r1, hm) * w;
}
p = x + vmin[y];
sir[0] = r[p];
sir[1] = g[p];
sir[2] = b[p];
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
stackpointer = (stackpointer + 1) % div;
sir = stack[stackpointer];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
yi += w;
}
}
return pix;
}
/**
* 获取文件夹下的所有图片
*
* @param rootPath
* @return 路径下的所有的图片
*/
private static java.util.List<String> listImgs(String rootPath) {
File f = new File(rootPath);
if (!f.exists()) {
System.out.println(rootPath + " not exists");
return new ArrayList<>();
}
File[] fa = f.listFiles();
java.util.List<String> images = new ArrayList<>();
for (int i = 0; i < fa.length; i++) {
File fs = fa[i];
if (!fs.isDirectory() && fs.getName().endsWith("jpeg")) {
System.out.println(fs.getName());
images.add(fs.getName());
}
}
return images;
}
}
方法二:
<dependency>
<groupId>com.jhlabs</groupId>
<artifactId>filters</artifactId>
<version>${filters.version}</version>
</dependency>
//srcImage: 待处理的图片
public static BufferedImage gaussianfilter(BufferedImage srcImage) {
GaussianFilter filter = new GaussianFilter();
filter.setRadius(80.0F); //设置模糊度,数字越大越模糊
BufferedImage dstImage = new BufferedImage(srcImage.getWidth(), srcImage.getHeight(), srcImage.getType());
//处理
filter.filter(srcImage, dstImage);
return dstImage; //处理后的图片
}
小插曲
插曲一
使用方法二的时候,我最开始 imageType 用的是 java.awt.image.BufferedImage#TYPE_BYTE_GRAY ,处理其他类型图片还没啥,到了处理人像图片的时候,差点没给我送走😂😂😂
下面是处理人像图片后的结果
插曲二
测试过程中,发现某些图片使用 java.awt.image.BufferedImage 读取不了,原因是默写图片虽然它的后缀是jpg、png、jpeg。但是用转移工具查看文件类型你就会发现它“包藏祸心”。图片如下
图片格式截图
格式查看器软件(我也是在网上下载的,不负责软件安全🎊🎊)c0inwuoh4o.feishu.cn/file/boxcnz…
解决方法在这里: blog.csdn.net/jf991804033…
在代码里引入以下依赖就行
<dependency>
<groupId>org.sejda.imageio</groupId>
<artifactId>webp-imageio</artifactId>
<version>0.1.6</version>
</dependency>
🧨🎇🧨顺便记录下tiff格式的解决办法
原文地址blog.51cto.com/u_15152252/…
在代码里引入以下依赖就行
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.6.4</version>
</dependency>