nullpointerexception when calling method after another method has been called? - java

I have an image editing program. It has several methods, such as grayscale, scale, merge images, etc. Each method works perfectly on its own. However, I am getting an error when calling grayScale method after mergeImg method has been called. It doesn't happen if I apply grayscale first.
Here is the error:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Picture.width(Picture.java:51)
at Picture$4.actionPerformed(Picture.java:222)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
at java.awt.Component.processMouseEvent(Component.java:6504)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6269)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4860)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2713)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:680)
at java.awt.EventQueue$4.run(EventQueue.java:678)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
And here is my code:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.lang.Math;
public class Picture{
JFileChooser fileChooser = new JFileChooser(); //file chooser
final JFrame frame = new JFrame("ImageEdit"); //creates JFrame
Container content; //creates container to place GUI objects in
static BufferedImage image; //original image
BufferedImage image2; //image after changes are made
BufferedImage mergeImage; //used for mergeImg method
JLabel imageLabel; //used to display image
//constructor; welcomes user, asks for image input
public Picture() {
//pops up prior to JFileChooser, intstructing user on what to do
Object[] options = {"Browse...", "Exit"};
ImageIcon welcomeIcon = new ImageIcon("GUI-images/welcome-icon.png");
int getFile = JOptionPane.showOptionDialog(frame, "Welcome to ImageEdit. To begin, please select an image file to edit.",
"Welcome!", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, welcomeIcon, options, options[0]);
//if user selects browse option, do this:
if (getFile == JOptionPane.YES_OPTION) {
//asks for image file as input
browse();
}
//otherwise, exit program
else {
//exit program
System.exit(0);
}
}
//method returns width of image
public int width() {
int width = image.getWidth();
return width;
}
//method returns height of image
public int height() {
int height = image.getHeight();
return height;
}
//method sets updated image as "original" image
public void setImage() {
this.image = image2;
}
//method writes image in destination
public void saveImage() {
//gets file name & destination from user through JFileChooser
fileChooser.setDialogTitle("Save As...");
fileChooser.showSaveDialog(frame);
//writes image to new file with given name & location
try {
ImageIO.write(this.image, "JPG", fileChooser.getSelectedFile());
}
catch (IOException f) {
System.out.println("Saving failed! Could not save image.");
}
}
//method browses for new file
public void browse() {
//asks for new image file
fileChooser.setDialogTitle("Choose an image file:");
fileChooser.showOpenDialog(frame);
File selectedFile = fileChooser.getSelectedFile();
//if user has selected image file, continue
if (fileChooser.getSelectedFile() != null) {
try {
//reads selectedFile as image
image = ImageIO.read(selectedFile);
}
catch (IOException e) {
System.out.println("Invalid image file: " + selectedFile);
System.exit(0);
}
}
//else print error message
else {
System.out.println("Error! No File Selected.");
}
}
//method creates frame, adds menubar with options, provides parameters for other methods
public void show() {
//set frame title, set it visible, etc
content = frame.getContentPane();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
//add the image to the frame
ImageIcon icon = new ImageIcon(image);
imageLabel = new JLabel(icon);
frame.setContentPane(imageLabel);
//adds a menubar on the frame with program name, File & Edit menus
JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
JMenu progName = new JMenu("ImageEdit");
progName.setBackground(Color.RED);
menuBar.add(progName);
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);
JMenu editMenu = new JMenu("Edit");
menuBar.add(editMenu);
//adds options to JMenus
//option to exit application
ImageIcon exitIcon = new ImageIcon("GUI-images/app-exit.png");
JMenuItem exitAction = new JMenuItem("Exit", exitIcon);
progName.add(exitAction);
//if exit option is selected, do this:
exitAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//prompts to save file before exiting
ImageIcon saveIcon = new ImageIcon("GUI-images/save-icon.png");
int askSave = JOptionPane.showConfirmDialog(null,"Save image before exit?", "Save...",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, saveIcon);
if (askSave == JOptionPane.YES_OPTION) {
//opens save image method, then exits
saveImage();
System.exit(0);
}
else {
//exits without saving
System.exit(0);
}
}
});
//option to open a new image
ImageIcon newIcon = new ImageIcon("GUI-images/new-image.png");
JMenuItem newAction = new JMenuItem("Open Image", newIcon);
fileMenu.add(newAction);
//if new option is selected, do this:
newAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//prompts to save image before opening new image
ImageIcon saveIcon = new ImageIcon("GUI-images/save-icon.png");
int askSave = JOptionPane.showConfirmDialog(null,"Save current image?", "Save...",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, saveIcon);
//if they do want to save first, do this:
if (askSave == JOptionPane.YES_OPTION) {
//opens save image method, then asks asks for new image file
saveImage();
//clears old image
imageLabel.setIcon(null);
//browses for new image
browse();
//displays new image
imageLabel.setIcon(new ImageIcon(image));
//resizes canvas to fit new image
frame.setSize(width(), height());
}
//if they don't want to save, do this:
else {
//erases old image
imageLabel.setIcon(null);
//browses for new image
browse();
//displays new image
imageLabel.setIcon(new ImageIcon(image));
//resizes canvas to fit new image
frame.setSize(width(), height());
}
}
});
//option to save current image
ImageIcon saveIcon = new ImageIcon("GUI-images/save-image.png");
JMenuItem saveAction = new JMenuItem("Save Image As...", saveIcon);
fileMenu.add(saveAction);
//if save option is selected, do this:
saveAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//opens save image method
saveImage();
}
});
//option to make current image grayscale
ImageIcon gsIcon = new ImageIcon("GUI-images/grayscale-image.png");
JMenuItem grayScale = new JMenuItem("Grayscale", gsIcon);
editMenu.add(grayScale);
//if grayscale option is selected, do this:
grayScale.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//grabs height and width of image,
//then calls grayscale method
grayscale(width(), height());
}
});
//option to scale current window to new dimensions
ImageIcon scaleIcon = new ImageIcon("GUI-images/scale-image.png");
JMenuItem scaleImg = new JMenuItem("Scale Image", scaleIcon);
editMenu.add(scaleImg);
//if scale option is selected, do this:
scaleImg.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//asks for height and width to create new image
ImageIcon widthIcon = new ImageIcon("GUI-images/LR-arrows.png");
String scaleWidth = (String)JOptionPane.showInputDialog(null,"What should the new width be?",
"Scale Image", JOptionPane.QUESTION_MESSAGE, widthIcon, null, null);
ImageIcon heightIcon = new ImageIcon("GUI-images/UD-arrows.png");
String scaleHeight = (String)JOptionPane.showInputDialog(null,"What should the new height be?",
"Scale Image", JOptionPane.QUESTION_MESSAGE, widthIcon, null, null);
//turns user input strings into doubles
double x = Double.parseDouble(scaleWidth);
double y = Double.parseDouble(scaleHeight);
//casts doubles as ints
int newWidth = (int)x;
int newHeight = (int)y;
//resizes frame to fit new image dimensions
frame.setSize(newWidth, newHeight);
//calls scale method to resize image using given dimensions
scale(newWidth, newHeight);
}
});
//option to merge two images together
ImageIcon mergeIcon = new ImageIcon("GUI-images/merge-image.png");
JMenuItem mergeImg = new JMenuItem("Merge Image", mergeIcon);
editMenu.add(mergeImg);
//if merge option is selected, do this:
mergeImg.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//asks for image file as input
fileChooser.setDialogTitle("Choose an image file to merge current image with.");
fileChooser.showOpenDialog(frame);
File mergeFile = fileChooser.getSelectedFile();
//if user has selected image file, continue
if (fileChooser.getSelectedFile() != null) {
try {
//reads selectedFile as image
mergeImage = ImageIO.read(mergeFile);
}
catch (IOException f) {
System.out.println("Invalid image file: " + mergeFile);
System.exit(0);
}
}
//else print error message
else {
System.out.println("Error! No File Selected.");
}
//if two images are same size, merge them
if (width() == mergeImage.getWidth() && height() == mergeImage.getHeight()) {
mergeImg(width(), height(), mergeImage);
}
//else, resize the second image to size of original, then merge
else {
scale(width(), height());
mergeImg(width(), height(), mergeImage);
}
}
});
//option to rotate image by x degrees
ImageIcon rotateIcon = new ImageIcon("GUI-images/rotate-image.png");
JMenuItem rotateImage = new JMenuItem("Rotate Image", rotateIcon);
editMenu.add(rotateImage);
//if rotate option is selected, do this:
rotateImage.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String rotateAngle = (String)JOptionPane.showInputDialog(null,"By what angle would you like to rotate?",
"Input Degrees", JOptionPane.QUESTION_MESSAGE, null/*icon goes here*/, null, null);
//turns user input strings into doubles
double angleDegs = Double.parseDouble(rotateAngle);
//converts degrees to rads
double angle = Math.toRadians(angleDegs);
//applies sine and cosine functions
int sin = (int)Math.sin(angle);
int cos = (int)Math.cos(angle);
//gets new width of rotated image
int newWidth = width()*sin + height()*cos;
int newHeight = height()*sin + width()*cos;
//sets frame to new image size
frame.setSize(newWidth, newHeight);
//calls rotate method to rotate image
rotate(newWidth, newHeight, angle);
}
});
//paint the frame
frame.pack();
frame.repaint();
frame.setVisible(true);
}
//method converts image to grayscale; 6 lines of code
public void grayscale(int width, int height) {
// create a grayscale image with original dimensions
image2 = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
// convert colored image to grayscale
ColorConvertOp grayScale = new ColorConvertOp(image.getColorModel().getColorSpace(),
image2.getColorModel().getColorSpace(),null);
grayScale.filter(image,image2);
imageLabel.setIcon(new ImageIcon(image2));
//sets new image as "original"
setImage();
}
//method scales image to user-input dimensions; 5 lines of code
public void scale(int width, int height){
//uses user-input dimensions to create new image
image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image2.createGraphics();
//gets new dimensions and resizes image
g.drawImage(image, 0, 0, image2.getWidth(), image2.getHeight(), 0, 0, width(), height(), null);
imageLabel.setIcon(new ImageIcon(image2));
//sets new image as "original"
setImage();
}
//method merges two images together; 14 lines of code
public void mergeImg(int width, int height, BufferedImage mergeImage) {
//creates new image from two images of same size
BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
//get color from original image
Color c = new Color(image.getRGB(i, j));
//get colors from merge image
Color c2 = new Color(mergeImage.getRGB(i, j));
//average the colors
int r = (c.getRed()+c2.getRed())/2;
int g = (c.getGreen()+c2.getGreen())/2;
int b = (c.getBlue()+c2.getBlue())/2;
Color avgColor = new Color(r, g, b);
//set colors of new image to average of the two images
image2.setRGB(i, j, avgColor.getRGB());
imageLabel.setIcon(new ImageIcon(image2));
}
}
mergeImage = null;
//sets new image as "original"
setImage();
}
//method rotates image by user-input angle; 18 lines of code
public void rotate(int width, int height, double angle) {
//rotates image around center point
BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//defines sin and cos functions
double sin = Math.sin(angle);
double cos = Math.cos(angle);
//gets coordinates of image center
double Xc = width/2;
double Yc = height/2;
//rotate
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
//new i,j at center of image
double iPrime = i - Xc;
double jPrime = j - Yc;
//i,j at new points after rotation
int xPrime = (int) (iPrime * cos - jPrime * sin + Xc);
int yPrime = (int) (iPrime * sin + jPrime * cos + Yc);
// plot pixel (i, j) the same color as (xPrime, yPrime) if it's in bounds
if (xPrime >= 0 && xPrime < width && yPrime >= 0 && yPrime < height) {
image2.setRGB(xPrime, yPrime, image.getRGB(i, j));
imageLabel.setIcon(new ImageIcon(image2));
}
}
}
//sets new image as "original"
setImage();
}
//main method; starts program
public static void main(String[] args) {
//creates new picture from image file
Picture p = new Picture();
//shows picture on JFrame
p.show();
}
}
Any ideas what could be up? Appreciate the help!

