Setting JPanel background to transparent - java

I'm trying to build my own video player using VLCJ, but I have a problem.
My code is
import java.awt.*;
import javax.swing.*;
import com.sun.jna.*;
import uk.co.caprica.vlcj.component.*;
import uk.co.caprica.vlcj.runtime.*;
public class MainFrame extends JFrame {
public MainFrame(String vlcPath, String username) {
super("Player");
setSize(1366,700);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), vlcPath);
EmbeddedMediaPlayerComponent player = new EmbeddedMediaPlayerComponent();
setContentPane(player);
JPanel panel = new JPanel();
player.add(panel, BorderLayout.EAST);
Dimension d = new Dimension(300,200);
panel.setOpaque(false);
panel.setLayout(null);
panel.setPreferredSize(d);
panel.setSize(d);
setVisible(true);
player.getMediaPlayer().playMedia("path to video");
}
}
Now, as you can see, I want the video player to be on the whole screen, and I want an overlay with transparent background on the right side.
This code gives me the following:
The background of the JPanel is for some reason black, not transparent. I tried creating my own class which extends JPanel and overrides paintComponent(Graphics g), but the result was the same.
The question is, how can I make it transparent?

The video is being played in a heavyweight AWT Canvas.
You can't overlay a transparent Swing component on top of that, it simply won't work.
Options:
Overlay a transparent top level Window and put your overlay in there - this works because your window manager can deal with transparency of a top-level window - the problem with this is it's a bit clunky because you have to keep both frames in sync if you move them or minimize them, also your window manager might implement some sort of blend effect which is not what you want;
Use the "direct" rendering media player and paint your own overlay on top of each frame - the downside is that it is less efficient than native rendering since your own application has to render each frame (it does work though);
Use only heavyweight components in your overlay, like Label - but even then the label itself will not have a transparent background;
For the approach described in #1, you can use the setOverlay() method on your EmbeddedMediaPlayer instance, also use enableOverlay() to turn the overlay on and off.
For the approach described in #2, well this is probably the cleanest approach since it does not rely on any clunky workarounds (like keeping two top-level windows in sync), at the cost of more CPU usage and non-native video playback.
None of this is ideal, but it's the best you can do.
You should also probably look in the vlcj test sources because there are examples showing how to do overlays like this.

Related

How do I import a image from my computer in my java program? [duplicate]

