裁剪动态签名图像

Crop dynamically signature images

我正在开发一个 java 应用程序,该应用程序从 Wacom USB 数位板捕获客户端签名,创建一个带有签名的 320x200 像素白色背景图像并存储到数据库中,稍后以 PDF 格式打印。

在保存它们之前,我想裁剪掉签名上的图像。我的意思是,一位客户可以在平板电脑的左侧区域签名,而另一位客户可以在右侧区域签名。所以所有的签名在签名图像中都会有不同的位置和无用的白色space。例如,different signature images and I would like something like this

所以我的问题是,这可能吗?是否有任何选项可以在保存之前通过签名动态裁剪这些图像?知道所有签名都有不同的大小不能总是从相同的位置裁剪。或者更好,例如,在平板电脑上打印一个矩形,迫使客户在里面签名? (不知道这是否可能,我想是的)。

谢谢。

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;

public class Cropper {

    public static void main(String[] args) throws IOException {
        BufferedImage src = ImageIO.read(new URL("https://www.citrix.com/blogs/wp-content/uploads/2015/02/Signature-Richard1.jpg"));
        int x0=src.getWidth();
        int y0=src.getHeight();
        int x1=0;
        int y1=0;
        //just a guess: the pixels color at 0,0 is wht you want to crop
        int unusedcolor=src.getRGB(0,0);
        //iterate over all pixels
        for (int y = 0; y < src.getHeight(); y++) {
            for (int x = 0; x < src.getWidth(); x++) {
                  int  clr   = src.getRGB(x, y);
                  if (clr!=unusedcolor)
                  {
                      //pixel is used, shift the new borders accordingly 
                      x0=Math.min(x0, x);
                      y0=Math.min(y0, y);
                      x1=Math.max(x1, x);
                      y1=Math.max(y1, y);
                  }
            }
        }
        if (x1>x0 && y1>y0)
        {
            BufferedImage dest = src.getSubimage(x0, y0, x1-x0,y1-y0);
            ImageIO.write(dest, "png", new File("out.png"));
            Runtime.getRuntime().exec("cmd /c start out.png");
        }

    }
}

我答应了并行流方法。在这里。

未裁剪图像 (png):http://assets-cdn.github.com/images/modules/open_graph/github-mark.png

public static void main(String[] args) throws Exception {
    BufferedImage img = ImageIO.read(new URL("http://assets-cdn.github.com/images/modules/open_graph/github-mark.png"));

    BufferedImage sigImage = cropSignature(img);

    SwingUtilities.invokeLater(() -> {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.setContentPane(new JLabel(new ImageIcon(sigImage)));
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    });
}

private static BufferedImage cropSignature(BufferedImage img) {
    // Iterating over height has better CPU cache performance.
    Rectangle sigRect = IntStream.range(0, img.getHeight())
                                 .parallel()
                                 .mapToObj(y -> getHorizontalSpan(img, y))
                                 .collect(() -> new Rectangle(0, 0, -1, -1),
                                          (r1, r2) -> r1.add(r2),
                                          (r1, r2) -> r1.add(r2));

    return img.getSubimage(sigRect.x, sigRect.y, sigRect.width, sigRect.height);
}

private static Rectangle getHorizontalSpan(BufferedImage img, int y) {
    // Don't parallelize. The 'combiner' is therefore not necessary and may be null.
    return IntStream.range(0, img.getWidth())
                    .filter(x -> isSignatureColor(img.getRGB(x, y)))
                    .collect(() -> new Rectangle(0, 0, -1, -1),
                             (r, x) -> r.add(x, y),
                             null);
}

private static boolean isSignatureColor(int rgb) {
    // Easiest criteria, but fails on JPG files because it doesn't use a tolerance. 
    return rgb != -1;
}