How to put user defined text on image? - java

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

Related

Swing - new ImageIcon from Color

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);
}
}

Java window doesn't repaint properly until I resize the window manually

I am using a quite basic setup with a class extending JPanel, which I add to a JFrame.
import java.awt.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.event.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.*;
import java.io.*;
import javax.imageio.ImageIO;
public class PinTestMCVE extends JPanel implements ActionListener{
BufferedImage loadedImage;
JButton calcButton;
public static void main(String[] args) {
new PinTestMCVE();
}
public PinTestMCVE() {
loadedImage = getTestImage();
JPanel toolbarPanel = new JPanel();
calcButton = new JButton("calcButton...");
toolbarPanel.add(calcButton);
calcButton.addActionListener(this);
JFrame jf = new JFrame();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.getContentPane().setLayout(new BorderLayout());
jf.getContentPane().add(toolbarPanel, BorderLayout.NORTH);
jf.getContentPane().add(this, BorderLayout.CENTER);
jf.setSize(1250, 950);
jf.setVisible(true);
}
public void paintComponent(Graphics g) {
g.drawImage(loadedImage, 0, 0, this);
}
public void actionPerformed(ActionEvent e) {
System.out.println("ActionEvent " + e.getActionCommand());
if(e.getSource().equals(calcButton)){
this.repaint();
}
}
//Please ignore the inner workings of this
public static BufferedImage getTestImage(){
BufferedImage image = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
g2d.setPaint(Color.GRAY);
g2d.fillRect ( 0, 0, image.getWidth(), image.getHeight() );
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setPaint(Color.gray);
int x = 5;
int y = 7;
GradientPaint redtowhite = new GradientPaint(x, y, Color.red, 200, y, Color.blue);
g2d.setPaint(redtowhite);
g2d.fill(new RoundRectangle2D.Double(x, y, 200, 200, 10, 10));
return image;
}
}
What happens is that INITIALLY the window is painted properly, but once paintComponent is called, a strip of the old image (with the same height as the toolbar panel) is visible below the newly painted images - similar to playing card sticking out from a deck. But then, if I manually resize the window by for instance dragging the border, the background is grayed out as it should.
What is going on and how do I fix this?
As outlined here, you need to pack() the frame before calling setVisible(). You can override getPreferredSize() to specify a suitable initial Dimension. Also consider using a Border. See also Initial Threads.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.*;
public class PinTestMCVE extends JPanel implements ActionListener{
private static final int SIZE = 200;
BufferedImage loadedImage;
JButton calcButton;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new PinTestMCVE();
}
});
}
public PinTestMCVE() {
loadedImage = getTestImage();
JPanel toolbarPanel = new JPanel();
calcButton = new JButton("calcButton...");
toolbarPanel.add(calcButton);
calcButton.addActionListener(this);
JFrame jf = new JFrame();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(toolbarPanel, BorderLayout.NORTH);
jf.add(this, BorderLayout.CENTER);
jf.pack();
jf.setLocationRelativeTo(null);
jf.setVisible(true);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(loadedImage, 0, 0, this);
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("ActionEvent " + e.getActionCommand());
if(e.getSource().equals(calcButton)){
this.repaint();
}
}
//Please ignore the inner workings of this
public static BufferedImage getTestImage(){
BufferedImage image = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
g2d.setPaint(Color.GRAY);
g2d.fillRect ( 0, 0, image.getWidth(), image.getHeight() );
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setPaint(Color.gray);
GradientPaint redtowhite = new GradientPaint(5, 5, Color.red, SIZE, 5, Color.blue);
g2d.setPaint(redtowhite);
g2d.fill(new RoundRectangle2D.Double(5, 5, SIZE - 10, SIZE - 10, 10, 10));
return image;
}
}

How to disable java.awt.Graphics.fillRect(int x, int y, int width, int height)'s effect?

