在MIDP2.0中新增了Alpha混合特性,我们可以使用这个特性来对图片进行一些处理。本文将结合一个具体的例子说明一下Alpha混合。
首先我们参考一下MIDP2.0 java doc中关于Alpha Processing的说明:在可修改图片中的每个像素都必须是完全模糊的,在不可修改图片中的每个像素可以是完全透明的,完全模糊的或者介于两者之间的,也就是半透明。系统的实现必须要支持存储,处理和绘画全透明和全模糊的像素,当从数据源创建一个图片的时候(数据源可能来自PNG图片或者一个字节数组),原图片中的不透明像素和透明像素应该在新图片中保持不变。对半透明像素的处理就和系统的实现相关了,要看Alpha混合是否被支持。如果系统实现支持Alpha混合,那么原图中的半透明像素在新图片中依然保持半透明,当然数值可能会根据系统支持的半透明的级别发生一些变化。如果系统实现不支持Alpha混合的话,任何半透明的像素在新图片中应该使用全透明的像素来替换。
接下来我们熟悉几个方法,正是他们的引入增加了Alpha混合特性。
public static Image createRGBImage(int[] rgb,
int width,
int height,
boolean processAlpha)
上面的方法来自于Image类,它允许我们从rgb数组创建一个不可修改的图片,数组中的数值形式为0xAARRGGBB,其中AA代表透明度,后面的代表颜色值。具体方法的介绍请参考MIDP Java doc。
public void getRGB(int[] rgbData,
int offset,
int scanlength,
int x,
int y,
int width,
int height)
下面的方法同样来自于Image类,这个方法可以让我们从图片的指定区域读取ARGB像素值,并存储到rgbData数组中。具体方法的介绍请参考MIDP Java doc。
public void drawRGB(int[] rgbData,
int offset,
int scanlength,
int x,
int y,
int width,
int height,
boolean processAlpha)
上面的方法是Graphics中新增的,使用这个方法我们可以在指定的区域绘画一些列和设备无关的(RGB+透明)值,rgbData中的元素形式为0xAARRGGBB。其中AA代表透明度,00代表全透明 ,FF代表完全模糊。具体方法的介绍请参考MIDP Java doc。
下面我们编写一个例子来介绍如何使用Alpha混合,通过实例形象的说明这一效果。我们打开一个图片,然后在图像的上面进行半透明的掩饰,制造出下面的效果,参考下图:
制作这样的效果并不难,我们只需要调用上面的drawRGB()方法即可,为了更好的掩饰这一效果。我们启动一个新的线程来不断的更新mask区域的高度,然后重新绘制屏幕(这里没有考虑优化)。代码如下:
public void paint(Graphics g) {
g.setColor(255, 255, 255);
g.fillRect(0, 0, getWidth(), getHeight());//paint Canvas background white
g.drawImage(backgroundImage, x, y, Graphics.TOP|Graphics.LEFT);
//render the semi-transparent mask
if (maskHeight != 0){
g.drawRGB(maskArray, 0, imageWidth, x, y, imageWidth, maskHeight, true);
}
}
public void run() {
for(int i = 1; i <= imageHeight; i++) {
maskHeight = i;
repaint();
try {
Thread.sleep(50);
}catch(InterruptedException ie) {}
}
}
下面给出这个应用程序的源代码,代码出自Programming Java 2 Micro Edition on Symbian OS一书。笔者只是借花献佛,因为最近论坛一直有人问Alpha相关的问题。
/*
* Copyright 2003, 2004 Symbian Ltd.
* For License terms see http://www.symbian.com/developer/techlib/codelicense.html
*/
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class AlphaBlending extends MIDlet implements CommandListener {
private Display display;
private Form form;
private Command exitCommand;
private Command startCommand;
private Command backCommand;
private AlphaCanvas alphaCanvas;
private static final String IMAGE_NAME = "/image.png";
public AlphaBlending() {
display = Display.getDisplay(this);
exitCommand = new Command("Exit", Command.EXIT, 2);
startCommand = new Command("Start", Command.SCREEN, 1);
backCommand = new Command("Back", Command.BACK, 1);
alphaCanvas = new AlphaCanvas(IMAGE_NAME);
form = new Form("Alpha Blending Demo");
form.append(new StringItem(null, "Press ‘Start’ to run demo."));
form.addCommand(exitCommand);
form.addCommand(startCommand);
form.setCommandListener(this);
}
public void startApp() {
display.setCurrent(form);
}
public void pauseApp() {}
public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable d) {
if (c == exitCommand) {
destroyApp(false);
notifyDestroyed();
}else if (c == startCommand) {
display.setCurrent(alphaCanvas);
alphaCanvas.addCommand(backCommand);
alphaCanvas.setCommandListener(this);
Thread t = new Thread(alphaCanvas);
t.start();
}else if (c == backCommand) {
display.setCurrent(form);
}
}
}
/*
* Copyright 2003, 2004 Symbian Ltd.
* For License terms see http://www.symbian.com/developer/techlib/codelicense.html
*/
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.io.*;
public class AlphaCanvas extends Canvas implements Runnable {
private Image backgroundImage;
private int[] maskArray;
private int imageWidth;
private int imageHeight;
private int x;
private int y;
private int maskHeight = 0;
public AlphaCanvas(String imageName) {
//create the background image
try {
backgroundImage = Image.createImage(imageName);
}catch(IOException ioe) {
ioe.printStackTrace() ;
}
imageWidth = backgroundImage.getWidth();
imageHeight = backgroundImage.getHeight();
//create a semi-transparent red mask to cover the background image
maskArray = new int[imageWidth*imageHeight];
for (int i = 0; i < imageWidth*imageHeight; i++) {
maskArray[i] = 0x11FFF000;//alpha coefficient set to 0.3
}
x = (getWidth() – imageWidth)/2;
y = (getHeight() – imageHeight)/2;
}
public void paint(Graphics g) {
g.setColor(255, 255, 255);
g.fillRect(0, 0, getWidth(), getHeight());//paint Canvas background white
g.drawImage(backgroundImage, x, y, Graphics.TOP|Graphics.LEFT);
//render the semi-transparent mask
if (maskHeight != 0){
g.drawRGB(maskArray, 0, imageWidth, x, y, imageWidth, maskHeight, true);
}
}
public void run() {
for(int i = 1; i <= imageHeight; i++) {
maskHeight = i;
repaint();
try {
Thread.sleep(50);
}catch(InterruptedException ie) {}
}
}
}