I have a JPanel to which I'd like to add JPEG and PNG images that I generate on the fly.
All the examples I've seen so far in the Swing Tutorials, specially in the Swing examples use ImageIcons.
I'm generating these images as byte arrays, and they are usually larger than the common icon they use in the examples, at 640x480.
Is there any (performance or other) problem in using the ImageIcon class to display an image that size in a JPanel?
What's the usual way of doing it?
How to add an image to a JPanel without using the ImageIcon class?
Edit: A more careful examination of the tutorials and the API shows that you cannot add an ImageIcon directly to a JPanel. Instead, they achieve the same effect by setting the image as an icon of a JLabel. This just doesn't feel right...
If you are using JPanels, then are probably working with Swing. Try this:
BufferedImage myPicture = ImageIO.read(new File("path-to-file"));
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
add(picLabel);
The image is now a swing component. It becomes subject to layout conditions like any other component.
Here's how I do it (with a little more info on how to load an image):
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class ImagePanel extends JPanel{
private BufferedImage image;
public ImagePanel() {
try {
image = ImageIO.read(new File("image name and path"));
} catch (IOException ex) {
// handle exception...
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this); // see javadoc for more info on the parameters
}
}
Fred Haslam's way works fine. I had trouble with the filepath though, since I want to reference an image within my jar. To do this, I used:
BufferedImage wPic = ImageIO.read(this.getClass().getResource("snow.png"));
JLabel wIcon = new JLabel(new ImageIcon(wPic));
Since I only have a finite number (about 10) images that I need to load using this method, it works quite well. It gets file without having to have the correct relative filepath.
I think there is no need to subclass of anything. Just use a Jlabel. You can set an image into a Jlabel. So, resize the Jlabel then fill it with an image. Its OK. This is the way I do.
You can avoid rolling your own Component subclass completely by using the JXImagePanel class from the free SwingX libraries.
Download
JLabel imgLabel = new JLabel(new ImageIcon("path_to_image.png"));
You can subclass JPanel - here is an extract from my ImagePanel, which puts an image in any one of 5 locations, top/left, top/right, middle/middle, bottom/left or bottom/right:
protected void paintComponent(Graphics gc) {
super.paintComponent(gc);
Dimension cs=getSize(); // component size
gc=gc.create();
gc.clipRect(insets.left,insets.top,(cs.width-insets.left-insets.right),(cs.height-insets.top-insets.bottom));
if(mmImage!=null) { gc.drawImage(mmImage,(((cs.width-mmSize.width)/2) +mmHrzShift),(((cs.height-mmSize.height)/2) +mmVrtShift),null); }
if(tlImage!=null) { gc.drawImage(tlImage,(insets.left +tlHrzShift),(insets.top +tlVrtShift),null); }
if(trImage!=null) { gc.drawImage(trImage,(cs.width-insets.right-trSize.width+trHrzShift),(insets.top +trVrtShift),null); }
if(blImage!=null) { gc.drawImage(blImage,(insets.left +blHrzShift),(cs.height-insets.bottom-blSize.height+blVrtShift),null); }
if(brImage!=null) { gc.drawImage(brImage,(cs.width-insets.right-brSize.width+brHrzShift),(cs.height-insets.bottom-brSize.height+brVrtShift),null); }
}
There shouldn't be any problem (other than any general problems you might have with very large images).
If you're talking about adding multiple images to a single panel, I would use ImageIcons. For a single image, I would think about making a custom subclass of JPanel and overriding its paintComponent method to draw the image.
(see 2)
JPanel is almost always the wrong class to subclass. Why wouldn't you subclass JComponent?
There is a slight problem with ImageIcon in that the constructor blocks reading the image. Not really a problem when loading from the application jar, but maybe if you're potentially reading over a network connection. There's plenty of AWT-era examples of using MediaTracker, ImageObserver and friends, even in the JDK demos.
I'm doing something very similar in a private project I'm working on. Thus far I've generated images up to 1024x1024 without any problems (except memory) and can display them very quickly and without any performance problems.
Overriding the paint method of JPanel subclass is overkill and requires more work than you need to do.
The way I do it is:
Class MapIcon implements Icon {...}
OR
Class MapIcon extends ImageIcon {...}
The code you use to generate the image will be in this class. I use a BufferedImage to draw onto then when the paintIcon() is called, use g.drawImvge(bufferedImage); This reduces the amount of flashing done while you generate your images, and you can thread it.
Next I extend JLabel:
Class MapLabel extends Scrollable, MouseMotionListener {...}
This is because I want to put my image on a scroll pane, I.e. display part of the image and have the user scroll around as needed.
So then I use a JScrollPane to hold the MapLabel, which contains only the MapIcon.
MapIcon map = new MapIcon ();
MapLabel mapLabel = new MapLabel (map);
JScrollPane scrollPane = new JScrollPane();
scrollPane.getViewport ().add (mapLabel);
But for your scenario (just show the whole image every time). You need to add the MapLabel to the top JPanel, and make sure to size them all to the full size of the image (by overriding the GetPreferredSize()).
This answer is a complement to #shawalli's answer...
I wanted to reference an image within my jar too, but instead of having a BufferedImage, I simple did this:
JPanel jPanel = new JPanel();
jPanel.add(new JLabel(new ImageIcon(getClass().getClassLoader().getResource("resource/images/polygon.jpg"))));
Create a source folder in your project directory, in this case I called it Images.
JFrame snakeFrame = new JFrame();
snakeFrame.setBounds(100, 200, 800, 800);
snakeFrame.setVisible(true);
snakeFrame.add(new JLabel(new ImageIcon("Images/Snake.png")));
snakeFrame.pack();
You can avoid using own Components and SwingX library and ImageIO class:
File f = new File("hello.jpg");
JLabel imgLabel = new JLabel(new ImageIcon(file.getName()));
I can see many answers, not really addressing the three questions of the OP.
1) A word on performance: byte arrays are likely unefficient unless you can use an exact pixel byte ordering which matches to your display adapters current resolution and color depth.
To achieve the best drawing performance, simply convert your image to a BufferedImage which is generated with a type corresponding to your current graphics configuration. See createCompatibleImage at https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html
These images will be automatically cached on the display card memory after drawing a few times without any programming effort (this is standard in Swing since Java 6), and therefore the actual drawing will take negligible amount of time - if you did not change the image.
Altering the image will come with an additional memory transfer between main memory and GPU memory - which is slow. Avoid "redrawing" the image into a BufferedImage therefore, avoid doing getPixel and setPixel at all means.
For example, if you are developing a game, instead of drawing all the game actors to a BufferedImage and then to a JPanel, it is a lot faster to load all actors as smaller BufferedImages, and draw them one by one in your JPanel code at their proper position - this way there is no additional data transfer between the main memory and GPU memory except of the initial transfer of the images for caching.
ImageIcon will use a BufferedImage under the hood - but basically allocating a BufferedImage with the proper graphics mode is the key, and there is no effort to do this right.
2) The usual way of doing this is to draw a BufferedImage in an overridden paintComponent method of the JPanel. Although Java supports a good amount of additional goodies such as buffer chains controlling VolatileImages cached in the GPU memory, there is no need to use any of these since Java 6 which does a reasonably good job without exposing all of these details of GPU acceleration.
Note that GPU acceleration may not work for certain operations, such as stretching translucent images.
3) Do not add. Just paint it as mentioned above:
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
"Adding" makes sense if the image is part of the layout. If you need this as a background or foreground image filling the JPanel, just draw in paintComponent. If you prefer brewing a generic Swing component which can show your image, then it is the same story (you may use a JComponent and override its paintComponent method) - and then add this to your layout of GUI components.
4) How to convert the array to a Bufferedimage
Converting your byte arrays to PNG, then loading it is quite resource intensive. A better way is to convert your existing byte array to a BufferedImage.
For that: do not use for loops and copy pixels. That is very very slow. Instead:
learn the preferred byte structure of the BufferedImage (nowadays it is safe to assume RGB or RGBA, which is 4 bytes per pixel)
learn the scanline and scansize in use (e.g. you might have a 142 pixels wide image - but in the real life that will be stored as a 256 pixel wide byte array since it is faster to process that and mask the unused pixes by the GPU hardware)
then once you have an array build according to these principles, the setRGB array method of the BufferedImage can copy your array to the BufferedImage.

