How do I read pixels from a PNG file? - java

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.

Related

Updating a panel every second, minute and hour [duplicate]

Original question:
This method is supposed to change the image being displayed on a JFrame gradually into another image. However, without some way to slow it down, it just seems to change from one image to the new image. In order to slow it down, I put in a Thread.sleep(1000) so the changes wouldn't happen instantly. However, with this line in there, my program freezes completely. No error message, no nothing. Can anyone please help me out? Suggest a better method to slow it down, or how this can be fixed.
For clarification: int k is the number of gradual steps in the change. k = 1 would be an instant change. Anything greater would be gradual changes. int l meanwhile controls the ratio of how much of each image is displayed.
public void morphImg(int width, int height, BufferedImage morphImage, int k) {
//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 morph image
Color c2 = new Color(morphImage.getRGB(i, j));
for (int l = 1; l <= k; l++) {
//gets colors at different stages
int r = ((k-l)*c.getRed()/k) + (l*c2.getRed()/k);
int g = ((k-l)*c.getGreen()/k) + (l*c2.getGreen()/k);
int b = ((k-l)*c.getBlue()/k) + (l*c2.getBlue()/k);
Color newColor = new Color(r, g, b);
//set colors of new image to average of the two images
image2.setRGB(i, j, newColor.getRGB());
//display new image
try {
imageLabel.setIcon(new ImageIcon(image2));
Thread.sleep(1000);
}
catch (InterruptedException e){
System.out.println("Exception caught.");
}
}
}
}
//sets modified image as "original" for further manipulation
setImage(image2);
}
UPDATED CODE: Using a Timer also causes the program to freeze...Am I not using it right?
public void morphImg(int width, int height, BufferedImage morphImage, int k) {
//creates new image from two images of same size
final BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int l = 1; l <= k; l++) {
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 morph image
Color c2 = new Color(morphImage.getRGB(i, j));
//gets colors at different stages
int r = ((k-l)*c.getRed()/k) + (l*c2.getRed()/k);
int g = ((k-l)*c.getGreen()/k) + (l*c2.getGreen()/k);
int b = ((k-l)*c.getBlue()/k) + (l*c2.getBlue()/k);
Color newColor = new Color(r, g, b);
//set colors of new image to average of the two images
image2.setRGB(i, j, newColor.getRGB());
//display new image
imageLabel.setIcon(new ImageIcon(image2));
final Timer t = new Timer(500,null);
t.setInitialDelay(500);
t.start();
}
}
}
//sets modified image as "original" for further manipulation
setImage(image2);
}
Never use Thread.sleep() when code is executing on the Event Dispatch Thread.
Instead you should use a Swing Timer to schedule your animation.
See the sections from the Swing tutorial on:
Concurrency in Swing
How to Use Timers
Or if you don't want to use a Timer, then you can use a SwingWorker (as described in the tutorial on concurrency) and then just publish() the image after you change it. Then you can use a Thread.sleep() since the SwingWorker doesn't execute on the EDT.
Simple Timer example:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class TimerTime extends JPanel implements ActionListener
{
private JLabel timeLabel;
private int count = 0;
public TimerTime()
{
timeLabel = new JLabel( new Date().toString() );
add( timeLabel );
Timer timer = new Timer(1000, this);
timer.setInitialDelay(1);
timer.start();
}
#Override
public void actionPerformed(ActionEvent e)
{
// Update the time
timeLabel.setText( new Date().toString() );
count++;
// Stop after 10 events have been generated
if (count == 10)
{
Timer timer = (Timer)e.getSource();
timer.stop();
System.out.println( "Timer stopped" );
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("TimerTime");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new TimerTime() );
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() );
}
}
The loop over k should be the outermost loop. Right now you are calling Thread.sleep k*width*height times.
If the intention is to show progressive animation of the morph effect, below is the test code I did without using Timer or Thread.sleep(), using the latest morph code given by OP:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JApplet;
import javax.swing.JFrame;
class MorphComponent extends Component {
/**
*
*/
private static final long serialVersionUID = 1L;
private BufferedImage bi;
private URL imageSrc1;
private URL imageSrc2;
public MorphComponent(URL imageSrc1, URL imageSrc2) {
this.imageSrc1 = imageSrc1;
this.imageSrc2 = imageSrc2;
try {
BufferedImage img1 = ImageIO.read(imageSrc1);
//BufferedImage img2 = ImageIO.read(imageSrc2);
int w = img1.getWidth(null);
int h = img1.getHeight(null);
bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.getGraphics();
g.drawImage(img1, 0, 0, null);
} catch (IOException e) {
System.out.println("Image could not be read");
System.exit(1);
}
}
public Dimension getPreferredSize() {
return new Dimension(bi.getWidth(null), bi.getHeight(null));
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.white);
g2d.fillRect(0,0, getWidth(), getHeight());
try {
BufferedImage img1 = ImageIO.read(imageSrc1);
BufferedImage img2 = ImageIO.read(imageSrc2);
int w = img1.getWidth(null);
int h = img1.getHeight(null);
bi = morphImg(g, img1, img2, w, h, 10);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private long start = System.currentTimeMillis();
public BufferedImage morphImg(Graphics gp, BufferedImage originalImage, BufferedImage morphImage, int width, int height, int k) {
//creates new image from two images of same size
final BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int l = 1; l <= k; l++) {
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
long elapsed = System.currentTimeMillis() - start;
//get color from original image
Color c = new Color(originalImage.getRGB(i, j));
//get colors from morph image
Color c2 = new Color(morphImage.getRGB(i, j));
//gets colors at different stages
int r = ((k-l)*c.getRed()/k) + (l*c2.getRed()/k);
int g = ((k-l)*c.getGreen()/k) + (l*c2.getGreen()/k);
int b = ((k-l)*c.getBlue()/k) + (l*c2.getBlue()/k);
Color newColor = new Color(r, g, b);
//set colors of new image to average of the two images
image2.setRGB(i, j, newColor.getRGB());
if( elapsed > 100 ) {
gp.drawImage(image2, 0, 0, null);
start = System.currentTimeMillis();
repaint();
}
}
}
}
return image2;
}
}
public class MorphImageApplet extends JApplet {
/**
*
*/
private static final long serialVersionUID = 1L;
static String imageFileName1 = "image_1.jpg";
static String imageFileName2 = "image_2.jpg";
private URL imageSrc1;
private URL imageSrc2;
public MorphImageApplet () {
}
public MorphImageApplet (URL imageSrc1, URL imageSrc2) {
this.imageSrc1 = imageSrc1;
this.imageSrc2 = imageSrc2;
}
public void init() {
try {
imageSrc1 = new URL(getCodeBase(), imageFileName1);
imageSrc2 = new URL(getCodeBase(), imageFileName2);
} catch (MalformedURLException e) {
}
buildUI();
}
public void buildUI() {
final MorphComponent st = new MorphComponent(imageSrc1, imageSrc2);
add("Center", st);
}
public static void main(String s[]) {
JFrame f = new JFrame("See Through Image");
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
URL imageSrc1 = null;
URL imageSrc2 = null;
try {
imageSrc1 = ((new File(imageFileName1)).toURI()).toURL();
imageSrc2 = ((new File(imageFileName2)).toURI()).toURL();
} catch (MalformedURLException e) {
}
MorphImageApplet sta = new MorphImageApplet(imageSrc1, imageSrc2);
sta.buildUI();
f.add("Center", sta);
f.pack();
f.setVisible(true);
}
}

