使用调色板修改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数组,以及需要替换颜色的颜色值还有目标颜色值就行了。因为可以同时替换多个颜色,所以输入参数是代表颜色的整形的数组。总之,要保证原始颜色与目标颜色一一对应就好了。方法简单实用。



昨天研究了BB同志发的算法一文,实验了一晚上,终于有点收获,发出来给大家共享.

我查阅了很多关于Png格式的文章,最后得到的心得就是,对于"索引类型的图片",即肯定包含PLTE调色板的Png图片,就可以通过对调色板的修改,再通过CRC算法生成新的验证码,再还原成新图片就可以得到所要的效果,为此,我写了如下的类.

/*
 用于PNG图片变色的类
 使用要求,需要美工将原始图片的需要换色的点
 设置为纯红色0xff0000
 */
import java.io.*;
import java.lang.*;
import javax.microedition.lcdui.*;
 
public class coloredImage {
    public coloredImage() {
    }
 
    public Image getColoredImage(String s, int newcolor) {
        try {
            byte[] pixel;
            InputStream is = getClass().getResourceAsStream(s);
            int i = 0;
            while (is.read() != -1) {
                i++;
            }
            pixel = new byte[i];
            is = null;
            is = getClass().getResourceAsStream(s);
            is.read(pixel);
            imgConvert(pixel, newcolor);
            return (Image.createImage(pixel, 0, pixel.length));
        } catch (Exception e) {
            return null;
        }
    }
 
    public void imgConvert(byte content[], int color) {
        try {
            int start = 0;
            int newcolor = -1;
            for (int idx = 0; idx < 8; idx++) {
                if (content[idx] == 0x50 && content[idx + 1] == 0x4c
                    && content[idx + 2] == 0x54 && content[idx + 3] == 0x45) {
                    start = idx;
                }
            }
            for (int idx = 0; idx < 4; idx++) {
                newcolor = pixelConvert(content[start + idx], newcolor);
            }
            int r, g, b, length;
            length = (content[start - 4] & 0xff << 24) |
                     (content[start - 3] & 0xff << 16) |
                     (content[start - 2] & 0xff << 8) |
                     (content[start - 1] & 0xff);
            for (int i = 0; i < length; i++) {
                r = content[start + 4 + i] & 0xff;
                g = content[start + 4 + i + 1] & 0xff;
                b = content[start + 4 + i + 2] & 0xff;
                if (r == 255 && g == 0 && b == 0) {
                    r = color >> 16 & 0xff;
                    g = color >> 8 & 0xff;
                    b = color & 0xff;
                    content[start + 4 + i] = (byte) r;
                    content[start + 4 + i + 1] = (byte) g;
                    content[start + 4 + i + 2] = (byte) b;
                }
                newcolor = pixelConvert(content[start + 4 + i], newcolor);
                newcolor = pixelConvert(content[start + 4 + i + 1], newcolor);
                newcolor = pixelConvert(content[start + 4 + i + 2], newcolor);
            }
            newcolor = ~newcolor;
            content[start + 4 + length] = (byte) (newcolor >> 24);
            content[start + 4 + length + 1] = (byte) (newcolor >> 16);
            content[start + 4 + length + 2] = (byte) (newcolor >> 8);
            content[start + 4 + length + 3] = (byte) (newcolor);
        } catch (Exception e) {}
    }
 
    /**
     * CRC检验算法
     * @param pixel 像素
     * @param color 颜色值
     * @return
     */
    public int pixelConvert(byte pixel, int color) {
        int tmp = pixel & 0xff;
        color ^= tmp;
        for (int idx = 0; idx < 8; idx++) {
            if ((color & 1) != 0) {
                color = color >>> 1 ^ 0xedb88320;
            } else {
                color >>>= 1;
            }
        }
        return color;
    }
}
这个类提供了一个转换图片颜色的方法getColoredImage,只要将源图片的路径以及需要转换的新颜色作为参数调用就可以得到转换后的图片.

相应的我把我的主类写出来供大家参考其用法.
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.*;
import com.nokia.mid.ui.*;
import java.io.*;
 
public class pengzhuang extends MIDlet {
    class test extends FullCanvas {
        Image[] a;
        byte[] pix;
        coloredImage ci;
        public test() {
            ci = new coloredImage();
            a = new Image[4];
            a[0] = ci.getColoredImage("/char.png", 0x0000ff);
            a[1] = ci.getColoredImage("/char.png", 0x00ff00);
            a[2] = ci.getColoredImage("/char.png", 0xffffff);
            a[3] = ci.getColoredImage("/char.png", 0x00ffff);
        }
 