JPanel: What is the simplest way to display an image?

I am working on a project and I need to display an image that I have already drawn. I need a background image and several foreground images that I can move around. What is the easiest way to do this? I haven't been able to find a clear answer.
ImageIcon image = new ImageIcon("imagename.jpg");
JLabel label = new JLabel("", image, JLabel.CENTER);
JPanel panel = new JPanel(new BorderLayout());
panel.add( label, BorderLayout.CENTER );
return panel;
The answer depends. Do you want to resize the background image to meet the requirements of the client are or not? If so, do you want to "fill" or "fit" the image to the area.
Take a look at Java: maintaining aspect ratio of JPanel background image for a lengthier discussion on the topic.
The next question you need to ask, is do you want to paint the animation on the surface or use existing components and move them instead...
You could check out...
Swing animation running extremely slow
https://stackoverflow.com/questions/15858623/how-to-use-a-swing-timer-to-animate/15859932#15859932
Drawing 2 Balls to move in different direction on Java but one disappeared
Java Bouncing Ball
Multiple bouncing balls thread issue
I am trying to make ball gradually move
the images are not loading
Which uses the paintComponent or direct paint method.
This approach is relatively common and easy to control. The problem is if you want to perform sub animation (ie animate the actually element separately from the main animation...think walking or spinning), then it becomes more difficult.
Check out
Java ball object doesn't bounce off of drawn rectangles like it's supposed to.
Which uses components instead. This method is good if you want to provide sub animation, but has the complexity of requiring you to size and position the components within the container.
Just as a side note. JLabel is a container ;)
The easiest way i've found is to create an entirely new class and extend JPanel like so:
import javax.swing.*;
import javax.imageio.*;
import java.io.*;
import java.awt.*;
public class Background extends JPanel {
private Image image;
public Background(){
this.setPreferredSize(new Dimension(width,height));
image =Toolkit.getDefaultToolkit().getImage("your_image.jpg");;
}
public void paintComponent(Graphics g) {
//paints the background image
super.paintComponent(g);
do{
}while(g.drawImage(image, 0, 0, null)==false);
}
}
To instantiate this class simply call this:
Background b= new Background();
From your main program.
Remember that b now acts as a Jpanel so you can simply call b.add(element)
If you don't understand what i've talked about and shown you, view this document on extending classes:
Extending Classes

