裁剪动态签名图像

时间:2018-01-31 12:18:19

标签: java image wacom

开发一个从Wacom USB平板电脑捕获客户端签名的Java应用程序,创建一个带有签名的320x200像素白色背景图像并存储到数据库中,以便稍后在PDF上打印。

在保存之前,我想将图像裁剪为签名。我的意思是,一个客户端可以在平板电脑的左侧区域和右侧区域的另一个区域上签名。因此,所有签名在签名图像和无用的空白区域中将具有不同的位置。例如,different signature images我想要this

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

感谢。

2 个答案:

答案 0 :(得分:1)

我承诺采用并行流方式。在这里。

未拍摄的图像(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;
}

答案 1 :(得分:0)

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");
        }

    }
}