Look into it ~

          present
          隨筆 - 32, 文章 - 0, 評(píng)論 - 3, 引用 - 0

          導(dǎo)航

          <2008年8月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          常用鏈接

          留言簿(2)

          隨筆分類

          隨筆檔案

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          修改png圖的調(diào)色板

          今天在硬盤上挖出這個(gè)存放了幾年的代碼。又回憶起3年前的那個(gè)j2me手機(jī)游戲程序員……

          這個(gè)算法是參考一位高人的文章,直接讀取并修改png格式圖片的調(diào)色板,然后生成新的調(diào)色板替代原來的。
          這樣可以實(shí)現(xiàn)游戲中常見的變色效果,可以解決游戲容量有限,不能存放太多精靈圖片的問題。

          具體過程其實(shí)并不復(fù)雜,大家可以先搜索資料,先看看png圖片的格式定義。這個(gè)算法正是找到調(diào)色板區(qū),根據(jù)原有格式修改之后,生成新的crc校驗(yàn)碼,然后替換原來的調(diào)色板。這樣就可以用一個(gè)png圖片,創(chuàng)建多個(gè)變色副本。
          public class PalettedImage {
           
              
          public Image getPalettedImage(byte[] data, int[] originalColors,
                      
          int[] palettedColors) {
                  
          byte[] tempData = new byte[data.length];
                  System.arraycopy(data, 
          0, tempData, 0, data.length);
                  Image img 
          = null;
                  
          int[] parameter = { 000 };
                  analyze(tempData, parameter);
                  
          for (int i = 0; i < originalColors.length; i++) {
                      replaceColor(tempData, parameter, originalColors[i],
                              palettedColors[i]);
                  }
                  fillData(tempData, parameter);
                  
          try {
                      img 
          = Image.createImage(tempData, 0, data.length);
                  } 
          catch (Exception e) {
                      System.out.println(
          "getPalettedImage  &&  " + e.toString());
                  }
                  
          return img;
              }
           
              
          private void analyze(byte[] data, int[] para) {
                  
          int offset = 8;
                  
          int chunkLen = 0;
                  
          while (data[offset + 4!= 0x50 || data[offset + 5!= 0x4c
                          
          || data[offset + 6!= 0x54 || data[offset + 7!= 0x45) {
                      chunkLen 
          = readInt(data, offset);
                      offset 
          += (4 + 4 + chunkLen + 4);
                  }
                  chunkLen 
          = readInt(data, offset);
                  para[
          2= chunkLen / 3;
                  para[
          0= offset + 8;
                  para[
          1= offset + 8 + chunkLen;
              }
           
              
          private int readInt(byte[] data, int offset) {
                  
          return ((data[offset] & 0xFF<< 24)
                          
          | ((data[offset + 1& 0xFF<< 16)
                          
          | ((data[offset + 2& 0xFF<< 8| (data[offset + 3& 0xFF);
              }
           
              
          private void replaceColor(byte[] data, int[] para, int oldColor,
                      
          int newColor) {
                  
          byte rr = (byte) ((oldColor >> 16& 0xff);
                  
          byte gg = (byte) ((oldColor >> 8& 0xff);
                  
          byte bb = (byte) (oldColor & 0xff);
                  
          for (int i = 0, offset = para[0], temp = 0; i < para[2]; i++, offset += 3) {
                      
          if (rr == data[offset] && gg == data[offset + 1]
                              
          && bb == data[offset + 2]) {
                          data[offset] 
          = (byte) ((newColor >> 16& 0xff);
                          data[offset 
          + 1= (byte) ((newColor >> 8& 0xff);
                          data[offset 
          + 2= (byte) (newColor & 0xff);
                          
          break;
                      }
                  }
              }
           
              
          private void fillData(byte[] data, int[] para) {
                  
          int checksum = update_crc(data, para[0- 4, para[2* 3 + 4);
                  data[para[
          1]] = (byte) ((checksum >> 24& 0xff);
                  data[para[
          1+ 1= (byte) ((checksum >> 16& 0xff);
                  data[para[
          1+ 2= (byte) ((checksum >> 8& 0xff);
                  data[para[
          1+ 3= (byte) ((checksum) & 0xff);
              }
           
              
          private int update_crc(byte[] buf, int off, int len) {
                  
          int c = 0xffffffff;
                  
          int n, k;
                  
          int xx;
                  
          int[] crc_table = new int[256];
                  
          for (n = 0; n < 256; n++) {
                      xx 
          = n;
                      
          for (k = 0; k < 8; k++) {
                          
          if ((xx & 1== 1) {
                              xx 
          = 0xedb88320 ^ (xx >>> 1);
                          } 
          else {
                              xx 
          = xx >>> 1;
                          }
                      }
                      crc_table[n] 
          = xx;
                  }
           
                  
          for (n = off; n < len + off; n++) {
                      c 
          = crc_table[(c ^ buf[n]) & 0xff^ (c >>> 8);
                  }
                  
          return (c ^ 0xffffffff);
              }
           
          }


          接口就是getPalettedImage()函數(shù),只需要輸入原始圖片的byte數(shù)組,以及需要替換顏色的顏色值還有目標(biāo)顏色值就行了。因?yàn)榭梢酝瑫r(shí)替換多個(gè)顏色,所以輸入?yún)?shù)是代表顏色的整形的數(shù)組。總之,要保證原始顏色與目標(biāo)顏色一一對(duì)應(yīng)就好了。方法簡單實(shí)用。

          歡迎大家使用并留下寶貴的意見。當(dāng)然,也可以修改一下這個(gè)函數(shù),做一些特殊的效果。這里就不多說了。
          不過這個(gè)代碼用處已經(jīng)不大,因?yàn)楝F(xiàn)在的手機(jī)基本上都支持midp2.0所以可以使用更方便的方法替換顏色。

          總之,再次感謝這位已經(jīng)被我忘掉名字的大俠,關(guān)鍵代碼是他寫的,我只是修改整理而已。

          posted on 2008-08-15 14:34 LukeW 閱讀(620) 評(píng)論(0)  編輯  收藏 所屬分類: Tips, Tricks, Hints & Code

          主站蜘蛛池模板: 乐东| 集安市| 巴青县| 阿城市| 台州市| 平阳县| 旬邑县| 睢宁县| 铁力市| 万源市| 攀枝花市| 喀喇| 依兰县| 大港区| 佳木斯市| 通辽市| 昌平区| 渭源县| 华坪县| 荣昌县| 莱州市| 交城县| 兴仁县| 常德市| 汾阳市| 定边县| 桓台县| 左云县| 西昌市| 同江市| 洞口县| 永嘉县| 孝昌县| 克拉玛依市| 濮阳市| 会宁县| 垦利县| 西峡县| 梁山县| 大悟县| 隆回县|