I have some .jpg's that I'm displaying in a panel. Unfortunately they're all about 1500x1125 pixels, which is way too big for what I'm going for. Is there a programmatic way to change the resolution of these .jpg's?
You can scale an image using Graphics2D methods (from java.awt). This tutorial at mkyong.com explains it in depth.
Load it as an ImageIcon and this'll do the trick:
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
public static ImageIcon resizeImageIcon( ImageIcon imageIcon , Integer width , Integer height )
{
BufferedImage bufferedImage = new BufferedImage( width , height , BufferedImage.TRANSLUCENT );
Graphics2D graphics2D = bufferedImage.createGraphics();
graphics2D.drawImage( imageIcon.getImage() , 0 , 0 , width , height , null );
graphics2D.dispose();
return new ImageIcon( bufferedImage , imageIcon.getDescription() );
}
you can try:
private BufferedImage getScaledImage(Image srcImg, int w, int h) {
BufferedImage resizedImg = new BufferedImage(w, h, Transparency.TRANSLUCENT);
Graphics2D g2 = resizedImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(srcImg, 0, 0, w, h, null);
g2.dispose();
return resizedImg;
}
Related
I have the original image:
I rotate the image with the following Java code:
BufferedImage bi = ImageHelper.rotateImage(bi, -imageSkewAngle);
ImageIO.write(bi, "PNG", new File("out.png"));
as the result I have the following image:
How to remove black bound around the image and make it a proper white rectangle and to not spent much space.. use only the required size for the transformation... equal to original or larger if needed?
The following program contains a method rotateImage that should be equivalent to the rotateImage method that was used in the question: It computes the bounds of the rotated image, creates a new image with the required size, and paints the original image into the center of the new one.
The method additionally receives a Color backgroundColor that determines the background color. In the example, this is set to Color.RED, to illustrate the effect.
The example also contains a method rotateImageInPlace. This method will always create an image that has the same size as the input image, and will also paint the (rotated) original image into the center of this image.
The program creates two panels, the left one showing the result of rotateImage and the right one the result of rotateImageInPlace, together with a slider that allows changing the rotation angle. So the output of this program is shown here:
(Again, Color.RED is just used for illustration. Change it to Color.WHITE for your application)
As discussed in the comments, the goal of not changing the image size may not always be achievable, depending on the contents of the image and the angle of rotation. So for certain angles, the rotated image may not fit into the resulting image. But for the use case of the question, this should be OK: The use case is that the original image already contains a rotated rectangular "region of interest". So the parts that do not appear in the output should usually be the parts of the input image that do not contain relevant information anyhow.
(Otherwise, it would be necessary to either provide more information about the structure of the input image, regarding the border size or the angle of rotation, or one would have to manually figure out the required size by examining the image, pixel by pixel, to see which pixels are black and which ones are white)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
public class RotateImageWithoutBorder
{
public static void main(String[] args) throws Exception
{
BufferedImage image =
ImageIO.read(new URL("https://i.stack.imgur.com/tMtFh.png"));
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ImagePanel imagePanel0 = new ImagePanel();
imagePanel0.setBackground(Color.BLUE);
ImagePanel imagePanel1 = new ImagePanel();
imagePanel1.setBackground(Color.BLUE);
JSlider slider = new JSlider(0, 100, 1);
slider.addChangeListener(e ->
{
double alpha = slider.getValue() / 100.0;
double angleRad = alpha * Math.PI * 2;
BufferedImage rotatedImage = rotateImage(
image, angleRad, Color.RED);
imagePanel0.setImage(rotatedImage);
BufferedImage rotatedImageInPlace = rotateImageInPlace(
image, angleRad, Color.RED);
imagePanel1.setImage(rotatedImageInPlace);
f.repaint();
});
slider.setValue(0);
f.getContentPane().add(slider, BorderLayout.SOUTH);
JPanel imagePanels = new JPanel(new GridLayout(1,2));
imagePanels.add(imagePanel0);
imagePanels.add(imagePanel1);
f.getContentPane().add(imagePanels, BorderLayout.CENTER);
f.setSize(800,500);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static BufferedImage rotateImage(
BufferedImage image, double angleRad, Color backgroundColor)
{
int w = image.getWidth();
int h = image.getHeight();
AffineTransform at = AffineTransform.getRotateInstance(
angleRad, w * 0.5, h * 0.5);
Rectangle rotatedBounds = at.createTransformedShape(
new Rectangle(0, 0, w, h)).getBounds();
BufferedImage result = new BufferedImage(
rotatedBounds.width, rotatedBounds.height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = result.createGraphics();
g.setColor(backgroundColor);
g.fillRect(0, 0, rotatedBounds.width, rotatedBounds.height);
at.preConcatenate(AffineTransform.getTranslateInstance(
-rotatedBounds.x, -rotatedBounds.y));
g.transform(at);
g.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(image, 0, 0, null);
g.dispose();
return result;
}
private static BufferedImage rotateImageInPlace(
BufferedImage image, double angleRad, Color backgroundColor)
{
int w = image.getWidth();
int h = image.getHeight();
AffineTransform at = AffineTransform.getRotateInstance(
angleRad, w * 0.5, h * 0.5);
Rectangle rotatedBounds = at.createTransformedShape(
new Rectangle(0, 0, w, h)).getBounds();
BufferedImage result = new BufferedImage(
w, h,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = result.createGraphics();
g.setColor(backgroundColor);
g.fillRect(0, 0, w, h);
at.preConcatenate(AffineTransform.getTranslateInstance(
-rotatedBounds.x - (rotatedBounds.width - w) * 0.5,
-rotatedBounds.y - (rotatedBounds.height - h) * 0.5));
g.transform(at);
g.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(image, 0, 0, null);
g.dispose();
return result;
}
static class ImagePanel extends JPanel
{
private BufferedImage image;
public void setImage(BufferedImage image)
{
this.image = image;
repaint();
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if (image != null)
{
g.drawImage(image, 0, 0, null);
}
}
}
}
My GUI output is picture 1. I want to print the card in the opposite direction, as in picture 2. I use JLabel to store each card as my code shown. Any .swing or .awt method can help me do this?
CardLabel = LabelCard(cardsInHand);
int xcoordinate = 100;
for ( JLabel Label : CardLabel){
this.add(Label);
Label.setBounds(i += 20 , (int) (frame.getHeight()/5.8 * game.getCurrentIdx() +20 ) , Label.getIcon().getIconWidth(), Label.getIcon().getIconHeight() );
}
Picture 1:
Picture 2:
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
-----------------------------------------------------------------------------
public static BufferedImage FlippTheImage(BufferedImage bi) {
BufferedImage flipped = new BufferedImage(bi.getWidth(), bi.getHeight(),
bi.getType());
AffineTransform tran = AffineTransform.getTranslateInstance(0,
bi.getHeight());
AffineTransform flip = AffineTransform.getScaleInstance(1d, -1d);
tran.concatenate(flip);
Graphics2D g = flipped.createGraphics();
g.setTransform(tran);
g.drawImage(bi, 0, 0, null);
g.dispose();
return flipped;
}
in this example im using AffineTransform to flip the image you can see the doumentation for more details https://docs.oracle.com/javase/tutorial/2d/advanced/transforming.html
you can convert your icon in jlabel to bufffered image by this approach
public BufferedImage getLabelTOBufferImg(){
BufferedImage img;
int imgW, imgH,
Icon icon = lable.getIcon();
imgW = icon.getIconWidth();
imgH = icon.getIconHeight();
img = new BufferedImage(imgW, imgH, BufferedImage.TYPE_INT_ARGB);
return img;
}
I try to scale image to 50x50 px, but I got black color. I need to make black to white
after scaled
this my code:
BufferedImage imgs = urlToBufferImage("src//imgTest.jpg");
BufferedImage resizedImage = new BufferedImage(50, 50, imgs.getType());
Graphics2D g = resizedImage.createGraphics();
// g.setBackground(Color.WHITE);
// g.drawImage(imgs, 0, 0, 50, 50,Color.WHITE, null);
g.drawImage(imgs.getScaledInstance(50, -1, Image.SCALE_DEFAULT), 0, 0, this);
g.dispose();
This is pretty simple.
My approach would be not to create a new BufferedImage, but to do:
BufferedImage imgs = urlToBufferImage("src//imgTest.jpg");
Graphics g = imgs.createGraphics();
g.drawImage(imgs, x, y, 50, 50, null);
or instead of drawing the image inside of the bounds, you could do
Graphics2D g2d = imgs.createGraphics();
g2d.scale(0.5, 0.5);
g2d.drawImage(imgs, x, y, null);
I am trying to write a string into a image using ImageIo. But while writing a large string ,full string is not written into that image.
Here's my code:
File url=new File(imgUrl);
BufferedImage image = ImageIO.read(url);
Graphics g = image.getGraphics();
g.setPaintMode();
g.setFont(g.getFont().deriveFont(30f));
g.drawString(text, 100, 100);
g.dispose();
This code works fine for small strings.but when the width of the string exceeds the width of the image,then full string is not displayed on that image.
Any suggestions?
i have an old method try it
public BufferedImage stringToImage(String text, Font font, Color bgColor, Color fgColor) {
BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
FontRenderContext fc = g2d.getFontRenderContext();
Rectangle2D bounds = font.getStringBounds(text, fc);
//calculate the size of the text
int width = (int) bounds.getWidth();
int height = (int) bounds.getHeight();
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
g2d = (Graphics2D) image.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setFont(font);
g2d.setColor(bgColor);
g2d.fillRect(0, 0, width, height);
g2d.setColor(fgColor);
g2d.drawString(text, 0, (int)-bounds.getY());
g2d.dispose();
return image;
}
and use
BufferedImage image = stringToImage(text, font, bgColor, fgColor);
ImageIO.write(image, "jpg", file);
Not tested, but it could be done as this:
JLabel label = new JLabel("<html><h2>Title</h2><p>large text ...</p>");
int w = image.getWidth();
int h = image.getHeigth();
label.setBounds(0, 0, w, h);
SwingUtilities.paintComponent(g, label, null, 0, 0, w, h);
There are many ways to acheive this.
FontRenderContext/GlyphVector as mentioned by pbaris. See this answer for an e.g.
FontMetrics as seen in this answer.
A JLabel (possibly multi-line) to contain and size the text. As mentioned by Joop E.G. LabelRenderTest
You can use JTextArea to layout text:
JTextArea textArea = new JTextArea(text);
textArea.setFont(g.getFont().deriveFont(30f));
textArea.setOpaque(false);
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
textArea.setBounds(0, 0, image.getWidth(), image.getHeight());
textArea.paint(g);
I've got a full-screen JFrame and I'd like to create an background for it by filling a JLabel with an image and matching it's size to the dimension of the screen.
Whilst I can create a JLabel that matches the screen's size I can't seem to resize my image to fit. In essence, I want to end up with a full-screen JFrame that is completely filled with an image (regardless of the image's or the screen's dimensions).
Current code is below, thanks!
public void addBackground(ImageIcon imgIcon) {
Image img = imgIcon.getImage();
BufferedImage buffImg = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
BufferedImage resizeBuffImg = resize(buffImg, screenSize.width, screenSize.height);
Image finalImg = Toolkit.getDefaultToolkit().createImage(resizeBuffImg.getSource());
ImageIcon back = new ImageIcon(finalImg);
System.out.println("IMAGE WIDTH: " + back.getIconWidth());
System.out.println("IMAGE HEIGHT: " + back.getIconHeight());
JLabel backgroundLabel = new JLabel(back);
getContentPane().add(backgroundLabel);
}
public BufferedImage resize(BufferedImage image, int width, int height) {
int type = image.getType() == 0? BufferedImage.TYPE_INT_ARGB : image.getType();
BufferedImage resizedImage = new BufferedImage(width, height, type);
Graphics2D g = resizedImage.createGraphics();
g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(image, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
EDIT - Got it! Using Image's getScaledInstance() works. It's not perfect, but I'm intending to scale down large images rather than expand smaller ones.