How to draw transparent image in java with BufferedImage? - java

I'm willing to show an transparent image on a canvas in java with the help of graphics2D and BufferedImage.
Here is the code which loads image.
private static BufferedImage sprites,board;
public static void load(){
try {
board = new BufferedImage(100,100,BufferedImage.TYPE_INT_ARGB);
board = ImageIO.read(new File("res/chesssprite.png"));
} catch (IOException ex) {
Logger.getLogger(SpriteManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
and here is the code which renders the image
public void render(){
BufferStrategy bs = this.getBufferStrategy();
if(bs == null){
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
Graphics2D g2d = (Graphics2D) g;
{
g2d.setColor(new Color(150,150,150));
g2d.fillRect(0,0,getWidth(), getHeight());
g2d.setComposite(AlphaComposite.Src);
g2d.drawImage(board,0,0,null);
}
g = g2d;
g.dispose();
bs.show();
}
I have search on net a lot but didn't come with an solution. If anyone knowns how to fix this.
Here is the image..
And here is how output looks like

Okay whoever facing these kind of problem:
Make sure the image is transparent. Test it in image viewer.
Remove the line g2d.setComposite(AlphaComposite.Src); This line adds alpha composites which make every transparent pixel black.

Related

Difference between drawing on JPanel via paintComponent and Buffered Image

I have experimented with two different methods of drawing the same shape, the first image is drawn by overriding JPanel's paintComponent(Graphics g) method and using g.drawOval(..) etc,
The second image is drawn by creating a buffered image and drawing on it by using buffered image's graphics. How can I achieve the same rendering quality on both approaches? I have tried using many different rendering hints but none of them gave the same quality. I also tried sharpening by using Kernel and filtering, still couldn't.
private void createImage() {
image = new BufferedImage(IMG_SIZE, IMG_SIZE, BufferedImage.TYPE_INT_ARGB);
Graphics2D gr = image.createGraphics();
gr.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gr.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
gr.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
//something along the way
gr.drawOval(.....);
gr.drawLine(.....);
gr.drawOval(.....);
panel.repaint();
gr.dispose();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(backgroundColor);
if (USE_BUFFERED_IMAGE) {
g.drawImage(image, startX, startY, null);
} else {
//something along the way
g.drawOval(.....);
g.drawLine(.....);
g.drawOval(.....);
}
}
Drawing using JPanel paintComponent graphics
Drawing using Buffered Image graphics then it is drawn on Jpanel via drawimage
EDIT
I found my solution by getting almost every setting of panel graphics and applying them to buffered image graphics. Not by using only using the same rendering hints or "minimal reproducible examples" approaches. Here, the importing thing is that the panel's graphic scales everything by 1.25 and then scales down to the original before showing it on the panel.
Here is an example, -this is not exactly how my code is, this is just an example to give you an idea-
private void createImages(Paint paint, RenderingHints hints,
AffineTransform transform, Stroke stroke,
Composite composite, GraphicsConfiguration config ){
image = config.createCompatibleImage(IMG_SIZE, IMG_SIZE,
BufferedImage.TYPE_INT_ARGB);
Graphics2D gr = image.createGraphics();
// same options
gr.setPaint(paint);
gr.setRenderingHints(hints);
gr.setTransform(transform);
gr.setStroke(stroke);
gr.setComposite(composite);
//something along the way
gr.drawOval(.....);
gr.drawLine(.....);
gr.drawOval(.....);
panel.repaint();
gr.dispose();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(backgroundColor);
if (USE_BUFFERED_IMAGE) {
Graphics2D g2 = (Graphics2D)g;
createImages(g2.getPaint(), g2.getRenderingHints(),g2.getTransform(),
g2.getStroke(),g2.getComposite(), g2.getDeviceConfiguration());
//scaling down is important because your drawings get scaled to 1.25
// by panels graphics' transformation
g.drawImage(image, startX, startY,(int)(IMG_SIZE*0.8),(int)(IMG_SIZE*0.8), null);
} else {
//something along the way
g.drawOval(.....);
g.drawLine(.....);
g.drawOval(.....);
}
}
I found my solution by getting almost every setting of panel graphics and applying them to buffered image graphics. Here, the importing thing is that the panel's graphic scales everything by 1.25 and then scales down to the original before showing it on the panel.
Here is an example, -this is not exactly how my code is, this is just an example to give you an idea-
private void createImages(Paint paint, RenderingHints hints,
AffineTransform transform, Stroke stroke,
Composite composite, GraphicsConfiguration config ){
image = config.createCompatibleImage(IMG_SIZE, IMG_SIZE,
BufferedImage.TYPE_INT_ARGB);
Graphics2D gr = image.createGraphics();
// same options
gr.setPaint(paint);
gr.setRenderingHints(hints);
gr.setTransform(transform);
gr.setStroke(stroke);
gr.setComposite(composite);
//something along the way
gr.drawOval(.....);
gr.drawLine(.....);
gr.drawOval(.....);
panel.repaint();
gr.dispose();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(backgroundColor);
if (USE_BUFFERED_IMAGE) {
Graphics2D g2 = (Graphics2D)g;
createImages(g2.getPaint(), g2.getRenderingHints(),g2.getTransform(),
g2.getStroke(),g2.getComposite(), g2.getDeviceConfiguration());
//scaling down is important because your drawings get scaled to 1.25
// by panels graphics' transformation
g.drawImage(image, startX, startY,(int)(IMG_SIZE*0.8),(int)(IMG_SIZE*0.8), null);
} else {
//something along the way
g.drawOval(.....);
g.drawLine(.....);
g.drawOval(.....);
}
}

Java buffer strategy sometimes doesn't draw properly

I created a game in Java which uses buffer strategy. But sometimes I just get a white frame or a white border. That happens about every fifth time. I searched a lot but I really can't figure out what I'm doing wrong. The code compiles and there aren't any errors printed out.
If if fails, the frame looks for example like that:
white border
completely white frame
Here's code (only the relevant parts):
private BufferStrategy bs;
public Testclass(){
setResizable(false);
setSize(1000,600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setIgnoreRepaint(true);
setVisible(true);
createBufferStrategy(2);
bs = getBufferStrategy();
}
protected void paint() {
do {
Graphics2D g=null;
try {
g = (Graphics2D) bs.getDrawGraphics();
g.setColor(Color.CYAN);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
} finally {
g.dispose();
}
bs.show();
} while (bs.contentsLost());
}
public static void main(String[] args) {
Testclass window = new Testclass();
window.paint();
}
I actually found a better way try this:
boolean BufferStrategyRunning = true;
while(BufferStrategyRunning == true) {
BufferStrategy BS = GUIFrame.getBufferStrategy();
if(BS == null) {
GUIFrame.createBufferStrategy(3);
continue;
}
Graphics g = BS.getDrawGraphics();
g.drawImage(CurrentScreen.BackgroundImage, 0, 0, null);
g.dispose();
BS.show();
}

The dicom bufferedImage from pixelmed is having low contrast

I would like to display a DICOM image in my java program. I am using pixelmed. However, I found that i cant correctly display the correct contrast. The contrast is too low.
Here is my code:
(SourceImage is a class provided by PixelMed, chosenImageFile.getPath() is just the path of the DICOM File.)
SourceImage dimg = new SourceImage(chosenImageFile.getPath());
BufferedImage image = dimg.getBufferedImage();
BufferedImage source = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = source.createGraphics();
g2d.drawImage(image, 0, 0, null);
dicomImgDisplayer1.setImage(source);
dicomImgDisplayer1 is an class extend JPanel. setImage() of this JPanel class will call the setImage() of an JFrame class.
The JFrame class's setImage() code:
public void setImage(BufferedImage image) {
this.image = image;
setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
repaint();
revalidate();
}
public void paint(Graphics graphics) {
Graphics2D g2d = (Graphics2D) graphics;
g2d.drawImage(image, null, 0, 0);
}
Is that something wrong with the color model? Please help. Thanks.
Does your image have a prescribed window width / window center? Be sure you set that (or allow the user to adjust it). See SingleImagePanel - there are some static methods to apply windowing to your buffered image.

BufferStrategy not scaling Graphics2D

I am currently trying to program a simple platform game. I would like to scale the graphics up by a factor of 2/4/whatever so that I can get an old-school look and feel from the game. However, when I call scale on my Graphics2D instance, nothing happens.
#Override
public void paint(Graphics g) {
BufferStrategy bf = this.getBufferStrategy();
Graphics2D bfg = (Graphics2D) bf.getDrawGraphics();
mLevel.draw(bfg, this);
for (GameEntity entity : mGameEntities) {
entity.draw(bfg, this);
}
bfg.scale(2.0, 2.0);
bf.show();
}
The draw calls basically just end up calling g.drawImage(..). Everything else is drawn correctly, so I do not understand why it isn't scaling everything up by a factor of 2.
#MadProgrammer was correct - one must scale the Graphics2D instance before making any draw calls.
#Override
public void paint(Graphics g) {
BufferStrategy bf = this.getBufferStrategy();
Graphics2D bfg = (Graphics2D) bf.getDrawGraphics();
bfg.scale(2.0, 2.0);
mLevel.draw(bfg, this);
for (GameEntity entity : mGameEntities) {
entity.step();
entity.draw(bfg, this);
}
bf.show();
}

Repaint an argb BufferedImage

In my applet I make use of different BufferedImages and use them as screen parts. Each screen part will only be repainted when the content needs to change.
This is the abstract ScreenPart class:
public abstract class ScreenPart extends BufferedImage{
Graphics2D g;
private BufferedImage buffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
public ScreenPart(int width, int height) {
super(width, height, BufferedImage.TYPE_INT_ARGB);
g = createGraphics();
repaint();
}
public abstract void paint(Graphics2D g);
public void repaint(){
g.drawImage(buffer, 0, 0, null);
paint(g);
}
}
But the buffer doesn't work because the buffer is also transparent. It will work when I change the BufferedImage type of the buffer from ARGB to RGB but this displays also a black background. So my question is: how can I correctly repaint this BufferedImage with a buffer?
Already found a solution:
public void repaint() {
g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
g.fillRect(0,0, getWidth(), getHeight());
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
paint(g);
}
This doesn't make use of another BufferedImage.

Categories

Resources