?? palettedimage.java
字號(hào):
import java.io.InputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.microedition.lcdui.Image;
/**
* PalettedImage調(diào)色板圖片類,使用PNG-8圖片,可更換其中的顏色。 <br>
* 注意,除了更換調(diào)色板中的顏色之外,這個(gè)類實(shí)際上是不可更改的Image。
*
* @author flyingghost
* @version 1.0
*/
public final class PalettedImage {
private Image image;//生成的圖片
private byte[] imgData;//圖片字節(jié)數(shù)據(jù)
private int paletteOffset;//調(diào)色板偏移量
private int CRCOffset;//CRC校驗(yàn)碼偏移量
private int paletteColors;//調(diào)色板顏色數(shù)
private boolean needRebuild;//改變,需要重建立圖片
private PalettedImage() {
}
/**
* 從字節(jié)數(shù)組中創(chuàng)建PalettedImage
*
* @param data
* 存放png圖片的字節(jié)數(shù)組
* @return PalettedImage對(duì)象
* @throws NullPointerException
* 當(dāng)data數(shù)組為空時(shí)
*/
public static PalettedImage createPalettedImage(byte[] data) {
if (data == null) {
throw new NullPointerException();
}
PalettedImage pImage = null;
pImage = new PalettedImage();
pImage.imgData = data;
pImage.analyze();
pImage.image = Image.createImage(pImage.imgData, 0,
pImage.imgData.length);
return pImage;
}
/**
* 從圖片文件中創(chuàng)建PalettedImage
*
* @param filename
* png圖片文件路徑
* @return PalettedImage對(duì)象
* @throws NullPointerException
* 當(dāng)filename為空時(shí)
* @throws IllegalArgumentException
* 當(dāng)路徑無效的時(shí)候
* @throws IOException
* 當(dāng)發(fā)生IO錯(cuò)誤時(shí)
*/
public static PalettedImage createPalettedImage(String filename)
throws IOException {
if (filename == null) {
throw new NullPointerException();
}
PalettedImage pImage = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
try {
is = filename.getClass().getResourceAsStream(filename);
if (is == null) {//創(chuàng)建不成功
throw new IllegalArgumentException();
}
baos = new ByteArrayOutputStream();
int ch = 0;
while ((ch = is.read()) != -1) {
baos.write(ch);
}
}
catch (IOException ioe) {
throw ioe;
}
finally {
if (baos != null) {
try {
baos.close();
}
catch (IOException e) {
}
}
if (is != null) {
try {
is.close();
}
catch (IOException e) {
}
}
}
pImage = createPalettedImage(baos.toByteArray());
return pImage;
}
/**
* 取得生成的Image對(duì)象
*
* @return Image對(duì)象
*/
public Image getImage() {
if (needRebuild) {
rebuild();
}
return image;
}
/**
* 設(shè)置調(diào)色板
*
* @param colors
* 調(diào)色板的所有顏色數(shù)組
* @throws NullPointerException
* 如果顏色數(shù)組為空
* @throws IllegalArgumentException
* 顏色數(shù)組長度和顏色個(gè)數(shù)不符
*/
public void setPalette(int[] colors) {
if (colors == null) {
throw new NullPointerException();
}
if (colors.length != paletteColors) {//長度不符
throw new IllegalArgumentException();
}
for (int i = 0, offset = paletteOffset; i < colors.length; i++, offset += 3) {
imgData[offset] = (byte) ((colors[i] >> 16) & 0xff);
imgData[offset + 1] = (byte) ((colors[i] >> 8) & 0xff);
imgData[offset + 2] = (byte) ((colors[i]) & 0xff);
}
needRebuild = true;
}
/**
* 取得調(diào)色板的顏色數(shù)
*
* @return 顏色數(shù)
*/
public int getColorCount() {
return paletteColors;
}
/**
* 設(shè)置某種顏色
*
* @param index
* 顏色索引號(hào)
* @param color
* 新的顏色值,以0xRRGGBB的格式
* @throws IllegalArgumentException
* 當(dāng)索引號(hào)不在范圍內(nèi)時(shí)
*/
public void setColor(int index, int color) {
if (index < 0 || index >= paletteColors) {
throw new IllegalArgumentException();
}
int offset = paletteOffset + index * 3;
imgData[offset] = (byte) ((color >> 16) & 0xff);
imgData[offset + 1] = (byte) ((color >> 8) & 0xff);
imgData[offset + 2] = (byte) ((color) & 0xff);
needRebuild = true;
}
/**
* 替換某種顏色
*
* @param oldColor
* 要替換的顏色值,0xRRGGBB格式
* @param newColor
* 新的顏色值,0xRRGGBB格式
*/
public void replaceColor(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 = paletteOffset; i < paletteColors; i++, offset += 3) {
if (rr == imgData[offset] && gg == imgData[offset + 1]
&& bb == imgData[offset + 2]) {//找到
imgData[offset] = (byte) ((newColor >> 16) & 0xff);
imgData[offset + 1] = (byte) ((newColor >> 8) & 0xff);
imgData[offset + 2] = (byte) (newColor & 0xff);
needRebuild = true;
break;
}
}
}
/**
* 取得調(diào)色板顏色
*
* @param index
* 顏色索引號(hào)
* @return int形式的顏色值
* @throws IllegalArgumentException
* 當(dāng)索引號(hào)不在范圍內(nèi)時(shí)
*/
public int getColor(int index) {
if (index < 0 || index >= paletteColors) {
throw new IllegalArgumentException();
}
int offset = paletteOffset + index * 3;
return ((imgData[offset] & 0xFF) << 16)
| ((imgData[offset + 1] & 0xFF) << 8)
| (imgData[offset + 2] & 0xFF);
}
private void rebuild() {//根據(jù)新的字節(jié)數(shù)據(jù)重建Image
CRCChecksum();//重新計(jì)算校驗(yàn)和
image = Image.createImage(imgData, 0, imgData.length);
needRebuild = false;
System.gc();
}
private void analyze() {//分析調(diào)色板相關(guān)資料
int offset = 8;//跳過8字節(jié)的PNG頭,遍歷每個(gè)塊
int chunkLen = 0;
while (imgData[offset + 4] != 0x50 || imgData[offset + 5] != 0x4c
|| imgData[offset + 6] != 0x54 || imgData[offset + 7] != 0x45) {//offset指向的塊名稱不是PLTE
chunkLen = readInt(offset);
offset += (4 + 4 + chunkLen + 4);
}
chunkLen = readInt(offset);//塊長
paletteColors = chunkLen / 3;//顏色數(shù)
paletteOffset = offset + 8;//調(diào)色板偏移量
CRCOffset = offset + 8 + chunkLen;//CRC校驗(yàn)碼偏移量
}
private int readInt(int offset) {//讀一個(gè)int
return ((imgData[offset] & 0xFF) << 24)
| ((imgData[offset + 1] & 0xFF) << 16)
| ((imgData[offset + 2] & 0xFF) << 8)
| (imgData[offset + 3] & 0xFF);
}
private void CRCChecksum() {//求得新的校驗(yàn)和
int checksum = CRCUtil.checksum(imgData, paletteOffset - 4,
paletteColors * 3 + 4);
imgData[CRCOffset] = (byte) ((checksum >> 24) & 0xff);
imgData[CRCOffset + 1] = (byte) ((checksum >> 16) & 0xff);
imgData[CRCOffset + 2] = (byte) ((checksum >> 8) & 0xff);
imgData[CRCOffset + 3] = (byte) ((checksum) & 0xff);
}
}
final class CRCUtil {
private static int[] crc_table;//CRC 表
private static void make_crc_table() {
int c;
int n, k;
crc_table = new int[256];
for (n = 0; n < 256; n++) {
c = n;
for (k = 0; k < 8; k++) {
if ((c & 1) == 1)
c = 0xedb88320 ^ (c >>> 1);
else
c = c >>> 1;
}
crc_table[n] = c;
}
}
private static int update_crc(byte[] buf, int off, int len) {
int c = 0xffffffff;
int n;
if (crc_table == null) {
make_crc_table();
}
for (n = off; n < len + off; n++) {
c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >>> 8);
}
return c;
}
static int checksum(byte[] buf, int off, int len) {
return update_crc(buf, off, len) ^ 0xffffffff;
}
CRCUtil() {
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -