/*
* Copyright 2012 Eric F. Savage, code@efsavage.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ajah.image;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
/**
* Automatically crops extraneous space from an image.
*
* @author <a href="http://efsavage.com">Eric F. Savage</a>, <a
* href="mailto:code@efsavage.com">code@efsavage.com</a>.
*/
public class AutoCrop {
private static Logger log = Logger.getLogger(AutoCrop.class.getName());
/**
* Crops an image based on the value of the top left pixel.
*
* @param image
* The image to crop.
* @param fuzziness
* The fuzziness allowed for minor deviations (~5 is
* recommended).
* @return The new image data, cropped.
* @throws IOException
* If the image could not be read.
*/
public static BufferedImage autoCrop(final BufferedImage image, final int fuzziness) throws IOException {
final Color color = new Color(image.getRGB(0, 0));
boolean stop = false;
int cropTop = 0;
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
if (!ColorUtils.match(color, image.getRGB(x, y), fuzziness)) {
stop = true;
break;
}
}
if (stop) {
if (y > 0) {
cropTop = y - 1;
}
break;
}
}
log.finest("Cropping top " + cropTop + " rows");
stop = false;
int cropBot = image.getHeight();
for (int y = (image.getHeight() - 1); y >= 0; y--) {
for (int x = 0; x < image.getWidth(); x++) {
if (!ColorUtils.match(color, image.getRGB(x, y), fuzziness)) {
stop = true;
break;
}
}
if (stop) {
if (y < image.getHeight()) {
cropBot = y + 1;
}
break;
}
}
log.finest("Cropping bottom " + (image.getHeight() - cropBot) + " rows");
stop = false;
int cropLeft = 0;
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
if (!ColorUtils.match(color, image.getRGB(x, y), fuzziness)) {
stop = true;
break;
}
}
if (stop) {
if (x > 0) {
cropLeft = x - 1;
}
break;
}
}
log.finest("Cropping left " + cropLeft + " rows");
stop = false;
int cropRight = 0;
for (int x = (image.getWidth() - 1); x >= 0; x--) {
for (int y = 0; y < image.getHeight(); y++) {
if (!ColorUtils.match(color, image.getRGB(x, y), fuzziness)) {
stop = true;
break;
}
}
if (stop) {
if (x < image.getWidth()) {
cropRight = x + 1;
}
break;
}
}
log.finest("Cropping right " + (image.getWidth() - cropRight) + " rows");
final BufferedImage cropped = image.getSubimage(cropLeft, cropTop, cropRight - cropLeft, cropBot - cropTop);
return cropped;
}
/**
* Crops an image based on the value of the top left pixel.
*
* @param data
* The image data.
* @param fuzziness
* The fuzziness allowed for minor deviations (~5 is
* recommended).
* @return The new image data, cropped.
* @throws IOException
* If the image could not be read.
*/
public static byte[] autoCrop(final byte[] data, final int fuzziness) throws IOException {
final BufferedImage image = ImageIO.read(new ByteArrayInputStream(data));
final BufferedImage cropped = autoCrop(image, fuzziness);
final ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(cropped, "png", out);
return out.toByteArray();
}
}