Sub-pixel Image rendering - java

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).

Related

Draw image as trapezoid in java

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);

How to rotate and draw an image in a specific way?

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.

String antialiasing don't work when image rotate

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.

Using java, how can I make a method taking in a BufferedImage, rotate it, and return a BufferedImage ( with correct width / height )

I have been looking up a lot of examples, every time I try, my image becomes offset, and also not rotated by the degree I am looking for.
I have a class which extends JPanel, and draws an image. This JPanel is then put into my JFrame. I need to have a method, which when I click a button can take the image of the JPanel, rotate it, and return ( with the new height and width ). - Then I can ask the JPanel to repaint using the new image, and.. it should have rotated.
If someone could please help me with an example, of rotating 90 degrees, and returning with now the height = the old width, and width = old height, that would be amazing!
Thanks,
Here you are
Image rotatedImage = new BufferedImage(imageToRotate.getHeight(null), imageToRotate.getWidth(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) rotatedImage.getGraphics();
g2d.rotate(Math.toRadians(90.0));
g2d.drawImage(imageToRotate, 0, -rotatedImage.getWidth(null), null);
g2d.dispose();

Java DirectColorModel vs. IndexColorModel when dealing with alphas

I have a BufferedImage that I get that has an IndexColorModel. I then wish to apply an AffineTransform with AffineTransformOP in order to create a transformed version of displayImage.
Here's a code snippet:
int type = isRGB() ? AffineTransformOp.TYPE_BILINEAR : AffineTransformOp.TYPE_NEAREST_NEIGHBOR;
AffineTransformOp op = new AffineTransformOp(atx, type);
displayImage = op.filter(displayImage, null);
I'm running this with many images, and from an earlier post I discovered that if I set the transform type to bilinear, then I was running out of memory because I was getting an image back with a DirectColorModel. However, this DirectColorModel had a correct alpha channel (when I drew the image an a green background after translating it, I could see green around the whole image). When I set the interpolation type to nearest neighbor, pixels above and to the left of the image appear black no matter what the background is. I'm assuming this means that the alpha is not getting set.
Can anyone tell me how to correctly set the alpha channel with an IndexColorModel, or change the AffineTransformOP parameters such that I get an IndexColorModel with the correct alpha?
Thanks!!
EDIT:
Here is the desired effect, with AffineTransformOp.TYPE_BINLINEAR:
Here is the effect that I'm seeing with AffineTransformOp.TYPE_NEAREST_NEIGHBOR:
The whole background is initially painted green for effect and in both cases the image is drawn at position (0, 0).
I'm not sure what effect you're trying to achieve, but I get expected results when I adjust the alpha before and/or after transforming. Typically, I start with setComposite(AlphaComposite.Clear) followed by fillRect(). If all else fails, you can filter() to a WritableRaster, and brute-force the result you want. Also, you might look at RenderingHints related to KEY_ALPHA_INTERPOLATION. Here's a toy I use to experiment with various combinations of alpha, mode and color.
I seem to recall seeing the effect your images show. Recalling that the AffineTransformOp may return an image with different co-ordinates, especially with rotation, I'm guessing the added "empty" space isn't getting initialized correctly. You can get a transparent border with the code below, which also makes rotation around the center somewhat more symmetric:
private BufferedImage getSquareImage(BufferedImage image) {
int w = image.getWidth();
int h = image.getHeight();
int max = Math.max(w, h);
BufferedImage square = new BufferedImage(
max, max, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = square.createGraphics();
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setComposite(AlphaComposite.Clear);
g2d.fillRect(0, 0, max, max);
g2d.setComposite(AlphaComposite.Src);
g2d.drawImage(image, (max - w) / 2, (max - h) / 2, null);
g2d.dispose();
return square;
}

Categories

Resources