ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

java通过接口把图片处理成透明背景,java通过接口抠图

2026/9/10 10:42:23 拓冰建站 浏览量
java通过接口把图片处理成透明背景,java通过接口抠图

1、图片工具类

package org.springblade.modules.api.utils;import org.springframework.mock.web.MockMultipartFile;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;public final class FileImageUtil {// 自定义的背景色,可以根据红绿蓝的平均值写public static int color_range = 120;private static BufferedImage rotate(Image src, int angel) {int src_width = src.getWidth(null);int src_height = src.getHeight(null);// calculate the new image sizeRectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);BufferedImage res = null;res = new BufferedImage(rect_des.width, rect_des.height,BufferedImage.TYPE_INT_RGB);Graphics2D g2 = res.createGraphics();res = g2.getDeviceConfiguration().createCompatibleImage(rect_des.width, rect_des.height, Transparency.TRANSLUCENT);g2.dispose();g2 = res.createGraphics();// transformg2.translate((rect_des.width - src_width) / 2,(rect_des.height - src_height) / 2);g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);g2.setColor(new Color(255, 0, 0));g2.setStroke(new BasicStroke(1));g2.drawImage(src, null, null);g2.dispose();return res;}public static Rectangle CalcRotatedSize(Rectangle src, int angel) {// if angel is greater than 90 degree, we need to do some conversionif (angel >= 90) {if (angel / 90 % 2 == 1) {int temp = src.height;src.height = src.width;src.width = temp;}angel = angel % 90;}double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;double angel_dalta_width = Math.atan((double) src.height / src.width);double angel_dalta_height = Math.atan((double) src.width / src.height);int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha- angel_dalta_width));int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha- angel_dalta_height));int des_width = src.width + len_dalta_width * 2;int des_height = src.height + len_dalta_height * 2;return new Rectangle(new Dimension(des_width, des_height));}/*** 顺时针旋转** @param base64FileStr* @param rotate* @return* @throws IOException*/public static String rotateImage(String base64FileStr, int rotate) throws IOException {if (StringUtils.isEmpty(base64FileStr)) {return "";}Base64.Decoder decoder = Base64.getDecoder();// Base64解码,对字节数组字符串进行Base64解码并生成文件final byte[] byt = decoder.decode(base64FileStr);for (int i = 0, len = byt.length; i < len; ++i) {// 调整异常数据if (byt[i] < 0) {byt[i] += 256;}}InputStream input = new ByteArrayInputStream(byt);ByteArrayOutputStream out = new ByteArrayOutputStream();BufferedImage src = ImageIO.read(input);BufferedImage des = rotate(src, rotate);ImageIO.write(des, "png", out);final Base64.Encoder encoder = Base64.getEncoder();final byte[] bytes = out.toByteArray();return encoder.encodeToString(bytes);}public static MultipartFile koutTu(@RequestParam MultipartFile file) {BufferedImage image = getBufferedImage(file);// 高度和宽度int height = image.getHeight();int width = image.getWidth();// 生产背景透明和内容透明的图片ImageIcon imageIcon = new ImageIcon(image);BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics(); // 获取画笔g2D.drawImage(imageIcon.getImage(), 0, 0, null); // 绘制Image的图片int alpha = 0; // 图片透明度// 外层遍历是Y轴的像素for (int y = bufferedImage.getMinY(); y < bufferedImage.getHeight(); y++) {// 内层遍历是X轴的像素for (int x = bufferedImage.getMinX(); x < bufferedImage.getWidth(); x++) {int rgb = bufferedImage.getRGB(x, y);// 对当前颜色判断是否在指定区间内if (colorInRange(rgb)) {alpha = 0;} else {// 设置为不透明alpha = 255;}// #AARRGGBB 最前两位为透明度rgb = (alpha << 24) | (rgb & 0x00ffffff);bufferedImage.setRGB(x, y, rgb);}}// 绘制设置了RGB的新图片g2D.drawImage(bufferedImage, 0, 0, null);//转换类型MultipartFile multipartFile = fileCase(bufferedImage);return multipartFile;}// 判断是背景还是内容public static boolean colorInRange(int color) {int red = (color & 0xff0000) >> 16;// 获取color(RGB)中R位int green = (color & 0x00ff00) >> 8;// 获取color(RGB)中G位int blue = (color & 0x0000ff);// 获取color(RGB)中B位// 通过RGB三分量来判断当前颜色是否在指定的颜色区间内if (red >= color_range && green >= color_range && blue >= color_range) {return true;}return false;}public static BufferedImage getBufferedImage(@RequestParam MultipartFile file) {BufferedImage image = null;try {image = ImageIO.read(file.getInputStream());} catch (IOException e) {System.out.println("读取图片文件出错!" + e.getMessage());}return image;}public static MultipartFile fileCase(BufferedImage image) {//得到BufferedImage对象MultipartFile multipartFile = null;try {//创建一个ByteArrayOutputStreamByteArrayOutputStream os = new ByteArrayOutputStream();//把BufferedImage写入ByteArrayOutputStreamImageIO.write(image, "png", os);//ByteArrayOutputStream转成InputStreamInputStream input = new ByteArrayInputStream(os.toByteArray());//InputStream转成MultipartFilemultipartFile = new MockMultipartFile("file", "file.png", "text/plain", input);} catch (IOException e) {e.printStackTrace();}return multipartFile;}}

2、接口

/*** 抠图** @param file 抠图* @return LocalFile*/@PostMapping("kouTu")public R<Kv> kouTu(@RequestParam MultipartFile file) {MultipartFile multipartFile = FileImageUtil.koutTu(file);//下面的方法,是框架里上传文件的方法,没有该框架可以自己写,返回的是图片路径LocalFile localFile = getFile(multipartFile);localFile.transfer();localFile.setUploadVirtualPath(localFile.getUploadVirtualPath().replace("//", "/"));//拼接urlString url = localFile.getDomain() + localFile.getUploadVirtualPath();Kv kv = Kv.create().set("url", url);return R.data(kv);}