TTT
TTT

Reputation: 186

How to Draw Portion of an Image Using Graphics2D in Java

So I am developing a Discord bot with a friend that keeps track of player levels and, when using the !rank command, edits together a custom "Rank Card" using Graphics2D that displays all sorts of information. The base card looks like this:

enter image description here

Users can customize this with various commands like changing the color, accent color, opacity, and background. All of these work great, except the background command seems to squish images way too much. Essentially, when a user does "!rank background " the bot uses that URL link to a PNG file (on IMGUR or some other similar website) to set as the background. The way I have it setup now, this background is clipped to the size of the default background, but this seems to scale the entire image to fit within these bounds.

Original Image URL: https://cdn.discordapp.com/attachments/558371806655021108/733489277031153764/image0.jpg

enter image description here

As you can see, it seems to be squeezing the entire image to fit the whole thing into the default background shape, when all I want is a small slice of some random section of the new iamge (even if parts of the image are cut off).

What I am looking for is a way to just take a small slice of a larger image and then just draw it in as the background. I don't need the full image squeezed into the background, just a tiny slice the size of the default background.

BufferedImage base = ImageIO.read(new File("data/images/rankCardBase.png"));
BufferedImage outline = ImageIO.read(new File("data/images/rankCardOutline.png"));
Graphics2D g = (Graphics2D) base.getGraphics();
 
//Add Custom Background
if (!player.getString("background").isEmpty()) {
    BufferedImage background = ImageIO.read(new URL(player.getString("background")));
    BufferedImage rectBuffer = new BufferedImage(base.getWidth(), base.getHeight(), BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = rectBuffer.createGraphics();
    g2.setClip(new Rectangle2D.Float(0, 0, base.getWidth(), base.getHeight()));
    g2.drawImage(background, 0, 0, base.getWidth(), base.getHeight(), 0, 0, background.getWidth(), background.getHeight(), null);
    g.drawImage(rectBuffer, 0, 0, base.getWidth(), base.getHeight(), null);
}

Upvotes: 0

Views: 587

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347204

Essentially, g2.drawImage(background, 0, 0, base.getWidth(), base.getHeight(), 0, 0, background.getWidth(), background.getHeight(), null); is going to try and scale the image to fit within the specified area.

You could, instead, just paint the image at some (possibly random) point, for example, the following will centre the background within the base image...

Example

BufferedImage baseImage = new BufferedImage(400, 121, BufferedImage.TYPE_INT_RGB);
BufferedImage background = ImageIO.read(new URL("https://cdn.discordapp.com/attachments/558371806655021108/733489277031153764/image0.jpg"));

Graphics2D g2d = baseImage.createGraphics();
g2d.setColor(Color.GRAY);
g2d.fillRect(0, 0, 400, 121);

g2d.setClip(new RoundRectangle2D.Float(20, 20, baseImage.getWidth() - 40, baseImage.getHeight() - 40, 20, 20));

Random rnd = new Random();

int x = baseImage.getWidth() - background.getWidth() / 2;
int y = baseImage.getHeight() - background.getHeight() / 2;

g2d.drawImage(background, x, y, null);

g2d.dispose();

JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(baseImage)));

Another idea might be to look at BufferedImage#getSubImage

Upvotes: 2

Related Questions