fixing blurrieness with Graphics2D in JAVA - java

I was wondering why displaying text in my frame has to be so blury, and i came across this piece of code, which is working by the way
public void paint(Graphics graphicsObject){
if(graphicsObject instanceof Graphics2D){
Graphics2D g2D = (Graphics2D) graphicsObject;
g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
graphicsObject.drawString("not blurry text display", 200, 200);
}
having dificulties trying to understand how this work out.
how come g2D.setRenderingHint is fixing my blurry problem, but i dont use it to paint my string?

First, what this fixed was not blurring. It was aliasing.
Aliasing occurs when drawing functions try to create curvy shapes using a raster image - a matrix of pixels, which are squares. If the lines are not vertical or horizontal, you end up with "stairs" - edges that are jaggy.
Antialiasing is a way to make this effect less visible to the eye, by using additional pixels around the drawn line, which are painted in different tones between the foreground and the background. This cheats our eyes to see the line as "smooth". If you zoom an image drawn with antialiasing, you may notice those pixels around the actual line.
So, actually, antialiasing blurs the line, and this makes it seem smoother to our eyes.
As to your actual question - you are using the graphics object to draw the line. You set the hint in the graphics object by accessing the object in its form as a Graphics2D. Even though you then go on and use the graphicsObject using its regular Graphics reference, the method drawString() is overridden. This means that it will be activated in the concrete object that implements it, which sees - and uses - the RenderingHint hash map where your hint is stored.

but i dont use it to paint my string?
Why do you think so? Because, you are actually using it.
Nowadays, Graphics is always a Graphics2D object, so your if-statement will be executed.
g2D and graphicsObject both point to the same object. For the compiler they are two variables of different types, allowing different methods to be called, but at execution time, these two variables actually point to the same object.
So by setting the rendering hint on g2D, and this being the same object as graphicsObject, drawing the string respects that hint and fixes the blurryness by using anti-aliasing as specified in the hint.

Related

Java How can I put an image on a rectangle

This is the code
player = createEntity(400, 600, 40, 60, Color.BLUE);
private Node createEntity(int x, int y, int w, int h, Color color) {
Rectangle entity = new Rectangle(w, h);
entity.setTranslateX(x);
entity.setTranslateY(y);
entity.setFill(color);
gameRoot.getChildren().add(entity);
return entity;
}
I'm not sure how to put an image to my player, any thoughts?
Java How can I put an image on a rectangle
My suggestion (if this is Swing) is not to use a Rectangle, or else use Rectangle but as part of a larger solution.
Instead I'd create a logical class, perhaps called Entity, that has a position, an image, and a draw method that accepts a Graphics parameter draws its image at whatever position needed, and then create Entity objects. Then within my JPanel's paintComponent method, I'd iterate through all the Entities created, calling their draw method.
First of all, you'll want to use active rendering. This'll prevent you from having all sorts of problems related to refreshing the display, and Java's BufferStrategy automatically handles multi-buffering for you, assuming you request more than one buffer.
Now that you're sure the screen gets updated, when rendering, you can draw a rectangle with a java.awt.Graphics object using the drawRect method. If you would like to fill this rectangle, use fillRect. The Graphics object draws everything in a pre-defined colour. If you would like to change colour, you can call setColor. This method requires a java.awt.Color object as an argument, which allows you to define all possible 64-bit transparent colours using one of the constructors. It also has a few predefined colours, like Color.RED, which is 0xFF0000.
I recommend you explore all the methods Graphics has to offer, and maybe even look into Graphics2D, which supports a few extra things. Note that most Graphics objects can be cast to Graphics2D, but if you're not sure, you might either want to look into Java's source code (there is an src.zip inside the JDK installation) or use an instanceof check. As a matter of fact, Graphics2D supports drawing shapes like your Rectangle using the drawShape or fillShape method.
For those of you who are curious, 0xFF0000 is a way of formatting colours. It is RGB encoded into hexadecimal (0xRRGGBB). It's also commonly represented #FF0000 in other languages, like CSS (Cascading Style Sheet, used for easily formatting HTML documents)

How to increase the quality strings drawn with Graphics2D?

After experimenting back and forth with Graphics2D vs. JPanels I have noticed that strings written on a JPanel are much higher resolution (less pixilated) then those drawn with g.drawString().
Is there any way to increase the resolution of strings drawn with Graphics2D?
Set the Graphics2D RenderingHints parameter, RenderingHints.KEY_TEXT_ANTIALIASING, to RenderingHints.VALUE_TEXT_ANTIALIAS_ON or one of the other constants that turn this anti-aliasing on.
When you draw using Graphics2D directly, are you using RenderingHints.KEY_TEXT_ANTIALIASING as mentioned here?

Draw Graphics2D to another Graphics2D

It is possible to draw from one Graphics2D to another Graphics2D?
Let me explain.
I have printing issues, when i display a JTextArea or JTextPanel in screen, internaly its used sun.java2d.SunGraphics2D, but when im printing its used sun.print.PeekGraphics and sun.awt.windows.WPathGraphics.
The problem is with some kind of Fonts, like Arial. In some sizes lines are cut.
I have tryed a lot of ways to render the text in printing, Graphics2D.drawString, SwingUtilities2.drawString, TextLayout.drawString, but in some cases lines are still cut, or lines are not cut but some kind of justification makes disapear white spaces.
So my idea is try to render components with sun.java2d.SunGraphics2D and "copy" the surface to the printer via sun.print.PeekGraphics or sun.awt.windows.WPathGraphics.
Thanks in advance.
Yes its possible, thats how double buffering is achieved in a lot of Java Games. What you need is the Graphics2D's drawImage() method which takes in another Graphics2D object to draw in. E.g. from a small game of mine:
private Main(){
...
/* Create the backbuffer as a BufferedImage object */
this.doubleBuffer = new BufferedImage(this.WIDTH, this.HEIGHT, BufferedImage.TYPE_INT_RGB);
/* create a Graphics 2D object to draw INTO this backbuffer */
this.doubleBufferG2D = (Graphics2D) doubleBuffer.createGraphics();
...
}
Somewhere else:
/*Now lets draw the backbuffer INTO the screen */
g2d.drawImage(doubleBuffer, null , 0, 0);
Edit: heh I realized its not exactly as above...lemme think on it.
Edit2: Alright the above can still be used a sample, but the sequence of steps to draw from one Graphics2D to another should be as such:
1. From a Graphics2D object to an Image/BufferedImage object using drawGraphics().
2. From the Image/BufferedImage above, extract its member Graphics2D object by using itscreateGraphics().
Looks like you can do one of two things:
create a Graphics2D on an image, do your rendering, then draw the image into another Graphics2D
or create Graphics2D from original Graphics2D using Graphics.create() methods and then do you rendering.

Java: line-stroke with filled shape

This is not really important, but it was bothering me for a little while.
Problem description:
Given: a line (Line2D)
Wanted: drawing the line as a wedge (Filled GeneralPath)
Surely this can be done by creating the wedge as General Path and then filling it by the Graphics (my solution).
My first approach would have been a wedge-stroked line, because I didn't want to change the line object for some reason, also I just wanted to draw the line object and not think about it any more.
Creating the wedge-stroke was no problem (Some calculations and then creating the General Path) - but I was not able to fill it (easily)
Apparently it seems the fill of Graphics2D only fills the shape it gets - and does not handle the filling of the stroke (that behavior makes sense if one thinks about it).
Question: Is there any way to fill a shape of a Stroke (filling a shape - more specifically: a GeneralPath - somehow before drawing it)?
May be BasicStroke.public Shape createStrokedShape(Shape s) can help if you pass the Line2D there?
Once you use createStrokedShape(), note that draw() "strokes the outline of a Shape," while fill() "fills the interior of a Shape."
import java.awt.*;
public static Shape strokeToShape(Shape path, float strokeWidth)
return new BasicStroke(strokeWidth).createStrokedShape(path);
}
You may also specify cap and join parameters of BasicStroke