How to set imageicon fix on jlabel

I am trying to make a java desktop application. I have a JLabel where I am shuffling image but all image sizes are different so I want to fix size of the image on JLabel.
How can I do this?
Here is my code :
public class ImageShuffle1 extends JPanel {
private List<Icon> list = new ArrayList<Icon>();
private List<Icon> shuffled;
private JLabel label = new JLabel();
private Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
update();
}
});
public ImageShuffle1() {
this.setLayout(new GridLayout(1, 0));
list.add(new ImageIcon("E:\\SOFTWARE\\TrainPIS\\res\\drawable\\e.jpg"));
list.add(new ImageIcon("E:\\SOFTWARE\\TrainPIS\\res\\drawable\\d.jpg"));
list.add(new ImageIcon("E:\\SOFTWARE\\TrainPIS\\res\\drawable\\yellow.png"));
list.add(new ImageIcon("E:\\SOFTWARE\\TrainPIS\\res\\drawable\\f.jpg"));
list.add(new ImageIcon("E:\\SOFTWARE\\TrainPIS\\res\\drawable\\l.jpg"));
//label.setIcon(UIManager.getIcon("OptionPane.informationIcon"));
for(Icon icon: list){
Image img = icon.getImage() ;
// put here the size properties
Image newimg = img.getScaledInstance( 45, 34, java.awt.Image.SCALE_SMOOTH ) ;
icon = new ImageIcon(newimg);
}
shuffled = new ArrayList<Icon>(list);
Collections.shuffle(shuffled);
timer.start();
}
private void update() {
if (shuffled.isEmpty()) {
shuffled = new ArrayList<Icon>(list);
Collections.shuffle(shuffled);
}
Icon icon = shuffled.remove(0);
label.setIcon(icon);
}
private void display() {
JFrame f = new JFrame("ImageShuffle");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.add(label);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ImageShuffle1().display();
}
});
}
}
I am getting error herein this.
line/variable getimage can not found mage img = icon.getImage() ;
Thanks in advance
Use BufferedImage in place of Icon that has a functionality to re size it.
Here is the code
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ImageShuffle1 extends JPanel {
private List<BufferedImage> list = new ArrayList<BufferedImage>();
private List<BufferedImage> shuffled;
private JLabel label = new JLabel();
private int width = 50;
private int height = 100;
private Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
update();
}
});
public ImageShuffle1() {
try {
list.add(resizeImage(ImageIO.read(new File("resources/1.png"))));
list.add(resizeImage(ImageIO.read(new File("resources/2.png"))));
list.add(resizeImage(ImageIO.read(new File("resources/6.png"))));
list.add(resizeImage(ImageIO.read(new File("resources/Tulips.jpg"))));
} catch (IOException e) {
e.printStackTrace();
}
shuffled = new ArrayList<BufferedImage>(list);
Collections.shuffle(shuffled);
timer.start();
}
private BufferedImage resizeImage(BufferedImage originalImage) throws IOException {
BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
private void update() {
if (shuffled.isEmpty()) {
shuffled = new ArrayList<BufferedImage>(list);
Collections.shuffle(shuffled);
}
BufferedImage icon = shuffled.remove(0);
label.setIcon(new ImageIcon(icon));
}
private void display() {
JFrame f = new JFrame("ImageShuffle");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.add(label);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ImageShuffle1().display();
}
});
}
}
Lets start with this...
for(Icon icon: list){
Image img = icon.getImage() ;
Icon does not have a method getImage, there is actually no way to get the "image" data maintained by the Icon class without first rendering it to something (like a BufferedImage)
A better solution might be to load the images into a List that supports BufferedImage. BufferedImage is a more versatile starting point and because it extends from Image, it can be used with ImageIcon. For example...
private List<BufferedImage> list = new ArrayList<BufferedImage>();
//...
list.add(ImageIO.read("E:\\SOFTWARE\\TrainPIS\\res\\drawable\\e.jpg"));
Take a look at Reading/Loading an Image
For scaling you might like to take a look at
The Perils of Image.getScaledInstance
Java: maintaining aspect ratio of JPanel background image
Quality of Image after resize very low -- Java
First you resize every image to a fixed size and it must be fit in JLabel
public static Boolean resizeImage(String sourceImage, String destinationImage, Integer Width, Integer Height) {
BufferedImage origImage;
try {
origImage = ImageIO.read(new File(sourceImage));
int type = origImage.getType() == 0? BufferedImage.TYPE_INT_ARGB : origImage.getType();
//*Special* if the width or height is 0 use image src dimensions
if (Width == 0) {
Width = origImage.getWidth();
}
if (Height == 0) {
Height = origImage.getHeight();
}
int fHeight = Height;
int fWidth = Width;
//Work out the resized width/height
if (origImage.getHeight() > Height || origImage.getWidth() > Width) {
fHeight = Height;
int wid = Width;
float sum = (float)origImage.getWidth() / (float)origImage.getHeight();
fWidth = Math.round(fHeight * sum);
if (fWidth > wid) {
//rezise again for the width this time
fHeight = Math.round(wid/sum);
fWidth = wid;
}
}
BufferedImage resizedImage = new BufferedImage(fWidth, fHeight, type);
Graphics2D g = resizedImage.createGraphics();
g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(origImage, 0, 0, fWidth, fHeight, null);
g.dispose();
ImageIO.write(resizedImage, "png", new File(destinationImage));
...

How can i re-size the width and height of a png file with custom defined value?

I am loading a button picture which is png format. But the format is too large. How can i resize the width and height of that to defined range, but avoid using the image size.
Before:
public JButton createButton(String name, String toolTip) {
Image a = null;
try {
a = ImageIO.read((InputStream) Test.class.getResourceAsStream("/image/menu/" + name + ".png"));
} catch (IOException ex) {
ex.printStackTrace();
}
ImageIcon iconRollover = new ImageIcon(a);
int w = iconRollover.getIconWidth();
int h = iconRollover.getIconHeight();
// get the cursor for this button
Cursor cursor =
Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
// make translucent default image
//Image image = screen.createCompatibleImage(w, h, Transparency.TRANSLUCENT);
Graphics2D g = (Graphics2D) a.getGraphics();
Composite alpha = AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, .5f);
g.setComposite(alpha);
g.drawImage(iconRollover.getImage(), 0, 0, null);
g.dispose();
ImageIcon iconDefault = new ImageIcon(a);
ImageIcon iconPressed = new ImageIcon(a);
// create the button
JButton button = new JButton();
button.setIgnoreRepaint(true);
button.setFocusable(false);
button.setToolTipText(toolTip);
button.setBorder(null);
button.setContentAreaFilled(false);
button.setCursor(cursor);
button.setIcon(iconDefault);
button.setRolloverIcon(iconRollover);
button.setPressedIcon(iconPressed);
return button;
}
After:
Follow up:
public JButton createButton(String name, String toolTip) {
// Create image
BufferedImage a = null;
try {
a = ImageIO.read((InputStream) P2P.class.getResourceAsStream("/image/menu/" + name + ".png"));
} catch (IOException ex) {
ex.printStackTrace();
}
BufferedImage bi = new BufferedImage(70, 70, BufferedImage.TRANSLUCENT);
Graphics2D g = (Graphics2D) bi.getGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(a, 0, 0, 70, 70, null);
g.dispose();
// get the cursor for this button
Cursor cursor =
Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
ImageIcon iconRollover = new ImageIcon(bi);
ImageIcon iconDefault = new ImageIcon(bi);
ImageIcon iconPressed = new ImageIcon(bi);
// create the button
JButton button = new JButton();
//button.addActionListener(this);
button.setIgnoreRepaint(true);
button.setFocusable(false);
button.setToolTipText(toolTip);
button.setBorder(null);
button.setContentAreaFilled(false);
button.setCursor(cursor);
button.setIcon(iconDefault);
button.setRolloverIcon(iconRollover);
button.setPressedIcon(iconPressed);
return button;
}
Why not use the getScaledInstance() method on your Image instance like this:
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
static int width=300;//change this to your wanted size
static int height =500;
public class Main extends JFrame implements ActionListener {
Image img;
JButton getPictureButton = new JButton("Get Picture");
public static void main(String[] args) {
new Main();
}
public Main() {
this.setSize(600, 600);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel picPanel = new PicturePanel();
this.add(picPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
getPictureButton.addActionListener(this);
buttonPanel.add(getPictureButton);
this.add(buttonPanel, BorderLayout.SOUTH);
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
String file = "a.png";
if (file != null) {
Toolkit kit = Toolkit.getDefaultToolkit();
img = kit.getImage(file);
img = img.getScaledInstance(width, height, Image.SCALE_SMOOTH);//scale the image to wanted size
this.repaint();
}
}
class PicturePanel extends JPanel {
public void paintComponent(Graphics g) {
g.drawImage(img, 0, 0, this);
}
}
}
/**
* #param img image (Image or ImageIcon)
* #param w the width of the returned image
* #param h the height of the returned image
* #param imgW the width of the graphics in the returned image
* #param imgH the height of the graphics in the returned image
* #return ImageIcon
*/
public static ImageIcon resizeImage(Object img, Integer w, Integer h, Integer imgW, Integer imgH) {
Image image = objectToImage(img);
if(w == null)
w=image.getWidth(null);
if(h == null)
h=image.getHeight(null);
if(imgW == null)
imgW=w;
else if(imgH == null)
imgH=imgW;
if(imgH == null)
imgH=h;
BufferedImage resizedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = resizedImage.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage(toBufferedImage(image), (w-imgW)/2, (h-imgH)/2, imgW, imgH, null);
g2d.dispose();
return new ImageIcon(resizedImage);
}
public static Image objectToImage(Object img) {
if(img instanceof ImageIcon)
return ((ImageIcon)img).getImage();
else if(img instanceof Image)
return (Image)img;
else
throw new ClassCastException();
}
public static BufferedImage toBufferedImage(Image img) {
BufferedImage bi = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = bi.createGraphics();
g2d.drawImage(img, 0, 0, null);
g2d.dispose();
return bi;
}
Works
public JButton createButton(String name, String toolTip) {
// Create image
BufferedImage a = null;
try {
a = ImageIO.read((InputStream) P2P.class.getResourceAsStream("/image/menu/" + name + ".png"));
} catch (IOException ex) {
ex.printStackTrace();
}
BufferedImage bi = new BufferedImage(70, 70, BufferedImage.TRANSLUCENT);
Graphics2D g = (Graphics2D) bi.getGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(a, 0, 0, 70, 70, null);
g.dispose();
// get the cursor for this button
Cursor cursor =
Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
ImageIcon iconRollover = new ImageIcon(bi);
ImageIcon iconDefault = new ImageIcon(bi);
ImageIcon iconPressed = new ImageIcon(bi);
// create the button
JButton button = new JButton();
//button.addActionListener(this);
button.setIgnoreRepaint(true);
button.setFocusable(false);
button.setToolTipText(toolTip);
button.setBorder(null);
button.setContentAreaFilled(false);
button.setCursor(cursor);
button.setIcon(iconDefault);
button.setRolloverIcon(iconRollover);
button.setPressedIcon(iconPressed);
return button;
}

ImageIcon not loading

So I am trying to make a small game for a project in college. I have an image class that loads the images etc. I know this class works because I tested it all when I made it. But then I decided to use a form maker, in this case WindowsBuilder Pro to make a form that was better then I could code. I am now trying to call a function that in theory will load call the images class and load the image then add that image as an imageicon to a label within a jPanel. But I am getting nothing. Any help?
private void loadres(){
String PROGRAM_DIRECTORY = "E:/WordGame/bin/Images/";
Functions.Resources rs = new Functions.Resources();
rs.loadResources();
Functions.ImageLib iL = rs.getIL();
try {
BGImage = new JLabel(new ImageIcon(iL.mergeImages(iL.getImageArray(0),iL.getImage(PROGRAM_DIRECTORY + "Astroid1Image.png"))));
} catch (IOException e) {
e.printStackTrace();
}
BGImage.revalidate();
BGImage.repaint();
}
And here is the Image functions I am using:
public class ImageLib {
private ArrayList<BufferedImage> BIArray = new ArrayList<BufferedImage>();
public ImageLib(){
}
public BufferedImage getImage(String ref){
BufferedImage Bi = null;
try{
Bi = ImageIO.read(new File(ref));
}catch (Exception e) {
e.printStackTrace();
}
return Bi;
}
public BufferedImage resizeImage(BufferedImage Bi, int nW, int nH){
int w = Bi.getWidth();
int h = Bi.getHeight();
BufferedImage nBi = new BufferedImage(nW, nH, Bi.getType());
Graphics2D g = nBi.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(Bi,0,0,nW,nH,0,0,w,h,null);
g.dispose();
return nBi;
}
public void addToArray(BufferedImage img){
BIArray.add(img);
}
public BufferedImage getImageArray(int index){
return (BufferedImage) BIArray.get(index);
}
public BufferedImage mergeImages(BufferedImage I1, BufferedImage I2) throws IOException{
int w = Math.max(I1.getWidth(), I2.getWidth());
int h = Math.max(I1.getHeight(), I2.getHeight());
BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = combined.getGraphics();
g.drawImage(I1, 0, 0, null);
g.drawImage(I2, 0, 0, null);
g.dispose();
return combined;
}
}
Here is my answer ^^
ClassLoader cldr = this.getClass().getClassLoader();
java.net.URL imageURL = cldr.getResource("path/to/your/images/picture.gif");
ImageIcon imgIcon = new ImageIcon(imageURL);

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