try
{
BufferedImage original = ImageIO.read(OriginalImage);
BufferedImage resized = new BufferedImage(width, null, original.getType());
Graphics2D g2 = resized.createGraphics();
g2.drawImage(original, 0, 0, width, null, null);
g2.dispose();
ImageIO.write(resized, format, resizedImage);
}
I want to increase image width only height automatic adjust by width pixel.
Use the method Image.getScaledInstance as it show in the example below
import java.awt.BorderLayout;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class ImageTest {
private static final int WIDTH_INCREMENT = 100;
public static void main(String[] args) throws Exception {
BufferedImage image = ImageIO.read(new File("D:\\DDownloads\\Download.png"));
int targetWidth = image.getWidth() + WIDTH_INCREMENT;
// compute height using the aspect ratio
int targetHeight = (int) ((double) targetWidth * image.getHeight()) / image.getWidth();
Image target = image.getScaledInstance(targetWidth, targetHeight, Image.SCALE_SMOOTH);
// also you can use -1 as new height
// image.getScaledInstance(targetWidth, -1, Image.SCALE_SMOOTH);
// in this case the method computes the correct width by himself
BufferedImage toWrite = new BufferedImage(
targetWidth, targetHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = toWrite.createGraphics();
g2.drawImage(target, 0, 0, targetWidth, targetHeight, null);
g2.dispose();
ImageIO.write(toWrite, "png", new File("D:\\\\DDownloads\\\\converted.png"));
// next code is to show the both original and converted image on the screen
// Use invokeLater ofr correct initialization of Swing components
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frm = new JFrame("Images");
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.add(new JLabel(new ImageIcon(image)), BorderLayout.NORTH);
frm.add(new JLabel(new ImageIcon(target)), BorderLayout.SOUTH);
frm.pack();
frm.setLocationRelativeTo(null); // center the window
frm.setVisible(true);
}
});
}
}
Related
I'm trying to develop a small rendering thing for a small project. I've gotten to a place where I can setup a Graphics2D object and call things from a simple render() loop, but when attempting to draw an image in place the image crops itself awkwardly and begins to lose data.
This is what I currently have in my draw function. Renderable is a pre-loaded BufferedImage.
public void draw(Graphics2D g2d, int x, int y, int scale, int rotation) {
scale = scale / 2;
AffineTransform at = new AffineTransform();
at.rotate(Math.toRadians(rotation), renderable.getWidth() / 2, renderable.getHeight() / 2);
AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);
BufferedImage copy = op.filter(renderable, null);
int pX = (400 - ((copy.getWidth() * scale) / 2)) + x;
int pY = (300 - ((copy.getHeight() * scale) / 2)) + y;
g2d.drawImage(copy, pX, pY, copy.getWidth() * scale, copy.getHeight() * scale, null);
}
When the rotation is not divisible by 90
When the rotation is divisible by 0, 90, 180, or 270
Is there something I am missing or should be doing differently? It appears to me that the image is losing data. The Graphics2D object passed into the function is the same one used to render the lines behind the checkered square and should cover the full Canvas, which is 800x600 pixels.
Update
int rotation = 0;
while (EngineGlue.isValid()) {
rotation = rotation + 15;
if (rotation >= 360) {
rotation = 0;
}
Graphics2D g2d = (Graphics2D)EngineGlue.getInstance().getCanvas().getBufferStrategy().getDrawGraphics();
g2d.clearRect(0, 0, 800, 600);
g2d.drawLine(0, 300, 800, 300);
g2d.drawLine(400, 0, 400, 600);
//ta1.draw(g2d, -100, 0, 2, rotation);
//ta2.draw(g2d, 100, 0, 3, -rotation);
ta3.draw(g2d, 0, 0, 1, rotation);
EngineGlue.getInstance().getCanvas().getBufferStrategy().show();
Thread.sleep(150);
}
frame = new JFrame(title);
canvas = new Canvas();
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setResizable(false);
frame.setVisible(true);
frame.add(canvas);
frame.pack();
frame.setSize(EngineGlue.Dimension.WIDTH.getValue(), EngineGlue.Dimension.HEIGHT.getValue());
frame.setLocationRelativeTo(null);
canvas.setSize(EngineGlue.Dimension.WIDTH.getValue(), EngineGlue.Dimension.HEIGHT.getValue());
canvas.createBufferStrategy(3);
You can use an AffineTransform to rotate and scale the image:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import java.io.*;
import javax.imageio.*;
import java.awt.geom.*;
import java.awt.image.*;
public class RotateAndScale extends JPanel
{
private Image image;
public RotateAndScale(Image image)
{
this.image = image;
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
// create the transform, note that the transformations happen
// in reversed order (so check them backwards)
AffineTransform at = new AffineTransform();
// 4. translate it to the center of the component
at.translate(getWidth() / 2, getHeight() / 2);
// 3. do the actual rotation
at.rotate(Math.toRadians(45));
// 2. scale the image
at.scale(0.5, 0.5);
// 1. translate the object to rotate around the center
at.translate(-image.getWidth(this) / 2, -image.getHeight(this) / 2);
// draw the image
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(image, at, null);
// continue drawing other stuff (non-transformed)
//...
}
private static void createAndShowGUI()
{
try
{
BufferedImage image = ImageIO.read(new File("splash.gif"));
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new RotateAndScale(image));
frame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
catch(Exception e) { System.out.println(e); }
}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
}
}
Above is code I found somewhere a long time ago.
If you just want to rotate an image, the easiest way is to rotate the graphics context rather than the image itself. This reads in an image of Mars so you'll have to substitute your own image.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class RotateImage extends JPanel {
JFrame frame;
int width;
int height;
BufferedImage b = null;
String imageFile = "f:/redmarble.jpg";
public RotateImage() {
frame = new JFrame();
setPreferredSize(new Dimension(width, height));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new RotateImage().startup());
}
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
public void startup() {
try {
b = ImageIO.read(new File(imageFile));
} catch (IOException ioe) {
ioe.printStackTrace();
}
// calculate the diagonal of the image to size the panel
// this allows all rotations to fit within the panel
double diag = Math.hypot(b.getHeight(), b.getWidth());
width = (int) diag;
height = (int) diag;
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (b == null) {
return;
}
Graphics2D g2d = (Graphics2D) g.create();
// set the angle of rotation and the center of rotation to the middle of the
// panel - width and height are equal but I still like to reference them
// independently (could save debugging time in the future).
g2d.rotate(Math.toRadians(45), width/2, height/2);
// now draw the image, adjusting x,y starting point to ensure rotation
// about the center.
g2d.drawImage(b, (width-b.getWidth())/2, (height-b.getHeight())/2,null);
}
}
I have following image
Now I want to resize it to paint as background for a label, so that the borders still have the original size.
Here ist the code:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.border.EmptyBorder;
/**
* <code>BackgroundTest</code>.
*/
public class BackgroundTest extends JLabel {
// probably you need to download it and change the URL
private static final Image BACKGROUND = read(
"https://i.stack.imgur.com/MIwyR.png");
private static Image read(String url) {
try {
return ImageIO.read(new URL(url));
} catch (Exception e) {
throw new IllegalArgumentException("Cannot resolve image!", e);
}
}
#Override
protected void paintComponent(Graphics g) {
g.drawImage(scaleRect(BACKGROUND, new Insets(7, 7, 7, 7), getWidth(), getHeight()), 0, 0, this);
super.paintComponent(g);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(BackgroundTest::startUp);
}
private static void startUp() {
BackgroundTest label = new BackgroundTest();
label.setOpaque(false);
label.setText("<html>Simple multiline test to check<br>the painting</html>");
label.setBorder(new EmptyBorder(7, 7, 7, 7));
JFrame frm = new JFrame("Test");
JPanel panel = new JPanel();
panel.add(label);
panel.add(new JLabel(new ImageIcon(BACKGROUND)));
frm.add(panel);
frm.setSize(300, 300);
frm.setLocationRelativeTo(null);
frm.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frm.setVisible(true);
}
private Image scaleRect(Image src, Insets safePart, int width, int height) {
BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = result.createGraphics();
g.drawImage(src, 0, 0, width, height, this);
g.dispose();
return result;
}
}
The result looks ugly, because the borders are upscaled:
In this code example I only need a correct implementation of the function scaleRect, so that it considers the border insets (safePart parameter). The Graphics2D class has some other drawImage methods, but I don't know how to use them to achieve my goal.
You can take the 9-patch image approach - basically split your image into 9 pieces, some of which can be stretched without any visual artifacts and some that will stay at fixed size.
Basically cut it along these lines:
Then you can stretch:
top center & bottom center ones horizontally (if needed)
left center & right center ones vertically (if needed)
middle one can be stretched both horizontally and vertically
corners should remain in fixed sizes, otherwise you will get artifacts
Also you don't really need to cut the image, you can simply paint a specific part of the image:
public class SampleComponent extends JLabel
{
#Override
protected void paintComponent ( final Graphics g )
{
final Graphics2D g2d = ( Graphics2D ) g;
final Image image = ...; // Your image
g2d.drawImage (
image,
dstX1, dstY1, dstX2, dstY2,
imgX1, imgY1, imgX2, imgY2,
null
);
super.paintComponent ( g );
}
}
dst* - are the drawing destination rectangle coordinates
img* - are the coordinates of rectangle on your image
Note that this approach will only work with images that you can actually be split like shown above, it obviously won't work for something like photos or paintings, but for those cases I don't know why would you want to upscale them in the first place.
Many thanks to #MikleGarin for the idea. Here is the complete solution:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.border.EmptyBorder;
/**
* <code>BackgroundTest</code>.
*/
public class BackgroundTest extends JLabel {
// probably you need to download it and change the URL
private static final Image BACKGROUND = read(
"https://i.stack.imgur.com/MIwyR.png");
private static Image read(String url) {
try {
return ImageIO.read(new URL(url));
} catch (Exception e) {
throw new IllegalArgumentException("Cannot resolve image!", e);
}
}
#Override
protected void paintComponent(Graphics g) {
g.drawImage(scaleRect(BACKGROUND, new Insets(7, 7, 7, 7), getWidth(), getHeight()), 0, 0, this);
super.paintComponent(g);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(BackgroundTest::startUp);
}
private static void startUp() {
BackgroundTest label = new BackgroundTest();
label.setOpaque(false);
label.setText("<html>Simple multiline test to check<br>the painting</html>");
label.setBorder(new EmptyBorder(7, 7, 7, 7));
JFrame frm = new JFrame("Test");
JPanel panel = new JPanel();
panel.add(label);
panel.add(new JLabel(new ImageIcon(BACKGROUND)));
frm.add(panel);
frm.setSize(300, 300);
frm.setLocationRelativeTo(null);
frm.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frm.setVisible(true);
}
private Image scaleRect(Image src, Insets safePart, int width, int height) {
BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = result.createGraphics();
int srcWidth = src.getWidth(null);
int srcHeight = src.getHeight(null);
// top left
g.drawImage(src, 0, 0, safePart.left, safePart.right, 0, 0, safePart.left, safePart.top, null);
// top center
g.drawImage(src, safePart.left, 0, width - safePart.right, safePart.top, safePart.left, 0,
srcWidth - safePart.right, safePart.top, null);
// top right
g.drawImage(src, width - safePart.right, 0, width, safePart.top, srcWidth - safePart.right, 0,
srcWidth, safePart.top, null);
// center left
g.drawImage(src, 0, safePart.top, safePart.left, height - safePart.bottom, 0, safePart.top,
safePart.left, srcHeight - safePart.bottom, null);
// center
g.drawImage(src, safePart.left, safePart.top, width - safePart.right, height - safePart.bottom, safePart.left, safePart.top,
srcWidth - safePart.right, srcHeight - safePart.bottom, null);
// center right
g.drawImage(src, width - safePart.right, safePart.top, width, height - safePart.bottom, srcWidth - safePart.right, safePart.top,
srcWidth, srcHeight - safePart.bottom, null);
// bottom left
g.drawImage(src, 0, height - safePart.bottom, safePart.left, height, 0, srcHeight - safePart.bottom, safePart.left, srcHeight,
null);
// bottom middle
g.drawImage(src, safePart.left, height - safePart.bottom, width - safePart.right, height, safePart.left,
srcHeight - safePart.bottom, srcWidth - safePart.right, srcHeight, null);
// bottom right
g.drawImage(src, width - safePart.right, height - safePart.bottom, width, height, srcWidth - safePart.right,
srcHeight - safePart.bottom, srcWidth, srcHeight, null);
g.dispose();
return result;
}
}
Now it looks as it was required:
I need to programmatically create an ImageIcon with a simple color (let's say blue):
So I started doing this :
ImageIcon imageIcon = new ImageIcon();
Now I am trying to fill my ImageIcon with a blue color.
This should do the trick
BufferedImage image = new BufferedImage(60, 60, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = image.createGraphics();
graphics.setPaint(new Color(0, 0, 128));
graphics.fillRect(0, 0, image.getWidth(), image.getHeight());
ImageIcon imageIcon = new ImageIcon(image);
Based on the answer Lonely Neuron, I created a method to create a new ImageIcon with the desired size and Color:
public static ImageIcon createImageIcon(Color color, int width, int height) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = image.createGraphics();
graphics.setPaint(color);
graphics.fillRect (0, 0, width, height);
return new ImageIcon(image);
}
Call it like so:
ImageIcon imageIcon = createImageIcon(new Color(0, 0, 128), 60, 60);
Here is an example
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;
public class CreateImage {
public static void main(String[] args) {
JFrame frm = new JFrame("Test");
frm.add(new JLabel(createImage(Color.BLUE, new Dimension(200, 100))));
frm.pack();
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
public static Icon createImage(Color c, Dimension size) {
BufferedImage img = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB);
Graphics g = img.createGraphics();
g.setColor(c);
g.fillRect(0, 0, size.width, size.height);
return new ImageIcon(img);
}
}
I would like to get user defined text on image, like if I'll make two text fields, one is for name and second for date so when I input someone's name and date, after inputting if I clicked OK then it'll display in that image.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class billFrame extends JFrame
{
public billFrame()
{
JFrame f1 = new JFrame("Billng Application");
f1.setDefaultCloseOperation(EXIT_ON_CLOSE);
f1.setSize(500,500);
f1.setBounds(30, 50, 500, 700);
f1.setExtendedState(JFrame.MAXIMIZED_BOTH);
ImageIcon icon = new
ImageIcon("C:\\Users\\Dhaval\\Downloads\\shrihari.png");
Image image = icon.getImage();
JPanel panel1;
panel1 = new JPanel()
{
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image, 1400, 0, 500, 700, this);
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(320, 200);
}
};
f1.add(panel1);
panel1.setVisible(true);
panel1.setLayout(null);
JLabel name = new JLabel("Name :");
name.setVisible(true);
name.setLocation(100,100);
name.setSize(100,100);
panel1.add(name);
JTextField namet = new JTextField();
namet.setVisible(true);
namet.setLocation(150, 137);
namet.setSize(200,30);
panel1.add(namet);
f1.setVisible(true);
}
#SuppressWarnings("unchecked")
public static void main(String args[])
{
billFrame bf = new billFrame();
}
}
Here is sample:
static void addTextWatermark(String text, File sourceImageFile, File destImageFile) {
try {
BufferedImage sourceImage = ImageIO.read(sourceImageFile);
Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();
// initializes necessary graphic properties
AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f);
g2d.setComposite(alphaChannel);
g2d.setColor(Color.BLUE);
g2d.setFont(new Font("Arial", Font.BOLD, 64));
FontMetrics fontMetrics = g2d.getFontMetrics();
Rectangle2D rect = fontMetrics.getStringBounds(text, g2d);
// calculates the coordinate where the String is painted
int centerX = (sourceImage.getWidth() - (int) rect.getWidth()) / 2;
int centerY = sourceImage.getHeight() / 2;
// paints the textual watermark
g2d.drawString(text, centerX, centerY);
ImageIO.write(sourceImage, "png", destImageFile);
g2d.dispose();
System.out.println("The tex watermark is added to the image.");
} catch (IOException ex) {
System.err.println(ex);
}
}
And here is usage
File sourceImageFile = new File("name.png");
File destImageFile = new File("anothername.png");
addTextWatermark("Text", sourceImageFile, destImageFile);
Or you can us libs for that. For example: http://www.gif4j.com
I want my JToggleButton not to repaint when It is selected. I indicate state changing by pair of words ("check/next").
Standard behavior is blue lighting but I want to disable it.
Perhaps you could show the words on ImageIcons. For example:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
public class ToggleFun {
private static final Color BACKGROUND_COLOR = new Color(200, 200, 255);
public static void main(String[] args) {
int biWidth = 60;
int biHeight = 30;
BufferedImage checkImg = new BufferedImage(biWidth, biHeight, BufferedImage.TYPE_INT_RGB);
BufferedImage nextImg = new BufferedImage(biWidth, biHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = checkImg.createGraphics();
g2.setColor(BACKGROUND_COLOR);
g2.fillRect(0, 0, biWidth, biHeight);
g2.setColor(Color.black);
g2.drawString("Check", 10, 20);
g2.dispose();
g2 = nextImg.createGraphics();
g2.setColor(BACKGROUND_COLOR);
g2.fillRect(0, 0, biWidth, biHeight);
g2.setColor(Color.black);
g2.drawString("Next", 15, 20);
g2.dispose();
ImageIcon checkIcon = new ImageIcon(checkImg);
ImageIcon nextIcon = new ImageIcon(nextImg);
JToggleButton toggleBtn = new JToggleButton(checkIcon);
toggleBtn.setSelectedIcon(nextIcon);
toggleBtn.setContentAreaFilled(false);
toggleBtn.setBorder(BorderFactory.createLineBorder(Color.black));
JPanel panel = new JPanel();
panel.add(toggleBtn);
JOptionPane.showMessageDialog(null, panel);
}
}
See: AbstractButton.setContentAreaFilled(false).
But note that users generally prefer a GUI element that follows the 'path of least surprise'. This type of rendering might be better described as going off on a bit of a crash-bang through the undergrowth beside that path.