        public void keyPressed(int i) {
        }
 
        public void paint(Graphics g) {
            g.setColor(0xffffff);
            g.fillRect(0, 0, getWidth(), getHeight());
            g.drawImage(a[0], 0, 0, 0);
            g.drawImage(a[1], 30, 30, 0);
            g.drawImage(a[2], 60, 60, 0);
            g.drawImage(a[3], 90, 90, 0);
        }
    }
 
 
    private Display display;
    test t;
    public pengzhuang() {
        try {
            t = new test();
        } catch (Exception e) {
        }
        display = Display.getDisplay(this);
    }
 
    public void startApp() {
        display.setCurrent(t);
    }
 
    public void pauseApp() {
 
    }
 
    public void destroyApp(boolean boo) {
 
    }
}

其中用到的源图是

 

 

运行程序后的效果为

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/31943.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android图像处理系列之三--图片色调饱和度、色相、亮度处理

原图&#xff1a; 处理后&#xff1a; 下面贴代码&#xff1a; 一、图片处理层&#xff1a; package com.jacp.tone.view;import java.util.ArrayList;import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.gra…

图片调色学习

色相环 色相混合正红&#xff08;0&#xff09;正黄&#xff08;60&#xff09;&#xff0c;透明度为&#xff08;50%&#xff09;即红黄等比例混合橙色&#xff08;30&#xff09; (060&#xff09;/230 真实调整透明度混合出并不一定为两者均值的色相,需要选择不同的混合方法…

图片颜色调节

云区 粉色云彩&#xff1a; 粉色云彩&#xff1a; 打开星图&#xff0c;清新滤镜马卡龙&#xff0c; 调节打开智能优化&#xff0c; 降低光感-100&#xff08;根据图片调&#xff09;、 色温最高、 色调最高&#xff0c; 增加结构让云更清晰&#xff0c; 增加饱和度。 晚霞&a…

excel如何快速将英文表格翻译为中文表格

1.打开excel&#xff0c;如下图想要快速将英文表格翻译为中 2.首先我们全选要翻译的表格区域单元格&#xff0c;接着点击【DIY工具箱】 ​ 3.点击【翻译】&#xff0c;选择【有道翻译】 4.接着鼠标点击【开始】 5.最后点击【确定】即可 6.完成效果如下图

CV大模型应用:Grounded-Segment-Anything实现目标分割、检测与风格迁移

Grounded-Segment-Anything实现目标分割、检测与风格迁移 文章目录 Grounded-Segment-Anything实现目标分割、检测与风格迁移一、Segment-Anything介绍二、Grounded-Segment-Anything1、简介2、测试 一、Segment-Anything介绍 代码链接&#xff1a;https://github.com/faceboo…

计算机视觉的应用6-利用VGG模型做毕加索风格图像迁移

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下计算机视觉的应用5-利用VGG模型做毕加索风格图像迁移&#xff0c;本文将利用VGG模型实现毕加索风格图像迁移的方法。首先&#xff0c;我们将简要说明图像风格迁移的原理&#xff0c;然后使用PyTorch框架&#xff0c…

如何让ChatGPT帮我们提高开发效率

3 天前 ChatGPT云炬学长 ​关注 ChatGPT非常可怕&#xff01;才不到短短的几个月时间有上亿用户。 火爆程度以至于官方都不得不暂停plus用户的升级&#xff0c;以缓解压力。 ChatGPT能够发展那么快&#xff0c;确实是因为他真的很强大&#xff01; 能帮我们做ppt、帮我们做…

《联众》并购案细节公布,海虹海外公司浮出水面(ZT)

《联众》一夜身价暴增到2亿美金&#xff0c;《海虹>以及联众创始人成功套现1亿美金&#xff01;这是中韩国际资本合作的典范&#xff1f;还是海外资本的大举进攻的信号&#xff1f;或者就是互联网第二次井喷的前奏&#xff1f;在历史给予答案之前&#xff0c;让我们理顺并购…

微信授权登录:移动端[unionid](一)

专栏简介 &#x1f492;个人主页 &#x1f4c4;本栏目录 &#x1f4d6;心灵鸡汤&#x1f4d6; 生活中其实没有绝境&#xff0c;绝境在于你自己的心没有打开。 ✍相关博文✍ 微信分享开发&#xff1a;准备工作微信PC端扫码登录 如果你有…

第三方对接-微信登陆对接

对接第三方之微信登陆 由于目前市面上社交软件的使用排行来看&#xff0c;基本上微信一马当先。因此在大多数应用上都会内置微信登陆的场景&#xff0c;这时候我们就非常有必要熟悉微信的登录流程。 微信登陆 微信官方开发文档说明目前移动应用上微信登录仅支持原生登陆方式…

