I am trying to create a method that will add a border to a BufferedImage where both border thickness and border color can be configurable by the parameters of the method.
Border thickness will be a non-negative integer (0, 1, 2, etc.) and corresponds to how many pixels thick the border should be on all four sides inside the perimeter of the image.
Border color is a length 3 integer array, corresponding to the RGB color value that the border should be.
This is the original image: original image
This is what the image should look like with a border of thickness 10 and RGB values 235, 64, 52: resulting image
This is the code I have but I keep running into an out-of-bounds error. error
I would greatly appreciate any help. I also realize I can use Java's graphics tools to edit on top of the image but I'm trying to edit the image itself and not create any kind of overlays.
public static void applyBorder(BufferedImage img, int borderThickness, int[] borderColor) {
int width = img.getWidth();
int height = img.getHeight();
int borderRgb = (borderColor[0] << 16) | (borderColor[1] << 8) | borderColor[2];
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < borderThickness; y++) {
img.setRGB(x, y, borderRgb); // Top border
img.setRGB(x, img.getHeight() - 1 - y, borderRgb); // Bottom border
}
}
for (int y = borderThickness; y < img.getHeight() - borderThickness; y++) {
for (int x = 0; x < borderThickness; x++) {
img.setRGB(x, y, borderRgb); // Left border
img.setRGB(img.getWidth() - 1 - x, y, borderRgb); // Right border
}
}
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
img.setRGB(x + borderThickness, y + borderThickness, img.getRGB(x, y));
}
}
}
This is how I am calling the method in the main class:
int borderThickness = 10;
int[] borderColor = {255, 0, 0};
applyBorder(img, borderThickness, borderColor);
File fileBorder = new File("dog_border.png");
ImageIO.write(img, "png", fileBorder);
There's a few ways you might do this, personally I might consider making use of
Area, as it allows you tosubtract(oradd) shapes together, for example...You're probably scratching your head trying to figure out why this would be of benefit.
Consider for a second, what if you wanted the border to have a rounded inner edge!
Well, that's pretty easy to achieve, simply modify the
applyBordermethod to subtract a different shape, for example...which generates...
You could also make use of the existing
BorderAPI if you really wanted to.The "problem"...
The reason you're getting a
java.lang.ArrayIndexOutOfBoundsExceptionis because the code which, I think, for some reason I don't understand, fills the image with the pixels of the image...I'm assuming you're trying to "insert" the image into the border, rather then having the border drawn on top of the image???Anyway, your problem is here...
When
xiswidth - 1, you're then addingborderThicknessto it, which attempts to place a pixel outside of the image range. Same thing goes foryposition.Assuming you want to add the border around the image, as apposed to adding the border over the image, you need to modify your code to create a new image which is large enough to contain the original image and the border, for example...
If, however, you want to have the border painted over the image, then you need to paint the original image first, for example...
fyi: Using my super accurate, scientific measurement tools (insert sarcasm ), the
Graphics2Dapproach is about 10 milliseconds faster then theget/setRGBapproach - while not a massive difference, the size of the image will have an increasingly large impact on these results - for example, using a 1920x1080 source image, theGraphics2Dapproach took about 9 milliseconds, where as your code took about 203 milliseconds - again, these are "observational" differences, butget/setRGBis known for been slow