我承诺采用并行流方法。这里是。
未裁剪的图像(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;
}