对三大数学软件 Mathematica 、Maple 、MATLAB 的小测试比较

今天一时兴起&#xff0c;突然想试试几个数学软件的功能&#xff0c;就测试了一个不定积分&#xff0c;看看哪个算得最好&#xff0c;最简洁。 计算&#xff1a; 以下计算结果我都一一验算了。 1).先在Mathematica&#xff08;我用的是在线的wolframalpha&#xff09;中计算,结…

【计算机图形学(译)】 二、各种各样的数学

【计算机图形学(译&#xff09;】 二、各种各样的数学 2 各种各样的数学 Miscellaneous Math2.1 集合和映射 Sets and Mapping2.1.1 反向映射 Inverse Mappings2.1.2 区间 Intervalsoft2.1.3 对数 Logarithms 2.2 解二次方程 Solving Quadratic Equations2.3 三角学 Trigonomet…

和托托一起学计算机图形学(一)-初识计算机图形学

文章目录 初识计算机图形学一、计算机科学与视觉信息处理二、计算机图形学的应用三、总结 数字图像基础一、像素二、RGB和CMY颜色模型三、颜色编码四、查色表五、图像文件六、总结 初识计算机图形学 一、计算机科学与视觉信息处理 计算机图形学&#xff1a;建模&#xff08;建…

如何使用 ChatGPT 掌握讲故事的艺术

想出一个故事情节&#xff0c;虽然有时很有趣&#xff0c;但可能是一个耗时的过程。或者你可能会发现自己遇到了作家的障碍——每个作家存在的祸根。 这个重要的灵感火花是 ChatGPT 可以提供帮助的地方。OpenAI流行的文本生成聊天机器人可以协助写作过程的任何部分&#xff0c…

仅剩1位73岁开发者苦撑!能求解超复杂物理方程式的计算程序,要没人维护了...

明敏 Alex 发自 凹非寺量子位 | 公众号 QbitAI 高能物理先进计算必备程序之一&#xff0c;快要没人维护了。 随着唯一的长期维护者达到73岁高龄&#xff0c;计算系统FORM的命运开始变得扑朔迷离起来。 过去30多年&#xff0c;这个程序被视为粒子物理学研究的基础工具之一&#…

苹果的头显,只要看一眼就行

阅读本文大概需要 1.66 分钟。 今年的 WWDC23 开发者大会&#xff0c;不少人表示 iOS 更新了个寂寞&#xff0c;但 Vision Pro 头显却意外吸引眼球&#xff0c;看来苹果工程师都忙着搞头显去了。 苹果的头显终于还是来了&#xff0c;关于它的传闻&#xff0c;似乎这几年从未间断…

AN OVERVIEW OF LANGUAGE MODELS RECENT DEVELOPMENTS AND OUTLOOK

LLM系列相关文章&#xff0c;针对《AN OVERVIEW OF LANGUAGE MODELS: RECENT DEVELOPMENTS AND OUTLOOK》的翻译。 语言模型综述&#xff1a;近年来的发展与展望 摘要1 引言2 语言模型的类型2.1 结构化LM2.2 双向LM2.3 置换LM 3 语言单元3.1 字符3.2 单词和子单词3.2.1 基于统…

使用 Sealos 三分钟打造鉴黄神器,我有个大胆的想法……

"NSFW" 是 "Not Safe For Work" 的缩写&#xff0c;通常用于标记那些在工作场所可能不适当的的在线内容。这种内容可能包含暴力、色情、血腥、或者其他可能被认为是令人反感或冒犯的材料&#xff0c;最常见的原因……是 18 成人内容。在许多在线平台&#…

8年前端带你HTML+CSS入门到实战(附视频+源码)

本文主要是解决&#xff1a; ☆ 想要自学前端开发&#xff0c; ☆ 但又不太想看博客文章&#xff0c; ☆ 觉得自学有点吃力&#xff0c;有点不知道学习步骤的同学 目录 一、HTML 1、需要了解熟练的标签 2、不太常用的标签 3、怎么算是HTML学好了&#xff0c;可以继续学CSS了…

NLP中的词向量对比:word2vec/glove/fastText/elmo/GPT/bert

点击上方&#xff0c;选择星标或置顶&#xff0c;每天给你送干货&#xff01; 阅读大概需要15分钟 跟随小博主&#xff0c;每天进步一丢丢 作者&#xff1a;JayLou&#xff0c;NLP算法工程师 知乎专栏&#xff1a;高能NLP之路 地址&#xff1a;https://zhuanlan.zhihu.com/p/56…