java项目抠图功能实现

14 篇文章 0 订阅

java项目抠图功能

  项目中需要一个上传文字签名并且抠掉背景图的功能,当初第一次听到这个需求时,差点惊掉下巴,我压根都不会觉得java里能实现这功能。但是既然客户需要,那就照办吧。
  经过这次功能的实现,我也更加坚定了一个想法,再奇葩的需求,也要先找找方法,不要果断拒绝,要相信Java天下第一,天下第一能有解决不了的事吗?(其实我现在内心已经对学python蠢蠢欲动了,嘿嘿~~~)

1.效果图

  经过我一番的搜索加改造,与前端小伙伴做了下边的效果。(整的跟PS一样,顿时有了高大上的感觉)
在这里插入图片描述
  功能比较简单,上传图片给后端,后端返回抠完图的路径。
  原图如下:
在这里插入图片描述
  上传这个图之后,先框选范围、旋转好方向,注意,框选、旋转图片都是前端的操作,这些前端都有方法,如下图:
在这里插入图片描述
  当设置好之后,则点击抠图,即可看到下图的效果,已经变成了透明的。在这一步操作上,抠图就调用了本次java提供的抠图接口。

在这里插入图片描述

2.扣图接口

  以下是抠图接口,在该接口里前端将裁剪后的图片传送到后端,在该接口里,后端将会把前端传过来的图片传给PictureUtils.transApla(restore,169)方法,在该方法里,将会进行抠图并再保存,保存后将该处理好的图片路径返回给前端,前端直接展示即可。详细步骤如下:

  1. 前端上传图片到面板上,此时并没有调用后端接口,仅由前端加载。
  2. 因为用户上传的图片大小方向都不固定,因此也要考虑一些旋转、裁剪功能,因此这里我们也加入了这些常用功能,经过旋转、裁剪,定好了范围。注意到这里都是前端自己完成。
  3. 当处理好之后,再调用裁剪接口,也就是下边的代码所写,重点只是PictureUtils.transApla(restore,169)方法。

  如下是裁剪接口:

/**
     * 签名图扣掉背景色
     * @param request
     * @return
     */
    @RequestMapping(value = "/signHandle",method = RequestMethod.POST)
    public Object getPsPictureSign(HttpServletRequest request){
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        String fileName = null;
        String msg = null;
        String result = "";
        try {
            //获取文件
            Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
            if(fileMap == null || fileMap.isEmpty()){
                return addResultMapMsg(false,"未上传签名图片");
            }
            MultipartFile multipartFile = null;//获取文件名
            for (Map.Entry<String, MultipartFile> set : fileMap.entrySet()) {
                multipartFile = set.getValue();// 文件名
                String uploadfileName = multipartFile.getOriginalFilename();
                String suffix = uploadfileName.substring(uploadfileName.lastIndexOf(".")+1).toLowerCase();
                if(!uploadSuffix.contains(suffix)){
                    return addResultMapMsg(false,"只能上传 png、jpg 图片格式");
                }
            }
            //先将文件保存到服务器中,然后操作文件
            String fileOriginalName = multipartFile.getOriginalFilename();
            String resultStr = File.separator + "pictureTmp" + File.separator  + File.separator + fileOriginalName.substring(0,fileOriginalName.lastIndexOf(".")+1) +".png";
            fileName = realPath + resultStr;
            File restore = new File(fileName);
            if(!restore.getParentFile().exists()){
                restore.getParentFile().mkdirs();
            }
            //System.out.println(3+"=="+fileName);
            multipartFile.transferTo(restore);
            // 抠图工具类
            PictureUtils.transApla(restore,169); // 169为灰色的rcb色值
            result = resultStr;
        } catch (Exception e) {
            e.printStackTrace();
            msg = "处理失败";
        }
        if(!StringUtils.isEmpty(msg)){ //说明上传有错
            return addResultMapMsg(false,msg);
        }else {
            return addResultMapMsg(true,result.replace("\\","/"));
        }
    }

  以下是封装好的工具类,可以直接用,另外,因为使用的方法java直接就有,不需要引用额外的jar包。
  如下是工具类方法:

package znxd.lxynzl.controller.photoshop;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.regex.Pattern;

/**
 * Created by lingsf on 2020/6/16.
 */
public class PictureUtils {
    public static int color_range = 210;
    public static Pattern pattern = Pattern.compile("[0-9]*");

    public static boolean isNo(String str) {
        return pattern.matcher(str).matches();
    }

    /**
     *
     * @param file 保存后要处理的png文件
     * @param rcb  要扣掉的rcb色值
     */
    public static void transApla(File file,int rcb){
        InputStream is=null;
        try {
            is = new FileInputStream(file);
            // 如果是MultipartFile类型,那么自身也有转换成流的方法:is = file.getInputStream();
            BufferedImage bi = ImageIO.read(is);
            Image image = (Image) bi;
            ImageIcon imageIcon = new ImageIcon(image);
            BufferedImage bufferedImage = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(),
                    BufferedImage.TYPE_4BYTE_ABGR);
            Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics();
            g2D.drawImage(imageIcon.getImage(), 0, 0, imageIcon.getImageObserver());
            int alpha = 0;
            color_range = 255 - rcb; // 0
            for (int j1 = bufferedImage.getMinY(); j1 < bufferedImage
                    .getHeight(); j1++) {
                for (int j2 = bufferedImage.getMinX(); j2 < bufferedImage
                        .getWidth(); j2++) {
                    int rgb = bufferedImage.getRGB(j2, j1);
                    if (colorInRange(rgb)) {
                        alpha = 0;
                    } else {
                        alpha = 255;
                    }
                    rgb = (alpha << 24) | (rgb & 0x00ffffff);
                    bufferedImage.setRGB(j2, j1, rgb);
                }
            }


            g2D.drawImage(bufferedImage, 0, 0, imageIcon.getImageObserver());
            ImageIO.write(bufferedImage, "png", file);// 直接输出文件
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(is!=null){
                try{
                    is.close();
                }catch (Exception e){}
            }
        }
    }

    public static boolean colorInRange(int color) {
        int red = (color & 0xff0000) >> 16;
        int green = (color & 0x00ff00) >> 8;
        int blue = (color & 0x0000ff);
        if (red >= color_range && green >= color_range && blue >= color_range) {
            return true;
        }
        return false;
    }

}

3.总结

  整体功能还是比较简单,后端只提供了一个接口,主要的解决办法,使用了swing的色素替换的方法,就是将固定的色值替换为透明色素,因此功能图上提示用户,尽量用白底黑字的签名上传。
  当然你们也看到了,上边的我写的签名图,拍出来也并不是白底黑字,照样也能抠图成功。

前端vue下载地址:百度网盘 提取码:nvt2

  • 13
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 23
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

茁壮成长的凌大大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值