博客信息

图片处理工具类(对现有的图片留白就行裁剪)

发布时间:『 2021-02-07 08:19』  博客类别:解决方案  阅读(1012)
起因:遇到一个需求,需要将手写签字生成图片上传,然后用于展示。但是展示的图片过大,如果等比例缩小,最终打印出的文件,签字图片又不清晰。


编码:首先实现手写签字,生成图片,这一点比较好实现。接下来就是对生成的图片就行代码裁剪。

两种方案:

1、根据需要裁剪的区域的坐标进行裁剪(但是我们没办法获取到客户到底在哪个区域签字,签字的边界在哪,所以这种方案可操作性不佳)

2、根据客户签字的白板颜色以及签字画笔的颜色的变化,取四个方向的最值确定签字区域


以下代码是第二种方案


package com.javaxl.utils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

/**
 * 簽字上传工具类
 */
public class ImageUtils {
    public static String GetImageStr(String imgFilePath) throws IOException {// 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
        byte[] data = null;

        // 读取图片字节数组
        InputStream in = new FileInputStream(imgFilePath);
        data = new byte[in.available()];
        in.read(data);
        in.close();

        // 对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);// 返回Base64编码过的字节数组字符串
    }

    public static boolean GenerateImage(String imgStr, String imgFilePath) throws IOException {// 对字节数组字符串进行Base64解码并生成图片
        if (imgStr == null) // 图像数据为空
            return false;
        BASE64Decoder decoder = new BASE64Decoder();
        // Base64解码
        byte[] bytes = decoder.decodeBuffer(imgStr);
        for (int i = 0; i < bytes.length; ++i) {
            if (bytes[i] < 0) {// 调整异常数据
                bytes[i] += 256;
            }
        }
        // 生成jpeg图片
        OutputStream out = new FileOutputStream(imgFilePath);
        out.write(bytes);
        out.flush();
        out.close();
        return true;
    }

    private static BufferedImage getCroppedImage(String address) throws IOException {
        BufferedImage source = ImageIO.read(new File(address)) ;

        boolean flag = false ;
        int upperBorder = -1 ;
        do{
            upperBorder ++ ;
            for (int c1 =0 ; c1 < source.getWidth() ; c1++){
                if(source.getRGB(c1, upperBorder) != Color.white.getRGB() ){
                    flag = true;
                    break ;
                }
            }

            if (upperBorder >= source.getHeight())
                flag = true ;
        }while(!flag) ;

        BufferedImage destination = new BufferedImage(source.getWidth(), source.getHeight() - upperBorder, BufferedImage.TYPE_INT_ARGB) ;
        destination.getGraphics().drawImage(source, 0, upperBorder*-1, null) ;

        return destination ;
    }


    public static BufferedImage getCroppedImage(BufferedImage source, double tolerance) {
        // Get our top-left pixel color as our "baseline" for cropping
        int baseColor = source.getRGB(0, 0);

        int width = source.getWidth();
        int height = source.getHeight();

        int topY = Integer.MAX_VALUE, topX = Integer.MAX_VALUE;
        int bottomY = -1, bottomX = -1;
        for(int y=0; y<height; y++) {
            for(int x=0; x<width; x++) {
                if (colorWithinTolerance(baseColor, source.getRGB(x, y), tolerance)) {
                    if (x < topX) topX = x;
                    if (y < topY) topY = y;
                    if (x > bottomX) bottomX = x;
                    if (y > bottomY) bottomY = y;
                }
            }
        }

        BufferedImage destination = new BufferedImage( (bottomX-topX+1),
                (bottomY-topY+1), BufferedImage.TYPE_INT_ARGB);

        int temp = 5;
        destination.getGraphics().drawImage(source, 0, 0,
                destination.getWidth(), destination.getHeight(),
                topX-temp, topY-temp, bottomX+temp, bottomY+temp, null);

        return destination;
    }

    private static boolean colorWithinTolerance(int a, int b, double tolerance) {
        int aAlpha  = (int)((a & 0xFF000000) >>> 24);   // Alpha level
        int aRed    = (int)((a & 0x00FF0000) >>> 16);   // Red level
        int aGreen  = (int)((a & 0x0000FF00) >>> 8);    // Green level
        int aBlue   = (int)(a & 0x000000FF);            // Blue level

        int bAlpha  = (int)((b & 0xFF000000) >>> 24);   // Alpha level
        int bRed    = (int)((b & 0x00FF0000) >>> 16);   // Red level
        int bGreen  = (int)((b & 0x0000FF00) >>> 8);    // Green level
        int bBlue   = (int)(b & 0x000000FF);            // Blue level

        double distance = Math.sqrt((aAlpha-bAlpha)*(aAlpha-bAlpha) +
                (aRed-bRed)*(aRed-bRed) +
                (aGreen-bGreen)*(aGreen-bGreen) +
                (aBlue-bBlue)*(aBlue-bBlue));

        // 510.0 is the maximum distance between two colors
        // (0,0,0,0 -> 255,255,255,255)
        double percentAway = distance / 510.0d;

        return (percentAway > tolerance);
    }

    /**
     * 将原有图片进行裁剪
     * @param source    原图
     * @param uuid1     原图的唯一标识
     * @param uuid2     裁剪后的唯一标识
     * @throws IOException
     * @return
     */
    public static String handlerImage(String source, String uuid1, String uuid2) throws IOException {
        Image img = getCroppedImage(getCroppedImage(source),0);
        int width = img.getWidth(null);
        int height = img.getHeight(null);
        BufferedImage bi = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        Graphics g = bi.getGraphics();
        g.drawImage(img,0,0,width,height,null);
        g.dispose();
        String sourceHandler = source.replace(uuid1, uuid2);
        File f = new File(sourceHandler);
        ImageIO.write(bi, "png", f);
        return sourceHandler;
    }

}














关键字:     解决方案       图片处理  

备案号:湘ICP备19000029号

Copyright © 2018-2019 javaxl晓码阁 版权所有