I have a requirement to draw a png/jpg in a trapezium shape.
.For ex : height reducing gradually along the x-axis. I could not find an API to do such, I see there is an API AffineTransform which may do such sorts, but could not figure out if trapezium could be achieved. Thanks for your help in advance
I tried something of this sorts,
Image image = imageIcon.getImage();
Graphics2D g2 = (Graphics2D) g;
AffineTransform saveXform = g2.getTransform();
AffineTransform toCenterAt = new AffineTransform();
//toCenterAt.concatenate(toCenterAt);
toCenterAt.translate(-(image.getWidth(null)/2), -(image.getHeight(null)/2));
//toCenterAt.setToRotation(5,4,4,4);
toCenterAt.scale(0.1, 1);
g2.transform(toCenterAt);
g2.drawImage(image, 200,200, null);
g2.setTransform(saveXform);
Related
I have a line. I know the endpoint of that line and an angle which tells by how many degrees it's tilted. I want to draw an image in such a way so that the bottom center point of the image would touch the endpoint of the line like so:
Sadly, I get the wanted result only if line isn't rotated, like above. If it's rotated by, for example, 90 degrees I get this:
This is the code that draws the image (line is already drawn by that point).
public void drawCreature(Graphics2D g) {
int centered = creature.getX() - creature.getImage().getWidth()/2;
BufferedImage image = creature.getImage();
BufferedImage rotatedImage = new BufferedImage(image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D)rotatedImage.getGraphics();
g2d.rotate(Math.toRadians(creature.getAngle()), rotatedImage.getWidth()/2,
rotatedImage.getHeight()/2);
g2d.drawImage(creature.getImage(), 0, 0, null);
g.drawImage(rotatedImage, centered, creature.getY(), null);
}
Any help would be appreciated.
I am trying to plot a graph using the java 2d graphics library and I thought I had it. I want to plot in the coordinate system where 0,0 is in the center of the panel on the left edge. I used the following code and it seemed to give me the result I needed.
private void doDraw(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform saveAT = g2d.getTransform();
// get the height of the panel
int height = getHeight();
// Find the middle of the panel
double yTrans = ((double)height)/2.0;
AffineTransform tform = AffineTransform.getTranslateInstance( 0.0, yTrans);
g2d.setTransform(tform);
//draw the line for the x-axis.
g2d.drawLine(0, 0, 100, 0);
//restore the old transform
g2d.setTransform(saveAT);
}
This plotted the origin centered in the window.
The problem shows itself when I added a menu. Then the origin was offset in the y direction about twice the size of the menu higher then it should be. Do I need to account for the size of the menu and other containers that I add to the panel?
private void doDraw(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
int height = getHeight();
double yTrans = ((double)height)/2.0;
AffineTransform tform = AffineTransform.getTranslateInstance( 0.0, yTrans);
g2d.transform(tform);
//draw the line for the x-axis.
g2d.drawLine(0, 0, 100, 0);
}
works, thank you for your help
You might try the approach outlined here. Override paintComponent() to obtain a graphics context relative to the enclosing panel, rather than the enclosing frame.
To center the origin at the left edge, use
g2d.translate(0, h / 2);
To get upright, cartesian coordinates, use
g2d.scale(1, -1);
I have some problem with string antialiasing in Java. If I use this code
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
on normal (not rotated string), all is fine. But, when I try use antialiasing on rotated image, where I draw string - this string rendering without antialiasing feature.
This is example of my code, where antialiasing doesn't work:
Graphics2D g = originalImage.createGraphics();
AffineTransform affineTransform2 = new AffineTransform();
affineTransform2.setToIdentity();
affineTransform2.translate(125, 325);
affineTransform2.rotate(Math.toRadians(345));
BufferedImage positionImage = new BufferedImage(100, 40, BufferedImage.TYPE_INT_ARGB);
Graphics2D positionImageG2D = positionImage.createGraphics();
positionImageG2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
positionImageG2D.setFont(getFont(30f));
positionImageG2D.drawString("Some Text",100, 40);
positionImageG2D.dispose();
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.drawImage(positionImage, affineTransform2, null);
You don't draw text to g (last line), so whatever value you pass to KEY_TEXT_ANTIALIASING won't have any effect.
You are drawing a rotated image with already antialiased text. Try setting KEY_INTERPOLATION to VALUE_INTERPOLATION_BICUBIC or VALUE_INTERPOLATION_BILINEAR, which should effect scaling and rotation of images.
Another thing you could try, is to draw the text (rotated) directly onto g, without the temporary image. Should also work, but you might have to adjust positioning relative to the rotation.
I am aware of sub-pixel shapes, such as Rectangle2D.Double, Ellipse2D.Double and Line2D.Double - but I couldn't find information about drawing an Image / BufferedImage with sub-pixel accuracy.
Perhaps something that would look like this - Image2D.Double?
Is there any way I can achieve this?
Images may be drawn with an AffineTransform, which can specify scaling and translation with floating point values.
(See drawImage(Image, AffineTransform, ImageObserver) method)
For example, to draw an image scaled to half size and at position (10.5, 10.5), use:
Graphics2D g = ...
BufferedImage myImage = ...
AffineTransform t = new AffineTransform();
t.translate(10.5, 10.5);
t.scale(0.5, 0.5);
g.drawImage(myImage, t, null);
You should ensure that appropriate RenderingHints have been set on the Graphics2D object (set KEY_ANTIALIASING to VALUE_ANTIALIAS_ON for starters).
I want to make a image with rounded corners. A image will come from input and I will make it rounded corner then save it. I use pure java. How can I do that? I need a function like
public void makeRoundedCorner(Image image, File outputFile){
.....
}
Edit : Added an image for information.
I suggest this method that takes an image and produces an image and keeps the image IO outside:
Edit: I finally managed to make Java2D soft-clip the graphics with the help of Java 2D Trickery: Soft Clipping by Chris Campbell. Sadly, this isn't something Java2D supports out of the box with some RenderhingHint.
public static BufferedImage makeRoundedCorner(BufferedImage image, int cornerRadius) {
int w = image.getWidth();
int h = image.getHeight();
BufferedImage output = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = output.createGraphics();
// This is what we want, but it only does hard-clipping, i.e. aliasing
// g2.setClip(new RoundRectangle2D ...)
// so instead fake soft-clipping by first drawing the desired clip shape
// in fully opaque white with antialiasing enabled...
g2.setComposite(AlphaComposite.Src);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.WHITE);
g2.fill(new RoundRectangle2D.Float(0, 0, w, h, cornerRadius, cornerRadius));
// ... then compositing the image on top,
// using the white shape from above as alpha source
g2.setComposite(AlphaComposite.SrcAtop);
g2.drawImage(image, 0, 0, null);
g2.dispose();
return output;
}
Here's a test driver:
public static void main(String[] args) throws IOException {
BufferedImage icon = ImageIO.read(new File("icon.png"));
BufferedImage rounded = makeRoundedCorner(icon, 20);
ImageIO.write(rounded, "png", new File("icon.rounded.png"));
}
This it what the input/output of the above method looks like:
Input:
Ugly, jagged output with setClip():
Nice, smooth output with composite trick:
Close up of the corners on gray background (setClip() obviously left, composite right):
I am writing a follow up to Philipp Reichart's answer.
the answer of as an answer.
To remove the white background (seems to be black in the pictures), change g2.setComposite(AlphaComposite.SrcAtop);
to g2.setComposite(AlphaComposite.SrcIn);
This was a big problem for me because I have different images with transparency that I don't want to lose.
My original image:
If I use g2.setComposite(AlphaComposite.SrcAtop);:
When I use g2.setComposite(AlphaComposite.SrcIn); the background is transparent.
I found another way using TexturePaint:
ImageObserver obs = ...;
int w = img.getWidth(obs);
int h = img.getHeight(obs);
// any shape can be used
Shape clipShape = new RoundRectangle2D.Double(0, 0, w, h, 20, 20);
// create a BufferedImage with transparency
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D bg = bi.createGraphics();
// make BufferedImage fully transparent
bg.setComposite(AlphaComposite.Clear);
bg.fillRect(0, 0, w, h);
bg.setComposite(AlphaComposite.SrcOver);
// copy/paint the actual image into the BufferedImage
bg.drawImage(img, 0, 0, w, h, obs);
// set the image to be used as TexturePaint on the target Graphics
g.setPaint(new TexturePaint(bi, new Rectangle2D.Float(0, 0, w, h)));
// activate AntiAliasing
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// translate the origin to where you want to paint the image
g.translate(x, y);
// draw the Image
g.fill(clipShape);
// reset paint
g.setPaint(null);
This code can be simplified if you have a non-animated image, by creating the BufferedImage only once and keeping it for each paint.
If your image is animated though you have to recreate the BufferedImage on each paint. (Or at least i have not found a better solution for this yet.)