package net.jimblackler.yourphotoswatch;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacpp.Pointer;
import org.bytedeco.javacpp.helper.opencv_objdetect;
import org.bytedeco.javacpp.opencv_core.CvMemStorage;
import org.bytedeco.javacpp.opencv_core.CvSeq;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacpp.opencv_objdetect.CvHaarClassifierCascade;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import static org.bytedeco.javacpp.opencv_core.CvRect;
import static org.bytedeco.javacpp.opencv_core.cvClearMemStorage;
import static org.bytedeco.javacpp.opencv_core.cvGetSeqElem;
import static org.bytedeco.javacpp.opencv_core.cvLoad;
import static org.bytedeco.javacpp.opencv_highgui.cvLoadImage;
import static org.bytedeco.javacpp.opencv_objdetect.CV_HAAR_SCALE_IMAGE;
import static org.bytedeco.javacpp.opencv_objdetect.cvHaarDetectObjects;
public class AutoCropper {
CvMemStorage storage;
CvHaarClassifierCascade classifier;
public AutoCropper(Context context) throws IOException {
storage = CvMemStorage.create(); // Allocate the memory storage.
// Preload the opencv_objdetect module to work around a known bug.
Loader.load(opencv_objdetect.class);
InputStream in = context.getAssets().open("haarcascade_frontalface_alt.xml");
final File file = File.createTempFile("classifier", ".xml");
streamToFile(in, file);
in.close();
String path = file.getPath();
Pointer p = cvLoad(path);
file.delete();
classifier = new CvHaarClassifierCascade(p);
}
public static void streamToFile(InputStream in, File file) throws IOException {
FileOutputStream out = new FileOutputStream(file);
byte[] buffer = new byte[16384];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
out.close();
}
public Bitmap crop(Bitmap bitmap) {
cvClearMemStorage(storage);
boolean debugMode = false;
try {
File tempFile = File.createTempFile("output", ".png");
FileOutputStream out = new FileOutputStream(tempFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
IplImage iplImage = cvLoadImage(tempFile.getAbsolutePath());
tempFile.delete();
CvSeq faces =
cvHaarDetectObjects(iplImage, classifier, storage, 1.025, 3, CV_HAAR_SCALE_IMAGE);
if (debugMode) {
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
}
float minX = Float.MAX_VALUE;
float maxX = Float.MIN_VALUE;
float minY = Float.MAX_VALUE;
float maxY = Float.MIN_VALUE;
for (int i = 0; i < faces.total(); i++) {
CvRect rect = new CvRect(cvGetSeqElem(faces, i));
if (debugMode) {
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
paint.setColor(Color.RED);
Canvas canvas = new Canvas(bitmap);
canvas.drawRect(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height(), paint);
}
float extraX = rect.width() * 0.33f;
float extraY = rect.height() * 0.33f;
minX = Math.max(Math.min(rect.x() - extraX, minX), 0);
maxX = Math.min(Math.max(rect.x() + rect.width() + extraX, maxX), bitmap.getWidth());
minY = Math.max(Math.min(rect.y() - extraY, minY), 0);
maxY = Math.min(Math.max(rect.y() + rect.height() + extraY, maxY), bitmap.getHeight());
}
float leftX;
float rightX;
float topY;
float bottomY;
if (bitmap.getHeight() > bitmap.getWidth()) {
// Tall image.
float centerY = bitmap.getHeight() / 2;
topY = centerY - bitmap.getWidth() / 2;
bottomY = centerY + bitmap.getWidth() / 2;
leftX = 0;
rightX = bitmap.getWidth();
if (faces.total() > 0) {
if (maxY - minY > bitmap.getWidth()) {
centerY = (minY + maxY) / 2;
topY = centerY - bitmap.getWidth() / 2;
bottomY = centerY + bitmap.getWidth() / 2;
} else if (minY < topY) {
topY = minY;
bottomY = topY + bitmap.getWidth();
} else if (maxY > bottomY) {
bottomY = maxY;
topY = bottomY - bitmap.getWidth();
}
}
} else {
// Wide image.
float centerX = bitmap.getWidth() / 2;
leftX = centerX - bitmap.getHeight() / 2;
rightX = centerX + bitmap.getHeight() / 2;
topY = 0;
bottomY = bitmap.getHeight();
if (faces.total() > 0) {
if (maxX - minX > bitmap.getHeight()) {
centerX = (minX + maxX) / 2;
leftX = centerX - bitmap.getHeight() / 2;
rightX = centerX + bitmap.getHeight() / 2;
} else if (minX < leftX) {
leftX = minX;
rightX = leftX + bitmap.getHeight();
} else if (maxX > rightX) {
rightX = maxX;
leftX = rightX - bitmap.getHeight();
}
}
}
if (debugMode) {
{
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(4);
paint.setColor(Color.GREEN);
Canvas canvas = new Canvas(bitmap);
canvas.drawRect(leftX, topY, rightX, bottomY, paint);
}
{
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
paint.setColor(Color.BLUE);
Canvas canvas = new Canvas(bitmap);
canvas.drawRect(minX, minY, maxX, maxY, paint);
}
} else {
bitmap = Bitmap.createBitmap(bitmap, (int) leftX, (int) topY,
(int) (rightX - leftX), (int) (bottomY - topY));
}
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
}