Image crop, Remove unwanted white portion of Image using Java. How can we Remove unwanted white portion of Image using Java? I am having image which have plan white region, I want to remove that unused white part of Image apart from my useful main image using JAVA Code. you can get clear idea form below shown image. i need to perform this task using Java code.
Asked
Active
Viewed 1,719 times
3
-
Ah, `BufferedImage#subImage`? `BufferedImage#drawImage`? Do you know how much of the image you want to remove? Is it always going to be the same style - how constant is the image layout? – MadProgrammer Feb 08 '18 at 07:33
-
image size,resolution, height, width,etc. will be same always, Actually I want to crop image because where i am using this image, it not looks good because of white unused area. @MadProgrammer – Mehul Purohit Feb 08 '18 at 07:38
-
What about the image position? Will it always be at the top? – MadProgrammer Feb 08 '18 at 07:39
-
yes, it will be always on top. @MadProgrammer – Mehul Purohit Feb 08 '18 at 07:40
-
This is not a dup of the cited question, as the present question is more general and the other question does not address the general case. The present question also requires trimming the top and left of the image, not just the right and bottom. Requires a different API for cropping. – Joe Lapp May 30 '19 at 16:40
2 Answers
1
This is a (very) simple example of a brute force method. Basically, it walks the image until the color changes from the desired fill color
This is woefully inefficient. I had thought about using a divide and conquer approach, but I really don't have the time to flesh it out.
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class Test {
public static void main(String[] args) throws IOException {
BufferedImage img = ImageIO.read(new File("/Users/swhitehead/Downloads/47hb1.png"));
Rectangle bounds = getBounds(img, Color.WHITE);
System.out.println(bounds);
BufferedImage trimmed = img.getSubimage(bounds.x, bounds.y, bounds.width, bounds.height);
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(trimmed)));
}
public static Rectangle getBounds(BufferedImage img, Color fillColor) {
int top = getYInset(img, 20, 0, 1, fillColor);
int bottom = getYInset(img, 20, img.getHeight() - 1, -1, fillColor);
int left = getXInset(img, 0, top, 1, fillColor);
int right = getXInset(img, img.getWidth() - 1, top, -1, fillColor);
return new Rectangle(left, top, right - left, bottom - top);
}
public static int getYInset(BufferedImage img, int x, int y, int step, Color fillColor) {
while (new Color(img.getRGB(x, y), true).equals(fillColor)) {
y += step;
}
return y;
}
public static int getXInset(BufferedImage img, int x, int y, int step, Color fillColor) {
while (new Color(img.getRGB(x, y), true).equals(fillColor)) {
x += step;
}
return x;
}
}

MadProgrammer
- 343,457
- 22
- 230
- 366
-
1its inefficient because you are creating all the Colors for each pixel - wow a waste of memory Colors are huge wasters - there is no divide-and-conquer unless you have a parallel machine - 2-3 cores wont do nothin – gpasch Feb 08 '18 at 16:03
-
@gpasch To lazy; walking the pixels from each edge in is in efficient, given the possible amount of white space. When I say divide and conquer I’m talking about simply using a binary search style approach, simply dividing the image and check the pixel in the middle, but I’d prefer to go to bed ;) – MadProgrammer Feb 08 '18 at 18:44
0
You can use an image processing framework to make image manipulation more easy.
In the example below I used Marvin. My approach:
- Use gray scale thresholding to separate the white pixels from the rest of the image.
- Find the bounding-box of the black segment
- Crop the original image using segment detected in previous step.
Input:
Output (board_cropped.png):
Source code:
import static marvin.MarvinPluginCollection.*;
import java.awt.Rectangle;
import marvin.image.MarvinImage;
import marvin.io.MarvinImageIO;
public class BoardSegmentation {
public BoardSegmentation() {
MarvinImage imageOriginal = MarvinImageIO.loadImage("./res/board.png");
MarvinImage image = imageOriginal.clone();
thresholding(image, 250);
Rectangle rect = getBoundingBox(image);
crop(imageOriginal, image, rect.x, rect.y, rect.width, rect.height);
MarvinImageIO.saveImage(image, "./res/board_cropped.png");
}
public Rectangle getBoundingBox(MarvinImage image) {
Rectangle r = new Rectangle();
r.x = -1; r.y = -1; r.width = -1; r.height = -1;
for(int y=0; y<image.getHeight(); y++) {
for(int x=0; x<image.getWidth(); x++) {
if(image.getIntColor(x, y) == 0xFF000000) {
if(r.x == -1 || x < r.x) { r.x = x; }
if(r.width == -1 || x > r.x + r.width) { r.width = x - r.x; }
if(r.y == -1 || x < r.y) { r.y = y; }
if(r.height == -1 || y > r.y + r.height) { r.height = y - r.y; }
}
}
}
return r;
}
public static void main(String[] args) {
new BoardSegmentation();
}
}

Gabriel Archanjo
- 4,547
- 2
- 34
- 41
-
Your solution is very interesting but is affected by a small bug. Please, have a look at the condition of the third nested if operator: ``` java if(r.y == -1 || x < r.y) { r.y = y; } ``` It should be (note the y): ``` java if(r.y == -1 || ((y)) < r.y) { r.y = y; } ``` – Edoardo Vencia Feb 23 '22 at 16:25