我们知道,在MIDP1.0中,除非我们利用特定厂商的API(比如Nokia),我们是没法对图片的像素进行操作的,但是在MIDP2.0中,Image和Graphics的功能都大大增强了。比如,我们可以获取Image的所有像素值,然后利用程序来修改这些像素(比如说ARGB各自的值),最后再把修改后的像素图绘制出来。通过直接操作图片像素,我们就获得了一种很强大的能力,用编程的方式实现出很多有趣的效果来,而不用额外制作新图片。比如说透明度渐变,颜色反转等。下面就是2个例子,分别实现透明度渐变和颜色反转的功能。 例题一: 透明度渐变效果的实现 给定一张图片,假如我们想实现这么一种效果:图片由全透明状态逐渐清楚,最后达到正常状态。要实现这一个过程,我们首先要获取该图片的所有像素值,逐步让这些像素的alpha值从0转变到正常,每改变图片的所有像素值一次,我们就请求刷屏一次,把最新的像素图画出来,这样我们就能实现透明度渐变的效果了。代码实现如下: import Java.io.IOException; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.Image; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; /** * * @author Jagie * */ public class ShadowMIDlet extends MIDlet { Canvas c = new ShadowCanvas(); public ShadowMIDlet() { } protected void startApp() throws MIDletStateChangeException { Display.getDisplay(this).setCurrent(c); } protected void pauseApp() { // TODO Auto-generated method stub } protected void destroyApp(boolean arg0) throws MIDletStateChangeException { // TODO Auto-generated method stub } } /** * * @author Jagie * */ class ShadowCanvas extends Canvas implements Runnable { int w, h; // 原始图片 Image srcImage; // 原始图片的像素数组 int[] srcRgbImage; // 渐变图片的像素数组 int[] shadowRgbImage; int imgWidth, imgHeight; int count; public ShadowCanvas() { w = this.getWidth(); h = this.getHeight(); try { srcImage = Image.createImage("/av.png"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } imgWidth = srcImage.getWidth(); imgHeight = srcImage.getHeight(); // 制造原始图片的像素数组,用一个int来代表每一个像素,按位表示方式是:0xAARRGGBB srcRgbImage = new int[imgWidth * imgHeight]; // 获取原始图片的所有像素,参见MIDP APPI文档 srcImage.getRGB(srcRgbImage, 0, imgWidth, 0, 0, imgWidth, imgHeight); shadowRgbImage = new int[srcRgbImage.length]; System.arraycopy(srcRgbImage, 0, shadowRgbImage, 0, shadowRgbImage.length); // 渐变图片的所有像素已开始都是全透明的 for (int i = 0; i < shadowRgbImage.length; i++) { shadowRgbImage[i] &= 0x00ffffff; } new Thread(this).start(); } public void paint(Graphics g) { g.setColor(0, 0, 0); g.fillRect(0, 0, w, h); // 绘制渐变图片 g.drawRGB(shadowRgbImage, 0, imgWidth, (w - imgWidth) / 2, (h - imgHeight) / 2, imgWidth, imgHeight, true); g.setColor(0, 255, 0); g.drawString("count=" + count, w / 2, 30, Graphics.HCENTER Graphics.TOP); } public void run() { while (true) { boolean changed = false; // 改变渐变图片的每一个像素 for (int i = 0; i < shadowRgbImage.length; i++) { // 获取渐变图片的某一像素的alpha值 int alpha = (shadowRgbImage[i] & 0xff000000) >>> 24; // 原始图片的对应像素的alpha值 int oldAlpha = (srcRgbImage[i] & 0xff000000) >>> 24; if (alpha < oldAlpha) { // alpha值++ shadowRgbImage[i] = ((alpha + 1) << 24) (shadowRgbImage[i] & 0x00ffffff); changed = true; } } try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } count++; repaint(); // 当所有像素的alpha值都达到原始值后,线程运行结束 if (!changed) { System.out.println("over"); break; } } } } 透明度渐变效果如下:     例题二:颜色反转 在手机游戏中,我们经常会碰上这样一种情况,比如我方飞机和敌方飞机外观是完全一样的,唯一的区别就是颜色不同,比如说敌方飞机是红色的,而我方飞机是绿色的。在MIDP1.0中,我们就只好制作2张图片来表示2种飞机,自然,这样会造成jar空间的极大浪费。但是在MIDP2.0中,通过对图片直接进行像素操作,反转RGB中的一个值,我们只需要一张图片就够了,样例代码如下: ColorMIDlet.java import java.io.IOException; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Display; import javax.microedition.lcdui.Graphics; import javax.microedition.lcdui.Image; import javax.microedition.midlet.MIDlet; import javax.microedition.midlet.MIDletStateChangeException; /** * * @author Jagie * */ public class ColorMIDlet extends MIDlet { Canvas c = new ColorCanvas(); public ColorMIDlet() { super(); // TODO Auto-generated constrUCtor stub } protected void startApp() throws MIDletStateChangeException { Display.getDisplay(this).setCurrent(c); } protected void pauseApp() { // TODO Auto-generated method stub } protected void destroyApp(boolean arg0) throws MIDletStateChangeException { // TODO Auto-generated method stub } } /** * * @author Jagie * */ class ColorCanvas extends Canvas { Image srcImage; int[] targetImage1; int[] targetImage2; public ColorCanvas() { try { srcImage = Image.createImage("/av.png"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } targetImage1 = GraphicsUtil.flipImageColor(srcImage, GraphicsUtil.SHIFT_RED_TO_BLUE); targetImage2 = GraphicsUtil.flipImageColor(srcImage, GraphicsUtil.SHIFT_RED_TO_GREEN); } public void paint(Graphics g) { g.setColor(0, 0, 0); g.fillRect(0, 0, this.getWidth(), this.getHeight()); g.setColor(0x00ff00); g.drawString("origin:", getWidth() / 2, 0, Graphics.TOP Graphics.HCENTER); g.drawImage(srcImage, 30, 20, Graphics.LEFT Graphics.TOP); g.drawString("SHIFT_RED_TO_BLUE:", getWidth() / 2, srcImage.getHeight() + 20, Graphics.TOP Graphics.HCENTER); g.drawRGB(targetImage1, 0, srcImage.getWidth(), 30, srcImage .getHeight() + 40, srcImage.getWidth(), srcImage.getHeight(), true); g.drawString("SHIFT_RED_TO_GREEN:", getWidth() / 2, srcImage .getHeight() * 2 + 40, Graphics.TOP Graphics.HCENTER); g.drawRGB(targetImage2, 0, srcImage.getWidth(), 30, srcImage .getHeight() * 2 + 60, srcImage.getWidth(), srcImage .getHeight(), true); } } GraphicsUtil.java import javax.microedition.lcdui.Image; /** * * @author Jagie *
|