裁剪动态签名图像
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;
}
我正在开发一个 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;
}