I'm trying to create a transparent image and then draw another image onto it that contains transparent/translucent pixels. After the image is added translucent pixels are set to white in comparison to being being a mixture of the colour and alpha. This is causing there to be a white outline around the image.
The image has to be shown on a ToolBar as a ToolItem with transparent pixels.
Is it possible to draw an image with transparency without it changing the transparent pixels to white?
Overlay Image
Processed Image
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setSize(285,305);
// Create a transparent image
final Image transparentImage = new Image(null, 256, 256);
final ImageData imageData = transparentImage.getImageData();
imageData.transparentPixel = imageData.getPixel(0, 0);
transparentImage.dispose();
// Create an image with the transparent data
final Image processedImage = new Image(Display.getCurrent(),
imageData);
// Get the image to draw onto the transparent image
final Image overlayImage = new Image(display, "overlay_image.png");
final GC imageGC = new GC(processedImage);
imageGC.setAntialias(SWT.ON);
imageGC.drawImage(overlayImage, 0, 0);
imageGC.dispose();
// Create the components and add the image
final ToolBar toolBar = new ToolBar(shell, SWT.FLAT | SWT.BORDER);
final ToolItem item = new ToolItem(toolBar, SWT.NONE);
item.setImage(processedImage);
toolBar.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
overlayImage.dispose();
display.dispose();
The problem is with the image you used, it has a transparent color white, so if you want to use that image, or you change transparent color manipulating the image with a program (GIMP?), or you can give the same transparent color to both the images, so first take the transparent color from the image "overlay_image.png" at position (0,0) and only alter set the same transparent color for the second (transparent) image. this is the working code with your image:
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
public class TestTransparency {
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setSize(285,305);
final Image overlayImage = new Image(display, "overlay_image.png");
final ImageData imageDataOverlay = overlayImage.getImageData();
imageDataOverlay.transparentPixel = imageDataOverlay.transparentPixel;
// Create a transparent image
final Image transparentImage = new Image(display, 800, 600);
final ImageData imageData = transparentImage.getImageData();
imageData.transparentPixel = imageDataOverlay.transparentPixel;
transparentImage.dispose();
final Image processedImage = new Image(Display.getCurrent(),
imageData);
final Image overlayImage2 = new Image(Display.getCurrent(),
imageDataOverlay);
final GC imageGC = new GC(processedImage);
imageGC.setAntialias(SWT.ON);
imageGC.drawImage(overlayImage2, 0, 0);
imageGC.dispose();
// Create the components and add the image
final ToolBar toolBar = new ToolBar(shell, SWT.FLAT | SWT.BORDER);
toolBar.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
final ToolItem item = new ToolItem(toolBar, SWT.NONE);
item.setImage(processedImage);
toolBar.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
overlayImage.dispose();
display.dispose();
}
}
Please note that, using GIMP manipulating your image:
or using a good transparent image like this: http://www.stickpng.com/img/icons-logos-emojis/tech-companies/youtube-play-logo your code works fine!
Related
I have made a Board class, where I import an image using ImageIcon and, instead of making a picture with the specified resolution, I want it to be full screen for any type of monitor.
public Board() {
p = new Dude();
addKeyListener(new AL());
setFocusable(true);
ImageIcon i = new ImageIcon("C:/test.jpg");
img = i.getImage();
time = new Timer(5, this);
time.start();
}
I've used this code before:
public class MainMenu2 {
MainMenu2() throws IOException{
JFrame Main_Menu = new JFrame("Main Menu");
Main_Menu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
final int widthScreen = screenSize.width;
final int heightScreen = screenSize.height;
BufferedImage backgroundImage = ImageIO.read(new File("P://My Pictures//background1.jpg"));
JLabel background = new JLabel(new ImageIcon(backgroundImage));
Image scaleBackground = backgroundImage.getScaledInstance(widthScreen, heightScreen, Image.SCALE_SMOOTH);
ImageIcon imageIcon = new ImageIcon(scaleBackground);
Main_Menu.setContentPane(new JLabel(imageIcon));
which uses scale smooth, which sets the image to the screen width and height, but I don't know how to apply it to my current code. The difference between both is that, Board class extends JPanel, and MainMenu2 is just a normal class, where a JFrame is created, etc. Please help! Thank you.
At the most basic level, it might look some like this...
ImageIcon i = ImageIO.read(new File("C:/test.jpg"));
Image scaleBackground = backgroundImage.getScaledInstance(widthScreen, heightScreen, Image.SCALE_SMOOTH);
img = scaleBackground.getImage();
Now, problems - the size of the component isn't likely to match he size of the screen.
As a preference, I might be tempted to do something like Scale the ImageIcon automatically to label size
You should also read The Perils of Image.getScaledInstance()
I have a BMP in a bytearray. I would like to display the BMP in an Eclipse Plugin using SWT.
If I want to display the BMP using swing - it can be done as follows:
BufferedImage bufferedImage = null;
try {
bufferedImage = ImageIO.read(new ByteArrayInputStream(getLocalByteArray()));
} catch (IOException ex) {
}
JLabel jLabel = new JLabel(new ImageIcon(bufferedImage));
JPanel jPanel = new JPanel();
jPanel.add(jLabel);
this.add(jPanel);
Update:
The BMP will be represented as a byte array. This is pre requisite of this.
How do I do this in an Eclipse Plugin using SWT? Note I am using a Perspective.
An SWT Image can directly be created from an input stream. Several data formats are supported, including Windows format BMPs.
For example:
Image image = new Image( display, new ByteArrayInputStream( ... ) );
The resulting image can then be set on a Label or used elsewhere.
You can simply specify the file in the Image constructor and then set it to a Label.
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
Label label = new Label(shell, SWT.NONE);
Image image = new Image(display, "image.bmp");
label.setImage(image);
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
{
display.sleep();
}
}
display.dispose();
image.dispose();
}
Remember that you have to dispose() of the image yourself to not create a memory leak.
OK - I figured it out. As the code is short I've included the context:
public void createPartControl(Composite parent) {
try {
BufferedInputStream inputStream = new BufferedInputStream(new ByteArrayInputStream(getLocalByteArray()));
ImageData imageData = new ImageData(inputStream);
Image image = ImageDescriptor.createFromImageData(imageData).createImage();
// Create the canvas for drawing
Canvas canvas = new Canvas( parent, SWT.NONE);
canvas.addPaintListener( new PaintListener() {
public void paintControl(PaintEvent e) {
GC gc = e.gc;
gc.drawImage( image,10,10);
}
});
I try to print a swt TreeViewer to png file. With:
Tree tree = treeViewer.getTree();
Image image = new Image(display, tree.getSize().x, tree.getParent().getSize().y);
GC gc = new GC(image);
System.out.println(new File(pathToSave).getAbsolutePath());
tree.print(gc);
ImageLoader loader = new ImageLoader();
loader.data = new ImageData[] { image.getImageData() };
loader.save(pathToSave, SWT.IMAGE_PNG);
gc.dispose();
image.dispose();
the png contains only the visible part of the tree. The tree has a scrollbar because it contains more elements than fit on the form.
I would like to print the tree with all elements visible and without scrollbar. Any ideas?
On swing components i could use .paintall().. swt components don't seem to know that.
First, the size of the image should have the size the tree would have without scrolls, and not the current size. For that you should use computeSize(SWT.DEFAULT, SWT.DEFAULT, true). Then you should resize the tree that size, print, and then resize it back. Since you don't want users to notice that, during this operation you should disabled draws with setRedraw(false).
Here is a full snippet that does all this:
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
Composite composite = new Composite(shell, SWT.NONE);
composite.setLayout(new FillLayout());
final Tree tree = new Tree(composite, SWT.NONE);
for (int i = 0; i < 100; i++) {
final TreeItem treeItem = new TreeItem(tree, SWT.NONE);
treeItem.setText(String.format("item %d long name", i));
}
tree.addListener(SWT.DefaultSelection, new Listener() {
#Override
public void handleEvent(Event event) {
tree.getParent().setRedraw(false);
final Point originalSize = tree.getSize();
final Point size = tree.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
final Image image = new Image(display, size.x, size.y);
final GC gc = new GC(image);
tree.setSize(size);
tree.print(gc);
tree.setSize(originalSize);
final ImageLoader loader = new ImageLoader();
loader.data = new ImageData[]{image.getImageData()};
final String pathToSave = "out.png";
System.out.println(new File(pathToSave).getAbsolutePath());
loader.save(pathToSave, SWT.IMAGE_PNG);
gc.dispose();
image.dispose();
tree.getParent().setRedraw(true);
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
Press enter to save the file.
I want to re-size my ImageIcon to fit my jLabel. Using the answer from this post Scale the ImageIcon automatically to label size I am using
public jfrmHome() {
initComponents();
this.setLocationRelativeTo(null);
ImageIcon iconimage;
iconimage = new ImageIcon(getClass().getResource("/org/me/musiconweb/resources/Music-icon.png"));
BufferedImage bi = new BufferedImage(iconimage.getIconWidth(), iconimage.getIconHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
iconimage.paintIcon(null, g, 0,0);
g.dispose();
BufferedImage resizedimage=resize(bi,jlblPicture.getWidth(), jlblPicture.getHeight());
ImageIcon resizedicon=new ImageIcon(resizedimage);
jlblPicture.setIcon(resizedicon);
}
This re-sizes the Image but i have a little problem. The background of the image becomes black instead of white that it was
This
turns to
Please what am i doing wrong?
That image has transparency. So change BufferedImage.TYPE_INT_RGB to BufferedImage.TYPE_INT_ARGB
It is not obvious at SO on a white BG, but try this SSCCE & it becomes more clear..
import java.net.URL;
import javax.swing.*;
class ShowImage {
public static void main(String[] args) throws Exception {
final URL url = new URL("http://i.stack.imgur.com/1yeUy.png");
Runnable r = new Runnable() {
#Override
public void run() {
JLabel l = new JLabel(new ImageIcon(url));
JOptionPane.showMessageDialog(null, l);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency
SwingUtilities.invokeLater(r);
}
}
Your image has a transparent background. Therefore it shows as black when drawn on a newly created opaque image. Use
g.setColor(Color.WHITE);
g.fillRect(0, 0, jlblPicture.getWidth(), jlblPicture.getHeight());
if you want a white background. For transparent background, draw on TYPE_INT_ARGB image instead.
Try out these codes
ImageIcon icon1 = new
ImageIcon(getClass().getResource("\\image\\"+f1.getName()));
BufferedImage bi = new
BufferedImage(icon1.getIconWidth(),icon1.getIconHeight()
, BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
icon1.paintIcon(null, g, 0,0);
g.dispose();`
//image resizing code...............>
ImageIcon resizedicon=new ImageIcon(bi.getScaledInstance(imglbl.getWidth(),
imglbl.getHeight(),1 ));
imglbl.setBackground(new java.awt.Color(255, 255, 255));
imglbl.setIcon(resizedicon);
I'm trying to use a Canvas to display an animated gif. I have the animation working, but the canvas is too small to see the entire image, and I cannot get it to resize.
I can't even get it to be the right size for the first frame, so the animation/threading code is being omitted. My code looks like:
Composite comp = new Composite(parent, SWT.None);
comp.setLayout(new GridLayout(1, false));
final ImageLoader loader = new ImageLoader();
loader.load(getClass().getClassLoader().getResourceAsStream("MYFILE.gif"));
final Canvas canvas = new Canvas(comp, SWT.None);
final Image image = new Image(Display.getCurrent(), loader.data[0]);
canvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
e.gc.drawImage(image, 0, 0);
}
});
The canvas area ends up being a tiny box of around 30x30, regardless of how big MYFILE.gif is. What the hell?
Anything I try to use to set the canvas size (setSize, setBounds, etc) does nothing.
Try using setPreferredSize. The layout manager will call setSize and/or setBounds and clobber the values you have set, but it will try to respect preferred size if it can. You can also use setMaximumSize and setMinimumSize to control how the canvas will resize if the enclosing component is resized.
EDIT: For SWT you could try this:
GridData gridData = new GridData();
gridData.widthHint = imageWidth;
gridData.heightHint = imageHeight;
canvas.setLayoutData(gridData);
I'm not an SWT expert, but the SWT documentation seems helpful.