兩種修改png圖片顏色方法的對比
在手機游戲開發中,為了節省資源,我們常常修改png圖片以實現一張圖片多種顯示效果。有兩種辦法可以實現這個功能:
第一種是裝載png圖片,使用getRGB()取得取得圖片的RGB顏色數據,然后修改RGB顏色數據,再用Image的靜態方法createRGBImage()將修改后的RGB顏色數據生成新的png圖片。示例代碼:testImage為測試的Image對象,imgW,imgH為其寬和高
// 取得圖片的RGB數據--這個數組是比較大的,因此修改RGB數據生成新的圖片效率很低
rgbData = new int[imgW * imgH];
testImage.getRGB(rgbData,0,imgW,0,0,imgW,imgH);
// 修改RGB數據并生成新的圖片
rgbImage = Image.createRGBImage(changeRGBData(rgbData),imgW,imgH,true);
第二中方法是取得png圖片的二進制數據,修改其中的調色板域(PLTE chunk)數據,再使用
Image的靜態對象createImage(byte[] imageData,int imageOffset,int imageLength)將修改后的二進制數據生成新的png對象。示例代碼:查看代碼中的getPLTEModifidImage()函數。
如果對png的數據格式組成不熟悉,可以查閱:http://www.w3.org/TR/PNG/
或者(不錯的中文介紹): http://www.ismyway.com/png/png-struct1.htm
通常,圖片的RGB顏色數據是比較大的,而調色板數據遠比RGB顏色數據要少的多,修改RGB顏色數據效率要高的多。下面我使用一張大小為52*28的png圖片作為測試圖片,從以下測試中打印的數據就可看出(1456對比144):
Load file Gold total data is 1084 ――――――――圖片的二進制字節數據個數
--------RGB data length is 1456―――――――――RGB顏色字節數據個數
--------The number of PLTE chunks is 48―――調色板數據塊個數(實際字節數據為48*3)
效果圖:
附測試的源代碼:
//-----------------------------------------------------Code--START------------------------------------------------
/**
* Dicription?????? : Create png image by modifying PLTE chunk.
* Author?????????? : 飄飄白云
* Created date???? : 2006-07-03
* Modified history :
*/
import java.io.DataInputStream;
import java.io.IOException;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
public class CreatePNG extends MIDlet
{
??? GameCanvas canvas;
??? Display display;
????????????? public CreatePNG()
????????????? {
??????????????????????????? super();
??????????????????????????? // TODO Auto-generated constructor stub
??????????????????????????? try {
??????????? display = Display.getDisplay(this);
??????????? canvas = new GameCanvas(this);
??????? } catch (Exception e) {}
????????????? }
????????????? protected void startApp() throws MIDletStateChangeException
????????????? {
??????????????????????????? // TODO Auto-generated method stub
??????????????????????????? if( canvas != null ){
????????????????????????????????????????? display.setCurrent(canvas);
????????????????????????????????????????? canvas.start();
??????????????????????????? }
????????????? }
????????????? protected void pauseApp()
????????????? {
??????????????????????????? // TODO Auto-generated method stub
??????????????????????????? canvas.beExit = true;
????????????? }
????????????? protected void destroyApp( boolean arg0) throws MIDletStateChangeException
????????????? {
??????????????????????????? // TODO Auto-generated method stub
????????????? }
}
class GameCanvas extends Canvas implements Runnable
{
????????????? CreatePNG app;
????????????? Thread mainThread;
?????????????
????????????? Image??????????????????????????????????????????????????????????? offImage????????????? = null;
????????????? public Graphics?????????????????????????????? g??????????????????????????????????????? = null;
?????????????
????????????? public boolean beExit = false;
????????????? long sleepTime = 30;
?????????????
????????????? int scrW;
????????????? int scrH;
????????????? Font font;
????????????? int fontH;
????????????? int fontW;
?????????????
????????????? //-------------------------------------
????????????? int gameMode;
????????????? int subMode;
?????????????
????????????? static final int smInit = 0;
????????????? static final int smProc = 1;
????????????? static final int smEnd = 2;
?????????????
????????????? static final int gmStart = 0;
????????????? static final int gmProcPNGData = 1;
?????????????
????????????? //--------------------------------------
????????????? Image testImage = null;
????????????? Image rgbImage = null;
????????????? Image plteImage = null;
????????????? int imgW;
????????????? int imgH;
????????????? int[] rgbData = null;
????????????? byte[] imgData = null;
????????????? String testFile = "Gold";
?????????????
????????????? public GameCanvas(MIDlet midlet)
????????????? {
??????????????????????????? app = (CreatePNG)midlet;
????????????? }
????????????? public void start()
????????????? {
??????????????????????????? changeGameMode(gmStart);
???????????????????????????
??????????????????????????? mainThread = new Thread(this);
??????????????????????????? mainThread.start();
????????????? }
?????????????
????????????? public void changeGameMode(int gm)
????????????? {
??????????????????????????? gameMode = gm;
??????????????????????????? subMode = smInit;
????????????? }
?????????????
????????????? protected void paint( Graphics _g)
????????????? {
??????????????????????????? // TODO Auto-generated method stub
??????????????????????????? if( offImage != null)
????????????????????????????????????????? _g.drawImage(offImage, 0, 0, 0);
????????????? }
????????????? public void run()
????????????? {
??????????????????????????? // TODO Auto-generated method stub
??????????????????????????? gameInit();
??????????????????????????? while( !beExit )
??????????????????????????? {
????????????????????????????????????????? gameMain();
????????????????????????????????????????? gameDraw();
????????????????????????????????????????? repaint();
????????????????????????????????????????? gcWait(sleepTime);
??????????????????????????? }
???????????????????????????
??????????????????????????? if( beExit ) {
????????????????????????????????????????? try {
??????????????????????????????????????????????????????? app.destroyApp(true);
????????????????????????????????????????? }
????????????????????????????????????????? catch ( MIDletStateChangeException e ) {
??????????????????????????????????????????????????????? // TODO Auto-generated catch block
??????????????????????????????????????????????????????? e.printStackTrace();
????????????????????????????????????????? }
??????????????????????????? }
????????????? }
?????????????
????????????? void gcWait(long tm)
????????????? {
??????????????????????????? System.gc();
??????????????????????????? try {
????????????????????????????????????????? Thread.sleep(tm);
??????????????????????????? }
??????????????????????????? catch ( InterruptedException e ) {
????????????????????????????????????????? // TODO Auto-generated catch block
????????????????????????????????????????? e.printStackTrace();
??????????????????????????? }
????????????? }
?????????????
????????????? void println(String str)
????????????? {
??????????????????????????? System.out.println( str );
????????????? }
????????????? void print(String str)
????????????? {
??????????????????????????? System.out.print( str );
????????????? }
?????????????
????????????? void gameInit()
????????????? {
??????????????????????????? scrW = getWidth();
??????????????????????????? scrH = getHeight();
??????????????????????????? if(g == null || offImage == null) {
????????????????????????????????????????? offImage = Image.createImage(scrW, scrH);
??????????????????????????????? g = offImage.getGraphics();
????????????????????????????????????????? g.translate(0,0);
??????????????????????????? }
??????????????????????????? repaint();
???????????????????????????
??????????????????????????? font?????? = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN,Font.SIZE_MEDIUM);
??????????????????????????? g.setFont(font);
?????????????????
????????????????? changeGameMode( gmStart );
????????????? }
?????????????
????????????? /**
?????????????? * 裝載圖片
?????????????? * @param fileName 圖片名稱
?????????????? * @return image 對象
?????????????? */
????????????? Image loadImage( String fileName)
????????????? {
??????????????????????????? Image tmp = null;
??????????????????????????? try {
????????????????????????????????????????? tmp = Image.createImage("/" + fileName + ".png");
??????????????????????????? }
??????????????????????????? catch ( IOException e ) {
????????????????????????????????????????? println("[Error] >> loadImage(): " + fileName + " Failed!");
????????????????????????????????????????? e.printStackTrace();
??????????????????????????? }
??????????????????????????? if( tmp == null ) {
????????????????????????????????????????? println("[Error] >> loadImage(): " + fileName + " Failed!");
??????????????????????????? }
??????????????????????????? return tmp;
????????????? }
?????????????
????????????? /**
?????????????? * 讀取文件的二進制數據
?????????????? * @param fileName 文件名
?????????????? * @return 文件二進制數據的字節數組.
?????????????? */
????????????? byte[] loadFile(String fileName)
????????????? {
??????????????????????????? DataInputStream isr = null;
??????????????????????????? byte[] bData;
??????????????????????????? try {
????????????????????????????????????????? try {
??????????????????????????????????????????????????????? isr = new DataInputStream(getClass().getResourceAsStream("/" + fileName + ".png"));
????????????????????????????????????????? }
????????????????????????????????????????? catch (Exception e) {
????????????????????????????????????????? }
?????????????????????????????????????????
????????????????????????????????????????? int res_size = 0;
????????????????????????????????????????? while (isr.read() != -1)
??????????????????????????????????????????????????????? res_size++;
????????????????????????????????????????? if (isr.markSupported())
??????????????????????????????????????????????????????? isr.reset();
????????????????????????????????????????? else {
??????????????????????????????????????????????????????? isr.close();
??????????????????????????????????????????????????????? isr = new DataInputStream(getClass().getResourceAsStream("/" + fileName + ".png"));
????????????????????????????????????????? }
????????????????????????????????????????? bData = new byte[res_size];
????????????????????????????????????????? int read_bytes = isr.read(bData, 0, res_size);
????????????????????????????????????????? isr.close();
????????????????????????????????????????? System.gc();
????????????????????????????????????????? println("Load file " + fileName + " total data is " + read_bytes);
????????????????????????????????????????? return bData;
??????????????????????????? }
??????????????????????????? catch (Exception e) {
????????????????????????????????????????? println("Error>>loadFile " + fileName);
????????????????????????????????????????? return null;
??????????????????????????? }
????????????? }
?????????????
?????????????
????????????? void gameMain()
????????????? {
??????????????????????????? if( gameMode == gmStart )
??????????????????????????? {
????????????????????????????????????????? if( subMode == smInit )
????????????????????????????????????????? {
??????????????????????????????????????????????????????? // 裝載圖片
??????????????????????????????????????????????????????? testImage = loadImage(testFile);
??????????????????????????????????????????????????????? imgW = testImage.getWidth();
??????????????????????????????????????????????????????? imgH = testImage.getHeight();
??????????????????????????????????????????????????????? subMode = smProc ;
????????????????????????????????????????? }
?????????????????????????????????????????
????????????????????????????????????????? else if( subMode == smProc )
????????????????????????????????????????? {
??????????????????????????????????????????????????????? // 取得圖片的RGB數據--這個數組是比較大的,因此修改RGB數據生成新的圖片效率很低
??????????????????????????????????????????????????????? rgbData = new int[imgW * imgH];
??????????????????????????????????????????????????????? testImage.getRGB(rgbData,0,imgW,0,0,imgW,imgH);
???????????????????????????????????????????????????????
??????????????????????????????????????????????????????? println("--------RGB data length is - " + rgbData.length);
??????????????????????????????????????????????????????? changeGameMode(gmProcPNGData);
????????????????????????????????????????? }
??????????????????????????? }
???????????????????????????
??????????????????????????? else if( gameMode == gmProcPNGData )
??????????????????????????? {
????????????????????????????????????????? if( subMode == smInit )
????????????????????????????????????????? {
??????????????????????????????????????????????????????? // 取得圖片的二進制數據
??????????????????????????????????????????????????????? imgData = loadFile(testFile);
??????????????????????????????????????????????????????? subMode = smProc ;
??????????????????????????????????????????????????????? println("----Start---All Image Data--length-" + imgData.length);
??????????????????????????????????????????????????????? for( int i = 0; i< imgData.length; i++ ){
????????????????????????????????????????????????????????????????????? if( i% 10 == 0 )
??????????????????????????????????????????????????????????????????????????????????? println("");
????????????????????????????????????????????????????????????????????? System.out.print(" " + imgData[i]);
??????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? println("\n----End---All Image Data--length-" + imgData.length);
??????????????????????????????????????????????????????? // 修改調色板數據,改變圖片顏色,這種方法修改的數據遠比修改RGB數據要少,效率高很多
??????????????????????????????????????????????????????? plteImage = getPLTEModifidImage(imgData,3);
????????????????????????????????????????? }
?????????????????????????????????????????
????????????????????????????????????????? else if( subMode == smProc )
????????????????????????????????????????? {????????????
??????????????????????????????????????????????????????? // 修改RGB數據生成新的圖片,非常低效
??????????????????????????????????????????????????????? rgbImage = Image.createRGBImage(changeRGBData(rgbData),imgW,imgH,true);
??????????????????????????????????????????????????????? subMode = smEnd;
????????????????????????????????????????? }
????????????????????????????????????????? else if( subMode == smEnd )
????????????????????????????????????????? {
????????????????????????????????????????? }
??????????????????????????? }
????????????? }
?????????????
????????????? void gameDraw()
????????????? {
??????????????????????????? if( gameMode == gmStart )
??????????????????????????? {
????????????????????????????????????????? if( subMode == smProc ){
??????????????????????????????????????????????????????? // 描繪原始圖片
??????????????????????????????????????????????????????? g.drawImage(testImage,20,20,0);
????????????????????????????????????????? }
??????????????????????????? }
??????????????????????????? else if( gameMode == gmProcPNGData )
??????????????????????????? {
????????????????????????????????????????? if( subMode == smProc ){
??????????????????????????????????????????????????????? // 描繪修改調試板數據生成的圖片
??????????????????????????????????????????????????????? g.drawImage(plteImage,20,80,0);
????????????????????????????????????????? }
????????????????????????????????????????? else if( subMode == smEnd ) {
??????????????????????????????????????????????????????? // 描繪修改RGB數據生成的圖片,也可以使用drawRGB()直接描繪RGB數據,不過要注意透明問題.
??????????????????????????????????????????????????????? g.drawImage(rgbImage,20,140,0);
????????????????????????????????????????? }
??????????????????????????? }
????????????? }
????????????? /**
?????????????? * 修改png圖片的調色板數據生成新的png圖片
?????????????? * @param imageSrc png圖片的二進制數據字節數組
?????????????? * @param type 修改策略
?????????????? * @return 新的png圖片
?????????????? */
????????????? public Image getPLTEModifidImage(byte[] imageSrc , int type)
????????????? {
??????????????????????????? if (imageSrc == null || imageSrc.length <= 1)
????????????????????????????????????????? return null;
??????????????????????????? if (crcTable == null)
????????????????????????????????????????? makeCrcTable();
??????????????????????????? // PLTE chunk數據域的類型標識
??????????????????????????? // see http://www.w3.org/TR/PNG/#11PLTE
??????????????????????????? String[] sPLTE = {"50", "4c", "54", "45"};
??????????????????????????? int i,j;
??????????????????????????? int pos = 0,startPos = 0;
??????????????????????????? byte[] data = imageSrc;
???????????????????????????
??????????????????????????? for (i = 0; i < data.length; i++)
??????????????????????????? {
??????????????????????? if (Integer.toHexString(data[i]).equals(sPLTE[0])
????????????????????????????????????????????????? && Integer.toHexString(data[i + 1]).equals(sPLTE[1])
????????????????????????????????????????????????? && Integer.toHexString(data[i + 2]).equals(sPLTE[2])
??????????????????? && Integer.toHexString(data[i + 3]).equals(sPLTE[3]))
??????????????????????? {
????????????????????????????????????? pos = i;
????????????????????????????????????? break;
??????????????????????? }
??????????????????????????? }
??????????????????????????? pos -= 4;
??????????????????????????? startPos = pos;
??????????????????????????? println("\n======================start Palette data process========================");
??????????????????????????? println("-------------Palette chunk start pos = " + pos);
??????????????????????????? // 取得PLTE chunk數據域的數據長度().
??????????????????????????? int imageNbColors = (
??????????????????????????????????????????????????????? ((data[pos] << 24) & 0xff000000)
??????????????????????????????????????????????????????? | ((data[pos + 1] << 16) & 0x00ff0000)
??????????????????????????????????????????????????????? | ((data[pos + 2] << 8 ) & 0x0000ff00)
??????????????????????????????????????????????????????? | ((data[pos + 3]????? ) & 0x000000ff));
??????????????????????????? // 計算的PLTE chunk數據個數(每個PLTE chunk數據由R,G,B三個字節數據組成)
??????????????????????????? imageNbColors = imageNbColors/3;
??????????????????????????? // 為整形的PLTE chunk data分配空間
??????????????????????????? int imageRGBColors[]??? = new int[ imageNbColors ];
?????
??????????????????????????? //12 = 數據長度(4個字節) + 類型標識(4個字節) + 校驗碼(4個字節)
?????????????????????????? for( i = pos,j = 0; i < pos + 12 + imageNbColors * 3 ; i++,j++ ){
????????????????????????????????????????? if( j >= 8 && (j -
%3 == 0 ) {
??????????????????????????????????????????????????????? println("");
????????????????????????????????????????? }
????????????????????????????????????????? System.out.print(" " + data[i]);
??????????????????????????? }
??????????????????????????
?????????????????????????? pos += 8;
?????????????????????????? println("\n--------The number of PLTE chunks is " + imageNbColors + "------------");
??
???????????
??????????????????????????? if (imageRGBColors == null)
????????????????????????????????????????? return null;
???????????????????????????
???????????????????????????? // 生成整形的PLTE chunk data
???????????????????????????? for( i = 0; i < imageNbColors; i++ )
???????????????????????????? {
?????????????????????????????????????????? imageRGBColors[i] = (
?????????????????????????????????????????????????????????????????????? (data[pos + 0] & 0x000000ff) << 16)
?????????????????????????????????????????????????????????????????????? | ((data[pos + 1] & 0x000000ff) <<
?????????????????????????????????????????????????????????????????????? | ((data[pos + 2] & 0x000000ff));
???????????????????????????????????????????????????????
?????????????????????????????????????????
????????????????????????????????????????? if( i % 10 == 0 && i != 0) {
??????????????????????????????????????????????????????? println("");
????????????????????????????????????????? }
????????????????????????????????????????? print(" " + imageRGBColors[i]);
????????????????????????????????????????? pos += 3;
??????????????????????????? }
???????????????????????????
??????????????????????????? // 修改 PLTE chunk data
??????????????????????????? switch (type)
??????????????????????????? {
????????????????????????????????????????? case 0:
??????????????????????????????????????????????????????? // don't modify
??????????????????????????????????????????????????????? break;
???????????????????????????????????????????????????????
????????????????????????????????????????? case 1: {
??????????????????????????????????????????????????????? int l,r,g,b;
??????????????????????????????????????????????????????? // gray
??????????????????????????????????????????????????????? for (j = 1; j < imageNbColors; j++) {
????????????????????????????????????????????????????????????????????? r = imageRGBColors[j];
????????????????????????????????????????????????????????????????????? g = (r & 0x00FF00) >> 8;
????????????????????????????????????????????????????????????????????? b = r & 0x0000FF;
????????????????????????????????????????????????????????????????????? r = (r & 0xFF0000) >> 16;
?????????????
????????????????????????????????????????????????????????????????????? l = (b + g * 6 + r * 3) / 16;
?????????????
????????????????????????????????????????????????????????????????????? imageRGBColors[j] = l << 16 | l << 8 | l;
??????????????????????????????????????????????????????? }
?????????????
??????????????????????????????????????????????????????? break;
????????????????????????????????????????? }
?????????????
????????????????????????????????????????? case 2: {
??????????????????????????????????????????????????????? // white
??????????????????????????????????????????????????????? for (j = 1; j < imageNbColors; j++)
????????????????????????????????????????????????????????????????????? imageRGBColors[j] = 0xFFFFFF;
?????????????
??????????????????????????????????????????????????????? break;
????????????????????????????????????????? }
?????????????
????????????????????????????????????????? case 3: {
??????????????????????????????????????????????????????? int l,r,g,b;
??????????????????????????????????????????????????????? // red
??????????????????????????????????????????????????????? for (j = 1; j < imageNbColors; j++) {
????????????????????????????????????????????????????????????????????? r = imageRGBColors[j];
????????????????????????????????????????????????????????????????????? g = (r & 0x00FF00) >> 8;
????????????????????????????????????????????????????????????????????? b = r & 0x0000FF;
????????????????????????????????????????????????????????????????????? r = (r & 0xFF0000) >> 16;
?????????????
????????????????????????????????????????????????????????????????????? l = (b + g * 6 + r * 3) / 10;
?????????????
????????????????????????????????????????????????????????????????????? imageRGBColors[j] = l << 16;
??????????????????????????????????????????????????????? }
?????????????
??????????????????????????????????????????????????????? break;
????????????????????????????????????????? }
??????????????????????????? }
???????????????????????????
??????????????????????????? // 生成新的 PLTE chunk data
??????????????????????????? pos = startPos + 8;
??????????????????????????? for( i = 0; i < imageNbColors ;i++)
??????????????????????????? {
????????????????????????????????????????? data[pos ] = (byte)((imageRGBColors[i] >> 16) ) ;
????????????????????????????????????????? data[pos + 1 ] = (byte)((imageRGBColors[i] >>
);
????????????????????????????????????????? data[pos + 2] = (byte)(imageRGBColors[i] );
????????????????????????????????????????? pos += 3;
??????????????????????????? }
??????????????????????????? // 更新 CRC 校驗碼
??????????????????????????? int crc = updateCrcChunk( data, startPos + 4, startPos + 4 + 4 + ( imageNbColors * 3 ) );
??????????????????????????? data[pos + 0] = (byte)(crc >> 24 & 0x000000FF);
??????????????????????????? data[pos + 1] = (byte)(crc >> 16 & 0x000000FF);
??????????????????????????? data[pos + 2] = (byte)(crc >> 8 & 0x000000FF);
??????????????????????????? data[pos + 3] = (byte)(crc & 0x000000FF);
???????????????????????????
??????????????????????????? pos = startPos;
??????????????????????????? println("\n---------------------New plte data crc " + crc +"--------------------------------");
??????????????????????????? for( i = 0; i < 4 + 4 + ( imageNbColors * 3 ) + 4; i++ )
??????????????????????????? {
????????????????????????????????????????? if( i >= 8 && (i -
%3 == 0 ) {
??????????????????????????????????????????????????????? println("");
????????????????????????????????????????? }
????????????????????????????????????????? print(" " + data[pos + i]);
??????????????????????????? }
??????????????????????????? println("\n=========================End plte data-=================================");
???????????????????????????
??????????????????????????? return Image.createImage(data,0,data.length);
????????????? }
?????????????
????????????? /**
?????????????? * 修改png圖片的RGB數據
?????????????? * @param rgbSrc png圖片的RGB數據的字節數組
?????????????? * @return 新的RGB數據的字節數組
?????????????? */
????????????? public int[] changeRGBData(int[] rgbSrc)
????????????? {
??????????????????????????? int len = rgbSrc.length;
??????????????????????????? int[] ret = new int[len];
???????????????????????????
??????????????????????????? int a,r,g,b;
??????????????????????????? int tmp;
???????????????????????????
??????????????????????????? for( int i = 0; i < len; i++ )
??????????????????????????? {
????????????????????????????????????????? b = rgbSrc[i];
?????????????????????????????????????????
????????????????????????????????????????? a = ((b & 0xff000000) >> 24);
????????????????????????????????????????? r = ((b & 0x00ff0000) >> 16);
????????????????????????????????????????? g = ((b & 0x0000ff00) >>
;
????????????????????????????????????????? b = ((b & 0x000000ff) >> 0);
?????????????????????????????????????????
????????????????????????????????????????? // exchange red and blue
????????????????????????????????????????? tmp = r;
????????????????????????????????????????? r = b;
????????????????????????????????????????? b = tmp;
?????????????????????????????????????????
????????????????????????????????????????? ret[i] = (a << 24) | (r << 16) | (g <<
| b;
??????????????????????????? }
???????????????????????????
??????????????????????????? return ret;
????????????? }
?????????????
????????????? // CRC校驗表,加速CRC計算
????????????? static long crcTable[];
????????????? static public void makeCrcTable()
????????????? {
??????????????????????????? long c;
??????????????????????????? int n, k;
??????????????????????????? crcTable = new long[256];
??????????????????????????? for (n = 0; n < 256; n++) {
????????????????????????????????????????? c = (long) n;
????????????????????????????????????????? for (k = 0; k < 8; k++) {
??????????????????????????????????????????????????????? if ((c & 1) == 1) {
????????????????????????????????????????????????????????????????????? c = 0xEDB88320L ^ (c >> 1);
??????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? else {
????????????????????????????????????????????????????????????????????? c = c >> 1;
??????????????????????????????????????????????????????? }
????????????????????????????????????????? }
????????????????????????????????????????? crcTable[n] = c;
??????????????????????????? }
????????????? }
????????????? /**
?????????????? * 計算CRC校驗碼
?????????????? */
????????????? static public int updateCrcChunk(byte[] buf, int dataOffsetStart,int dataOffsetEnd)
????????????? {
??????????????????????????? long c = 0xFFFFFFFFL;
??????????????????????????? for (int i = dataOffsetStart; i < dataOffsetEnd; i++)
????????????????????????????????????????? c = (crcTable[(int) ((c ^ buf[i]) & 0xFF)] ^ (c >>
);
??????????????????????????? return (int) (c ^ 0xFFFFFFFFL);
????????????? }
}
//-----------------------------------------------------Code------END----------------------------------------------
//2
游戲幀速度處理
保持游戲在不同性能手機平臺的流暢性很重要,這就需要針對不通硬件設置相應合適的幀速度。假設一般
手機用戶能接受的游戲幀速為40/s 則相關參數和代碼如下:
//====================================================
// 游戲幀速度調整
//====================================================
??? private long framerate= 1000/40; // 設置幀速為每秒40幀,(25 ms / frame)
???? private long frameStart;? // 幀開始的時間time the frame begin????????
???? private long frameCount = 0; // 這一秒的幀數???
???? private long elapsedTime;? // 一幀消耗的時間?
???? private long totalElapsedTime = 0; // 多幀累計消耗的時間
???? private long reportedFramerate; // 實際計算出來的幀速
public void updateFrame()
{
? frameStart = System.currentTimeMillis();
? repaint();
? elapsedTime = System.currentTimeMillis() - frameStart;
?
? //幀速同步
? try {
?? if( elapsedTime < framerate ) {
??? Thread.sleep(framerate - elapsedTime);
?? }else {
??? Thread.sleep(5);
?? }
? }catch( Exception e ) {
?? e.printStackTrace();
? }
?
? //更新實際的幀速
? ++ frameCount;
? totalElapsedTime +=? (System.currentTimeMillis() - frameStart);
? if( totalElapsedTime > 1000 ) {
?? reportedFramerate = (long)((double)frameCount/(double)
totalElapsedTime*1000.0);
?? //在調試時可屏幕中顯示幀速
????????????? //g.drawString("fps: " + reportedFramerate,x,y,0);
????????????? frameCount = 0;
????????????? totalElapsedTime = 0;
? }
}
////3
J2me中實現淡入淡出效果
飄飄白云(l_zhaohui@163.com)
??? 在J2me中實現淡入淡出效果,據我所知至少有三種方法。
第一種是取得需要變換圖片的像素,依次設置每個象素的alpha通道值,讓它在0~100之間變化。
??? 第二種是修改圖片的調色板數據,讓其在調色板原始數據到255之間變化。
??? 第三種,其實也是利用上面的辦法,先描畫圖片,然后在圖片上覆蓋一個黑色矩形,改變這個黑色矩形透明度就可以實現淡入淡出的效果。
??? 前兩種方法相比較的話,第一種方法運算量是比較大的,而且第一種方法由于midp1.0不支持alpha通道,在一些手機上無法實現。
??? 下面給出第二種方法的示例,在我們開始之前,應該熟悉png文件格式,如果還不是很明白的話,可以google一下,或者查看前面的帖子中的相關連接。
??? 代碼很清楚,下面是源代碼:
------------CODE__START-----------------------
import java.io.DataInputStream;
import java.util.Timer;
import java.util.TimerTask;
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;
/**
* Discription????? : 修改調色板數據實現淡入淡出效果
* Author?????????? : 飄飄白云(l_zhaohui@163.com)
* Created date???? : 2006/07/13 18:06:39
* Modified history :
*/
public class PngFadeInOut extends MIDlet
{
?????????????????????????? GameCanvas canvas;
????????????????? Display display;
??????????????????????????? public PngFadeInOut()
??????????????????????????? {
????????????????????????????????????????? super();
????????????????????????????????????????? try {
????????????????????????? display = Display.getDisplay(this);
????????????????????????? canvas = new GameCanvas(this);
????????????????????? } catch (Exception e) {}
??????????????????????????? }
??????????????????????????? protected void startApp() throws MIDletStateChangeException
??????????????????????????? {
????????????????????????????????????????? if( canvas != null ){
??????????????????????????????????????????????????????? display.setCurrent(canvas);
??????????????????????????????????????????????????????? canvas.start();
????????????????????????????????????????? }
??????????????????????????? }
??????????????????????????? protected void pauseApp()
??????????????????????????? {
????????????????????????????????????????? canvas.isExit = true;
??????????????????????????? }
??????????????????????????? protected void destroyApp( boolean arg0) throws MIDletStateChangeException
??????????????????????????? {
??????????????????????????? }
????????????? }
????????????? class GameCanvas extends Canvas
????????????? {
??????????????????????????? static String imageName = "/fadeInOut.png";
??????????????????????????? public static final int??? MAX_TARDINESS = 30;
???????????????????????????
??????????????????????????? //---------------------------------------------------
??????????????????????????? PngFadeInOut app;
??????????????????????????? boolean isInited = false;
??????????????????????????? public boolean isExit = false;
??????????????????????????? Image offImage???????????? = null;
??????????????????????????? public Graphics???????????? g = null;
??????????????????????????? int scrW;
??????????????????????????? int scrH;
??????????????????????????? //---------------------------------------------------
??????????????????????????? int gameMode;
??????????????????????????? int subMode;
???????????????????????????
??????????????????????????? static final int smInit = 0;
??????????????????????????? static final int smProc = 1;
??????????????????????????? static final int smEnd = 2;
???????????????????????????
??????????????????????????? static final int gmStart = 0;
???????????????????????????
??????????????????????????? //---------------------------------------------------
??????????????????????????? Image testImage = null;
???????????????????????????
??????????????????????????? byte[] oldRGBData = null;
??????????????????????????? byte[] imgData = null;
???????????????????????????
??????????????????????????? static final int FADE_IN = 0;
??????????????????????????? static final int FADE_OUT = 1;
??????????????????????????? static final int FADE_STEP = 1;
???????????????????????????
??????????????????????????? static int fadeType = FADE_IN;
???????????????????????????
??????????????????????????? //---------------------------------------------------
??????????????????????????? //---Timer process
??????????????????????????? //---------------------------------------------------
??????????????????????????? TimerTask task;
??????????????????????????? Timer timer;
??????????????????????????? int timerDelayTime;
??????????????????????????? public boolean isTimerRunning;
???????????????????????????
??????????????????????????? void startTimer(int delayTime){
????????????????????????????????????????? timerDelayTime = delayTime;
????????????????????????????????????????? isTimerRunning = true;
?????????????????????????????????????????
????????????????????????????????????????? timer = new Timer();
????????????????????????????????????????? task = new ProcessingRunner();
????????????????????????????????????????? timer.scheduleAtFixedRate(task, 0, delayTime);
??????????????????????????? }
???????????????????????????
??????????????????????????? public void stopTimer(){
????????????????????????????????????????? if( task != null )
??????????????????????????????????????????????????????? task.cancel();
?????????????????????????????????????????
????????????????????????????????????????? isTimerRunning = false;
????????????????????????????????????????? timer = null;
????????????????????????????????????????? task = null;
??????????????????????????? }
??????????????????????????? //-----------------------------------------------------
??????????????????????????? class ProcessingRunner extends TimerTask
??????????????????????????? {
????????????????????????????????????????? public void run()
????????????????????????????????????????? {
??????????????????????????????????????????????????????? if( isExit ) {
????????????????????????????????????????????????????????????????????? stopTimer();
????????????????????????????????????????????????????????????????????? app.notifyDestroyed();
??????????????????????????????????????????????????????? }
???????????????????????????????????????????????????????
??????????????????????????????????????????????????????? if (!isTimerRunning || System.currentTimeMillis() -
??????????????????????????????????????????????????????????????????????????????????? scheduledExecutionTime() >= timerDelayTime)
??????????????????????????????????????????????????????? {
????????????????????????????????????????????????????????????????????? return;
??????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? gameMain();
??????????????????????????????????????????????????????? gameDraw();
???????????????????????????????????????????????????????
??????????????????????????????????????????????????????? repaint();
??????????????????????????????????????????????????????? serviceRepaints();
??????????????????????????????????????????????????????? System.gc();
????????????????????????????????????????? }
??????????????????????????? }
??????????????????????????? //-------------------------------------------------
???????????????????????????
??????????????????????????? public GameCanvas(MIDlet midlet)
??????????????????????????? {
????????????????????????????????????????? app = (PngFadeInOut)midlet;
??????????????????????????? }
?????????????
???????????????????????????
??????????????????????????? public void start()
??????????????????????????? {
????????????????????????????????????????? setFullScreenMode(true);
????????????????????????????????????????? while (!isShown())
??????????????????????????????????????????????????????? ;
?????????????????????????????????????????
????????????????????????????????????????? if( !isInited ) {
??????????????????????????????????????????????????????? gameInit();
??????????????????????????????????????????????????????? isInited = true;
????????????????????????????????????????? }
????????????????????????????????????????? startTimer(MAX_TARDINESS);
??????????????????????????? }
???????????????????????????
??????????????????????????? void gameInit()
??????????????????????????? {
????????????????????????????????????????? scrW = getWidth();
????????????????????????????????????????? scrH = getHeight();
????????????????????????????????????????? if(g == null || offImage == null) {
??????????????????????????????????????????????????????? offImage = Image.createImage(scrW, scrH);
????????????????????????????????????????????? g = offImage.getGraphics();
????????????????????????????????????????? }
?????????????????????????????????????????
????????????????????????????????????????? changeGameMode(gmStart);
??????????????????????????? }
??????????????????????????? public void changeGameMode(int gm){
????????????????????????????????????????? gameMode = gm;
????????????????????????????????????????? subMode = smInit;
??????????????????????????? }
???????????????????????????
??????????????????????????? //---------------------------------------------------
??????????????????????????? // 游戲主邏輯處理
??????????????????????????? //---------------------------------------------------
??????????????????????????? void gameMain()
??????????????????????????? {
????????????????????????????????????????? if( gameMode == gmStart )
????????????????????????????????????????? {
??????????????????????????????????????????????????????? if( subMode == smInit )
??????????????????????????????????????????????????????? {
????????????????????????????????????????????????????????????????????? // 取得圖片的二進制數據
????????????????????????????????????????????????????????????????????? imgData = loadFile(imageName);
???????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????? //保存原始圖片的調色板rgb數據
????????????????????????????????????????????????????????????????????? oldRGBData = getPlteRGBData(imgData);
???????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????? if( fadeType == FADE_IN) {
??????????????????????????????????????????????????????????????????????????????????? // 設置調色板顏色為白色,淡入效果
??????????????????????????????????????????????????????????????????????????????????? for(int i = rgbDataStartPos; i < rgbDataStartPos + rgbDataLength;i++ ) {
????????????????????????????????????????????????????????????????????????????????????????????????? imgData[i] = (byte)255;
??????????????????????????????????????????????????????????????????????????????????? }
????????????????????????????????????????????????????????????????????? }
????????????????????????????????????????????????????????????????????? // 生成新的圖片
????????????????????????????????????????????????????????????????????? testImage = createFadeImage(imgData,rgbDataStartPos,rgbDataLength);
????????????????????????????????????????????????????????????????????? subMode = smProc ;
??????????????????????????????????????????????????????? }
???????????????????????????????????????????????????????
??????????????????????????????????????????????????????? else if( subMode == smProc )
??????????????????????????????????????????????????????? {
????????????????????????????????????????????????????????????????????? try {
??????????????????????????????????????????????????????????????????????????????????? // 淡入淡出效果處理
??????????????????????????????????????????????????????????????????????????????????? fade(fadeType);
??????????????????????????????????????????????????????????????????????????????????? testImage = createFadeImage(imgData,rgbDataStartPos,rgbDataLength);
????????????????????????????????????????????????????????????????????? }
????????????????????????????????????????????????????????????????????? catch ( Exception e ) {
??????????????????????????????????????????????????????????????????????????????????? println("Create fade image error. \n" + e);
????????????????????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? }
????????????????????????????????????????? }
??????????????????????????? }
???????????????????????????
??????????????????????????? //---------------------------------------------------
??????????????????????????? // 游戲描畫處理
??????????????????????????? //---------------------------------------------------
???????????????????????????
??????????????????????????? protected void paint( Graphics _g){
????????????????????????????????????????? if( offImage != null)
??????????????????????????????????????????????????????? _g.drawImage(offImage, 0, 0, 0);
??????????????????????????? }
???????????????????????????
??????????????????????????? void gameDraw()
??????????????????????????? {
????????????????????????????????????????? if( gameMode == gmStart )
????????????????????????????????????????? {
??????????????????????????????????????????????????????? if( subMode == smProc ){
????????????????????????????????????????????????????????????????????? g.setColor(0xffffff);
????????????????????????????????????????????????????????????????????? g.fillRect(0,0,scrW,scrH);
????????????????????????????????????????????????????????????????????? g.drawImage(testImage,20,140,0);
??????????????????????????????????????????????????????? }
????????????????????????????????????????? }
??????????????????????????? }
???????????????????????????
??????????????????????????? /**
???????????????????????????? * 淡入淡出效果處理
???????????????????????????? * @param type
???????????????????????????? */
??????????????????????????? public void fade( int type)
??????????????????????????? {
????????????????????????????????????????? int m = 0;
????????????????????????????????????????? int n = 0;
????????????????????????????????????????? // 淡入
????????????????????????????????????????? if ( type == FADE_IN ) {
??????????????????????????????????????????????????????? for( int i = 0; i < rgbDataLength; i++ )
??????????????????????????????????????????????????????? {
????????????????????????????????????????????????????????????????????? m = imgData[rgbDataStartPos + i] & 0x000000ff;
????????????????????????????????????????????????????????????????????? n = oldRGBData[i] & 0x000000ff;
????????????????????????????????????????????????????????????????????? m = m < 0? m + 256 : m;
????????????????????????????????????????????????????????????????????? n = n < 0? n + 256 : n;
?????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????? m = m > n ? m - FADE_STEP : n;
?????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????? imgData[rgbDataStartPos + i] = (byte)(m & 0xff);
??????????????????????????????????????????????????????? }
????????????????????????????????????????? }
????????????????????????????????????????? // 淡出
????????????????????????????????????????? else if ( type == FADE_OUT ) {
??????????????????????????????????????????????????????? for( int i = 0; i < rgbDataLength; i++ )
??????????????????????????????????????????????????????? {
????????????????????????????????????????????????????????????????????? m = imgData[rgbDataStartPos + i] & 0x000000ff;
????????????????????????????????????????????????????????????????????? m = m < 0? m + 256 : m;
????????????????????????????????????????????????????????????????????? m = m < 255 ? m + FADE_STEP : 255;
?????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????? imgData[rgbDataStartPos + i] = (byte)(m & 0xff);
??????????????????????????????????????????????????????? }
????????????????????????????????????????? }
??????????????????????????? }
???????????????????????????
??????????????????????????? /**
???????????????????????????? * 這里不是單純創建一幅圖片,crc32校驗碼也在這個函數里更新
???????????????????????????? * @param data
???????????????????????????? * @param startPos 需要校驗的數據的起始位置
???????????????????????????? * @return
???????????????????????????? */
??????????????????????????? public Image createFadeImage(byte[] data,int startPos,int length)
??????????????????????????? {
????????????????????????????????????????? if (crcTable == null)
??????????????????????????????????????????????????????? makeCrcTable();
?????????????????????????????????????????
????????????????????????????????????????? int endPos = startPos + length ;
????????????????????????????????????????? int crc = updateCrcChunk( data, startPos -8,endPos );
????????????????????????????????????????? data[endPos + 0] = (byte)(crc >> 24 & 0x000000FF);
????????????????????????????????????????? data[endPos + 1] = (byte)(crc >> 16 & 0x000000FF);
????????????????????????????????????????? data[endPos + 2] = (byte)(crc >> 8 & 0x000000FF);
????????????????????????????????????????? data[endPos + 3] = (byte)(crc & 0x000000FF);
?????????????????????????????????????????
????????????????????????????????????????? return Image.createImage(data,0,data.length);
??????????????????????????? }
???????????????????????????
??????????????????????????? static int rgbDataStartPos = 0;
??????????????????????????? static int rgbDataLength = 0;
???????????????????????????
??????????????????????????? /**
???????????????????????????? * @param imgData png圖片的二進制數據
???????????????????????????? * @return 調色板顏色數據的字節數組
???????????????????????????? */
??????????????????????????? public byte[] getPlteRGBData(byte[] imgData)
??????????????????????????? {
????????????????????????????????????????? if (imgData == null || imgData.length <= 1)
??????????????????????????????????????????????????????? return null;
????????????????????????????????????????? // PLTE chunk數據域的類型標識
????????????????????????????????????????? // see http://www.w3.org/TR/PNG/#11PLTE
????????????????????????????????????????? String[] sPLTE = {"50", "4c", "54", "45"};
????????????????????????????????????????? int i;
????????????????????????????????????????? int pos = 0;
????????????????????????????????????????? //定位調色板數據的位置
????????????????????????????????????????? for (i = 0; i < imgData.length; i++)
????????????????????????????????????????? {
???????????????????????????????????? if (Integer.toHexString(imgData[i]).equals(sPLTE[0])
????????????????????????????????????????????????????????????? && Integer.toHexString(imgData[i + 1]).equals(sPLTE[1])
????????????????????????????????????????????????????????????? && Integer.toHexString(imgData[i + 2]).equals(sPLTE[2])
????????????????????????????????? && Integer.toHexString(imgData[i + 3]).equals(sPLTE[3]))
????????????????????????????????????? {
????????????????????????????????????????????????? pos = i;
????????????????????????????????????????????????? break;
????????????????????????????????????? }
????????????????????????????????????????? }
?????????????????????????????????????????
????????????????????????????????????????? pos -= 4;
????????????????????????????????????????? // 取得PLTE chunk的字節數據長度.
????????????????????????????????????????? int imageNbColors = (
????????????????????????????????????????????????????????????????????? ((imgData[pos] << 24) & 0xff000000)
????????????????????????????????????????????????????????????????????? | ((imgData[pos + 1] << 16) & 0x00ff0000)
????????????????????????????????????????????????????????????????????? | ((imgData[pos + 2] << 8 ) & 0x0000ff00)
????????????????????????????????????????????????????????????????????? | ((imgData[pos + 3]????? ) & 0x000000ff));
???????????????????????????
????????????????????????????????????????? //8 = 數據長度(4個字節) + 類型標識(4個字節)???????????
????????????????????????????????????????? pos += 8;
?????????????????????????????????????????
????????????????????????????????????????? // 設置全局變量
????????????????????????????????????????? rgbDataStartPos = pos;
????????????????????????????????????????? rgbDataLength = imageNbColors;
?????????????????????????????????????????
????????????????????????????????????????? //復制數據
????????????????????????????????????????? byte[] data = new byte[rgbDataLength ];
????????????????????????????????????????? for( i = 0 ; i < rgbDataLength ; i++){
??????????????????????????????????????????????????????? data[i] = imgData[i + rgbDataStartPos ];
????????????????????????????????????????? }
??????????????????????????????????????????
????????????????????????????????????????? return data;
??????????????????????????? }
???????????????????????????
??????????????????????????? // CRC校驗查找表,加速CRC32運算
??????????????????????????? static long crcTable[];
??????????????????????????? static public void makeCrcTable()
??????????????????????????? {
????????????????????????????????????????? long c;
????????????????????????????????????????? int n, k;
????????????????????????????????????????? crcTable = new long[256];
????????????????????????????????????????? for (n = 0; n < 256; n++) {
??????????????????????????????????????????????????????? c = (long) n;
??????????????????????????????????????????????????????? for (k = 0; k < 8; k++) {
????????????????????????????????????????????????????????????????????? if ((c & 1) == 1) {
??????????????????????????????????????????????????????????????????????????????????? c = 0xEDB88320L ^ (c >> 1);
????????????????????????????????????????????????????????????????????? }
????????????????????????????????????????????????????????????????????? else {
??????????????????????????????????????????????????????????????????????????????????? c = c >> 1;
????????????????????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? crcTable[n] = c;
????????????????????????????????????????? }
??????????????????????????? }
??????????????????????????? /**
???????????????????????????? * 計算crc32校驗碼
???????????????????????????? */
??????????????????????????? static public int updateCrcChunk(byte[] buf, int dataOffsetStart,int dataOffsetEnd)
??????????????????????????? {
????????????????????????????????????????? long c = 0xFFFFFFFFL;
????????????????????????????????????????? for (int i = dataOffsetStart; i < dataOffsetEnd; i++)
??????????????????????????????????????????????????????? c = (crcTable[(int) ((c ^ buf[i]) & 0xFF)] ^ (c >>
);
????????????????????????????????????????? return (int) (c ^ 0xFFFFFFFFL);
??????????????????????????? }
???????????????????????????
???????????????????????????
??????????????????????????? /**
???????????????????????????? * 讀取文件的二進制數據
???????????????????????????? * @param fileName 文件名
???????????????????????????? * @return 文件二進制數據
???????????????????????????? */
??????????????????????????? byte[] loadFile(String fileName)
??????????????????????????? {
????????????????????????????????????????? DataInputStream isr = null;
????????????????????????????????????????? byte[] bData;
????????????????????????????????????????? try {
??????????????????????????????????????????????????????? try {
????????????????????????????????????????????????????????????????????? isr = new DataInputStream(getClass().getResourceAsStream(fileName));
??????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? catch (Exception e) {
??????????????????????????????????????????????????????? }
???????????????????????????????????????????????????????
??????????????????????????????????????????????????????? int res_size = 0;
??????????????????????????????????????????????????????? while (isr.read() != -1)
????????????????????????????????????????????????????????????????????? res_size++;
??????????????????????????????????????????????????????? if (isr.markSupported())
????????????????????????????????????????????????????????????????????? isr.reset();
??????????????????????????????????????????????????????? else {
????????????????????????????????????????????????????????????????????? isr.close();
????????????????????????????????????????????????????????????????????? isr = new DataInputStream(getClass().getResourceAsStream(fileName));
??????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? bData = new byte[res_size];
??????????????????????????????????????????????????????? int read_bytes = isr.read(bData, 0, res_size);
??????????????????????????????????????????????????????? isr.close();
??????????????????????????????????????????????????????? System.gc();
??????????????????????????????????????????????????????? return bData;
????????????????????????????????????????? }
????????????????????????????????????????? catch (Exception e) {
??????????????????????????????????????????????????????? println("Error>>loadFile " + fileName);
??????????????????????????????????????????????????????? return null;
????????????????????????????????????????? }
??????????????????????????? }
???????????????????????????
??????????????????????????? static void println(String str){
????????????????????????????????????????? System.out.println( str );
??????????????????????????? }
???????????????????????????
????????????? }
----------------------CODE__END-------------------------------
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/liu01983zm/archive/2006/08/30/1143132.aspx
在手機游戲開發中,為了節省資源,我們常常修改png圖片以實現一張圖片多種顯示效果。有兩種辦法可以實現這個功能:
第一種是裝載png圖片,使用getRGB()取得取得圖片的RGB顏色數據,然后修改RGB顏色數據,再用Image的靜態方法createRGBImage()將修改后的RGB顏色數據生成新的png圖片。示例代碼:testImage為測試的Image對象,imgW,imgH為其寬和高
// 取得圖片的RGB數據--這個數組是比較大的,因此修改RGB數據生成新的圖片效率很低
rgbData = new int[imgW * imgH];
testImage.getRGB(rgbData,0,imgW,0,0,imgW,imgH);
// 修改RGB數據并生成新的圖片
rgbImage = Image.createRGBImage(changeRGBData(rgbData),imgW,imgH,true);
第二中方法是取得png圖片的二進制數據,修改其中的調色板域(PLTE chunk)數據,再使用
Image的靜態對象createImage(byte[] imageData,int imageOffset,int imageLength)將修改后的二進制數據生成新的png對象。示例代碼:查看代碼中的getPLTEModifidImage()函數。
如果對png的數據格式組成不熟悉,可以查閱:http://www.w3.org/TR/PNG/
或者(不錯的中文介紹): http://www.ismyway.com/png/png-struct1.htm
通常,圖片的RGB顏色數據是比較大的,而調色板數據遠比RGB顏色數據要少的多,修改RGB顏色數據效率要高的多。下面我使用一張大小為52*28的png圖片作為測試圖片,從以下測試中打印的數據就可看出(1456對比144):
Load file Gold total data is 1084 ――――――――圖片的二進制字節數據個數
--------RGB data length is 1456―――――――――RGB顏色字節數據個數
--------The number of PLTE chunks is 48―――調色板數據塊個數(實際字節數據為48*3)
效果圖:
附測試的源代碼:
//-----------------------------------------------------Code--START------------------------------------------------
/**
* Dicription?????? : Create png image by modifying PLTE chunk.
* Author?????????? : 飄飄白云
* Created date???? : 2006-07-03
* Modified history :
*/
import java.io.DataInputStream;
import java.io.IOException;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
public class CreatePNG extends MIDlet
{
??? GameCanvas canvas;
??? Display display;
????????????? public CreatePNG()
????????????? {
??????????????????????????? super();
??????????????????????????? // TODO Auto-generated constructor stub
??????????????????????????? try {
??????????? display = Display.getDisplay(this);
??????????? canvas = new GameCanvas(this);
??????? } catch (Exception e) {}
????????????? }
????????????? protected void startApp() throws MIDletStateChangeException
????????????? {
??????????????????????????? // TODO Auto-generated method stub
??????????????????????????? if( canvas != null ){
????????????????????????????????????????? display.setCurrent(canvas);
????????????????????????????????????????? canvas.start();
??????????????????????????? }
????????????? }
????????????? protected void pauseApp()
????????????? {
??????????????????????????? // TODO Auto-generated method stub
??????????????????????????? canvas.beExit = true;
????????????? }
????????????? protected void destroyApp( boolean arg0) throws MIDletStateChangeException
????????????? {
??????????????????????????? // TODO Auto-generated method stub
????????????? }
}
class GameCanvas extends Canvas implements Runnable
{
????????????? CreatePNG app;
????????????? Thread mainThread;
?????????????
????????????? Image??????????????????????????????????????????????????????????? offImage????????????? = null;
????????????? public Graphics?????????????????????????????? g??????????????????????????????????????? = null;
?????????????
????????????? public boolean beExit = false;
????????????? long sleepTime = 30;
?????????????
????????????? int scrW;
????????????? int scrH;
????????????? Font font;
????????????? int fontH;
????????????? int fontW;
?????????????
????????????? //-------------------------------------
????????????? int gameMode;
????????????? int subMode;
?????????????
????????????? static final int smInit = 0;
????????????? static final int smProc = 1;
????????????? static final int smEnd = 2;
?????????????
????????????? static final int gmStart = 0;
????????????? static final int gmProcPNGData = 1;
?????????????
????????????? //--------------------------------------
????????????? Image testImage = null;
????????????? Image rgbImage = null;
????????????? Image plteImage = null;
????????????? int imgW;
????????????? int imgH;
????????????? int[] rgbData = null;
????????????? byte[] imgData = null;
????????????? String testFile = "Gold";
?????????????
????????????? public GameCanvas(MIDlet midlet)
????????????? {
??????????????????????????? app = (CreatePNG)midlet;
????????????? }
????????????? public void start()
????????????? {
??????????????????????????? changeGameMode(gmStart);
???????????????????????????
??????????????????????????? mainThread = new Thread(this);
??????????????????????????? mainThread.start();
????????????? }
?????????????
????????????? public void changeGameMode(int gm)
????????????? {
??????????????????????????? gameMode = gm;
??????????????????????????? subMode = smInit;
????????????? }
?????????????
????????????? protected void paint( Graphics _g)
????????????? {
??????????????????????????? // TODO Auto-generated method stub
??????????????????????????? if( offImage != null)
????????????????????????????????????????? _g.drawImage(offImage, 0, 0, 0);
????????????? }
????????????? public void run()
????????????? {
??????????????????????????? // TODO Auto-generated method stub
??????????????????????????? gameInit();
??????????????????????????? while( !beExit )
??????????????????????????? {
????????????????????????????????????????? gameMain();
????????????????????????????????????????? gameDraw();
????????????????????????????????????????? repaint();
????????????????????????????????????????? gcWait(sleepTime);
??????????????????????????? }
???????????????????????????
??????????????????????????? if( beExit ) {
????????????????????????????????????????? try {
??????????????????????????????????????????????????????? app.destroyApp(true);
????????????????????????????????????????? }
????????????????????????????????????????? catch ( MIDletStateChangeException e ) {
??????????????????????????????????????????????????????? // TODO Auto-generated catch block
??????????????????????????????????????????????????????? e.printStackTrace();
????????????????????????????????????????? }
??????????????????????????? }
????????????? }
?????????????
????????????? void gcWait(long tm)
????????????? {
??????????????????????????? System.gc();
??????????????????????????? try {
????????????????????????????????????????? Thread.sleep(tm);
??????????????????????????? }
??????????????????????????? catch ( InterruptedException e ) {
????????????????????????????????????????? // TODO Auto-generated catch block
????????????????????????????????????????? e.printStackTrace();
??????????????????????????? }
????????????? }
?????????????
????????????? void println(String str)
????????????? {
??????????????????????????? System.out.println( str );
????????????? }
????????????? void print(String str)
????????????? {
??????????????????????????? System.out.print( str );
????????????? }
?????????????
????????????? void gameInit()
????????????? {
??????????????????????????? scrW = getWidth();
??????????????????????????? scrH = getHeight();
??????????????????????????? if(g == null || offImage == null) {
????????????????????????????????????????? offImage = Image.createImage(scrW, scrH);
??????????????????????????????? g = offImage.getGraphics();
????????????????????????????????????????? g.translate(0,0);
??????????????????????????? }
??????????????????????????? repaint();
???????????????????????????
??????????????????????????? font?????? = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN,Font.SIZE_MEDIUM);
??????????????????????????? g.setFont(font);
?????????????????
????????????????? changeGameMode( gmStart );
????????????? }
?????????????
????????????? /**
?????????????? * 裝載圖片
?????????????? * @param fileName 圖片名稱
?????????????? * @return image 對象
?????????????? */
????????????? Image loadImage( String fileName)
????????????? {
??????????????????????????? Image tmp = null;
??????????????????????????? try {
????????????????????????????????????????? tmp = Image.createImage("/" + fileName + ".png");
??????????????????????????? }
??????????????????????????? catch ( IOException e ) {
????????????????????????????????????????? println("[Error] >> loadImage(): " + fileName + " Failed!");
????????????????????????????????????????? e.printStackTrace();
??????????????????????????? }
??????????????????????????? if( tmp == null ) {
????????????????????????????????????????? println("[Error] >> loadImage(): " + fileName + " Failed!");
??????????????????????????? }
??????????????????????????? return tmp;
????????????? }
?????????????
????????????? /**
?????????????? * 讀取文件的二進制數據
?????????????? * @param fileName 文件名
?????????????? * @return 文件二進制數據的字節數組.
?????????????? */
????????????? byte[] loadFile(String fileName)
????????????? {
??????????????????????????? DataInputStream isr = null;
??????????????????????????? byte[] bData;
??????????????????????????? try {
????????????????????????????????????????? try {
??????????????????????????????????????????????????????? isr = new DataInputStream(getClass().getResourceAsStream("/" + fileName + ".png"));
????????????????????????????????????????? }
????????????????????????????????????????? catch (Exception e) {
????????????????????????????????????????? }
?????????????????????????????????????????
????????????????????????????????????????? int res_size = 0;
????????????????????????????????????????? while (isr.read() != -1)
??????????????????????????????????????????????????????? res_size++;
????????????????????????????????????????? if (isr.markSupported())
??????????????????????????????????????????????????????? isr.reset();
????????????????????????????????????????? else {
??????????????????????????????????????????????????????? isr.close();
??????????????????????????????????????????????????????? isr = new DataInputStream(getClass().getResourceAsStream("/" + fileName + ".png"));
????????????????????????????????????????? }
????????????????????????????????????????? bData = new byte[res_size];
????????????????????????????????????????? int read_bytes = isr.read(bData, 0, res_size);
????????????????????????????????????????? isr.close();
????????????????????????????????????????? System.gc();
????????????????????????????????????????? println("Load file " + fileName + " total data is " + read_bytes);
????????????????????????????????????????? return bData;
??????????????????????????? }
??????????????????????????? catch (Exception e) {
????????????????????????????????????????? println("Error>>loadFile " + fileName);
????????????????????????????????????????? return null;
??????????????????????????? }
????????????? }
?????????????
?????????????
????????????? void gameMain()
????????????? {
??????????????????????????? if( gameMode == gmStart )
??????????????????????????? {
????????????????????????????????????????? if( subMode == smInit )
????????????????????????????????????????? {
??????????????????????????????????????????????????????? // 裝載圖片
??????????????????????????????????????????????????????? testImage = loadImage(testFile);
??????????????????????????????????????????????????????? imgW = testImage.getWidth();
??????????????????????????????????????????????????????? imgH = testImage.getHeight();
??????????????????????????????????????????????????????? subMode = smProc ;
????????????????????????????????????????? }
?????????????????????????????????????????
????????????????????????????????????????? else if( subMode == smProc )
????????????????????????????????????????? {
??????????????????????????????????????????????????????? // 取得圖片的RGB數據--這個數組是比較大的,因此修改RGB數據生成新的圖片效率很低
??????????????????????????????????????????????????????? rgbData = new int[imgW * imgH];
??????????????????????????????????????????????????????? testImage.getRGB(rgbData,0,imgW,0,0,imgW,imgH);
???????????????????????????????????????????????????????
??????????????????????????????????????????????????????? println("--------RGB data length is - " + rgbData.length);
??????????????????????????????????????????????????????? changeGameMode(gmProcPNGData);
????????????????????????????????????????? }
??????????????????????????? }
???????????????????????????
??????????????????????????? else if( gameMode == gmProcPNGData )
??????????????????????????? {
????????????????????????????????????????? if( subMode == smInit )
????????????????????????????????????????? {
??????????????????????????????????????????????????????? // 取得圖片的二進制數據
??????????????????????????????????????????????????????? imgData = loadFile(testFile);
??????????????????????????????????????????????????????? subMode = smProc ;
??????????????????????????????????????????????????????? println("----Start---All Image Data--length-" + imgData.length);
??????????????????????????????????????????????????????? for( int i = 0; i< imgData.length; i++ ){
????????????????????????????????????????????????????????????????????? if( i% 10 == 0 )
??????????????????????????????????????????????????????????????????????????????????? println("");
????????????????????????????????????????????????????????????????????? System.out.print(" " + imgData[i]);
??????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? println("\n----End---All Image Data--length-" + imgData.length);
??????????????????????????????????????????????????????? // 修改調色板數據,改變圖片顏色,這種方法修改的數據遠比修改RGB數據要少,效率高很多
??????????????????????????????????????????????????????? plteImage = getPLTEModifidImage(imgData,3);
????????????????????????????????????????? }
?????????????????????????????????????????
????????????????????????????????????????? else if( subMode == smProc )
????????????????????????????????????????? {????????????
??????????????????????????????????????????????????????? // 修改RGB數據生成新的圖片,非常低效
??????????????????????????????????????????????????????? rgbImage = Image.createRGBImage(changeRGBData(rgbData),imgW,imgH,true);
??????????????????????????????????????????????????????? subMode = smEnd;
????????????????????????????????????????? }
????????????????????????????????????????? else if( subMode == smEnd )
????????????????????????????????????????? {
????????????????????????????????????????? }
??????????????????????????? }
????????????? }
?????????????
????????????? void gameDraw()
????????????? {
??????????????????????????? if( gameMode == gmStart )
??????????????????????????? {
????????????????????????????????????????? if( subMode == smProc ){
??????????????????????????????????????????????????????? // 描繪原始圖片
??????????????????????????????????????????????????????? g.drawImage(testImage,20,20,0);
????????????????????????????????????????? }
??????????????????????????? }
??????????????????????????? else if( gameMode == gmProcPNGData )
??????????????????????????? {
????????????????????????????????????????? if( subMode == smProc ){
??????????????????????????????????????????????????????? // 描繪修改調試板數據生成的圖片
??????????????????????????????????????????????????????? g.drawImage(plteImage,20,80,0);
????????????????????????????????????????? }
????????????????????????????????????????? else if( subMode == smEnd ) {
??????????????????????????????????????????????????????? // 描繪修改RGB數據生成的圖片,也可以使用drawRGB()直接描繪RGB數據,不過要注意透明問題.
??????????????????????????????????????????????????????? g.drawImage(rgbImage,20,140,0);
????????????????????????????????????????? }
??????????????????????????? }
????????????? }
????????????? /**
?????????????? * 修改png圖片的調色板數據生成新的png圖片
?????????????? * @param imageSrc png圖片的二進制數據字節數組
?????????????? * @param type 修改策略
?????????????? * @return 新的png圖片
?????????????? */
????????????? public Image getPLTEModifidImage(byte[] imageSrc , int type)
????????????? {
??????????????????????????? if (imageSrc == null || imageSrc.length <= 1)
????????????????????????????????????????? return null;
??????????????????????????? if (crcTable == null)
????????????????????????????????????????? makeCrcTable();
??????????????????????????? // PLTE chunk數據域的類型標識
??????????????????????????? // see http://www.w3.org/TR/PNG/#11PLTE
??????????????????????????? String[] sPLTE = {"50", "4c", "54", "45"};
??????????????????????????? int i,j;
??????????????????????????? int pos = 0,startPos = 0;
??????????????????????????? byte[] data = imageSrc;
???????????????????????????
??????????????????????????? for (i = 0; i < data.length; i++)
??????????????????????????? {
??????????????????????? if (Integer.toHexString(data[i]).equals(sPLTE[0])
????????????????????????????????????????????????? && Integer.toHexString(data[i + 1]).equals(sPLTE[1])
????????????????????????????????????????????????? && Integer.toHexString(data[i + 2]).equals(sPLTE[2])
??????????????????? && Integer.toHexString(data[i + 3]).equals(sPLTE[3]))
??????????????????????? {
????????????????????????????????????? pos = i;
????????????????????????????????????? break;
??????????????????????? }
??????????????????????????? }
??????????????????????????? pos -= 4;
??????????????????????????? startPos = pos;
??????????????????????????? println("\n======================start Palette data process========================");
??????????????????????????? println("-------------Palette chunk start pos = " + pos);
??????????????????????????? // 取得PLTE chunk數據域的數據長度().
??????????????????????????? int imageNbColors = (
??????????????????????????????????????????????????????? ((data[pos] << 24) & 0xff000000)
??????????????????????????????????????????????????????? | ((data[pos + 1] << 16) & 0x00ff0000)
??????????????????????????????????????????????????????? | ((data[pos + 2] << 8 ) & 0x0000ff00)
??????????????????????????????????????????????????????? | ((data[pos + 3]????? ) & 0x000000ff));
??????????????????????????? // 計算的PLTE chunk數據個數(每個PLTE chunk數據由R,G,B三個字節數據組成)
??????????????????????????? imageNbColors = imageNbColors/3;
??????????????????????????? // 為整形的PLTE chunk data分配空間
??????????????????????????? int imageRGBColors[]??? = new int[ imageNbColors ];
?????
??????????????????????????? //12 = 數據長度(4個字節) + 類型標識(4個字節) + 校驗碼(4個字節)
?????????????????????????? for( i = pos,j = 0; i < pos + 12 + imageNbColors * 3 ; i++,j++ ){
????????????????????????????????????????? if( j >= 8 && (j -

??????????????????????????????????????????????????????? println("");
????????????????????????????????????????? }
????????????????????????????????????????? System.out.print(" " + data[i]);
??????????????????????????? }
??????????????????????????
?????????????????????????? pos += 8;
?????????????????????????? println("\n--------The number of PLTE chunks is " + imageNbColors + "------------");
??
???????????
??????????????????????????? if (imageRGBColors == null)
????????????????????????????????????????? return null;
???????????????????????????
???????????????????????????? // 生成整形的PLTE chunk data
???????????????????????????? for( i = 0; i < imageNbColors; i++ )
???????????????????????????? {
?????????????????????????????????????????? imageRGBColors[i] = (
?????????????????????????????????????????????????????????????????????? (data[pos + 0] & 0x000000ff) << 16)
?????????????????????????????????????????????????????????????????????? | ((data[pos + 1] & 0x000000ff) <<

?????????????????????????????????????????????????????????????????????? | ((data[pos + 2] & 0x000000ff));
???????????????????????????????????????????????????????
?????????????????????????????????????????
????????????????????????????????????????? if( i % 10 == 0 && i != 0) {
??????????????????????????????????????????????????????? println("");
????????????????????????????????????????? }
????????????????????????????????????????? print(" " + imageRGBColors[i]);
????????????????????????????????????????? pos += 3;
??????????????????????????? }
???????????????????????????
??????????????????????????? // 修改 PLTE chunk data
??????????????????????????? switch (type)
??????????????????????????? {
????????????????????????????????????????? case 0:
??????????????????????????????????????????????????????? // don't modify
??????????????????????????????????????????????????????? break;
???????????????????????????????????????????????????????
????????????????????????????????????????? case 1: {
??????????????????????????????????????????????????????? int l,r,g,b;
??????????????????????????????????????????????????????? // gray
??????????????????????????????????????????????????????? for (j = 1; j < imageNbColors; j++) {
????????????????????????????????????????????????????????????????????? r = imageRGBColors[j];
????????????????????????????????????????????????????????????????????? g = (r & 0x00FF00) >> 8;
????????????????????????????????????????????????????????????????????? b = r & 0x0000FF;
????????????????????????????????????????????????????????????????????? r = (r & 0xFF0000) >> 16;
?????????????
????????????????????????????????????????????????????????????????????? l = (b + g * 6 + r * 3) / 16;
?????????????
????????????????????????????????????????????????????????????????????? imageRGBColors[j] = l << 16 | l << 8 | l;
??????????????????????????????????????????????????????? }
?????????????
??????????????????????????????????????????????????????? break;
????????????????????????????????????????? }
?????????????
????????????????????????????????????????? case 2: {
??????????????????????????????????????????????????????? // white
??????????????????????????????????????????????????????? for (j = 1; j < imageNbColors; j++)
????????????????????????????????????????????????????????????????????? imageRGBColors[j] = 0xFFFFFF;
?????????????
??????????????????????????????????????????????????????? break;
????????????????????????????????????????? }
?????????????
????????????????????????????????????????? case 3: {
??????????????????????????????????????????????????????? int l,r,g,b;
??????????????????????????????????????????????????????? // red
??????????????????????????????????????????????????????? for (j = 1; j < imageNbColors; j++) {
????????????????????????????????????????????????????????????????????? r = imageRGBColors[j];
????????????????????????????????????????????????????????????????????? g = (r & 0x00FF00) >> 8;
????????????????????????????????????????????????????????????????????? b = r & 0x0000FF;
????????????????????????????????????????????????????????????????????? r = (r & 0xFF0000) >> 16;
?????????????
????????????????????????????????????????????????????????????????????? l = (b + g * 6 + r * 3) / 10;
?????????????
????????????????????????????????????????????????????????????????????? imageRGBColors[j] = l << 16;
??????????????????????????????????????????????????????? }
?????????????
??????????????????????????????????????????????????????? break;
????????????????????????????????????????? }
??????????????????????????? }
???????????????????????????
??????????????????????????? // 生成新的 PLTE chunk data
??????????????????????????? pos = startPos + 8;
??????????????????????????? for( i = 0; i < imageNbColors ;i++)
??????????????????????????? {
????????????????????????????????????????? data[pos ] = (byte)((imageRGBColors[i] >> 16) ) ;
????????????????????????????????????????? data[pos + 1 ] = (byte)((imageRGBColors[i] >>

????????????????????????????????????????? data[pos + 2] = (byte)(imageRGBColors[i] );
????????????????????????????????????????? pos += 3;
??????????????????????????? }
??????????????????????????? // 更新 CRC 校驗碼
??????????????????????????? int crc = updateCrcChunk( data, startPos + 4, startPos + 4 + 4 + ( imageNbColors * 3 ) );
??????????????????????????? data[pos + 0] = (byte)(crc >> 24 & 0x000000FF);
??????????????????????????? data[pos + 1] = (byte)(crc >> 16 & 0x000000FF);
??????????????????????????? data[pos + 2] = (byte)(crc >> 8 & 0x000000FF);
??????????????????????????? data[pos + 3] = (byte)(crc & 0x000000FF);
???????????????????????????
??????????????????????????? pos = startPos;
??????????????????????????? println("\n---------------------New plte data crc " + crc +"--------------------------------");
??????????????????????????? for( i = 0; i < 4 + 4 + ( imageNbColors * 3 ) + 4; i++ )
??????????????????????????? {
????????????????????????????????????????? if( i >= 8 && (i -

??????????????????????????????????????????????????????? println("");
????????????????????????????????????????? }
????????????????????????????????????????? print(" " + data[pos + i]);
??????????????????????????? }
??????????????????????????? println("\n=========================End plte data-=================================");
???????????????????????????
??????????????????????????? return Image.createImage(data,0,data.length);
????????????? }
?????????????
????????????? /**
?????????????? * 修改png圖片的RGB數據
?????????????? * @param rgbSrc png圖片的RGB數據的字節數組
?????????????? * @return 新的RGB數據的字節數組
?????????????? */
????????????? public int[] changeRGBData(int[] rgbSrc)
????????????? {
??????????????????????????? int len = rgbSrc.length;
??????????????????????????? int[] ret = new int[len];
???????????????????????????
??????????????????????????? int a,r,g,b;
??????????????????????????? int tmp;
???????????????????????????
??????????????????????????? for( int i = 0; i < len; i++ )
??????????????????????????? {
????????????????????????????????????????? b = rgbSrc[i];
?????????????????????????????????????????
????????????????????????????????????????? a = ((b & 0xff000000) >> 24);
????????????????????????????????????????? r = ((b & 0x00ff0000) >> 16);
????????????????????????????????????????? g = ((b & 0x0000ff00) >>

????????????????????????????????????????? b = ((b & 0x000000ff) >> 0);
?????????????????????????????????????????
????????????????????????????????????????? // exchange red and blue
????????????????????????????????????????? tmp = r;
????????????????????????????????????????? r = b;
????????????????????????????????????????? b = tmp;
?????????????????????????????????????????
????????????????????????????????????????? ret[i] = (a << 24) | (r << 16) | (g <<

??????????????????????????? }
???????????????????????????
??????????????????????????? return ret;
????????????? }
?????????????
????????????? // CRC校驗表,加速CRC計算
????????????? static long crcTable[];
????????????? static public void makeCrcTable()
????????????? {
??????????????????????????? long c;
??????????????????????????? int n, k;
??????????????????????????? crcTable = new long[256];
??????????????????????????? for (n = 0; n < 256; n++) {
????????????????????????????????????????? c = (long) n;
????????????????????????????????????????? for (k = 0; k < 8; k++) {
??????????????????????????????????????????????????????? if ((c & 1) == 1) {
????????????????????????????????????????????????????????????????????? c = 0xEDB88320L ^ (c >> 1);
??????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? else {
????????????????????????????????????????????????????????????????????? c = c >> 1;
??????????????????????????????????????????????????????? }
????????????????????????????????????????? }
????????????????????????????????????????? crcTable[n] = c;
??????????????????????????? }
????????????? }
????????????? /**
?????????????? * 計算CRC校驗碼
?????????????? */
????????????? static public int updateCrcChunk(byte[] buf, int dataOffsetStart,int dataOffsetEnd)
????????????? {
??????????????????????????? long c = 0xFFFFFFFFL;
??????????????????????????? for (int i = dataOffsetStart; i < dataOffsetEnd; i++)
????????????????????????????????????????? c = (crcTable[(int) ((c ^ buf[i]) & 0xFF)] ^ (c >>

??????????????????????????? return (int) (c ^ 0xFFFFFFFFL);
????????????? }
}
//-----------------------------------------------------Code------END----------------------------------------------
//2
游戲幀速度處理
保持游戲在不同性能手機平臺的流暢性很重要,這就需要針對不通硬件設置相應合適的幀速度。假設一般
手機用戶能接受的游戲幀速為40/s 則相關參數和代碼如下:
//====================================================
// 游戲幀速度調整
//====================================================
??? private long framerate= 1000/40; // 設置幀速為每秒40幀,(25 ms / frame)
???? private long frameStart;? // 幀開始的時間time the frame begin????????
???? private long frameCount = 0; // 這一秒的幀數???
???? private long elapsedTime;? // 一幀消耗的時間?
???? private long totalElapsedTime = 0; // 多幀累計消耗的時間
???? private long reportedFramerate; // 實際計算出來的幀速
public void updateFrame()
{
? frameStart = System.currentTimeMillis();
? repaint();
? elapsedTime = System.currentTimeMillis() - frameStart;
?
? //幀速同步
? try {
?? if( elapsedTime < framerate ) {
??? Thread.sleep(framerate - elapsedTime);
?? }else {
??? Thread.sleep(5);
?? }
? }catch( Exception e ) {
?? e.printStackTrace();
? }
?
? //更新實際的幀速
? ++ frameCount;
? totalElapsedTime +=? (System.currentTimeMillis() - frameStart);
? if( totalElapsedTime > 1000 ) {
?? reportedFramerate = (long)((double)frameCount/(double)
totalElapsedTime*1000.0);
?? //在調試時可屏幕中顯示幀速
????????????? //g.drawString("fps: " + reportedFramerate,x,y,0);
????????????? frameCount = 0;
????????????? totalElapsedTime = 0;
? }
}
////3
J2me中實現淡入淡出效果
飄飄白云(l_zhaohui@163.com)
??? 在J2me中實現淡入淡出效果,據我所知至少有三種方法。
第一種是取得需要變換圖片的像素,依次設置每個象素的alpha通道值,讓它在0~100之間變化。
??? 第二種是修改圖片的調色板數據,讓其在調色板原始數據到255之間變化。
??? 第三種,其實也是利用上面的辦法,先描畫圖片,然后在圖片上覆蓋一個黑色矩形,改變這個黑色矩形透明度就可以實現淡入淡出的效果。
??? 前兩種方法相比較的話,第一種方法運算量是比較大的,而且第一種方法由于midp1.0不支持alpha通道,在一些手機上無法實現。
??? 下面給出第二種方法的示例,在我們開始之前,應該熟悉png文件格式,如果還不是很明白的話,可以google一下,或者查看前面的帖子中的相關連接。
??? 代碼很清楚,下面是源代碼:
------------CODE__START-----------------------
import java.io.DataInputStream;
import java.util.Timer;
import java.util.TimerTask;
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;
/**
* Discription????? : 修改調色板數據實現淡入淡出效果
* Author?????????? : 飄飄白云(l_zhaohui@163.com)
* Created date???? : 2006/07/13 18:06:39
* Modified history :
*/
public class PngFadeInOut extends MIDlet
{
?????????????????????????? GameCanvas canvas;
????????????????? Display display;
??????????????????????????? public PngFadeInOut()
??????????????????????????? {
????????????????????????????????????????? super();
????????????????????????????????????????? try {
????????????????????????? display = Display.getDisplay(this);
????????????????????????? canvas = new GameCanvas(this);
????????????????????? } catch (Exception e) {}
??????????????????????????? }
??????????????????????????? protected void startApp() throws MIDletStateChangeException
??????????????????????????? {
????????????????????????????????????????? if( canvas != null ){
??????????????????????????????????????????????????????? display.setCurrent(canvas);
??????????????????????????????????????????????????????? canvas.start();
????????????????????????????????????????? }
??????????????????????????? }
??????????????????????????? protected void pauseApp()
??????????????????????????? {
????????????????????????????????????????? canvas.isExit = true;
??????????????????????????? }
??????????????????????????? protected void destroyApp( boolean arg0) throws MIDletStateChangeException
??????????????????????????? {
??????????????????????????? }
????????????? }
????????????? class GameCanvas extends Canvas
????????????? {
??????????????????????????? static String imageName = "/fadeInOut.png";
??????????????????????????? public static final int??? MAX_TARDINESS = 30;
???????????????????????????
??????????????????????????? //---------------------------------------------------
??????????????????????????? PngFadeInOut app;
??????????????????????????? boolean isInited = false;
??????????????????????????? public boolean isExit = false;
??????????????????????????? Image offImage???????????? = null;
??????????????????????????? public Graphics???????????? g = null;
??????????????????????????? int scrW;
??????????????????????????? int scrH;
??????????????????????????? //---------------------------------------------------
??????????????????????????? int gameMode;
??????????????????????????? int subMode;
???????????????????????????
??????????????????????????? static final int smInit = 0;
??????????????????????????? static final int smProc = 1;
??????????????????????????? static final int smEnd = 2;
???????????????????????????
??????????????????????????? static final int gmStart = 0;
???????????????????????????
??????????????????????????? //---------------------------------------------------
??????????????????????????? Image testImage = null;
???????????????????????????
??????????????????????????? byte[] oldRGBData = null;
??????????????????????????? byte[] imgData = null;
???????????????????????????
??????????????????????????? static final int FADE_IN = 0;
??????????????????????????? static final int FADE_OUT = 1;
??????????????????????????? static final int FADE_STEP = 1;
???????????????????????????
??????????????????????????? static int fadeType = FADE_IN;
???????????????????????????
??????????????????????????? //---------------------------------------------------
??????????????????????????? //---Timer process
??????????????????????????? //---------------------------------------------------
??????????????????????????? TimerTask task;
??????????????????????????? Timer timer;
??????????????????????????? int timerDelayTime;
??????????????????????????? public boolean isTimerRunning;
???????????????????????????
??????????????????????????? void startTimer(int delayTime){
????????????????????????????????????????? timerDelayTime = delayTime;
????????????????????????????????????????? isTimerRunning = true;
?????????????????????????????????????????
????????????????????????????????????????? timer = new Timer();
????????????????????????????????????????? task = new ProcessingRunner();
????????????????????????????????????????? timer.scheduleAtFixedRate(task, 0, delayTime);
??????????????????????????? }
???????????????????????????
??????????????????????????? public void stopTimer(){
????????????????????????????????????????? if( task != null )
??????????????????????????????????????????????????????? task.cancel();
?????????????????????????????????????????
????????????????????????????????????????? isTimerRunning = false;
????????????????????????????????????????? timer = null;
????????????????????????????????????????? task = null;
??????????????????????????? }
??????????????????????????? //-----------------------------------------------------
??????????????????????????? class ProcessingRunner extends TimerTask
??????????????????????????? {
????????????????????????????????????????? public void run()
????????????????????????????????????????? {
??????????????????????????????????????????????????????? if( isExit ) {
????????????????????????????????????????????????????????????????????? stopTimer();
????????????????????????????????????????????????????????????????????? app.notifyDestroyed();
??????????????????????????????????????????????????????? }
???????????????????????????????????????????????????????
??????????????????????????????????????????????????????? if (!isTimerRunning || System.currentTimeMillis() -
??????????????????????????????????????????????????????????????????????????????????? scheduledExecutionTime() >= timerDelayTime)
??????????????????????????????????????????????????????? {
????????????????????????????????????????????????????????????????????? return;
??????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? gameMain();
??????????????????????????????????????????????????????? gameDraw();
???????????????????????????????????????????????????????
??????????????????????????????????????????????????????? repaint();
??????????????????????????????????????????????????????? serviceRepaints();
??????????????????????????????????????????????????????? System.gc();
????????????????????????????????????????? }
??????????????????????????? }
??????????????????????????? //-------------------------------------------------
???????????????????????????
??????????????????????????? public GameCanvas(MIDlet midlet)
??????????????????????????? {
????????????????????????????????????????? app = (PngFadeInOut)midlet;
??????????????????????????? }
?????????????
???????????????????????????
??????????????????????????? public void start()
??????????????????????????? {
????????????????????????????????????????? setFullScreenMode(true);
????????????????????????????????????????? while (!isShown())
??????????????????????????????????????????????????????? ;
?????????????????????????????????????????
????????????????????????????????????????? if( !isInited ) {
??????????????????????????????????????????????????????? gameInit();
??????????????????????????????????????????????????????? isInited = true;
????????????????????????????????????????? }
????????????????????????????????????????? startTimer(MAX_TARDINESS);
??????????????????????????? }
???????????????????????????
??????????????????????????? void gameInit()
??????????????????????????? {
????????????????????????????????????????? scrW = getWidth();
????????????????????????????????????????? scrH = getHeight();
????????????????????????????????????????? if(g == null || offImage == null) {
??????????????????????????????????????????????????????? offImage = Image.createImage(scrW, scrH);
????????????????????????????????????????????? g = offImage.getGraphics();
????????????????????????????????????????? }
?????????????????????????????????????????
????????????????????????????????????????? changeGameMode(gmStart);
??????????????????????????? }
??????????????????????????? public void changeGameMode(int gm){
????????????????????????????????????????? gameMode = gm;
????????????????????????????????????????? subMode = smInit;
??????????????????????????? }
???????????????????????????
??????????????????????????? //---------------------------------------------------
??????????????????????????? // 游戲主邏輯處理
??????????????????????????? //---------------------------------------------------
??????????????????????????? void gameMain()
??????????????????????????? {
????????????????????????????????????????? if( gameMode == gmStart )
????????????????????????????????????????? {
??????????????????????????????????????????????????????? if( subMode == smInit )
??????????????????????????????????????????????????????? {
????????????????????????????????????????????????????????????????????? // 取得圖片的二進制數據
????????????????????????????????????????????????????????????????????? imgData = loadFile(imageName);
???????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????? //保存原始圖片的調色板rgb數據
????????????????????????????????????????????????????????????????????? oldRGBData = getPlteRGBData(imgData);
???????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????? if( fadeType == FADE_IN) {
??????????????????????????????????????????????????????????????????????????????????? // 設置調色板顏色為白色,淡入效果
??????????????????????????????????????????????????????????????????????????????????? for(int i = rgbDataStartPos; i < rgbDataStartPos + rgbDataLength;i++ ) {
????????????????????????????????????????????????????????????????????????????????????????????????? imgData[i] = (byte)255;
??????????????????????????????????????????????????????????????????????????????????? }
????????????????????????????????????????????????????????????????????? }
????????????????????????????????????????????????????????????????????? // 生成新的圖片
????????????????????????????????????????????????????????????????????? testImage = createFadeImage(imgData,rgbDataStartPos,rgbDataLength);
????????????????????????????????????????????????????????????????????? subMode = smProc ;
??????????????????????????????????????????????????????? }
???????????????????????????????????????????????????????
??????????????????????????????????????????????????????? else if( subMode == smProc )
??????????????????????????????????????????????????????? {
????????????????????????????????????????????????????????????????????? try {
??????????????????????????????????????????????????????????????????????????????????? // 淡入淡出效果處理
??????????????????????????????????????????????????????????????????????????????????? fade(fadeType);
??????????????????????????????????????????????????????????????????????????????????? testImage = createFadeImage(imgData,rgbDataStartPos,rgbDataLength);
????????????????????????????????????????????????????????????????????? }
????????????????????????????????????????????????????????????????????? catch ( Exception e ) {
??????????????????????????????????????????????????????????????????????????????????? println("Create fade image error. \n" + e);
????????????????????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? }
????????????????????????????????????????? }
??????????????????????????? }
???????????????????????????
??????????????????????????? //---------------------------------------------------
??????????????????????????? // 游戲描畫處理
??????????????????????????? //---------------------------------------------------
???????????????????????????
??????????????????????????? protected void paint( Graphics _g){
????????????????????????????????????????? if( offImage != null)
??????????????????????????????????????????????????????? _g.drawImage(offImage, 0, 0, 0);
??????????????????????????? }
???????????????????????????
??????????????????????????? void gameDraw()
??????????????????????????? {
????????????????????????????????????????? if( gameMode == gmStart )
????????????????????????????????????????? {
??????????????????????????????????????????????????????? if( subMode == smProc ){
????????????????????????????????????????????????????????????????????? g.setColor(0xffffff);
????????????????????????????????????????????????????????????????????? g.fillRect(0,0,scrW,scrH);
????????????????????????????????????????????????????????????????????? g.drawImage(testImage,20,140,0);
??????????????????????????????????????????????????????? }
????????????????????????????????????????? }
??????????????????????????? }
???????????????????????????
??????????????????????????? /**
???????????????????????????? * 淡入淡出效果處理
???????????????????????????? * @param type
???????????????????????????? */
??????????????????????????? public void fade( int type)
??????????????????????????? {
????????????????????????????????????????? int m = 0;
????????????????????????????????????????? int n = 0;
????????????????????????????????????????? // 淡入
????????????????????????????????????????? if ( type == FADE_IN ) {
??????????????????????????????????????????????????????? for( int i = 0; i < rgbDataLength; i++ )
??????????????????????????????????????????????????????? {
????????????????????????????????????????????????????????????????????? m = imgData[rgbDataStartPos + i] & 0x000000ff;
????????????????????????????????????????????????????????????????????? n = oldRGBData[i] & 0x000000ff;
????????????????????????????????????????????????????????????????????? m = m < 0? m + 256 : m;
????????????????????????????????????????????????????????????????????? n = n < 0? n + 256 : n;
?????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????? m = m > n ? m - FADE_STEP : n;
?????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????? imgData[rgbDataStartPos + i] = (byte)(m & 0xff);
??????????????????????????????????????????????????????? }
????????????????????????????????????????? }
????????????????????????????????????????? // 淡出
????????????????????????????????????????? else if ( type == FADE_OUT ) {
??????????????????????????????????????????????????????? for( int i = 0; i < rgbDataLength; i++ )
??????????????????????????????????????????????????????? {
????????????????????????????????????????????????????????????????????? m = imgData[rgbDataStartPos + i] & 0x000000ff;
????????????????????????????????????????????????????????????????????? m = m < 0? m + 256 : m;
????????????????????????????????????????????????????????????????????? m = m < 255 ? m + FADE_STEP : 255;
?????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????? imgData[rgbDataStartPos + i] = (byte)(m & 0xff);
??????????????????????????????????????????????????????? }
????????????????????????????????????????? }
??????????????????????????? }
???????????????????????????
??????????????????????????? /**
???????????????????????????? * 這里不是單純創建一幅圖片,crc32校驗碼也在這個函數里更新
???????????????????????????? * @param data
???????????????????????????? * @param startPos 需要校驗的數據的起始位置
???????????????????????????? * @return
???????????????????????????? */
??????????????????????????? public Image createFadeImage(byte[] data,int startPos,int length)
??????????????????????????? {
????????????????????????????????????????? if (crcTable == null)
??????????????????????????????????????????????????????? makeCrcTable();
?????????????????????????????????????????
????????????????????????????????????????? int endPos = startPos + length ;
????????????????????????????????????????? int crc = updateCrcChunk( data, startPos -8,endPos );
????????????????????????????????????????? data[endPos + 0] = (byte)(crc >> 24 & 0x000000FF);
????????????????????????????????????????? data[endPos + 1] = (byte)(crc >> 16 & 0x000000FF);
????????????????????????????????????????? data[endPos + 2] = (byte)(crc >> 8 & 0x000000FF);
????????????????????????????????????????? data[endPos + 3] = (byte)(crc & 0x000000FF);
?????????????????????????????????????????
????????????????????????????????????????? return Image.createImage(data,0,data.length);
??????????????????????????? }
???????????????????????????
??????????????????????????? static int rgbDataStartPos = 0;
??????????????????????????? static int rgbDataLength = 0;
???????????????????????????
??????????????????????????? /**
???????????????????????????? * @param imgData png圖片的二進制數據
???????????????????????????? * @return 調色板顏色數據的字節數組
???????????????????????????? */
??????????????????????????? public byte[] getPlteRGBData(byte[] imgData)
??????????????????????????? {
????????????????????????????????????????? if (imgData == null || imgData.length <= 1)
??????????????????????????????????????????????????????? return null;
????????????????????????????????????????? // PLTE chunk數據域的類型標識
????????????????????????????????????????? // see http://www.w3.org/TR/PNG/#11PLTE
????????????????????????????????????????? String[] sPLTE = {"50", "4c", "54", "45"};
????????????????????????????????????????? int i;
????????????????????????????????????????? int pos = 0;
????????????????????????????????????????? //定位調色板數據的位置
????????????????????????????????????????? for (i = 0; i < imgData.length; i++)
????????????????????????????????????????? {
???????????????????????????????????? if (Integer.toHexString(imgData[i]).equals(sPLTE[0])
????????????????????????????????????????????????????????????? && Integer.toHexString(imgData[i + 1]).equals(sPLTE[1])
????????????????????????????????????????????????????????????? && Integer.toHexString(imgData[i + 2]).equals(sPLTE[2])
????????????????????????????????? && Integer.toHexString(imgData[i + 3]).equals(sPLTE[3]))
????????????????????????????????????? {
????????????????????????????????????????????????? pos = i;
????????????????????????????????????????????????? break;
????????????????????????????????????? }
????????????????????????????????????????? }
?????????????????????????????????????????
????????????????????????????????????????? pos -= 4;
????????????????????????????????????????? // 取得PLTE chunk的字節數據長度.
????????????????????????????????????????? int imageNbColors = (
????????????????????????????????????????????????????????????????????? ((imgData[pos] << 24) & 0xff000000)
????????????????????????????????????????????????????????????????????? | ((imgData[pos + 1] << 16) & 0x00ff0000)
????????????????????????????????????????????????????????????????????? | ((imgData[pos + 2] << 8 ) & 0x0000ff00)
????????????????????????????????????????????????????????????????????? | ((imgData[pos + 3]????? ) & 0x000000ff));
???????????????????????????
????????????????????????????????????????? //8 = 數據長度(4個字節) + 類型標識(4個字節)???????????
????????????????????????????????????????? pos += 8;
?????????????????????????????????????????
????????????????????????????????????????? // 設置全局變量
????????????????????????????????????????? rgbDataStartPos = pos;
????????????????????????????????????????? rgbDataLength = imageNbColors;
?????????????????????????????????????????
????????????????????????????????????????? //復制數據
????????????????????????????????????????? byte[] data = new byte[rgbDataLength ];
????????????????????????????????????????? for( i = 0 ; i < rgbDataLength ; i++){
??????????????????????????????????????????????????????? data[i] = imgData[i + rgbDataStartPos ];
????????????????????????????????????????? }
??????????????????????????????????????????
????????????????????????????????????????? return data;
??????????????????????????? }
???????????????????????????
??????????????????????????? // CRC校驗查找表,加速CRC32運算
??????????????????????????? static long crcTable[];
??????????????????????????? static public void makeCrcTable()
??????????????????????????? {
????????????????????????????????????????? long c;
????????????????????????????????????????? int n, k;
????????????????????????????????????????? crcTable = new long[256];
????????????????????????????????????????? for (n = 0; n < 256; n++) {
??????????????????????????????????????????????????????? c = (long) n;
??????????????????????????????????????????????????????? for (k = 0; k < 8; k++) {
????????????????????????????????????????????????????????????????????? if ((c & 1) == 1) {
??????????????????????????????????????????????????????????????????????????????????? c = 0xEDB88320L ^ (c >> 1);
????????????????????????????????????????????????????????????????????? }
????????????????????????????????????????????????????????????????????? else {
??????????????????????????????????????????????????????????????????????????????????? c = c >> 1;
????????????????????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? crcTable[n] = c;
????????????????????????????????????????? }
??????????????????????????? }
??????????????????????????? /**
???????????????????????????? * 計算crc32校驗碼
???????????????????????????? */
??????????????????????????? static public int updateCrcChunk(byte[] buf, int dataOffsetStart,int dataOffsetEnd)
??????????????????????????? {
????????????????????????????????????????? long c = 0xFFFFFFFFL;
????????????????????????????????????????? for (int i = dataOffsetStart; i < dataOffsetEnd; i++)
??????????????????????????????????????????????????????? c = (crcTable[(int) ((c ^ buf[i]) & 0xFF)] ^ (c >>

????????????????????????????????????????? return (int) (c ^ 0xFFFFFFFFL);
??????????????????????????? }
???????????????????????????
???????????????????????????
??????????????????????????? /**
???????????????????????????? * 讀取文件的二進制數據
???????????????????????????? * @param fileName 文件名
???????????????????????????? * @return 文件二進制數據
???????????????????????????? */
??????????????????????????? byte[] loadFile(String fileName)
??????????????????????????? {
????????????????????????????????????????? DataInputStream isr = null;
????????????????????????????????????????? byte[] bData;
????????????????????????????????????????? try {
??????????????????????????????????????????????????????? try {
????????????????????????????????????????????????????????????????????? isr = new DataInputStream(getClass().getResourceAsStream(fileName));
??????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? catch (Exception e) {
??????????????????????????????????????????????????????? }
???????????????????????????????????????????????????????
??????????????????????????????????????????????????????? int res_size = 0;
??????????????????????????????????????????????????????? while (isr.read() != -1)
????????????????????????????????????????????????????????????????????? res_size++;
??????????????????????????????????????????????????????? if (isr.markSupported())
????????????????????????????????????????????????????????????????????? isr.reset();
??????????????????????????????????????????????????????? else {
????????????????????????????????????????????????????????????????????? isr.close();
????????????????????????????????????????????????????????????????????? isr = new DataInputStream(getClass().getResourceAsStream(fileName));
??????????????????????????????????????????????????????? }
??????????????????????????????????????????????????????? bData = new byte[res_size];
??????????????????????????????????????????????????????? int read_bytes = isr.read(bData, 0, res_size);
??????????????????????????????????????????????????????? isr.close();
??????????????????????????????????????????????????????? System.gc();
??????????????????????????????????????????????????????? return bData;
????????????????????????????????????????? }
????????????????????????????????????????? catch (Exception e) {
??????????????????????????????????????????????????????? println("Error>>loadFile " + fileName);
??????????????????????????????????????????????????????? return null;
????????????????????????????????????????? }
??????????????????????????? }
???????????????????????????
??????????????????????????? static void println(String str){
????????????????????????????????????????? System.out.println( str );
??????????????????????????? }
???????????????????????????
????????????? }
----------------------CODE__END-------------------------------
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/liu01983zm/archive/2006/08/30/1143132.aspx
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
