Adding partial transparency to an image
Say we have an Image or BufferedImage loaded from a JPEG or GIF file. Basically the image consists of foreground chart and a plain background. The background is not important for that chart and we'd like to make the background transparent on our fancy(?) custom component.
What should be the steps of the process to get that kind of partially transparent Image or BufferedImage from original ones? I think I theoretically know that: get RGB array of the image -> convert it to RGBA array -> modify some of 'A' values -> reconstruct Java image from the RGBA array. However, for concrete steps using Java2D APIs, I am totally lost.
Thanks in advance.
[679 byte] By [
hiwaa] at [2007-10-3 9:51:56]

I have found a solution. It is so simple that it is anticlimatic for me!
import javax.swing.*;
import javax.imageio.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
public class Transparentize{
static final int th = 200; // whity threshold R/G/B value
// could be 240, 254, whatever
JFrame frame;
Container con;
RPanel rp;
BufferedImage scr, scrt;
int scrw; // image width
public Transparentize(){
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
con = frame.getContentPane();
try{
scr = ImageIO.read(new File("youngdad.jpg"));
}
catch (IOException e){
e.printStackTrace();
}
scrt = tp(scr); // get transparentized image
rp = new RPanel(scr.getWidth(), scr.getHeight());
con.add(rp, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
/* get transparentized image */
BufferedImage tp(BufferedImage orig){
int w = orig.getWidth(null);
int h = orig.getHeight(null);
scrw = w;
int[] rgbs = new int[w * h];
orig.getRGB(0, 0, w, h, rgbs, 0, w);
for (int i = 0; i < rgbs.length; ++i){
int p = rgbs[i];
int r = (p >>> 16) & 0x000000ff;
int g = (p >>> 8) & 0x000000ff;
int b = p & 0x000000ff;
if (r > th && g > th && b > th){
p &= 0x00ffffff;
rgbs[i] = p;
}
}
// if you use 'orig' here, you fail in adding transparency to the image
// you should make a new BufferedImage with a proper image-type
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
bi.setRGB(0, 0, w, h, rgbs, 0, w);
return bi;
}
class RPanel extends JPanel{
public RPanel(int imgw, int imgh){
setPreferredSize(new Dimension(imgw * 2, imgh));
setBackground(new Color(255, 255, 150));
}
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D)g;
super.paintComponent(g);
g2.drawImage(scr, 0, 0, this); // original image
g2.drawImage(scrt, scrw, 0, this); // transparent image
}
}
public static void main(String[] args){
new Transparentize();
}
}
hiwaa at 2007-7-15 5:09:21 >

Another option:
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class XPImage {
public static void main(String[] args) {
BufferedImage image = getImage();
JPanel panel = new JPanel();
panel.setBackground(Color.pink);
panel.add(new JLabel(new ImageIcon(image)));
JOptionPane.showMessageDialog(null, panel, "",
JOptionPane.PLAIN_MESSAGE);
}
private static BufferedImage getImage() {
int w = 100, h = 100, PAD = 10;
int type = BufferedImage.TYPE_INT_ARGB;
BufferedImage image = new BufferedImage(w, h, type);
Graphics2D g2 = image.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(new Color(0,0,0,0));
g2.fillRect(0,0,w,h);
g2.setPaint(Color.black);
g2.draw(new Line2D.Double(10, h-PAD, w-PAD, h-PAD));
g2.draw(new Line2D.Double(w/2, PAD, w/2, h-PAD));
g2.setPaint(Color.blue);
g2.draw(new QuadCurve2D.Double(PAD,PAD,w/2,h*27/16,w-PAD,PAD));
g2.dispose();
return image;
}
}
The three places in which you can select certain parts of the image to modify/avoid are:
orig.getRGB(0, 0, w, h, rgbs, 0, w);
for (int i = 0; i < rgbs.length; ++i){
...
bi.setRGB(0, 0, w, h, rgbs, 0, w);
The [x, y, width, height] rectangular section arguments allow you to specifically select the areas you can search and modify rgb values.