It's the original image:
I use java.awt.Graphics.fillRect(int x, int y, int width, int height) to add a coloured rectangle on the image.
Graphics imageGraphics = image.createGraphics();
Color color = new Color(0,0,0,100);
imageGraphics.setColor(color);
imageGraphics.fillRect(0, 0, 800, 600);
So the image has been inverted and looks like this:
After that,I want to clear the black transparent rectangle partly and show the original image.
imageGraphics.clearRect(100,100,100,100);
But the effect is like this:
What my requirement is:
I want to know why it doesn't work and is there any other way to realize it?
Remember, painting is destructive. It might be possible to use AlphaComposite to achieve this result, but a simpler solution might be to simple constructive a compound shape and paint that instead.
The following example creates two Rectangles, one been the area we want to fill and one been the area we want to show, the second is then subtracted from the first (to create the window) and then the result is painted on top of the image
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Area;
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.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ShowArea {
public static void main(String[] args) {
new ShowArea();
}
public ShowArea() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage img;
public TestPane() {
try {
img = ImageIO.read(new File("sample.png"));
Rectangle bounds = new Rectangle(0, 0, img.getWidth(), img.getHeight());
Rectangle clip = new Rectangle(150, 10, 100, 100);
Area area = new Area(bounds);
area.subtract(new Area(clip));
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.BLACK);
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.fill(area);
g2d.dispose();
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
}
If I were doing some kind of paint program, I would do this all within the paintComponent method or in some way that it didn't effect the original image, otherwise you've basic destroyed the image until you re-load it
Another solution might be to take a copy of the original area you want to keep and repaint it back on top after, for example...
img = ImageIO.read(new File("sample.png"));
// This is the portion of the image we want to save...
BufferedImage cutout = img.getSubimage(150, 10, 100, 100);
// This is the area we want to paint over...
Rectangle bounds = new Rectangle(0, 0, img.getWidth(), img.getHeight());
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.BLACK);
// Save the current Composite so we can reset it...
Composite comp = g2d.getComposite();
// Apply the composite and fill the area...
g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
g2d.fill(area);
// Reset the composite
g2d.setComposite(comp);
// Draw the part of the image we saved previously...
g2d.drawImage(cutout, 150, 10, this);
g2d.dispose();
You cant do that the way you're trying to.
It can be done by creating a BufferedImage filled with Color(0,0,0,200), then in that image draw rectangle with color Color(0,0,0,200) and then apply it on image.
Remember, that drawing filledRectange is not a "undo operation"- it is written on pixels and it can't be undone.
EDIT
Icon imageIcon = new javax.swing.ImageIcon("image.jpg");
BufferedImage mask = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(), BufferedImage.TYPE_4BYTE_ABGR);
BufferedImage image = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(), BufferedImage.TYPE_4BYTE_ABGR);
imageIcon.paintIcon(null, image.getGraphics(), 0, 0);
Graphics maskGraphics = mask.getGraphics();
//drawing grey background
maskGraphics.setColor(new Color(0, 0, 0, 120));
maskGraphics.fillRect(0, 0, mask.getWidth(), mask.getHeight());
//drawing black frame
maskGraphics.setColor(new Color(0, 0, 0, 255));
maskGraphics.drawRect(99, 99, 301, 301);
//drawing original image window
maskGraphics.drawImage(image, 100, 100, 400, 400, 100, 100, 400, 400, null);
//apply mask on image
new ImageIcon(mask).paintIcon(null, image.getGraphics(), 0, 0);
//result presentation
label.setIcon(new ImageIcon(image));
Yes this is easily doable. The problem is that any draw operation is destructive, what you see is what you get, the information that was painted upon is lost.
Something like this where you store a subimage, do your paint operation then draw the subimage back on top.
public class Q23709070 {
public static void main(String[] args) {
JFrame frame = new JFrame();
Panel p = new Panel();
frame.getContentPane().add(p);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
static class Panel extends JPanel {
int w = 400;
int h = 400;
int x = 100;
int y = 100;
BufferedImage img;
BufferedImage subImg;
BufferedImage save;
public Panel() {
try {
img = ImageIO.read(getClass().getResourceAsStream("0qzCf.jpg"));
} catch (IOException e) {
}
subImg = img.getSubimage(x, y, w, h);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Color g2dColor = g2d.getColor();
Color fillColor = new Color(0, 0, 0, 100);
g2d.drawImage(img, 0, 0, null);
g2d.setColor(fillColor);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.drawImage(subImg, x, y, null);
g2d.setColor(g2dColor);
if (save == null) {
save = new BufferedImage(img.getWidth(), img.getHeight(),
img.getType());
this.paint(save.getGraphics());
try {
ImageIO.write(save, "jpg", new File("save.jpg"));
} catch (IOException e) {
}
}
}
#Override
#Transient
public Dimension getPreferredSize() {
return new Dimension(img.getWidth(), img.getHeight());
}
}
}
Rendering

Java, Text on Image, update

I want to write some text on a image(BufferedImage), but when the text is updated the new text is written over the old one, e.g. all numbers are written in same place, Can someone help.
i'm usins this code:
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Prove extends JPanel {
int size = 800;
private BufferedImage sc ;
JLabel label ;
private int counter =0 ;
public Prove()
{
JFrame frame = new JFrame();
frame.getContentPane().add(this);
frame.setSize(2*size, size);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
try{ sc = ImageIO.read(new File("Images/ser.jpg"));
label =new JLabel(new ImageIcon(sc));
this.add(label);
}catch(IOException e){}
}
public void paintComponent(Graphics g)
{
g.setColor(Color.GRAY);
g.fillRect(0,0, getWidth(),getHeight()); //prapavijen
Graphics2D g2 = (Graphics2D)g;
paintScore(g2);
}
public void paintScore(Graphics g2)
{
if(sc != null)
{
Graphics gi = sc.createGraphics();
gi.setFont(new Font("Times New Roman", Font.BOLD, 20));
String r = counter+"";
gi.drawString(r, 20, 20);
counter ++;
this.repaint();
try{Thread.sleep(500);}
catch(InterruptedException e){}
System.out.println(counter);
}
}
public static void main(String[] args)
{
new Prove();
}
}
There is no reason to draw the text directly on the image. Simply draw the image to the component Graphics instance then draw the string to the same Graphics.
You are drawing the text to the same position, it is bound to overwrite
gi.drawString(r, 20, 20);
You will need to change the vertical coordinate if you want the new text to appear below the old one
You must keep an unmodified copy of the original image. Try this pseudocode:
BufferedImage img1 = loadImage();
And in your paint code:
BufferedImage img2 = createEmptyImage( img1 ); // same size, mode and depth
Graphics g = img2.getGraphics();
try {
g.draw( img1 ); // background
g.drawString(); // render text on top of it
} finally {
g.dispose();
}

java ImageObserver stop updating an animated gif

textPane contains text and animated gif images. imageUpdate used to update each new gif frame. When I delete a image from textPane, imageupdate continues to update it. How can I stop it?
How to make imageupdate updated only image that got a new frame rather than the entire textPane? imageupdate always displays the x = 0 and y = 0, although the images are in the other coordinates and I can not get a specific image rectangle.
Image 001.gif http://plasmon.rghost.ru/37834058.image
Image 000.gif http://plasmon.rghost.ru/37834053.image
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.*;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
import javax.swing.*;
import java.awt.BorderLayout;
import javax.swing.text.*;
public class HighlightExample {
public static JTextPane textPane;
public static HTMLEditorKit kit = new HTMLEditorKit();
public static char c = (char)(int)10022007;
public static void main(String[] args) {
final JTextField tf = new JTextField();
JFrame f = new JFrame("Highlight example");
textPane = new JTextPane(){
#Override
public void paintComponent(Graphics g) {
Graphics2D graphics2d = (Graphics2D) g;
graphics2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
try {
Document d = (this).getDocument();
String content = d.getText(0, d.getLength()).toLowerCase();
int lastIndex = 0;
super.paintComponent(g);
Image[] image=new Image[] {Toolkit.getDefaultToolkit().getImage("000.gif"), Toolkit.getDefaultToolkit().getImage("001.gif")};
while ((lastIndex = content.indexOf(c, lastIndex)) != -1) {
g.drawImage(image[Integer.parseInt(content.substring(lastIndex+1, lastIndex+4))],(int)(this).modelToView(lastIndex).getX(),(int)(this).modelToView(lastIndex).getY(),this);
++lastIndex;
}
} catch (BadLocationException e) {}
}
public boolean imageUpdate( Image img, int flags, int x, int y, int w, int h )
{
System.out.println("Image update:" + img + " flags="+flags+" x="+x+" y="+y+" w="+w+" h="+h);
repaint(); //repaint(x, y, w, h);
return true;
}
};
tf.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
textPane.setText(tf.getText().trim());
}
});
textPane.setEditorKit(kit);
StyleSheet styleSheet = kit.getStyleSheet();
styleSheet.addRule("sm {color: red;}");
JPanel pane = new JPanel();
pane.setLayout(new BorderLayout());
pane.add(tf, "Center");
f.getContentPane().add(pane, "South");
f.getContentPane().add(new JScrollPane(textPane), "Center");
textPane.setEditable(false);
textPane.setContentType("text/html");
textPane.setText("ab<span style=\"font-size: 0px;color: white;\">"+c+"001</span> пїЅdefghijkl bпїЅlmnop12345678<span style=\"font-size: 0px;color: white;\">"+c+"000</span> ;)<br><br><br><br><br><br><br><br>");
f.setSize(400, 400);
f.setVisible(true);
}
}
load the images only once not every time you repaint
for each image hold a list where you drew it during the last paint
in imageUpdate use the given img to select the list of coordinates you populated in paintComponent for that very image and only repaint regions for that coordinates
Note: images not currently used in your text will still call imageUpdate but are automatically skipped since their list of coordinates should be empty

Categories