Realization of java project cutout function

java project cutout function

  The project needs a function of uploading text signatures and removing the background image. When I first heard this requirement, my jaw almost dropped. I never thought that this function could be realized in java. But since the customer needs it, let's do it.
  After the realization of this function, I have also strengthened my idea. No matter how weird the demand is, I must first find a way. Don't refuse decisively. Believe, can there be Java天下第一anything that can't be solved by No. 1 in the world? (Actually, I am already pythoneager to learn in my heart, hehe~~~)

1. Rendering

  After some searching and modification, I made the following effect with my front-end friends. (The whole is the same as PS, and it immediately feels taller)
insert image description here
  The function is relatively simple, upload pictures to the backend, and the backend returns the path of the cutout picture.
  The original picture is as follows:
insert image description here
  After uploading this picture, first frame select the range and rotate the direction. Note that frame selection and rotate the picture are both front-end operations, and these front-end operations have methods, as shown in the figure below: After setting,
insert image description here
  click 抠图to See the effect of the picture below, it has become transparent. In this step, the cutout calls the cutout interface provided by java.

insert image description here

2. Button interface

  The following is the image cutout interface. In this interface, the front end transmits the cropped picture to the back end. In this interface, the back end will pass the picture passed by the front end to the PictureUtils.transApla(restore,169)method. In this method, the cutout will be performed. And save it again. After saving, return the processed image path to the front end, and the front end can display it directly. The detailed steps are as follows:

  1. The front-end uploads pictures to the panel. At this time, the back-end interface is not called, and it is only loaded by the front-end.
  2. Because the size and direction of the pictures uploaded by users are not fixed, some rotation and cropping functions should also be considered. Therefore, we also added these common functions here, and after rotation and cropping, the range was determined. Note that this is all done by the front end itself.
  3. After processing, call the tailoring interface, which is written in the code below, the focus is only on PictureUtils.transApla(restore,169)the method.

  The following is the clipping interface:

/**
     * 签名图扣掉背景色
     * @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("\\","/"));
        }
    }

  The following are packaged tool classes, which can be used directly. In addition, because the method used is directly available in java, there is no need to reference additional jar packages.
  The following is the tool class method:

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. Summary

  The overall function is relatively simple. The backend only provides an interface. The main solution swingis to replace the pigment used. 固定的色值替换为透明色素Therefore, the function diagram prompts the user 白底黑字to upload with the signature as much as possible.
  Of course, you have also seen that the signature picture I wrote above was not taken out 白底黑字, and the picture can still be cut out successfully.

Front-end vue download address: Baidu network disk Extraction code:nvt2

Guess you like

Origin blog.csdn.net/wohaqiyi/article/details/109266869