Filling with transparency using Graphics2D - java

I created an ARGB BufferedImage. Now I'd like to reinitialize it with a transparent background. I tried the following code:
(...)
if( this.offscreen==null ||
this.offscreen.getWidth()!= dim.width ||
this.offscreen.getHeight()!= dim.height )
{
this.offscreen=new BufferedImage(
dim.width,
dim.height,
BufferedImage.TYPE_INT_ARGB);
}
Graphics2D g=this.offscreen.createGraphics();
g.setColor(new Color(255,255,255,0));
g.clearRect(0, 0, dim.width, dim.height);
(...)
but it didn't work.
Any idea on how to do this please ?
Thanks !

g.clearRect(..) fills the selected rectangle with the background colour of the Graphics2D object. You're better off doing g.fillRect(..) which would give the intended result with your code, or set the background colour of the Graphics2D object beforehand (g.setBackground(..)).
Also, you may have to do g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC)); before the fill so that it sets the buffer properly (ignore destination buffer data, only use source data -- in this case, the fill operation). Not sure what the default is for this value, but you should set it back to that afterwards to ensure proper operation.

I had this problem before and I solved it with a really narrow trick.
Here is the deal:
In the constructor of the paint Class take a screen shot of the System but be careful
BufferedImage image = new Robot().createScreenCapture(new Rectangle(0, 23, xScreen, yScreen));
And where you want to clear the screen
g2D.drawImage(image, null, /*your Image observer*/);

Related

Transparency overlapping in Java

So I'm making a simple pause function in my game, and I want to have a grey transparent background, the problem is, the rectangle keeps overlapping and is just causing a fade out look. I've tried g2.dispose, and it works, but I can't draw anything else over that.
I have my render method, which is being called 60 times a second. (I issume the rectangle is being drawn 60 times a second)
public void render(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(new Color(0, 0, 0, 50));
g2.fillRect(0, 0, RPG.getWidth(), RPG.getHeight());
g2.drawImage(paused, 0, 0, null);
}
Thanks!
Edit: I feel like an idiot... I just had to draw my ingame screen underneath that!
If I understand correctly what you mean by "causing a fade out look" (although I'm not sure I do), you want to fill a background with a transparent color without blending the new transparent color with pixels that are already present. You can do this by setting the composite mode to "source":
g2.setComposite(AlphaComposite.Src);
You can set it back to the default "source over destination" rule to return to normal drawing afterwards by doing:
g2.setComposite(AlphaComposite.SrcOver);
Edit: Or perhaps you do want to blend the transparent color, but with the rest of the game graphics and not with itself? In that case, just make sure that you're redrawing the game background each time you draw the transparency over the top, although I'd suggest pausing the 60fps refresh during game pause if nothing on the screen is changing, just to avoid wasting CPU/battery.
Consider trying to create a copy of the Graphics context first and then disposing of it when your finished...
public void render(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setColor(new Color(0, 0, 0, 50));
g2.fillRect(0, 0, RPG.getWidth(), RPG.getHeight());
g2.drawImage(paused, 0, 0, null);
g2.dispose();
}
This way, the changes to the Graphics state remain isolated between the create and dispose calls and don't affect anything else painted after it
Also, remember, unless you are clearing what was previously painted to the Graphics context, it will accumulate on repeated calls.

Unable to resize image and maintain transparency

The below code resizes an image. Unfortunately the image which is a vertical image has black bars on the sides. It looks as though the transparent, or blank space is being filled with black. I've tried setting the background color to white, and using alphaRGB but can't seem to shake it.
OrderProductAssetEntity orderProductAssetEntity = productAssets.get(jobUnitEntity.getId());
File asset = OrderProductAssetService.getAssetFile(orderProductAssetEntity);
if (asset.exists()) {
//resize the asset to a smaller size
BufferedImage resizedImage = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
Graphics2D g = resizedImage.createGraphics();
g.setBackground(Color.WHITE);
g.drawImage(ImageIO.read(asset), 0, 0, width, height, null);
g.dispose();
jobUnitImages.put(orderProductAssetEntity.getOriginalLocation(), new PDJpeg(document, resizedImage));
} else {
jobUnitImages.put(orderProductAssetEntity.getOriginalLocation(), null);
}
First, if you need transparency, BufferedImage.TYPE_INT_RGB won't work, you'll need BufferedImage.TYPE_INT_ARGB. Not sure if you already tried it, just want to be clear.
Second, this line:
g.setBackground(Color.WHITE);
...does only set the current background color for the graphics context. It does not fill the background with that color. For that, you'll need to do g.clearRect(0, 0, width, height) as well. But I usually prefer to use g.setColor(...) and g.fillRect(...) instead to avoid confusion.
Or, if you like, you can also use the drawImage method that takes a Color as the second last parameter like this:
g.drawImage(image, 0, 0, width, height, Color.WHITE, null);
EDIT:
Third, the class name PDJpeg implies that the image is later stored as JPEG, so you will probably lose transparency anyway. So the best is probably to stick with TYPE_INT_RGB, and fill the background with the right color (and do it the right way ;-).

Getting transparency to work in Java

I am trying to rotate an image in Java, but when I do the transparency in the png goes away. Is there any way i can rotate the image AND keep the transparency?
AffineTransform trans = new AffineTransform();
trans.setTransform(identity);
trans.translate(100, 100);
trans.rotate( Math.toRadians(45) );
gr.drawImage(image.getImage(), trans, this);
This makes the transparency in the png black, but
gr.drawImage(image.getImage(), 0, 200, null);
Has no problem with the transparency.
Try to set rendering hints on Graphics2D object.
gr.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY );
Check reference for optimal settings.

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

Fit Java Image into JFrame

I'm trying to display an Image that is bigger than the JFrame Dimensions. If I try to resize the Image smaller, then the Image quality is lost.
If I make the Image larger, the quality is not lost. Is this normal behavior in Java image package?
I guess what I'm trying to figure out is that probably I'm doing something wrong when reducing the Image size. So does Java provide a method to automatically do this without loosing image quality?
Same behavior like JButtons, where java automatically adjusts the space occupied by a JButton in a JPanel.
bufferedImage = resize(bufImage,500,600);
ImageIcon imageIcon = new ImageIcon(bufferedImage);
resizedIMage = imageIcon.getImage();
The actual resize is below. I took it from the internet.
private static BufferedImage resize(BufferedImage image, int width, int height) {
int type = image.getType() == 0? BufferedImage.TYPE_INT_ARGB : image.getType();
BufferedImage resizedImage = new BufferedImage(width, height, type);
Graphics2D g = resizedImage.createGraphics();
g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(image, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
If you are using Java 5 or newer you can try RenderingHints.VALUE_INTERPOLATION_BICUBIC for your interpolation hint.
There is a very detailed description of the different scaling behaviours of Java2D in this article: perils-of-getScaledInstance
It contains examples of the different downscale results you can expect to see with the different approaches available in Java.
It also provides sample code that uses a multi-step aproach to downscale the image which appears to produce much better results than VALUE_INTERPOLATION_BILINEAR.
Override the paintComponent(Graphics g) method of whatever component will display the image and look at Graphics.drawImage()
You can even cast your Graphics instance into a Graphics2D for more functionalities. For example setRenderingHings()
Graphics2D g2 = (Graphics2D) g;
RenderingHints rh = g2.getRenderingHints ();
rh.put (RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHints (rh);
I would get rid of this:
int type = image.getType() == 0? BufferedImage.TYPE_INT_ARGB : image.getType();
And always use BufferedImage.TYPE_INT_ARGB
That seems to give me good results.

Categories

Resources