Judging from the stack trace and the code, it seems like this method
//method returns width of image
public int width() {
int width = image.getWidth();
return width;
}
throws a NullPointerException. The only thing that can cause this is if image is null.
I suggest you step through your problematic methods and check where and why null is assigned to the image variable.
One possible problem is that you redeclare image2 in method rotate and mergeImg.
BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
This effectively "hides" this.image2. When you later call setImage and do
this.image = image2;
image2 doesn't refer to the local variable which you have prepared.

From the stacktrace, you instance variable image seems to be null.
public int width() {
int width = image.getWidth();
return width;
}
try to add :
public int width() {
int width = 0;
if (null != image) {
width = image.getWidth();
}
return width;
}
EDIT : as someone already commented, you should not use so many instance varibale. having a setImage() with no param should ring a bell ;-). i would add a image parameter to this method so you will be sure to update your image instance variable with something you just worked with!
like
public void setImage(BufferedImage workingImg)
Relying on the state of different instance variables modified by many class method is the best way to have unpredictable results.
Good luck

Related

Problems with getting back rotated images from HashMap

I have the following problems:
I don't know why my function, when displaying already rotated images, shows only one in as many jpanels as there were photos given.
Let me give an example: I load 4 images into hashmap. Then I put them into my rotate function and try to display them. I end up with 4 tabs of one rotated image.
When I'm trying to rotate twice using the same deegres as used previously (I'm using slider to take degrees) it doesn't rotate anymore but if I touch slider and move it, the function rotates normally.
I had no idea how to convert an Image type into File object thus I converted it into BufferedImage and then to File. I browsed through the Internet but could not find anything helpful.
My main's class piece of code:
JPanel panel_2e = new JPanel();
panel_2e.setOpaque(true);
panel_2e.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED, Color.GRAY, Color.DARK_GRAY), "Rotate options"));
panel_2e.setLayout(new BoxLayout(panel_2e,BoxLayout.Y_AXIS));
JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 180);
slider.setMinorTickSpacing(10);
slider.setMajorTickSpacing(90);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setLabelTable(slider.createStandardLabels(45));
JPanel radio_buttons_rotate=new JPanel();
radio_buttons_rotate.setLayout(new BoxLayout(radio_buttons_rotate, BoxLayout.Y_AXIS));
JCheckBox cut_frame = new JCheckBox("Cut edges");
cut_frame.setSelected(true);
cut_frame.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if(e.getStateChange() == ItemEvent.SELECTED)
{check = true;
System.out.println("Cut-edge mode selected");}
else
{check = false;
System.out.println("Cut-edge mode deselected");}
}
});
cut_frame.setBounds(78, 41, 60, 23);
radio_buttons_rotate.add(cut_frame);
JRadioButton black_rdbutton = new JRadioButton("Black background");
black_rdbutton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
black = true;
}
});
black_rdbutton.setBounds(78, 41, 60, 23);
radio_buttons_rotate.add(black_rdbutton);
JRadioButton white_rdbutton = new JRadioButton("White background");
white_rdbutton.setSelected(true);
white_rdbutton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
black = false;
}
});
white_rdbutton.setBounds(78, 41, 60, 23);
radio_buttons_rotate.add(white_rdbutton);
ButtonGroup group_frame_rotate = new ButtonGroup();
group_frame_rotate.add(black_rdbutton);
group_frame_rotate.add(white_rdbutton);
panel_2e.add(radio_buttons_rotate);
JLabel Rotate = new JLabel();
Rotate.setText(deg+"\u00b0");
panel_2e.add(slider);
JButton btnRotate = new JButton("Rotate");
JPanel RotatePanel=new JPanel();
RotatePanel.add(Rotate);
RotatePanel.add(btnRotate);
RotatePanel.setLayout(new FlowLayout());
btnRotate.setBounds(28, 158, 89, 23);
btnRotate.setBackground(Color.DARK_GRAY);
btnRotate.setForeground(Color.WHITE);
panel_2e.add(RotatePanel);
panel_2.add(panel_2e);
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent ce) {
deg=((JSlider) ce.getSource()).getValue();
Rotate.setText(deg+"\u00b0"); }
});
btnRotate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if(AddDirectory.all_chosen.isEmpty())
{Object[] options = {"OK"};
int n = JOptionPane.showOptionDialog(frame,
"Please choose at least 1 image to rotate.","Empty work list",
JOptionPane.PLAIN_MESSAGE,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]);}
else
{RotateFunction rot = new RotateFunction(AddDirectory.all_chosen);
rot.main();
BufferedImage kk = null;
Display disp= new Display(); // invoke Display class
for(File i : all_chosen_images.values()){
try{
kk = ImageIO.read(new File(i.getAbsolutePath()));
disp.createFrame(center, i, kk); //create new frame with image
}
catch (IOException es){
es.printStackTrace();
}
}
}
}
});
And here is my rotate function:
public class RotateFunction{
HashMap<JButton,File> map;
Image spiral;
RotateFunction(HashMap<JButton,File> source_of_image)
{
map = AddDirectory.all_chosen;
}
public void main(){
int counter = 0;
if (spiral == null){
for(Map.Entry<JButton, File> entry: map.entrySet()) //////Moving through hashMap
{
try {
spiral = getImage(entry.getValue().getAbsolutePath());
counter++;
System.out.println("Path of image " + counter + " : " +entry.getValue().getAbsolutePath());
if (PhotoEdit.check == true){
rotateImage(PhotoEdit.deg, null);
System.out.println("Rotating image "+counter+" by "+PhotoEdit.deg+" degrees (edge cut)");
}
else{
rotateImage1(PhotoEdit.deg, null);
System.out.println("Rotating image "+counter+" by "+PhotoEdit.deg+" degrees (bigger frame)");
}
BufferedImage tmp = toBufferedImage(spiral);
File f;
f = new File( "image.png" );
try
{
ImageIO.write( tmp, "PNG", f );
}
catch ( IOException x )
{
// Complain if there was any problem writing
// the output file.
x.printStackTrace();
}
map.put(entry.getKey(), f);
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
PhotoEdit.all_chosen_images.clear();
PhotoEdit.all_chosen_images.putAll(map); //Putting HashMap with rotated images into global HashMap
System.out.println("Images have been successfully rotated");
}
}
public Image getImage(String path){
Image tempImage = null;
try
{
tempImage = Toolkit.getDefaultToolkit().getImage(path);
}
catch (Exception e)
{
System.out.println("An error occured - " + e.getMessage());
}
return tempImage;
}
////////////////////////////////////////////////////////////////////
///////////////////IMAGE ROTATION /////////////////////////////////
public void rotateImage(double degrees, ImageObserver o){
ImageIcon icon = new ImageIcon(this.spiral);
BufferedImage blankCanvas = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D)blankCanvas.getGraphics();
g2.rotate(Math.toRadians(degrees), icon.getIconWidth()/2, icon.getIconHeight()/2);
g2.drawImage(this.spiral, 0, 0, o);
this.spiral = blankCanvas;
}
public void rotateImage1(double degrees, ImageObserver o){
double sin = Math.abs(Math.sin(Math.toRadians(degrees)));
double cos = Math.abs(Math.cos(Math.toRadians(degrees)));
ImageIcon icon = new ImageIcon(this.spiral);
int w = icon.getIconWidth();
int h = icon.getIconHeight();
int neww = (int)Math.floor(w*cos+h*sin);
int newh = (int)Math.floor(h*cos+w*sin);
BufferedImage blankCanvas = new BufferedImage(neww, newh, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = (Graphics2D)blankCanvas.getGraphics();
g2.translate((neww-w)/2, (newh-h)/2);
g2.rotate(Math.toRadians(degrees), icon.getIconWidth()/2, icon.getIconHeight()/2);
g2.drawImage(this.spiral, 0, 0, o);
this.spiral = blankCanvas;
}
//////////////////////////////////////////////////////////////////////////
public static BufferedImage toBufferedImage(Image img)
{
if (img instanceof BufferedImage)
{
return (BufferedImage) img;
}
// Create a buffered image with transparency
BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
// Draw the image on to the buffered image
Graphics2D bGr = bimage.createGraphics();
bGr.drawImage(img, 0, 0, null);
bGr.dispose();
// Return the buffered image
return bimage;
}
}
In the display function i have the following arguments - createFrame(JDekstopPane where_to_put_the_image, File img, BufferedImage image)
HashMap - all_chosen_images is the global HashMap storing all the images
Really hope for your help.
Aleksander

How to put a picture in java code?

here is my code im trying to put a image but every time, i have an error in the getimage() part. Can you please help? Thank you. I know it's a weird project. Or can you tell me how to write a code for drawing a circle and dividing them to pieces. Every piece is a different color then i put them in a linked list and ask the user which color they hate and then i remove it. I do the same thing every time until i only have one color left. I don't know how to do that so i did it a different way so can you help me:
import java.util.*;
import java.util.Scanner;
import javax.swing.*;
import java.applet.*;
import java.awt.*;
public class ExtraCredit extends Applet
{
//graphic
public void paintOr(Graphics g)
{
Image img;
MediaTracker tr;
tr = new MediaTracker(this);
img = getImage(getCodeBase(), "Or.png");
tr.addImage(img,0);
g.drawImage(img, 0, 0, this);
}
public void paintRed(Graphics g1)
{
Image img;
MediaTracker tr;
tr = new MediaTracker(this);
img = getImage(getCodeBase(), "red.png");
tr.addImage(img,0);
g1.drawImage(img, 0, 0, this);
}
public void paintR(Graphics g2)
{
Image img;
MediaTracker tr;
tr = new MediaTracker(this);
img = getImage(getCodeBase(), "R.png");
tr.addImage(img,0);
g2.drawImage(img, 0, 0, this);
}
public void paintRBrown(Graphics g3)
{
Image img;
MediaTracker tr;
tr = new MediaTracker(this);
img = getImage(getCodeBase(), "rbrown.png");
tr.addImage(img,0);
g3.drawImage(img, 0, 0, this);
}
public void paintBr(Graphics g4)
{
Image img;
MediaTracker tr;
tr = new MediaTracker(this);
img = getImage(getCodeBase(), "Br.png");
tr.addImage(img,0);
g4.drawImage(img, 0, 0, this);
}
public void paintBrBlue(Graphics g5)
{
Image img;
MediaTracker tr;
tr = new MediaTracker(this);
img = getImage(getCodeBase(), "brblue.png");
tr.addImage(img,0);
g5.drawImage(img, 0, 0, this);
}
//----
public static void main(String[] args)
{
ExtraCredit ex = new ExtraCredit();
String cF;
int i=0;
LinkedList<String> c = new LinkedList<String>();
c.add("red");
c.add("brown");
c.add("blue");
c.add("green");
Scanner scan = new Scanner (System.in);
//first loop
while(i!=4)
{
i++;
System.out.println ("You have a list of color:brown, blue, green, red");
Graphics g = ex.getGraphics();
ex.paintOr(g);
System.out.println ("which color you most hate:");
String color1 = scan.nextLine();
//cF=c.getFirst();
if(color1 == c.getFirst())
{
Graphics g1 = ex.getGraphics();
ex.paintRed(g1);
}
c.remove(color1);
}
i=0;
// second loop
while(i!=3)
{
i++;
System.out.println ("You have a list of color:"+ c);
Graphics g2 =ex.getGraphics();
ex.paintR(g2);
System.out.println ("which color you most hate:");
String color2 = scan.nextLine();
if(color2 == c.getFirst())
{
Graphics g3 = ex.getGraphics();
ex.paintRBrown(g3);
}
c.remove(color2);
}
i=0;
//third loop
while(i!=2)
{
i++;
System.out.println ("You have a list of color:"+ c);
Graphics g4=ex.getGraphics();
ex.paintBr(g4);
System.out.println ("which color you most hate:");
String color3 = scan.nextLine();
cF=c.getFirst();
if(color3 == c.getFirst())
{
System.out.println ("The color you like:" + c);
Graphics g5 = ex.getGraphics();
ex.paintBrBlue(g5);
}
c.remove(color3);
}
}
}
This ex.getGraphics() is a really bad idea. This is NOT how painting is done in AWT or Swing.
Mixing command line input and UI elements is never a good idea, add in the fact that you are using a Applet and your user losses the ability to actually provide feedback...
AWT/Swing are event driven environments. Events are created from (mostly) mouse and keyboard inputs.
Take the time to read through Creating a GUI with Swing for details.
Don't forget to also take a look at Performing Custom Painting and 2D Graphics, in particular, the section on shapes.

Displaying and manipulating updated image

This program should first open an image, and then allow it to be manipulated via grayscale, scale, and rotate methods (not functional at the moment; disregard it). However, I'm not sure how I can call upon the updated image every time a method is performed. For example, if I grayscale an image, it goes to grayscale. But if I then scale it to a different size, the resulting image is a scaled version of the original image, not a scaled grayscale image. I tried putting in "image2 = image;" to no avail. How can I fix this?
Thanks.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
public class Picture{
JFileChooser fileChooser = new JFileChooser();
final JFrame frame = new JFrame("Edit Image");
Container content;
static BufferedImage image;
BufferedImage image2;
JLabel imageLabel;
public Picture() {
//asks for image file as input
fileChooser.setDialogTitle("Choose an image file to begin:");
fileChooser.showOpenDialog(frame);
File selectedFile = fileChooser.getSelectedFile();
if (fileChooser.getSelectedFile() != null) {
try {
//reads File as image
image = ImageIO.read(selectedFile);
}
catch (IOException e) {
System.out.println("Invalid image file: " + selectedFile);
System.exit(0);
}
}
else {
System.out.println("No File Selected!");
}
}
public int width() {
//returns width of present image
int width = image.getWidth();
return width;
}
public int height() {
//returns height of present image
int height = image.getHeight();
return height;
}
public void getImage() {
this.image2 = image;
}
public void saveImage() {
//saves current image as JPEG
fileChooser.setDialogTitle("Save this image?");
fileChooser.showSaveDialog(frame);
try {
//writes new file
ImageIO.write(this.image, "JPG", fileChooser.getSelectedFile());
}
catch (IOException f) {
System.out.println("Saving failed! Could not save image.");
}
}
public void show() {
//set frame title, set it visible, etc
content = frame.getContentPane();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
//add the image to the frame
ImageIcon icon = new ImageIcon(image);
imageLabel = new JLabel(icon);
frame.setContentPane(imageLabel);
//add a menubar on the frame with a single option: saving the image
JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
JMenu progName = new JMenu("Edit Image");
progName.setBackground(Color.RED);
menuBar.add(progName);
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);
JMenu editMenu = new JMenu("Edit");
menuBar.add(editMenu);
ImageIcon exitIcon = new ImageIcon("app-exit.png");
JMenuItem exitAction = new JMenuItem("Exit", exitIcon);
progName.add(exitAction);
exitAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ImageIcon saveIcon = new ImageIcon("save-icon.png");
int askSave = JOptionPane.showConfirmDialog(null,"Save current image?", "", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, saveIcon);
if (askSave == JOptionPane.YES_OPTION) {
//opens save image method, then exits
saveImage();
System.exit(0);
}
else {
//exits without saving
System.exit(0);
}
}
});
ImageIcon newIcon = new ImageIcon("new-image.png");
JMenuItem newAction = new JMenuItem("Open Image", newIcon);
fileMenu.add(newAction);
newAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ImageIcon saveIcon = new ImageIcon("save-icon.png");
int askSave = JOptionPane.showConfirmDialog(null,"Save current image?", "", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, saveIcon);
if (askSave == JOptionPane.YES_OPTION) {
//opens save image method, then asks asks for new image file
saveImage();
Picture p = new Picture();
imageLabel.setIcon(new ImageIcon(image));
//resizes canvas to fit new image
frame.setSize(width(), height());
}
else {
//asks for new image file since user did not want to save original
Picture p = new Picture();
imageLabel.setIcon(new ImageIcon(image));
//resizes canvas to fit new image
frame.setSize(width(), height());
}
}
});
ImageIcon saveIcon = new ImageIcon("save-image.png");
JMenuItem saveAction = new JMenuItem("Save Image As...", saveIcon);
fileMenu.add(saveAction);
saveAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//opens save image method
saveImage();
}
});
ImageIcon gsIcon = new ImageIcon("grayscale-image.png");
JMenuItem grayScale = new JMenuItem("Grayscale", gsIcon);
editMenu.add(grayScale);
grayScale.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//grabs height and width of image, then grayscales it
grayscale(width(), height());
}
});
ImageIcon scaleIcon = new ImageIcon("scale-image.png");
JMenuItem scaleImg = new JMenuItem("Scale Image", scaleIcon);
editMenu.add(scaleImg);
scaleImg.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//asks for height and width to create new image
ImageIcon widthIcon = new ImageIcon("LR-arrows.png");
String scaleWidth = (String)JOptionPane.showInputDialog(null,"What should the new width be?", "", JOptionPane.QUESTION_MESSAGE, widthIcon, null, null);
ImageIcon heightIcon = new ImageIcon("UD-arrows.png");
String scaleHeight = (String)JOptionPane.showInputDialog(null,"What should the new height be?", "", JOptionPane.QUESTION_MESSAGE, widthIcon, null, null);
//turns user input strings into doubles
double x = Double.parseDouble(scaleWidth);
double y = Double.parseDouble(scaleHeight);
//casts doubles as ints
int newWidth = (int)x;
int newHeight = (int)y;
//resizes frame to fit new image dimensions
frame.setSize(newWidth, newHeight);
//calls scale method to resize image using given dimensions
scale(newWidth, newHeight);
}
});
ImageIcon rotateIcon = new ImageIcon("rotate-image.png");
JMenuItem rotateImg = new JMenuItem("Rotate Image", rotateIcon);
editMenu.add(rotateImg);
rotateImg.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
//paint the frame
frame.pack();
frame.repaint();
frame.setVisible(true);
}
// convert to grayscale
public void grayscale(int width, int height) {
// create a grayscale image with original dimensions
image2 = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
// convert colored image to grayscale
ColorConvertOp grayScale = new ColorConvertOp(image.getColorModel().getColorSpace(),image2.getColorModel().getColorSpace(),null);
grayScale.filter(image,image2);
imageLabel.setIcon(new ImageIcon(image2));
getImage();
}
//scales image by a given factor
public void scale(int width, int height){
//uses user-input dimensions to create new image
image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image2.createGraphics();
//gets new dimensions and resizes image
g.drawImage(image, 0, 0, image2.getWidth(), image2.getHeight(), 0, 0, width(), height(), null);
imageLabel.setIcon(new ImageIcon(image2));
getImage();
}
//rotates the image
public void rotate(int width, int height, int theta) {
}
public static void main(String[] args) {
Picture p = new Picture();
p.show();
}
}
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
public class Picture{
JFileChooser fileChooser = new JFileChooser();
final JFrame frame = new JFrame("Edit Image");
Container content;
static BufferedImage image;
BufferedImage image2;
JLabel imageLabel;
public Picture() {
//asks for image file as input
fileChooser.setDialogTitle("Choose an image file to begin:");
fileChooser.showOpenDialog(frame);
File selectedFile = fileChooser.getSelectedFile();
if (fileChooser.getSelectedFile() != null) {
try {
//reads File as image
image = ImageIO.read(selectedFile);
}
catch (IOException e) {
System.out.println("Invalid image file: " + selectedFile);
System.exit(0);
}
}
else {
System.out.println("No File Selected!");
}
}
public int width() {
//returns width of present image
int width = image.getWidth();
return width;
}
public int height() {
//returns height of present image
int height = image.getHeight();
return height;
}
/*
public void getImage() {
this.image2 = image;
}
*/
public void saveImage() {
//saves current image as JPEG
fileChooser.setDialogTitle("Save this image?");
fileChooser.showSaveDialog(frame);
try {
//writes new file
ImageIO.write(this.image, "JPG", fileChooser.getSelectedFile());
}
catch (IOException f) {
System.out.println("Saving failed! Could not save image.");
}
}
public void show() {
//set frame title, set it visible, etc
content = frame.getContentPane();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
//add the image to the frame
ImageIcon icon = new ImageIcon(image);
imageLabel = new JLabel(icon);
frame.setContentPane(imageLabel);
//add a menubar on the frame with a single option: saving the image
JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
JMenu progName = new JMenu("Edit Image");
progName.setBackground(Color.RED);
menuBar.add(progName);
JMenu fileMenu = new JMenu("File");
menuBar.add(fileMenu);
JMenu editMenu = new JMenu("Edit");
menuBar.add(editMenu);
ImageIcon exitIcon = new ImageIcon("app-exit.png");
JMenuItem exitAction = new JMenuItem("Exit", exitIcon);
progName.add(exitAction);
exitAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ImageIcon saveIcon = new ImageIcon("save-icon.png");
int askSave = JOptionPane.showConfirmDialog(null,"Save current image?", "", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, saveIcon);
if (askSave == JOptionPane.YES_OPTION) {
//opens save image method, then exits
saveImage();
System.exit(0);
}
else {
//exits without saving
System.exit(0);
}
}
});
ImageIcon newIcon = new ImageIcon("new-image.png");
JMenuItem newAction = new JMenuItem("Open Image", newIcon);
fileMenu.add(newAction);
newAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ImageIcon saveIcon = new ImageIcon("save-icon.png");
int askSave = JOptionPane.showConfirmDialog(null,"Save current image?", "", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, saveIcon);
if (askSave == JOptionPane.YES_OPTION) {
//opens save image method, then asks asks for new image file
saveImage();
Picture p = new Picture();
imageLabel.setIcon(new ImageIcon(image));
//resizes canvas to fit new image
frame.setSize(width(), height());
}
else {
//asks for new image file since user did not want to save original
Picture p = new Picture();
imageLabel.setIcon(new ImageIcon(image));
//resizes canvas to fit new image
frame.setSize(width(), height());
}
}
});
ImageIcon saveIcon = new ImageIcon("save-image.png");
JMenuItem saveAction = new JMenuItem("Save Image As...", saveIcon);
fileMenu.add(saveAction);
saveAction.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//opens save image method
saveImage();
}
});
ImageIcon gsIcon = new ImageIcon("grayscale-image.png");
JMenuItem grayScale = new JMenuItem("Grayscale", gsIcon);
editMenu.add(grayScale);
grayScale.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//grabs height and width of image, then grayscales it
grayscale(width(), height());
}
});
ImageIcon scaleIcon = new ImageIcon("scale-image.png");
JMenuItem scaleImg = new JMenuItem("Scale Image", scaleIcon);
editMenu.add(scaleImg);
scaleImg.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//asks for height and width to create new image
ImageIcon widthIcon = new ImageIcon("LR-arrows.png");
String scaleWidth = (String)JOptionPane.showInputDialog(null,"What should the new width be?", "", JOptionPane.QUESTION_MESSAGE, widthIcon, null, null);
ImageIcon heightIcon = new ImageIcon("UD-arrows.png");
String scaleHeight = (String)JOptionPane.showInputDialog(null,"What should the new height be?", "", JOptionPane.QUESTION_MESSAGE, widthIcon, null, null);
//turns user input strings into doubles
double x = Double.parseDouble(scaleWidth);
double y = Double.parseDouble(scaleHeight);
//casts doubles as ints
int newWidth = (int)x;
int newHeight = (int)y;
//resizes frame to fit new image dimensions
frame.setSize(newWidth, newHeight);
//calls scale method to resize image using given dimensions
scale(newWidth, newHeight);
}
});
ImageIcon rotateIcon = new ImageIcon("rotate-image.png");
JMenuItem rotateImg = new JMenuItem("Rotate Image", rotateIcon);
editMenu.add(rotateImg);
rotateImg.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
//paint the frame
frame.pack();
frame.repaint();
frame.setVisible(true);
}
// convert to grayscale
public void grayscale(int width, int height) {
// create a grayscale image with original dimensions
image2 = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
// convert colored image to grayscale
ColorConvertOp grayScale = new ColorConvertOp(image.getColorModel().getColorSpace(),image2.getColorModel().getColorSpace(),null);
grayScale.filter(image,image2);
imageLabel.setIcon(new ImageIcon(image2));
//getImage();
image = image2;
}
//scales image by a given factor
public void scale(int width, int height){
//uses user-input dimensions to create new image
image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image2.createGraphics();
//gets new dimensions and resizes image
g.drawImage(image, 0, 0, image2.getWidth(), image2.getHeight(), 0, 0, width(), height(), null);
imageLabel.setIcon(new ImageIcon(image2));
//getImage();
image = image2;
}
//rotates the image
public void rotate(int width, int height, int theta) {
}
public static void main(String[] args) {
Picture p = new Picture();
p.show();
}
}
public void getImage() {
this.image2 = image;
}
//..............................................
// convert to grayscale
public void grayscale(int width, int height) {
// create a grayscale image with original dimensions
image2 = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
// convert colored image to grayscale
ColorConvertOp grayScale = new ColorConvertOp(image.getColorModel().getColorSpace(),image2.getColorModel().getColorSpace(),null);
grayScale.filter(image,image2);
imageLabel.setIcon(new ImageIcon(image2));
getImage();
}
ColorConvertOp.filter(BufferedImage src, BufferedImage dest)
Your grayscale method has image2 as the dest, when you call getImage() it replaces image2 with the original not settieng the original to your new image2.
Either have grayscale(int, int) return a BuffereImage or change getImage to:
public void getImage() {
this.image = image2;
}

