Java Text on Image - java

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.

Related

The image turns mostly red after processing [duplicate]

I am trying to transform an image by flipping it horizontally and resizing it. The problem is that when the transformation is done the picture's colors are all weird, it has gotten this reddish tone. Is it possible to fix this somehow, I think I read somewhere that it might be some bug in the AWT library but I am not sure?
Here is the code:
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class LocalImageSizeFlip {
public static void main(String[] args) {
BufferedImage img = null;
try {
img = ImageIO.read(new File("C:\\picture.jpg"));
AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
tx.translate(0, -img.getHeight(null));
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
img = op.filter(img, null);
img = resize(img, 100, 75);
File newFile = new File("newPicture.jpg");
ImageIO.write(img, "JPEG", newFile);
} catch (IOException e) {
e.printStackTrace();
}
}
private static BufferedImage resize(BufferedImage image, int width, int height) {
BufferedImage resizedImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(image, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
}
Having an image develop a tint usually means the image is being rendered using the wrong colorspace, Adobe RGB vs. sRGB being a perennial favorite. Try changing TYPE_INT_ARGB to TYPE_INT_RGB in your code.
You can also try the following type: BufferedImage.TYPE_3BYTE_BGR
If you have any images already converted and those are almost pinkish/reddish.
You can convert those into RGB again.
try {
File folder = new File("photo/old");
File[] list = folder.listFiles();
for (File f : list) {
String url = f.getAbsolutePath();
String replce1 = url.replace('\\', '/');
File file = new File(replce1);
if (file.exists()) {
FileInputStream fis = new FileInputStream(file);
byte[] buff = new byte[fis.available()];
fis.read(buff);
BufferedImage bi = ImageIO.read(file);
BufferedImage biOriginal = new BufferedImage(1200, 800,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(bi, 0, 0, 1200, 800, null);
g.dispose();
fis.close();
FileOutputStream fos2 = new FileOutputStream("photo/new/"+file.getName());
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
ImageIO.write(biOriginal, Main.extensionWithotDot, baos2);
baos2.flush();
byte[] imageInByte2 = baos2.toByteArray();
fos2.write(imageInByte2);
fos2.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}

Load and Resize Image [duplicate]

This question already has answers here:
Resizing an image in swing
(4 answers)
Closed 8 years ago.
I am loading an image in Java Swing and want to display it in JPanel..The problem I am facing is that despite of image being loaded, it is not showing in JPanel..I can say that image is successfully loaded because it is showing me the correct path of the loaded image in my label..
Here is my code..
private static final int IMG_WIDTH = 120;
private static final int IMG_HEIGHT = 120;
JLabel label;
ImageIcon photo;
WritableRaster raster;
DataBufferByte data;
File image;
JFileChooser chooser;
FileNameExtensionFilter filter;
chooser = new JFileChooser();
chooser.setCurrentDirectory(image);
filter = new FileNameExtensionFilter("jpeg, gif and png files", "jpg", "gif", "png");
chooser.addChoosableFileFilter(filter);
int i = chooser.showOpenDialog(this);
if (i == JFileChooser.APPROVE_OPTION) {
image = chooser.getSelectedFile();
jLabel8.setText(image.getAbsolutePath());
try {
BufferedImage originalImage = ImageIO.read(image);
int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType();
BufferedImage resizeImageJpg = resizeImage(originalImage, type);
photo = new ImageIcon(toImage(resizeImageJpg));
jPanel2.removeAll();
label = new JLabel("", photo, JLabel.CENTER);
label.setIcon(photo);
jPanel2.add(label);
setVisible(true);
//converting buffered image to byte array
raster = resizeImageJpg.getRaster();
data = (DataBufferByte) raster.getDataBuffer();
} catch (IOException e) {
System.out.println(e.getMessage());
}
repaint();
chooser.setCurrentDirectory(image);
}
public Image toImage(BufferedImage bufferedImage) {
return Toolkit.getDefaultToolkit().createImage(bufferedImage.getSource());
}
private static BufferedImage resizeImage(BufferedImage originalImage, int type) {
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
return resizedImage;
}
First, forget the toImage() method, BufferedImage already extends the Image class.
Then try to use
try {
BufferedImage originalImage = ImageIO.read( image );
int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType();
BufferedImage resizeImageJpg = resizeImage( originalImage, type );
//forget the toImage() method, BufferedImage already extends the Image class.
photo = new ImageIcon( resizeImageJpg );
//And by the way, if you remove components and add new ones, use validate() instead.
//And don't remove the JLabel, just change the icon, it will repaint automatically.
label.setIcon(photo);
}
catch ( java.io.IOException iOException ) {
System.out.println(e.getMessage());
}
And for the resized BufferedImage, use AffineTransform to scale the image to the new size.
private static BufferedImage resizeImage(BufferedImage originalImage, int type) {
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
//Calculate de scale ratio;
double scaledDx = ((IMG_WIDTH*1.0d)/originalImage.getWidth());
double scaledDy = ((IMG_HEIGHT*1.0d)/originalImage.getHeight());
AffineTransform resizeAffine = AffineTransform.getScaleInstance( scaledDx, scaledDy );
BufferedImageOp buffResized = new AffineTransformOp( resizeAffine, null );
Graphics2D g2 = resizedImage.createGraphics();
g2.drawImage( resizedImage, buffResized, 0, 0 );
g2.dispose(); //Don't forget to dispose to release resources.
}
I hope I could help.

Convert a JPanel to an image in a JScrollPane

I want to convert an JPanel to an image. I used the following method:
public BufferedImage createImage(){
int w = getWidth();
int h = getHeight();
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bi.createGraphics();
paint(g);
return bi;
}
But the problem is that the JPanel is contained within a JScrollPane. So when I convert the jpanel to an image, the image contains only the parts visible in the jpanel and the parts that are hidden inside the scrollpane aren't contained in the image.
Are there any solutions to get the full content of the JPanel into an image?
But the problem is that the JPanel is contained within a JScrollPane.
So when I convert the jpanel to an image, the image contains only the
parts visible in the jpanel and the parts that are hidden inside the
scrollpane aren't contained in the image.
This doesnt happen to me... have you tried paintAll instead of paint?
Here is a great method which will capture the content of any Component visible or not (Its not mine I got it somewhere off the SO and have used it since):
public static BufferedImage componentToImage(Component component, boolean visible) {
if (visible) {
BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) img.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
component.paintAll(g2d);
return img;
} else {
component.setSize(component.getPreferredSize());
layoutComponent(component);
BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TRANSLUCENT);
CellRendererPane crp = new CellRendererPane();
crp.add(component);
crp.paintComponent(img.createGraphics(), component, crp, component.getBounds());
return img;
}
}
private static void layoutComponent(Component c) {
synchronized (c.getTreeLock()) {
c.doLayout();
if (c instanceof Container) {
for (Component child : ((Container) c).getComponents()) {
layoutComponent(child);
}
}
}
}
Here is an example showcasing the above:
The frame view:
capture of the panel:
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.CellRendererPane;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class Test {
public Test() {
createAndShowGui();
}
private void createAndShowGui() {
JFrame frame = new JFrame() {
#Override
public Dimension getPreferredSize() {//size frame purposefully smaller
return new Dimension(100, 100);
}
};
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Image img = null;
try {
img = ImageIO.read(new URL("http://images4.wikia.nocookie.net/__cb20120515073660/naruto/images/0/09/Naruto_newshot.png")).getScaledInstance(200, 200, Image.SCALE_SMOOTH);
} catch (Exception ex) {
ex.printStackTrace();
}
final ImagePanel imagePanel = new ImagePanel(200, 200, img);
JScrollPane jsp = new JScrollPane(imagePanel);
frame.add(jsp);
frame.pack();
frame.setVisible(true);
BufferedImage bi = componentToImage(imagePanel, true);
try {
File outputfile = new File("c:/saved.png");
ImageIO.write(bi, "png", outputfile);
} catch (IOException e) {
e.printStackTrace();
}
}
public static BufferedImage componentToImage(Component component, boolean visible) {
if (visible) {
BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) img.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
component.paintAll(g2d);
return img;
} else {
component.setSize(component.getPreferredSize());
layoutComponent(component);
BufferedImage img = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TRANSLUCENT);
CellRendererPane crp = new CellRendererPane();
crp.add(component);
crp.paintComponent(img.createGraphics(), component, crp, component.getBounds());
return img;
}
}
private static void layoutComponent(Component c) {
synchronized (c.getTreeLock()) {
c.doLayout();
if (c instanceof Container) {
for (Component child : ((Container) c).getComponents()) {
layoutComponent(child);
}
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
}
class ImagePanel extends JPanel {
int width, height;
Image bg;
public ImagePanel(int width, int height, Image bg) {
this.width = width;
this.height = height;
this.bg = bg;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
#Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
grphcs.drawImage(bg, 0, 0, null);
}
}
UPDATE:
As per your comment:
I wrote the BufferedImage into a file by using
ImageIO.write(bufferedImage, "jpg" , file); this works fine for both
png and gif images, but jpg image shows a red background instead of
white. How can i slove that problem. Thanks
See this similar question/answer for more. You would do something like:
private static final int[] RGB_MASKS = {0xFF0000, 0xFF00, 0xFF};
private static final ColorModel RGB_OPAQUE = new DirectColorModel(32, RGB_MASKS[0], RGB_MASKS[1], RGB_MASKS[2]);
...
BufferedImage image = componentToImage(imagePanel, true);
saveJPeg(image, "c:/saved.jpg");
private void saveJPeg(BufferedImage image, String name) {
PixelGrabber pg = new PixelGrabber(image, 0, 0, -1, -1, true);
try {
pg.grabPixels();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
int width = pg.getWidth(), height = pg.getHeight();
DataBuffer buffer = new DataBufferInt((int[]) pg.getPixels(), pg.getWidth() * pg.getHeight());
WritableRaster raster = Raster.createPackedRaster(buffer, width, height, width, RGB_MASKS, null);
BufferedImage bi = new BufferedImage(RGB_OPAQUE, raster, false, null);
try {
ImageIO.write(bi, "jpg", new File(name));
} catch (IOException ex) {
ex.printStackTrace();
}
}
SwingUtilities.paintComponent does it:
static void drawComponent(JComponent c,
BufferedImage destination) {
JFrame frame = new JFrame();
Graphics g = destination.createGraphics();
SwingUtilities.paintComponent(g, c, frame.getContentPane(),
0, 0, destination.getWidth(), destination.getHeight());
g.dispose();
frame.dispose();
}
static BufferedImage createSnapshotOf(JComponent c) {
Dimension size = c.getSize();
if (size.width <= 0 || size.height <= 0) {
size = c.getPreferredSize();
}
BufferedImage snapshot =
new BufferedImage(size.width, size.height,
BufferedImage.TYPE_INT_ARGB);
drawComponent(c, snapshot);
return snapshot;
}
I don't know why you need to do something so complicated. As long as your Buffered image and paint function all use the component (huge) that is the in the JScroolPane, the whole thing should be saved.
//create a tree data structure
DefaultMutableTreeNode tree = new DefaultMutableTreeNode("root");
//optional: you can make the tree really big
//now show the tree
JFrame frame = new JFrame("TreeDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create a Jtree component to display your data structure
JTree treeDisplay = new JTree(tree);
//expand the tree all out
for(int i = 0; i < treeDisplay.getRowCount(); i++) {
treeDisplay.expandRow(i);
}
//put your tree display component in a scroll pane
frame.add(new JScrollPane(treeDisplay));
//Display the window.
frame.pack();
frame.setVisible(true);
//save tree in the window to a file
BufferedImage img = new BufferedImage(treeDisplay.getWidth(), treeDisplay.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D graphics = img.createGraphics();
//put graphics on the buffered image
treeDisplay.paintAll(graphics);
graphics.dispose();
try {
ImageIO.write(img, "png", new File("tree.png"));
}
catch (IOException e) {
e.printStackTrace();
}

Image transformation results in a red image?

I am trying to transform an image by flipping it horizontally and resizing it. The problem is that when the transformation is done the picture's colors are all weird, it has gotten this reddish tone. Is it possible to fix this somehow, I think I read somewhere that it might be some bug in the AWT library but I am not sure?
Here is the code:
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class LocalImageSizeFlip {
public static void main(String[] args) {
BufferedImage img = null;
try {
img = ImageIO.read(new File("C:\\picture.jpg"));
AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
tx.translate(0, -img.getHeight(null));
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
img = op.filter(img, null);
img = resize(img, 100, 75);
File newFile = new File("newPicture.jpg");
ImageIO.write(img, "JPEG", newFile);
} catch (IOException e) {
e.printStackTrace();
}
}
private static BufferedImage resize(BufferedImage image, int width, int height) {
BufferedImage resizedImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(image, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
}
Having an image develop a tint usually means the image is being rendered using the wrong colorspace, Adobe RGB vs. sRGB being a perennial favorite. Try changing TYPE_INT_ARGB to TYPE_INT_RGB in your code.
You can also try the following type: BufferedImage.TYPE_3BYTE_BGR
If you have any images already converted and those are almost pinkish/reddish.
You can convert those into RGB again.
try {
File folder = new File("photo/old");
File[] list = folder.listFiles();
for (File f : list) {
String url = f.getAbsolutePath();
String replce1 = url.replace('\\', '/');
File file = new File(replce1);
if (file.exists()) {
FileInputStream fis = new FileInputStream(file);
byte[] buff = new byte[fis.available()];
fis.read(buff);
BufferedImage bi = ImageIO.read(file);
BufferedImage biOriginal = new BufferedImage(1200, 800,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(bi, 0, 0, 1200, 800, null);
g.dispose();
fis.close();
FileOutputStream fos2 = new FileOutputStream("photo/new/"+file.getName());
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
ImageIO.write(biOriginal, Main.extensionWithotDot, baos2);
baos2.flush();
byte[] imageInByte2 = baos2.toByteArray();
fos2.write(imageInByte2);
fos2.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}

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.

Categories