Component painted to image renders with ugly fonts - java

When I'm rendering a Swing component to an image the fonts are different then when the component is rendered on screen. Here is an image showing the difference:
And this is the code:
public static BufferedImage renderComponent(Component component) {
int width = component.getWidth();
int height = component.getHeight();
BufferedImage buffImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) buffImage.getGraphics();
g.setFont(component.getFont());
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
component.paint(g);
g.dispose();
return buffImage;
}
What should I change to make a perfect screen shot of a Swing component? (The app is running on Windows 7)

What should I change to make a perfect screen shot of a Swing component?
I would guess you should not be providing rendering hints.
I use the Screen Image class for this (it is basically your code with a few other features built in).

After comparing the ScreenImage class (suggested by camickr) I found the cause of the problem. If I create a BufferedImage with the type set to TYPE_INT_RGB instead of TYPE_INT_ARGB the fonts are fine.

Class Robot
public synchronized BufferedImage createScreenCapture(Rectangle screenRect)
?

Related

Can I assign an image gradient to a rectangle

I'm currently making Mario as a school graphics project.
I have most of the collisions done, but I just want the land and bricks to actually look like land and bricks instead of just colored rectangles. I have an ImageIcon for the "land" in my graphics project. The problem is that it is only 16x16 pixels large. In order to make enough land by just making each part of the land one 16x16 pixel, it would essentially be horribly inefficient.
I was wondering if I could get the ImageIcon or possibly buffered image and use it as the "color" for a rectangle to make the chunks of land easier. If that's not possible, can you offer other suggestions on how to go about this problem?
Using a background of tiled images, a texture:
private BufferedImage image;
URL url = getClass().getResource("/mytexture.png");
assert url != null;
image = ImageIO.read(url);
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Rectangle rect = new Rectangle(0, 0, width, height);
Rectangle textureRect = new Rectangle(0, 0, image.getWidth(), image.getHeight());
TexturePaint paint = new TexturePaint(image, textureRect);
g2.setPaint(paint);
g2.fill(rect);
}
In general create your own JPanel.
Gimp and other tools allow to create a tilable image by ensuring that a line running to a border will enter at the opposite border.

Save a drawn picture on a JPanel in a file [java]

I've made a code to draw on a Jpanel
frame1.add( new JPanel() {
public void paintComponent( Graphics g ) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.white);
g2.fillRect(0, 0, width, height);
//Drawnig Part
});
Every thing is OK
Now My question is how to save what I've drawn on my JPanel in a file a.PNG or any other type
I have spent a lot of time to write the Drawing Part, So it will be helpful if you can suggest a solution by changing the required parts of my code, instead of rewriting the whole code.
I suggest that you buffer your drawing operations with a BufferedImage, like so:
// This should not be done in the draw method, but rather when
// the frame is created. You should also make a new buffer image when
// the frame is resized. `frameWidth` and `frameHeight` are the
// frame's dimensions.
BufferedImage bufferImage = new BufferedImage(frameWidth, frameHeight,
BufferedImage.TYPE_INT_ARGB);
Graphics2D bufferGraphics = bufferImage.createGraphics();
// In your draw method, do the following steps:
// 1. Clear the buffer:
bufferGraphics.clearRect(0, 0, width, height);
// 2. Draw things to bufferGraphics...
// 3. Copy the buffer:
g2.drawImage(bufferImage, null, 0, 0);
// When you want to save your image presented in the frame, call the following:
ImageIO.write(bufferImage, "png", new File("frameImage.png"));
The Java Tutorial on Creating and Drawing to an Image, along with the ImageIO API reference might be helpful should you require more information.
Have a look at Writing/Saving an Image for more details, but essentially you can do something like...
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
// Draw what ever you want to to the graphics context
g2d.dispose();
ImageIO.write(img, "png", new File("My Awesome Drawing.png"));
If you can't separate the drawing logic from your panel, you could simply use the Graphics context from the BufferedImage to paint the the component with.
Have a look at Exporting a JPanel to an image and Print the whole program layout for examples

How to resize image to maximize their dimensions into a panel without changing aspect ratio

I want to draw some images into a panel, I need that the images conserves their aspect ratio with the biggest dimensions to be drawn over a panel. So given the panel dimensions I must create a Java code to maximize that dimensions. The only ideas that I had needed to solve some linear programming, and I don't know how to do it in Java.
Which should be the easiest way to do what I need?
Here is the method to get a re-sized BufferedImage.
private BufferedImage resizeImage(BufferedImage originalImage, int width, int height)
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;
}
You can use Darryl's Stretch Icon. It will dynamically resize the Icon to fill the space available to the label.