How do I read pixels from a PNG file?

I know how to capture a screenshot by using Robot, Windowtester or FEST. I also know how to read a pixel from the screen by using robot.
int x = 10;
int y = 10;
Color px = getPixelColor(int x, int y);
However, I don't know how to read a pixel from an image that is already captured. I'm planning to compare a current image, with an image from file. Lets say both are PNG. Are there any frameworks that I can use to compare images pixel by pixel?
Is this in Java? If so, you can use ImageIO.read( "yourImage.png" ) to get a BufferedImage. That will have a getData() method which will give you a Raster object, on which you can call getPixel. See link
This should work:
javax.imageio.ImageIO.read(new File("filename.png"))
Then you can walk through the pixels and compare with the images pixel by pixel with this:
java.awt.image.BufferedImage.getRGB(int x, int y).
You can read image file: Reading/Loading an Image.
And then get color using getRGB method.
Load them as BufferedImage instances and it is relatively easy.
Here is part of code that creates images with text, then creates a new image that shows the difference between the image with & without text.
for (int xx=0; xx<width; xx++) {
for (int yy=0; yy<height; yy++) {
Color originalColor = new Color(originalImage.getRGB(xx,yy));
int r1 = originalColor.getRed();
int g1 = originalColor.getGreen();
int b1 = originalColor.getBlue();
Color newColor = new Color(textImage.getRGB(xx,yy));
int r2 = newColor.getRed();
int g2 = newColor.getGreen();
int b2 = newColor.getBlue();
Color bnw = Color.black;
if (r1==r2 && g1==g2 && b1==b2) {
bnw = Color.white;
}
bnwImage.setRGB(xx, yy, bnw.getRGB());
int rD = Math.abs(r1-r2);
int gD = Math.abs(g1-g2);
int bD = Math.abs(b1-b2);
Color differenceColor = new Color(rD,gD,bD);
differenceImage.setRGB(xx, yy, differenceColor.getRGB());
}
}
Screensot
Full code
import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.imageio.*;
import java.io.*;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import java.util.Locale;
class ImageWriteTest {
private BufferedImage originalImage;
private BufferedImage textImage;
private BufferedImage differenceImage;
private BufferedImage bnwImage;
private JPanel gui;
private JCheckBox antialiasing;
private JCheckBox rendering;
private JCheckBox fractionalMetrics;
private JCheckBox strokeControl;
private JCheckBox colorRendering;
private JCheckBox dithering;
private JComboBox textAntialiasing;
private JComboBox textLcdContrast;
private JLabel label0_1;
private JLabel label0_4;
private JLabel label0_7;
private JLabel label1_0;
private JTextArea output;
final static Object[] VALUES_TEXT_ANTIALIASING = {
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON,
RenderingHints.VALUE_TEXT_ANTIALIAS_GASP,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB
};
final static Object[] VALUES_TEXT_LCD_CONTRAST = {
new Integer(100),
new Integer(150),
new Integer(200),
new Integer(250)
};
ImageWriteTest() {
int width = 280;
int height = 100;
gui = new JPanel(new BorderLayout(0,4));
originalImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
textImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
differenceImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
bnwImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
JPanel controls = new JPanel(new GridLayout(0,2,0,0));
antialiasing = new JCheckBox("Anti-aliasing", false);
rendering = new JCheckBox("Rendering - Quality", true);
fractionalMetrics = new JCheckBox("Fractional Metrics", true);
strokeControl = new JCheckBox("Stroke Control - Pure", false);
colorRendering = new JCheckBox("Color Rendering - Quality", true);
dithering = new JCheckBox("Dithering", false);
controls.add(antialiasing);
controls.add(rendering);
controls.add(fractionalMetrics);
controls.add(colorRendering);
textLcdContrast = new JComboBox(VALUES_TEXT_LCD_CONTRAST);
JPanel lcdContrastPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
lcdContrastPanel.add(textLcdContrast);
lcdContrastPanel.add(new JLabel("Text LCD Contrast"));
controls.add(lcdContrastPanel);
controls.add(strokeControl);
textAntialiasing = new JComboBox(VALUES_TEXT_ANTIALIASING);
controls.add(textAntialiasing);
controls.add(dithering);
ItemListener itemListener = new ItemListener(){
public void itemStateChanged(ItemEvent e) {
updateImages();
}
};
antialiasing.addItemListener(itemListener);
rendering.addItemListener(itemListener);
fractionalMetrics.addItemListener(itemListener);
strokeControl.addItemListener(itemListener);
colorRendering.addItemListener(itemListener);
dithering.addItemListener(itemListener);
textAntialiasing.addItemListener(itemListener);
textLcdContrast.addItemListener(itemListener);
Graphics2D g2d = originalImage.createGraphics();
GradientPaint gp = new GradientPaint(
0f, 0f, Color.red,
(float)width, (float)height, Color.orange);
g2d.setPaint(gp);
g2d.fillRect(0,0, width, height);
g2d.setColor(Color.blue);
for (int ii=0; ii<width; ii+=10) {
g2d.drawLine(ii, 0, ii, height);
}
g2d.setColor(Color.green);
for (int jj=0; jj<height; jj+=10) {
g2d.drawLine(0, jj, width, jj);
}
updateImages();
gui.add(controls, BorderLayout.NORTH);
JPanel images = new JPanel(new GridLayout(0,2,0,0));
images.add(new JLabel(new ImageIcon(originalImage)));
images.add(new JLabel(new ImageIcon(textImage)));
images.add(new JLabel(new ImageIcon(differenceImage)));
images.add(new JLabel(new ImageIcon(bnwImage)));
try {
label0_1 = new JLabel(new ImageIcon(getJpegCompressedImage(0.1f, textImage)));
images.add(label0_1);
label0_4 = new JLabel(new ImageIcon(getJpegCompressedImage(0.4f, textImage)));
images.add(label0_4);
label0_7 = new JLabel(new ImageIcon(getJpegCompressedImage(0.7f, textImage)));
images.add(label0_7);
label1_0 = new JLabel(new ImageIcon(getJpegCompressedImage(1.0f, textImage)));
images.add(label1_0);
} catch(IOException ioe) {
}
gui.add(images, BorderLayout.CENTER);
StringBuilder sb = new StringBuilder();
String[] names = {
"java.vendor",
"java.version",
"java.vm.version",
"os.name",
"os.version"
};
for (String name : names) {
addProperty(sb, name);
}
output = new JTextArea(sb.toString(),6,40);
gui.add(new JScrollPane(output), BorderLayout.SOUTH);
JOptionPane.showMessageDialog(null, gui);
}
private static void addProperty(StringBuilder builder, String name) {
builder.append( name + " \t" + System.getProperty(name) + "\n" );
}
/** Adapted from SO post by x4u. */
private Image getJpegCompressedImage(float quality, BufferedImage image) throws IOException {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
ImageWriter imgWriter = ImageIO.getImageWritersByFormatName( "jpg" ).next();
ImageOutputStream ioStream = ImageIO.createImageOutputStream( outStream );
imgWriter.setOutput( ioStream );
JPEGImageWriteParam jpegParams = new JPEGImageWriteParam( Locale.getDefault() );
jpegParams.setCompressionMode( ImageWriteParam.MODE_EXPLICIT );
jpegParams.setCompressionQuality( quality );
imgWriter.write( null, new IIOImage( image, null, null ), jpegParams );
ioStream.flush();
ioStream.close();
imgWriter.dispose();
BufferedImage compressedImage = ImageIO.read(new ByteArrayInputStream(outStream.toByteArray()));
JLabel label = new JLabel("Quality: " + quality);
label.setBackground(new Color(255,255,255,192));
label.setOpaque(true);
label.setSize(label.getPreferredSize());
label.paint(compressedImage.getGraphics());
return compressedImage;
}
private void updateImages() {
int width = originalImage.getWidth();
int height = originalImage.getHeight();
Graphics2D g2dText = textImage.createGraphics();
if (antialiasing.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
}
if (rendering.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_SPEED);
}
if (fractionalMetrics.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
}
if (strokeControl.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_NORMALIZE);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_PURE);
}
if (dithering.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_ENABLE);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_DISABLE);
}
if (colorRendering.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_QUALITY);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_SPEED);
}
g2dText.setRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST,
textLcdContrast.getSelectedItem());
g2dText.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
textAntialiasing.getSelectedItem());
g2dText.drawImage(originalImage, 0,0, null);
g2dText.setColor(Color.black);
g2dText.drawString("The quick brown fox jumped over the lazy dog.", 10,50);
Graphics2D g2dDifference = differenceImage.createGraphics();
Graphics2D g2dBnW = bnwImage.createGraphics();
for (int xx=0; xx<width; xx++) {
for (int yy=0; yy<height; yy++) {
Color originalColor = new Color(originalImage.getRGB(xx,yy));
int r1 = originalColor.getRed();
int g1 = originalColor.getGreen();
int b1 = originalColor.getBlue();
Color newColor = new Color(textImage.getRGB(xx,yy));
int r2 = newColor.getRed();
int g2 = newColor.getGreen();
int b2 = newColor.getBlue();
Color bnw = Color.black;
if (r1==r2 && g1==g2 && b1==b2) {
bnw = Color.white;
}
bnwImage.setRGB(xx, yy, bnw.getRGB());
int rD = Math.abs(r1-r2);
int gD = Math.abs(g1-g2);
int bD = Math.abs(b1-b2);
Color differenceColor = new Color(rD,gD,bD);
differenceImage.setRGB(xx, yy, differenceColor.getRGB());
}
}
gui.repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
ImageWriteTest iwt = new ImageWriteTest();
}
} );
}
}
In C/C++, if you're comfortable requiring a minimum version of Windows, it's rather easy, you can use GDI+ to load the image and draw it to a memory bitmap, then you can use the returned pointer to get the pixel data.
Use GdiplusStartup() and GdiplusShutdown() to initialise and uninitialise GDI+.
Use a GDI+ Image object, using the overload that takes a filename, to load the image, then use the methods GetWidth() and GetHeight(), a BITMAPINFO structure and the CreateDIBSection() GDI function to create a memory bitmap.
Then use CreateCompatibleDC() to create a device context for the bitmap and SelectObject() to select the bitmap into that device context.
Then you use a GDI+ Graphics object, using the overload that takes a device context, and its DrawImage() method, using the overload that takes x, y, width and height, to draw the image to the bitmap's device context.
After that, you can get/set the pixel data using the pointer returned by CreateDIBSection().
When you're done, use DeleteDC() to get rid of the bitmap's device context BEFORE using DeleteObject() to get rid of the bitmap. GDI+ Image objects can also be used to save images in a supported format, including PNG.