permanent background image on a JPanel

I am building a swing interface for drawing overlays over a particular image. I have found several examples of how to draw an image on a JPanel, and I am able to do this without difficulty. However, I would like to keep this image completely static while dynamically drawing overlays on top of it. With that in mind, it would be better if I could set the image as a permanent background of the panel, rather than having paintComponent() redraw the image every time. This would be particularly useful, as there will frequently be situations where I want to removeAll() graphics currently on the panel and redraw new ones.
So my question is this: is there a way to set a permanent background image in JPanel, or do I have to redraw the image every time paintComponent() is called?
put Image as Icon / ImageIcon to the JLabel
use this JLabel instread of JPanel
JLabel hasn't implemented any LayoutManager in compare with JFrame(BorderLayout) or JPanel(FlowLayout)
you have to define the proper LayoutManager, that accepting PreferredSize came its child(s)
then there are accesible (almost nearly) all methods as for JPanel, as container works
maybe you can try putting the Jpanel inside another Jpanel. You draw the image on the container JPanel. then make your inner JPanel a transparent one. this way, when there are no objects on it, you see the background of the parent JPanel which did not change.

Why is attaching a JPanel better?

I've just started coding video games and I've heard that doing all your drawing on a JPanel and attaching that panel onto a JFrame is better than simply drawing onto the JFrame. I was just wondering why is this better?
It is better for various reasons, including:
In most Swing components, custom painting is achieved by overriding the paintComponent(Graphics) method. Top-level Swing containers (e.g. JFrame, JApplet, JWindow) have only paint(Graphics). As a result of the common method for painting, people who answer often forget about this difference between common and top-level components, and therefore suggest silly advice. ;)
A JComponent can be added to a JFrame, or a JApplet, or a JDialog, or a constraint of a layout in a JPanel, or a JInternalFrame, or a.. Just when you think your GUI is complete, the client says "Hey, wouldn't it be great to throw in a tool-bar & offer it as an applet as well?" The JComponent approach adapts easily to that.
As explained (complete with code!) by Richante, it is easier to calculate the co-ordinates required for painting the custom component, and if it has a preferred size, to size the JFrame to be 'exactly the right size' to contain the GUI (using pack()). That is especially the case when other components are added as well.
Now, two minor disagreements with the advice offered.
If the entire component is custom painted, it might be better to simply put a BufferedImage inside an ImageIcon/JLabel combo. Here is an example of painting to an image. When it comes time to update it:
Call getGraphics() for a Graphics or createGraphics() for a Graphics2D
Draw the custom painting to that graphics instance
Dispose of the graphics instance
Call repaint() on the label.
It is an easy way to do Double Buffering.
Let me elaborate a bit. In video games, to avoid the flicker caused by redrawing and display smoother graphics, people usually use double buffering. They create an offscreen surface, draw everything on that and then display the entire off-screen surface on the screen in one go.
In Java2D and Swing, the easiest way to do this, is to simply do your game sprite drawing on a JPanel, and then add the JPanel to a JFrame.
Secondly, by drawing things on a JPanel, you allow more GUI widgets and other graphical objects to be displayed on the JFrame without having to paint them manually in the game loop. For example buttons, menus, other panels, even other rendering JPanels.
Thirdly, it allows you to use automatically translated co-ordinates for your game. You can draw everything from the top-left to the bottom-right without having to worry about the window manager specific things like window border-widths, task panes, titles etc.!
Moreover, this is not just a convention only used by Game Programmers in Java. Creating a separate Game Board, Render Panel or Graphics Widget is quite popular when programming games using a library with an internal mainloop such as a GUI Toolkit. You can use a User Form in Windows Forms and a Drawing Board in GTK+.
The JFrame includes things like the menu, title bar and border. Therefore, when you refer to coordinates you have to account for these. You might also decide to add a menu bar, or some other components, to the frame. If your painting is all in a JPanel, then this won't change how you need to refer to coordinates.
For example, try:
public class Test extends JFrame {
public Test() {
super();
setVisible(true);
setBounds(100, 100, 200, 100);
}
#Override
public void paint(Graphics g) {
g.fillRect(0, 0, 50, 50);
}
public static void main(String[] args) {
new Test();
}
}
and you will see that the black square is not square! Because (0, 0) is the top left corner of the entire frame, not the corner of the visible area.

