ImageUtils { public static boolean getObjectRectangle(BufferedImage image, Rectangle rectangle) { int maxMargin = ComparisonParameterDefaults.getDefaultGroupDistance(); int x = (int) rectangle.getX(); int y = (int) rectangle.getY(); int w = (int) rectangle.getWidth(); int h = (int) rectangle.getHeight(); BufferedImage subImage = image.getSubimage(x, y, w, h); int width = w - 2; int height = h - 2; if (width <= 3 * maxMargin || height <= 3 * maxMargin) { return false; } boolean[][] edgeMap = new boolean[height][width]; for (int i = 0; i < maxMargin; i++) { for (int j = 0; j < maxMargin; j++) { edgeMap[i][j] = subImage.getRGB(j + 1, i + 1) != subImage.getRGB(j, i); edgeMap[i][width - 1 - j] = subImage.getRGB(width - j, i + 1) != subImage.getRGB(width - j + 1, i); edgeMap[height - 1 - i][j] = subImage.getRGB(j + 1, height - i) != subImage.getRGB(j, height - i + 1); edgeMap[height - 1 - i][width - 1 - j] = subImage.getRGB(width - j, height - i) != subImage.getRGB( width - j + 1, height - i + 1); } for (int j = maxMargin; j < width - maxMargin; j++) { edgeMap[i][j] = subImage.getRGB(j + 1, i + 1) != subImage.getRGB(j + 1, i); edgeMap[height - 1 - i][j] = subImage.getRGB(j + 1, height - i) != subImage.getRGB(j + 1, height - i + 1); } for (int j = maxMargin; j < height - maxMargin; j++) { edgeMap[j][i] = subImage.getRGB(i + 1, j + 1) != subImage.getRGB(i, j + 1); edgeMap[j][width - 1 - i] = subImage.getRGB(width - i, j + 1) != subImage.getRGB(width - i + 1, j + 1); } } int shrinkLength = 2 * maxMargin + 1; boolean[][] shrinkMap = new boolean[shrinkLength][shrinkLength]; boolean[][] verticalMap = new boolean[shrinkLength][shrinkLength]; boolean[][] horizontalMap = new boolean[shrinkLength][shrinkLength]; for (int i = 0; i < maxMargin; i++) { for (int j = 0; j < maxMargin; j++) { shrinkMap[i][j] = edgeMap[i][j]; shrinkMap[i][shrinkLength - 1 - j] = edgeMap[i][width - 1 - j]; shrinkMap[shrinkLength - 1 - i][j] = edgeMap[height - 1 - i][j]; shrinkMap[shrinkLength - 1 - i][shrinkLength - 1 - j] = edgeMap[height - 1 - i][width - 1 - j]; } } shrinkMap[maxMargin][maxMargin] = false; for (int i = 0; i < maxMargin; i++) { int leftIdx = maxMargin, rightIdx = maxMargin, topIdx = maxMargin, bottomIdx = maxMargin; while (leftIdx < height - maxMargin && edgeMap[leftIdx][i]) { leftIdx++; } shrinkMap[maxMargin][i] = (leftIdx == height - maxMargin); while (rightIdx < height - maxMargin && edgeMap[rightIdx][width - 1 - i]) { rightIdx++; } shrinkMap[maxMargin][shrinkLength - 1 - i] = (rightIdx == height - maxMargin); while (topIdx < width - maxMargin && edgeMap[i][topIdx]) { topIdx++; } shrinkMap[i][maxMargin] = (topIdx == width - maxMargin); while (bottomIdx < width - maxMargin && edgeMap[height - 1 - i][bottomIdx]) { bottomIdx++; } shrinkMap[shrinkLength - 1 - i][maxMargin] = (bottomIdx == width - maxMargin); } for (int i = 0; i < shrinkLength; i++) { for (int j = 0; j < shrinkLength; j++) { verticalMap[i][j] = shrinkMap[i][j]; horizontalMap[i][j] = shrinkMap[i][j]; } } for (int i = 0; i < maxMargin; i++) { for (int j = 1; j <= maxMargin; j++) { verticalMap[maxMargin - j][i] &= verticalMap[maxMargin - j + 1][i]; verticalMap[maxMargin + j][i] &= verticalMap[maxMargin + j - 1][i]; verticalMap[maxMargin - j][shrinkLength - 1 - i] &= verticalMap[maxMargin - j + 1][shrinkLength - 1 - i]; verticalMap[maxMargin + j][shrinkLength - 1 - i] &= verticalMap[maxMargin + j - 1][shrinkLength - 1 - i]; horizontalMap[i][maxMargin - j] &= horizontalMap[i][maxMargin - j + 1]; horizontalMap[i][maxMargin + j] &= horizontalMap[i][maxMargin + j - 1]; horizontalMap[shrinkLength - 1 - i][maxMargin - j] &= horizontalMap[shrinkLength - 1 - i][maxMargin - j + 1]; horizontalMap[shrinkLength - 1 - i][maxMargin + j] &= horizontalMap[shrinkLength - 1 - i][maxMargin + j - 1]; } } for (int i = 0; i < shrinkLength; i++) { for (int j = 0; j < shrinkLength; j++) { shrinkMap[i][j] = verticalMap[i][j] & horizontalMap[i][j]; } } int top, bottom, left, right; for (top = 0; top < maxMargin; top++) { if (!shrinkMap[top][maxMargin]) continue; for (left = 0; left < maxMargin; left++) { if (!shrinkMap[top][left]) continue; for (bottom = 0; bottom < maxMargin; bottom++) { if (!shrinkMap[shrinkLength - 1 - bottom][left]) continue; for (right = 0; right < maxMargin; right++) { if (shrinkMap[top][shrinkLength - 1 - right] && shrinkMap[shrinkLength - 1 - bottom][shrinkLength - 1 - right]) { width -= left + right; height -= top + bottom; x += left; y += top; rectangle.setBounds(x, y, width, height); return true; } } } } } return false; } private  ImageUtils(); static ImageComparedResult compare(BufferedImage image1, Rectangle imageArea1, BufferedImage image2,
			Rectangle imageArea2, CompareOption[] options); static boolean isContained(BufferedImage entireImage, BufferedImage partImage); static double[][] calcIntegralImage(BufferedImage source); static boolean imageEquals(BufferedImage image1, BufferedImage image2); static BufferedImage getMaskedImage(BufferedImage image, List<Rectangle> maskAreas); static BufferedImage getMarkedImage(BufferedImage image, DiffPoints diffPoints); static BufferedImage getDiffImage(BufferedImage leftImage, BufferedImage rightImage, DiffPoints diffPoints); static BufferedImage trim(BufferedImage image, int trimTop, int trimLeft, int trimBottom, int trimRight); static BufferedImage verticalMerge(List<BufferedImage> images); static BufferedImage merge(List<List<BufferedImage>> images); static int[] getRGB(BufferedImage image, int width, int height); static int[] toARGB(int pixel); static int toPixel(int[] argb); static int toPixel(int r, int g, int b); static int toPixel(int a, int r, int g, int b); static int detectBackgroundColor(BufferedImage b); static boolean getObjectRectangle(BufferedImage image, Rectangle rectangle); static double norm(int pixel1, int pixel2); static double[] countSubpixel(BufferedImage bimage); static void removeRedundantRectangles(List<Rectangle> rectangles, int xLimit, int yLimit); static void removeOverlappingRectangles(List<Rectangle> rectangles); static void reshapeRect(Rectangle rectangle, int xLimit, int yLimit); static Rectangle getTightDiffArea(Rectangle rectangle, int xLimit, int yLimit); static List<Rectangle> convertObjectGroupsToAreas(List<ObjectGroup> objectGroups); static List<ObjectGroup> convertDiffPointsToObjectGroups(DiffPoints DP, int group_distance); static BufferedImage getSubImage(BufferedImage image, Rectangle rectangle); static Offset findDominantOffset(BufferedImage expectedImage, BufferedImage actualImage, double diffThreshold); static BufferedImage getDominantImage(BufferedImage expectedImage, BufferedImage actualImage, Offset offset); static int getSizeRelationType(int expectedWidth, int expectedHeight, int actualWidth, int actualHeight);  }
@Test public void testGetObjectRectangle() throws Exception { BufferedImage image = ImageIO.read(getClass().getResource("ImageUtilsTest_get_object_rectangle.png")); Rectangle rectangle = new Rectangle(247, 225, 109, 109); Rectangle expected = new Rectangle(251, 229, 99, 99); boolean result = ImageUtils.getObjectRectangle(image, rectangle); assertThat(result, is(true)); assertThat(rectangle, is(expected)); }