Skip to content

Commit

Permalink
MagicCrop is now fully working
Browse files Browse the repository at this point in the history
  • Loading branch information
pverscha committed Jun 7, 2017
1 parent 87200e9 commit b3ce109
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public void testSimpleGradientAurora() throws Exception {

Bitmap gradient = factory.createAuroraBasedUponColour(output, 400, 800);

saveImageToExternalStorage(gradient);
saveImageToExternalStorage(gradient, Bitmap.CompressFormat.JPEG);
}

@Test
Expand All @@ -78,23 +78,39 @@ public void testBlurryAurora() throws Exception {

Bitmap gradient = factory.createAuroraBasedUponDrawable(redImage, new BlurryAurora(appContext), 1200, 1920);

saveImageToExternalStorage(gradient);
saveImageToExternalStorage(gradient, Bitmap.CompressFormat.JPEG);
}

private void saveImageToExternalStorage(Bitmap finalBitmap) {
@Test
public void testMagicCrop() throws Exception {
Context appContext = InstrumentationRegistry.getTargetContext();

Drawable logo = getInstrumentation().getContext().getResources().getDrawable(be.abyx.aurora.test.R.drawable.delhaize, null);
ImageUtils utils = new ImageUtils(appContext);

Bitmap cropped = utils.magicCrop(((BitmapDrawable) logo).getBitmap(), Color.WHITE, 0.75f);
saveImageToExternalStorage(cropped, Bitmap.CompressFormat.PNG);
}

private void saveImageToExternalStorage(Bitmap finalBitmap, Bitmap.CompressFormat format) {
File myDir = getInstrumentation().getContext().getExternalFilesDir("gradient");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-" + n + ".jpg";
String fname;
if (format.equals(Bitmap.CompressFormat.JPEG)) {
fname = "Image-" + n + ".jpg";
} else {
fname = "Image-" + n + ".png";
}
File file = new File(myDir, fname);
System.out.println(file.getAbsolutePath());
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 98, out);
finalBitmap.compress(format, 100, out);
out.flush();
out.close();
}
Expand Down
Binary file added app/src/androidTest/res/drawable/delhaize.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 changes: 0 additions & 50 deletions app/src/main/java/be/abyx/aurora/ColourParser.java

This file was deleted.

60 changes: 41 additions & 19 deletions app/src/main/java/be/abyx/aurora/ImageUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,43 +26,65 @@ public ImageUtils(Context context) {
*
* @param input A Bitmap that should be automatically cropped.
* @param colour The colour of the edges that should be removed.
* @param tolerance How much a colour can deviate from the real given value and should still
* be removed (A value between 0 and 1 where 1 indicates full tolerance).
* @return Bitmap A new Bitmap whose corners are removed.
*/
public void magicCrop(Bitmap input, int colour) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inScaled = false;

Bitmap originalBitmap = BitmapFactory.decodeResource(context.getResources(), R.raw.aurora_fancy_template, opts);

int width = originalBitmap.getWidth();
int height = originalBitmap.getHeight();
public Bitmap magicCrop(Bitmap input, int colour, float tolerance) {
int width = input.getWidth();
int height = input.getHeight();

int[] pixels = new int[width * height];
originalBitmap.getPixels(pixels, 0, width, 0, 0, width, height);
input.getPixels(pixels, 0, width, 0, 0, width, height);

// We're working with a Stack-based approach of the Flood Fill algorithm to determine
// the edges that should get removed.
Stack<ImageCoordinate> coordinates = new Stack<>();
// Start filling from the four corners of the image
coordinates.push(new ImageCoordinate(0, 0));
coordinates.push(new ImageCoordinate(0, height - 1));
coordinates.push(new ImageCoordinate(width - 1, height - 1));
coordinates.push(new ImageCoordinate(width - 1, 0));
coordinates.push(new ImageCoordinate(0, 0));

int referenceRed = Color.red(colour);
int referenceGreen = Color.green(colour);
int referenceBlue = Color.blue(colour);
int sum = referenceBlue + referenceGreen + referenceRed;
float treshold = 3 * 255 * tolerance;

while (!coordinates.isEmpty()) {
ImageCoordinate current = coordinates.pop();

if (pixels[current.getY() * height + current.getX()] == colour) {
pixels[current.getY() * height + current.getX()] = Color.TRANSPARENT;
if (validPosition(current.getX(), current.getY(), width, height) && pixels[current.getY() * width + current.getX()] == colour) {
int pixel = pixels[current.getY() * width + current.getX()];
int red = Color.red(pixel);
int blue = Color.blue(pixel);
int green = Color.green(pixel);

float difference = Math.abs((red + blue + green) - sum);

// Reuse current ImageCoordinate-object.
current.setY(current.getY() + 1);
coordinates.push(current);
coordinates.push(new ImageCoordinate(current.getX(), current.getY() - 1));
coordinates.push(new ImageCoordinate(current.getX() + 1, current.getY()));
coordinates.push(new ImageCoordinate(current.getX() - 1, current.getY()));
if (difference <= treshold) {
pixels[current.getY() * width + current.getX()] = Color.TRANSPARENT;

// Reuse current ImageCoordinate-object.
coordinates.push(new ImageCoordinate(current.getX() + 1, current.getY()));
coordinates.push(new ImageCoordinate(current.getX() - 1, current.getY()));
coordinates.push(new ImageCoordinate(current.getX(), current.getY() - 1));
current.setY(current.getY() + 1);
coordinates.push(current);
}
}
}

input.setPixels(pixels, 0, width, 0, 0, width, height);
Bitmap output = input.copy(input.getConfig(), true);
output.setHasAlpha(true);
output.setPixels(pixels, 0, width, 0, 0, width, height);

return output;
}


private boolean validPosition(int x, int y, int width, int height) {
return x >= 0 && x < width && y >= 0 && y < height;
}
}

0 comments on commit b3ce109

Please sign in to comment.