How to add an image to a JPanel?

I have a JPanel to which I'd like to add JPEG and PNG images that I generate on the fly.
All the examples I've seen so far in the Swing Tutorials, specially in the Swing examples use ImageIcons.
I'm generating these images as byte arrays, and they are usually larger than the common icon they use in the examples, at 640x480.
Is there any (performance or other) problem in using the ImageIcon class to display an image that size in a JPanel?
What's the usual way of doing it?
How to add an image to a JPanel without using the ImageIcon class?
Edit: A more careful examination of the tutorials and the API shows that you cannot add an ImageIcon directly to a JPanel. Instead, they achieve the same effect by setting the image as an icon of a JLabel. This just doesn't feel right...
If you are using JPanels, then are probably working with Swing. Try this:
BufferedImage myPicture = ImageIO.read(new File("path-to-file"));
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
add(picLabel);
The image is now a swing component. It becomes subject to layout conditions like any other component.
Here's how I do it (with a little more info on how to load an image):
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class ImagePanel extends JPanel{
private BufferedImage image;
public ImagePanel() {
try {
image = ImageIO.read(new File("image name and path"));
} catch (IOException ex) {
// handle exception...
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this); // see javadoc for more info on the parameters
}
}
Fred Haslam's way works fine. I had trouble with the filepath though, since I want to reference an image within my jar. To do this, I used:
BufferedImage wPic = ImageIO.read(this.getClass().getResource("snow.png"));
JLabel wIcon = new JLabel(new ImageIcon(wPic));
Since I only have a finite number (about 10) images that I need to load using this method, it works quite well. It gets file without having to have the correct relative filepath.
I think there is no need to subclass of anything. Just use a Jlabel. You can set an image into a Jlabel. So, resize the Jlabel then fill it with an image. Its OK. This is the way I do.
You can avoid rolling your own Component subclass completely by using the JXImagePanel class from the free SwingX libraries.
Download
JLabel imgLabel = new JLabel(new ImageIcon("path_to_image.png"));
You can subclass JPanel - here is an extract from my ImagePanel, which puts an image in any one of 5 locations, top/left, top/right, middle/middle, bottom/left or bottom/right:
protected void paintComponent(Graphics gc) {
super.paintComponent(gc);
Dimension cs=getSize(); // component size
gc=gc.create();
gc.clipRect(insets.left,insets.top,(cs.width-insets.left-insets.right),(cs.height-insets.top-insets.bottom));
if(mmImage!=null) { gc.drawImage(mmImage,(((cs.width-mmSize.width)/2) +mmHrzShift),(((cs.height-mmSize.height)/2) +mmVrtShift),null); }
if(tlImage!=null) { gc.drawImage(tlImage,(insets.left +tlHrzShift),(insets.top +tlVrtShift),null); }
if(trImage!=null) { gc.drawImage(trImage,(cs.width-insets.right-trSize.width+trHrzShift),(insets.top +trVrtShift),null); }
if(blImage!=null) { gc.drawImage(blImage,(insets.left +blHrzShift),(cs.height-insets.bottom-blSize.height+blVrtShift),null); }
if(brImage!=null) { gc.drawImage(brImage,(cs.width-insets.right-brSize.width+brHrzShift),(cs.height-insets.bottom-brSize.height+brVrtShift),null); }
}
There shouldn't be any problem (other than any general problems you might have with very large images).
If you're talking about adding multiple images to a single panel, I would use ImageIcons. For a single image, I would think about making a custom subclass of JPanel and overriding its paintComponent method to draw the image.
(see 2)
JPanel is almost always the wrong class to subclass. Why wouldn't you subclass JComponent?
There is a slight problem with ImageIcon in that the constructor blocks reading the image. Not really a problem when loading from the application jar, but maybe if you're potentially reading over a network connection. There's plenty of AWT-era examples of using MediaTracker, ImageObserver and friends, even in the JDK demos.
I'm doing something very similar in a private project I'm working on. Thus far I've generated images up to 1024x1024 without any problems (except memory) and can display them very quickly and without any performance problems.
Overriding the paint method of JPanel subclass is overkill and requires more work than you need to do.
The way I do it is:
Class MapIcon implements Icon {...}
OR
Class MapIcon extends ImageIcon {...}
The code you use to generate the image will be in this class. I use a BufferedImage to draw onto then when the paintIcon() is called, use g.drawImvge(bufferedImage); This reduces the amount of flashing done while you generate your images, and you can thread it.
Next I extend JLabel:
Class MapLabel extends Scrollable, MouseMotionListener {...}
This is because I want to put my image on a scroll pane, I.e. display part of the image and have the user scroll around as needed.
So then I use a JScrollPane to hold the MapLabel, which contains only the MapIcon.
MapIcon map = new MapIcon ();
MapLabel mapLabel = new MapLabel (map);
JScrollPane scrollPane = new JScrollPane();
scrollPane.getViewport ().add (mapLabel);
But for your scenario (just show the whole image every time). You need to add the MapLabel to the top JPanel, and make sure to size them all to the full size of the image (by overriding the GetPreferredSize()).
This answer is a complement to #shawalli's answer...
I wanted to reference an image within my jar too, but instead of having a BufferedImage, I simple did this:
JPanel jPanel = new JPanel();
jPanel.add(new JLabel(new ImageIcon(getClass().getClassLoader().getResource("resource/images/polygon.jpg"))));
Create a source folder in your project directory, in this case I called it Images.
JFrame snakeFrame = new JFrame();
snakeFrame.setBounds(100, 200, 800, 800);
snakeFrame.setVisible(true);
snakeFrame.add(new JLabel(new ImageIcon("Images/Snake.png")));
snakeFrame.pack();
You can avoid using own Components and SwingX library and ImageIO class:
File f = new File("hello.jpg");
JLabel imgLabel = new JLabel(new ImageIcon(file.getName()));
I can see many answers, not really addressing the three questions of the OP.
1) A word on performance: byte arrays are likely unefficient unless you can use an exact pixel byte ordering which matches to your display adapters current resolution and color depth.
To achieve the best drawing performance, simply convert your image to a BufferedImage which is generated with a type corresponding to your current graphics configuration. See createCompatibleImage at https://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html
These images will be automatically cached on the display card memory after drawing a few times without any programming effort (this is standard in Swing since Java 6), and therefore the actual drawing will take negligible amount of time - if you did not change the image.
Altering the image will come with an additional memory transfer between main memory and GPU memory - which is slow. Avoid "redrawing" the image into a BufferedImage therefore, avoid doing getPixel and setPixel at all means.
For example, if you are developing a game, instead of drawing all the game actors to a BufferedImage and then to a JPanel, it is a lot faster to load all actors as smaller BufferedImages, and draw them one by one in your JPanel code at their proper position - this way there is no additional data transfer between the main memory and GPU memory except of the initial transfer of the images for caching.
ImageIcon will use a BufferedImage under the hood - but basically allocating a BufferedImage with the proper graphics mode is the key, and there is no effort to do this right.
2) The usual way of doing this is to draw a BufferedImage in an overridden paintComponent method of the JPanel. Although Java supports a good amount of additional goodies such as buffer chains controlling VolatileImages cached in the GPU memory, there is no need to use any of these since Java 6 which does a reasonably good job without exposing all of these details of GPU acceleration.
Note that GPU acceleration may not work for certain operations, such as stretching translucent images.
3) Do not add. Just paint it as mentioned above:
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
"Adding" makes sense if the image is part of the layout. If you need this as a background or foreground image filling the JPanel, just draw in paintComponent. If you prefer brewing a generic Swing component which can show your image, then it is the same story (you may use a JComponent and override its paintComponent method) - and then add this to your layout of GUI components.
4) How to convert the array to a Bufferedimage
Converting your byte arrays to PNG, then loading it is quite resource intensive. A better way is to convert your existing byte array to a BufferedImage.
For that: do not use for loops and copy pixels. That is very very slow. Instead:
learn the preferred byte structure of the BufferedImage (nowadays it is safe to assume RGB or RGBA, which is 4 bytes per pixel)
learn the scanline and scansize in use (e.g. you might have a 142 pixels wide image - but in the real life that will be stored as a 256 pixel wide byte array since it is faster to process that and mask the unused pixes by the GPU hardware)
then once you have an array build according to these principles, the setRGB array method of the BufferedImage can copy your array to the BufferedImage.

Categories