Seeing pixels of a SVG file when scaling in Java

I am handling a SVG file in Java using Batik library. The problem occurs when i scale it. I can see pixels of lines. Off course this should not happen, i should be able to zoom at least about 4000% and maintain the smoothness.
SVG file is read from an extended class, and it is painted from an override paint method. First i set new scale to AffineTransform variable, apply this to graphics of the method and paint using super.paint().
I am really stuck and can't figure out the problem. SVG files I am using are ok, I opened them in Inkscape and could zoom without the pixels showing. Please help.
code:
#Override
public void paint(Graphics g) {
try {
rad = (int)(radInit*zoom);
updateTransform();
Graphics2D g2d = (Graphics2D) g;
g2d.setTransform(transform);
super.paint(g);
paintElements(g2d);
} catch(NullPointerException nulle) {
// System.out.println("SVG not loaded yet");
}
}
private void updateTransform(){
transform = new AffineTransform();
transform.translate((-1)*zoom*centarX, (-1)*zoom*centarY);
transform.scale(zoom, zoom);
}
What was needed was
this.setRenderingTransform(transform, true);
This way no pixels can be seen or rather, everything is painted as it should be.

How can I edit a jpg image through Java?

I have loaded a jpg image in which I want to draw letters and circles, given a x,y coordinate.
I have been trying to figure out the paintIcon of the ImageIcon class
public void paintIcon(Component c,
Graphics g,
int x,
int y)
Does this method allow me to edit jpg images the way I want to? What are supposd to be the Component c and Graphics g paramethers? What would I add to its body to paint circles or letters?
I'm working on Netbeans 6.5, do I have anything builtin for this task (instead of ImageIcon)?
The pure-Java way is to use ImageIO to load the image as a BufferedImage. Then you can call createGraphics() to get a Graphics2D object; you can then draw whatever you want onto the image.
You can use an ImageIcon embedded in a JLabel to do the displaying, and you can add a MouseListener and/or a MouseMotionListener to the JLabel if you're trying to allow the user to edit the image.
Manipulating images in Java can be achieved by using the Graphics or Graphics2D contexts.
Loading images such as JPEG and PNG can be performed by using the ImageIO class. The ImageIO.read method takes in a File to read in and returns a BufferedImage, which can be used to manipulate the image via its Graphics2D (or the Graphics, its superclass) context.
The Graphics2D context can be used to perform many image drawing and manipulation tasks. For information and examples, the Trail: 2D Graphics of The Java Tutorials would be a very good start.
Following is a simplified example (untested) which will open a JPEG file, and draw some circles and lines (exceptions are ignored):
// Open a JPEG file, load into a BufferedImage.
BufferedImage img = ImageIO.read(new File("image.jpg"));
// Obtain the Graphics2D context associated with the BufferedImage.
Graphics2D g = img.createGraphics();
// Draw on the BufferedImage via the graphics context.
int x = 10;
int y = 10;
int width = 10;
int height = 10;
g.drawOval(x, y, width, height);
g.drawLine(0, 0, 50, 50);
// Clean up -- dispose the graphics context that was created.
g.dispose();
The above code will open an JPEG image, and draw an oval and a line. Once these operations are performed to manipulate the image, the BufferedImage can be handled like any other Image, as it is a subclass of Image.
For example, by creating an ImageIcon using the BufferedImage, one can embed the image into a JButton or JLabel:
JLabel l = new JLabel("Label with image", new ImageIcon(img));
JButton b = new JButton("Button with image", new ImageIcon(img));
The JLabel and JButton both have constructors which take in an ImageIcon, so that can be an easy way to add an image to a Swing component.
Use a library to do just that. One that you might try is JMagick.
I have used Java Advanced Imaging library (http://java.sun.com/products/java-media/jai/forDevelopers/jaifaq.html), but you can also look at ImageJ (http://rsbweb.nih.gov/ij/index.html)
I imagen you could use this method to overlay the elements you need every time the image is drawn in the UI (this would happen numerous times as you are not drawing ON the image data its self) but may be suitable to your purposes (and advantageous if the overlay changes over time).
Something like:
new ImageIcon("someUrl.png"){
public void paintIcon(Component c, Graphics g, int x, int y) {
super(c, g, x, y);
g.translate(x, y);
g.drawOval(0, 0, 10, 10);
...
g.translate(-x, -y);
}
};
Having said that, mmyers' answer is much better if you want to modify the image data.

Categories