打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
使用调色板修改png图片


这个算法是参考一位高人的文章,直接读取并修改png格式图片的调色板,然后生成新的调色板替代原来的。
这样可以实现游戏中常见的变色效果,可以解决游戏容量有限,不能存放太多精灵图片的问题。

具体过程其实并不复杂,大家可以先搜索资料,先看看png图片的格式定义。这个算法正是找到调色板区,根据原有格式修改之后,生成新的crc校验码,然后替换原来的调色板。这样就可以用一个png图片,创建多个变色副本。

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 = {0, 0, 0};        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()函数,只需要输入原始图片的byte数组,以及需要替换颜色的颜色值还有目标颜色值就行了。因为可以同时替换多个颜色,所以输入参数是代表颜色的整形的数组。总之,要保证原始颜色与目标颜色一一对应就好了。方法简单实用。

 


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
CRC循环校验 java代码实现
PNG文件结构分析
png图片的压缩与解压缩
整理:java整型数与网络字节序的 byte[] 数组转换关系
byte[]数组和int之间的转换
C# 在PC上的通过蓝牙(bluetooth)发送数据到手机
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服