Java Text on Image

I am loading an image in bufferedimage and then writing some text on it .After I add text it makes image blurry and text distorted. I have TEXT ANTIALIASING ON . It can be seen as attached.
import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.imageio.*;
import java.io.*;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import java.util.Locale;
class ImageCompressionDemo {
private BufferedImage originalImage;
private BufferedImage textImage;
private JPanel gui;
private JCheckBox antialiasing;
private JCheckBox rendering;
private JCheckBox fractionalMetrics;
private JCheckBox strokeControl;
private JCheckBox colorRendering;
private JCheckBox dithering;
private JComboBox textAntialiasing;
private JComboBox textLcdContrast;
private JLabel jpegLabel;
private JLabel pngLabel;
private JTextArea output;
private JSlider quality;
private int pngSize;
private int jpgSize;
final static Object[] VALUES_TEXT_ANTIALIASING = {
RenderingHints.VALUE_TEXT_ANTIALIAS_OFF,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON,
RenderingHints.VALUE_TEXT_ANTIALIAS_GASP,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB
};
final static Object[] VALUES_TEXT_LCD_CONTRAST = {
new Integer(100),
new Integer(150),
new Integer(200),
new Integer(250)
};
ImageCompressionDemo() {
int width = 280;
int height = 100;
gui = new JPanel(new BorderLayout(3,4));
quality = new JSlider(JSlider.VERTICAL, 0, 100, 75);
quality.setSnapToTicks(true);
quality.setPaintTicks(true);
quality.setPaintLabels(true);
quality.setMajorTickSpacing(10);
quality.setMinorTickSpacing(5);
quality.addChangeListener( new ChangeListener(){
public void stateChanged(ChangeEvent ce) {
updateImages();
}
} );
gui.add(quality, BorderLayout.WEST);
originalImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
textImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
JPanel controls = new JPanel(new GridLayout(0,1,0,0));
antialiasing = new JCheckBox("Anti-aliasing", false);
rendering = new JCheckBox("Rendering - Quality", true);
fractionalMetrics = new JCheckBox("Fractional Metrics", true);
strokeControl = new JCheckBox("Stroke Control - Pure", false);
colorRendering = new JCheckBox("Color Rendering - Quality", true);
dithering = new JCheckBox("Dithering", false);
controls.add(antialiasing);
controls.add(fractionalMetrics);
textLcdContrast = new JComboBox(VALUES_TEXT_LCD_CONTRAST);
JPanel lcdContrastPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
lcdContrastPanel.add(textLcdContrast);
lcdContrastPanel.add(new JLabel("Text LCD Contrast"));
controls.add(lcdContrastPanel);
textAntialiasing = new JComboBox(VALUES_TEXT_ANTIALIASING);
controls.add(textAntialiasing);
controls.add(dithering);
controls.add(rendering);
controls.add(colorRendering);
controls.add(strokeControl);
ItemListener itemListener = new ItemListener(){
public void itemStateChanged(ItemEvent e) {
updateImages();
}
};
antialiasing.addItemListener(itemListener);
rendering.addItemListener(itemListener);
fractionalMetrics.addItemListener(itemListener);
strokeControl.addItemListener(itemListener);
colorRendering.addItemListener(itemListener);
dithering.addItemListener(itemListener);
textAntialiasing.addItemListener(itemListener);
textLcdContrast.addItemListener(itemListener);
Graphics2D g2d = originalImage.createGraphics();
GradientPaint gp = new GradientPaint(
0f, 0f, Color.red,
(float)width, (float)height, Color.orange);
g2d.setPaint(gp);
g2d.fillRect(0,0, width, height);
g2d.setColor(Color.blue);
for (int ii=0; ii<width; ii+=10) {
g2d.drawLine(ii, 0, ii, height);
}
g2d.setColor(Color.green);
for (int jj=0; jj<height; jj+=10) {
g2d.drawLine(0, jj, width, jj);
}
gui.add(controls, BorderLayout.EAST);
JPanel images = new JPanel(new GridLayout(0,1,2,2));
images.add(new JLabel(new ImageIcon(textImage)));
try {
pngLabel = new JLabel(new ImageIcon(getPngCompressedImage(textImage)));
images.add(pngLabel);
jpegLabel = new JLabel(new ImageIcon(getJpegCompressedImage(textImage)));
images.add(jpegLabel);
} catch(IOException ioe) {
}
gui.add(images, BorderLayout.CENTER);
output = new JTextArea(4,40);
output.setEditable(false);
gui.add(new JScrollPane(output), BorderLayout.SOUTH);
updateImages();
JOptionPane.showMessageDialog(null, gui);
}
private Image getPngCompressedImage(BufferedImage image) throws IOException {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
ImageIO.write( image, "png", outStream );
pngSize = outStream.toByteArray().length;
BufferedImage compressedImage =
ImageIO.read(new ByteArrayInputStream(outStream.toByteArray()));
return compressedImage;
}
private Image getJpegCompressedImage(BufferedImage image) throws IOException {
float qualityFloat = (float)quality.getValue()/100f;
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
ImageWriter imgWriter = ImageIO.getImageWritersByFormatName( "jpg" ).next();
ImageOutputStream ioStream = ImageIO.createImageOutputStream( outStream );
imgWriter.setOutput( ioStream );
JPEGImageWriteParam jpegParams = new JPEGImageWriteParam( Locale.getDefault() );
jpegParams.setCompressionMode( ImageWriteParam.MODE_EXPLICIT );
jpegParams.setCompressionQuality( qualityFloat );
imgWriter.write( null, new IIOImage( image, null, null ), jpegParams );
ioStream.flush();
ioStream.close();
imgWriter.dispose();
jpgSize = outStream.toByteArray().length;
BufferedImage compressedImage = ImageIO.read(new ByteArrayInputStream(outStream.toByteArray()));
return compressedImage;
}
private void updateText() {
StringBuilder builder = new StringBuilder();
builder.append("Fractional Metrics: \t");
builder.append( fractionalMetrics.isSelected() );
builder.append("\n");
builder.append( textAntialiasing.getSelectedItem() );
builder.append("\nPNG size: \t");
builder.append(pngSize);
builder.append(" bytes\n");
builder.append("JPG size: \t");
builder.append(jpgSize);
builder.append(" bytes \tquality: ");
builder.append(quality.getValue());
output.setText(builder.toString());
}
private void updateImages() {
int width = originalImage.getWidth();
int height = originalImage.getHeight();
Graphics2D g2dText = textImage.createGraphics();
if (antialiasing.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
}
if (rendering.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_SPEED);
}
if (fractionalMetrics.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
}
if (strokeControl.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_NORMALIZE);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_PURE);
}
if (dithering.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_ENABLE);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_DITHERING,
RenderingHints.VALUE_DITHER_DISABLE);
}
if (colorRendering.isSelected()) {
g2dText.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_QUALITY);
} else {
g2dText.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
RenderingHints.VALUE_COLOR_RENDER_SPEED);
}
g2dText.setRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST,
textLcdContrast.getSelectedItem());
g2dText.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
textAntialiasing.getSelectedItem());
g2dText.drawImage(originalImage, 0,0, null);
g2dText.setColor(Color.black);
g2dText.drawString("The quick brown fox jumped over the lazy dog.", 10,50);
try {
jpegLabel.setIcon(new ImageIcon(getJpegCompressedImage(textImage)));
pngLabel.setIcon(new ImageIcon(getPngCompressedImage(textImage)));
} catch(IOException ioe) {
}
gui.repaint();
updateText();
}
public static void main(String[] args) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
ImageCompressionDemo iwt = new ImageCompressionDemo();
}
} );
}
}
Screen shot
Typical outputs
Fractional Metrics: true
Nonantialiased text mode
PNG size: 7390 bytes
JPG size: 7036 bytes quality: 35
Fractional Metrics: true
Antialiased text mode
PNG size: 8741 bytes
JPG size: 8663 bytes quality: 55
Fractional Metrics: false
Antialiased text mode
PNG size: 8720 bytes
JPG size: 8717 bytes quality: 55
You should be able to control the text quality with the rendering hints that are shown in the other responses. I know that it works because I have done it a lot, so I think it must be something else that causes the quality degradation in this case.
How do you check the image quality? Do you paint the generated BufferedImage directly into a screen graphics in your java application or do you save to disk, i.e. as JPEG? If you save it to disk try to save it as PNG 24 and not as JPEG. I assume your desktop screen is running in True Color (32 or 24 bits color depth), right?
Are you sure that the image is actually created as BufferedImage.TYPE_INT_RGB? If you have no control over the creation of the BufferedImage in your code try to create a new BufferedImage with TYPE_INT_RGB and paint the source into this one and then draw the text into it.
Try setting the RenderingHints.KEY_DITHERING to RenderingHints.VALUE_DITHER_DISABLE (although this shouldn't be needed for true color images).
If this still doesn't help you to find the cause please provide some more information (VM version, operating system) and source code. The text rendering has become quite good with JDK 1.6 Update 10 but also earlier releases were able to produce clean text in images, it just didn't look as good because of less sophisticated antialiasing.
in response to your comment:
High contrast sharp edges as in text are a general problem with JPEG compression since it is not a lossless compression. If you really need to go with JPEG and can't switch to PNG, you can tune the compression quality of your saved image to find a better compromise between image quality and file size. See the following code on how to set the compression quality when you save a JPEG.
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;
//----
float quality = 0.85f;
File outfile = new File( "MyImage.jpg" );
BufferedImage image = ...;
ImageWriter imgWriter = ImageIO.getImageWritersByFormatName( "jpg" ).next();
ImageOutputStream ioStream = ImageIO.createImageOutputStream( outfile );
imgWriter.setOutput( ioStream );
JPEGImageWriteParam jpegParams = new JPEGImageWriteParam( Locale.getDefault() );
jpegParams.setCompressionMode( ImageWriteParam.MODE_EXPLICIT );
jpegParams.setCompressionQuality( quality );
imgWriter.write( null, new IIOImage( image, null, null ), jpegParams );
ioStream.flush();
ioStream.close();
imgWriter.dispose();
try this:
public static void setGraphicsQuality(Graphics2D g2D) {
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2D.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
}
thats just java. simply turn off text anti aliasing.
or if you really need it, render the text on a separate image, if the text is black the get all pixels with color under about rgb(100,100,100) and set them to 0. then paint that buffer onto your main image.

Categories