Cannot get image to move where I want it to (and update continuously)?

I'm Basically programming a simple game engine but I'm having problems with my sprites/images not appearing when they should... or at all!
I'll try and keep this as simple as possible. I have a Sprite, GameEngine and Display class. In the gameloop, I have a method that sets the new position of my Sprite (so it just sets the x and y variables). Next I call a transform method which does the following:
public void transform() {
affineTransform.setToIdentity();
affineTransform.translate(x, y);
}
Following that, I then call a draw method in the Sprite:
public void draw() {
graphics2D.drawImage(image, affineTransform, jFrame);
}
Finally, in my thread I then call repaint() on the JFrame (the Display class). My paint method for that class is as follows:
public void paint(Graphics g) {
g.drawImage(backbuffer, insets.left, insets.top, this);
}
But nothing is appearing, apart from a black screen!
I'm also getting confused between Graphics g, and Graphics2D and when to use either. (The overridden paint method uses Graphics g). For the record, I do have a Graphics2D variable in the class that is created by calling backbuffer.createGraphics();
Another thing that is confusing me is this AffineTransform... I've read the documentation but I'm still utterly confused on how and when to use it - and what exactly it seems to do. Is there any explanation in relatively simple terms?
Surely this should be working... am I missing something out here?
To answer part of your question:
From the Graphics2D JavaDoc
This Graphics2D class extends the Graphics class to provide more sophisticated control over geometry, coordinate transformations, color management, and text layout. This is the fundamental class for rendering 2-dimensional shapes, text and images on the Java(tm) platform.
Essentially, with Graphics2D you can do much more than you can with Graphics. And with a Sun JVM 1.5+, it should be safe to cast the Graphics object you get in paint() to Graphics2D
I just noticed this: For the record, I do have a Graphics2D variable in the class that is created by calling backbuffer.createGraphics();
You should make sure you're not drawing on a Graphics[2D] canvas (I'll use this term to refer to the drawable area that the Graphics[2D] object provides) that you later throw away. If you're drawing your image on a separate canvas, you should ensure that you then draw that image onto your actual display canvas.
I don't really have a good explanation of AffineTransform but maybe these will help?
http://www.javalobby.org/java/forums/t19387.html
https://secure.wikimedia.org/wikipedia/en/wiki/Affine_transformation
From Wikipedia - In general, an affine transformation is composed of linear transformations (rotation, scaling or shear) and a translation (or "shift"). Several linear transformations can be combined into a single one. Basically, you use this class to perform operations such as rotation, translation, zoom etc.

Categories