📄 pngresource.java
字号:
import java.io.IOException;
import java.io.InputStream;
import javax.microedition.lcdui.Image;
/*
* @(#) PNGResource.java 2006-4-4
*
* Copyright 2005-2006 城市边缘工作室.All rights reserved.
* Use is subject to license term
*/
public class PNGResource {
// 定义标志PNG文件的标识数据
private final byte[] MARK_FILE = { (byte) 0x89, (byte) 0x50, (byte) 0x4E,
(byte) 0x47, (byte) 0x0D, (byte) 0x0A, (byte) 0x1A, (byte) 0x0A };
// 定义标志PNG文件头的标识数据
private final byte[] MARK_HEADER = { (byte) 0x49, (byte) 0x48, (byte) 0x44,
(byte) 0x52 };
// 定义标志PNG文件调色板的标识数据
private final byte[] MARK_PALETTE = { (byte) 0x50, (byte) 0x4C,
(byte) 0x54, (byte) 0x45 };
// 定义标志PNG文件透明度的标识数据
private final byte[] MARK_TRANS = { (byte) 0x74, (byte) 0x52, (byte) 0x4E,
(byte) 0x53 };
// 定义标志PNG文件数据的标识数据
private final byte[] MARK_IDAT = { (byte) 0x49, (byte) 0x44, (byte) 0x41,
(byte) 0x54 };
// 定义标志PNG文件结束的标识数据
private final byte[] MARK_END = { (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x49, (byte) 0x45, (byte) 0x4E, (byte) 0x44,
(byte) 0xAE, (byte) 0x42, (byte) 0x60, (byte) 0x82 };
// 定义CRC的数据
private final int[] CRC_TABLE_ = new int[256];
// 定义PNG文件的输入流
private InputStream is_ = null;
// 定义资源文件中PNG文件的数目
private int file_number_ = 0;
// 定义当前已经装载范围的开始
private byte from_ = 0;
// 定义当前已经装载范围的结束
private byte to_ = 0;
// 各个PNG文件在资源文件中的偏移量
private int[] address_ = null;
// 定义Image对列主要用于存储PNG文件
private Image[] images_ = null;
// 定义资源文件名
private String file_name_ = null;
/**
* PNGResource的构造函数,主要完成crc数据的构造
*
*/
public PNGResource() {
for (int n = 0, c = 0; n < 256; n++) {
c = n;
for (int k = 0; k < 8; k++) {
c = (((c & 1) == 1)) ? (0xedb88320 ^ (c >>> 1)) : (c >>> 1);
}
CRC_TABLE_[n] = c;
}
}
/**
* 打开PNG资源文件,并检测是否正确和进行定位
*
* @param filename
* @return
*/
public int open(String filename) {
if ((is_ = getClass().getResourceAsStream(filename)) == null) {
// 资源装载失败返回-1
return -1;
}
file_name_ = filename;
byte[] file_number = new byte[2];
boolean succeed = true;
try {
is_.read(file_number, 0, 2);
file_number_ = get_int_from_bytes(file_number);
System.out.println("file_number = " + file_number_);
address_ = new int[file_number_ + 1];
images_ = new Image[file_number_];
int i, offset = 2;
for (i = 0; i < file_number_; i++) {
address_[i] = offset;
offset += 6;
is_.skip(6);
byte[] colors = new byte[2];
is_.read(colors, 0, 2);
int skip = get_int_from_bytes(colors) * 3;
//System.out.println("skip 1 = " + skip);
offset += 2 + skip;
is_.skip(skip);
byte[] trans = new byte[1];
is_.read(trans, 0, 1);
offset++;
if (trans[0] == 1) {
byte[] l = new byte[2];
is_.read(l, 0, 2);
skip = get_int_from_bytes(l);
offset += (skip + 2);
is_.skip(skip);
}
byte[] datas = new byte[1];
is_.read(datas, 0, 1);
offset++;
byte[] d = new byte[4];
for (int k = 0; k < datas[0]; k++) {
is_.read(d, 0, 4);
skip = get_int_from_bytes(d);
//System.out.println("skip 2 = " + skip);
offset += (4 + skip);
is_.skip(skip);
}
}
address_[i] = offset;
} catch (IOException e) {
e.printStackTrace();
succeed = false;
}
try {
is_.close();
} catch (IOException e) {
}
is_ = null;
System.gc();
return succeed ? 0 : -1;
}
/**
* 从资源文件中开始装在数据,并拼成PNG的Image
*
* @param from
* @param to
* @return
*/
public int loading(byte from, byte to) {
if (from < 0 || to < 0 || from > file_number_ || to > file_number_
|| from > to) {
// 输入参数有错误
return -1;
}
if ((is_ = getClass().getResourceAsStream(file_name_)) == null) {
// 资源装载失败返回-1
return -1;
}
from_ = from;
to_ = to;
int offset = 0, len = 0;
try {
is_.skip(address_[from_]);
} catch (IOException e) {
return -1;
}
boolean succeed = true;
for (int i = from_; i <= to_; i++) {
// 分配png图片所需的内存资源,因为需要加其他的信息需要多分配点
int size = address_[i + 1] - address_[i] + 200;
byte[] buffer = new byte[size];
System.arraycopy(MARK_FILE, 0, buffer, 0, 8);
offset = 8;
//System.out.println("==============================>>>1");
if ((len = update_header(buffer, offset, is_)) == -1) {
succeed = false;
break;
}
offset += len;
//System.out.println("==============================>>>2");
if ((len = update_palette(buffer, offset, is_)) == -1) {
succeed = false;
break;
}
offset += len;
if ((len = update_trans(buffer, offset, is_)) == -1) {
succeed = false;
break;
}
offset += len;
//System.out.println("==============================>>>3");
if ((len = update_idata(buffer, offset, is_)) == -1) {
succeed = false;
break;
}
offset += len;
//System.out.println("==============================>>>4");
System.arraycopy(MARK_END, 0, buffer, offset, 12);
offset += 12;
images_[i] = Image.createImage(buffer, 0, offset);
buffer = null;
System.gc();
}
try {
is_.close();
} catch (IOException e) {
}
is_ = null;
System.gc();
return succeed ? 0 : -1;
}
/**
* 根据索引值获得所需Image的句柄
*
* @param index
* @return
*/
public Image create_image(int index) {
return images_[index];
}
/**
* 释放资源管理器中某一个Image的资源
*
* @param index
*/
public void release(int index) {
}
/**
* 释放资源管理器中所有的已经已经装在的Image资源
*/
public void release() {
}
/**
* 从16进制的缓冲区中获得10进制的整数
*
* @param data
* @return
*/
private int get_int_from_bytes(byte[] data) {
if (data.length > 4) {
return -1;
}
int result = 0;
for (int i = data.length - 1, j = 0; i >= 0; i--, j += 8) {
result |= (data[i] & 0xFF) << j;
}
return result;
}
/**
* 计算缓冲区中的数据的CRC校验码,该函数主要确定需要校验数据的开始位置
* 和长度,同时需要将校验码放入缓冲区最后的4个字节的位置中
*
* @param data
* @param offset
* @param len
* @return 0 成功 -1 失败
*/
private int update_crc(byte[] buffer, int offset, int len) {
if (buffer.length < (offset + len + 4)) {
// 输入的数据缓冲区不正确
return -1;
}
int c = 0xFFFFFFFF;
for (int n = offset; n < len + offset; n++) {
c = CRC_TABLE_[(c ^ buffer[n]) & 0xff] ^ (c >>> 8);
}
int result = c ^ 0xFFFFFFFF;
int crc_offset = offset + len;
buffer[crc_offset + 0] = (byte) ((result >> 24) & 0xff); //237
buffer[crc_offset + 1] = (byte) ((result >> 16) & 0xff); //221
buffer[crc_offset + 2] = (byte) ((result >> 8) & 0xff); //226
buffer[crc_offset + 3] = (byte) ((result >> 0) & 0xff); //82
return 0;
}
/**
*
* @param buffer
* @param offset
* @param length
* @return
*/
private int update_length(byte[] buffer, int offset, int length) {
buffer[offset + 0] = (byte) ((length & 0xff000000) >> 24);
buffer[offset + 1] = (byte) ((length & 0x00ff0000) >> 16);
buffer[offset + 2] = (byte) ((length & 0x0000ff00) >> 8);
buffer[offset + 3] = (byte) ((length & 0x000000ff) >> 0);
return 4;
}
/**
* 还原PNG文件头的数据
*
* @param buffer
* @param offset
* @param is
* @return
*/
private int update_header(byte[] buffer, int offset, InputStream is) {
byte[] buf = new byte[6];
try {
is.read(buf);
} catch (IOException e) {
return -1;
}
update_length(buffer, offset, 13);
offset += 4;
int crc_offset = offset;
System.arraycopy(MARK_HEADER, 0, buffer, offset, 4);
offset += 4;
buffer[offset + 2] = buf[0];
buffer[offset + 3] = buf[1];
buffer[offset + 6] = buf[2];
buffer[offset + 7] = buf[3];
buffer[offset + 8] = buf[4];
buffer[offset + 9] = buf[5];
update_crc(buffer, crc_offset, 17);
return 25;
}
/**
* 还原PNG调色板的数据
*
* @param buffer
* @param offset
* @param is
* @return
*/
private int update_palette(byte[] buffer, int offset, InputStream is) {
byte[] buf = new byte[2];
int colors = 0;
try {
is.read(buf);
colors = get_int_from_bytes(buf) * 3;
//System.out.println("colors = " + colors);
buf = new byte[colors];
is.read(buf);
} catch (IOException e) {
return -1;
}
update_length(buffer, offset, colors);
offset += 4;
int crc_offset = offset;
System.arraycopy(MARK_PALETTE, 0, buffer, offset, 4);
offset += 4;
System.arraycopy(buf, 0, buffer, offset, colors);
update_crc(buffer, crc_offset, colors + 4);
return colors + 12;
}
private int update_trans(byte[] buffer, int offset, InputStream is) {
byte[] buf = new byte[1];
int count = 0;
//int a = offset;
try {
is.read(buf);
if (buf[0] == 0) {
return 0;
}
buf = new byte[2];
is.read(buf);
count = get_int_from_bytes(buf);
} catch (IOException e) {
return -1;
}
//System.out.println("count = " + count);
buffer[offset + 2] = buf[0];
buffer[offset + 3] = buf[1];
int crc_offset = offset + 4;
System.arraycopy(MARK_TRANS, 0, buffer, offset + 4, 4);
buf = new byte[count];
try {
is.read(buf);
} catch (IOException e) {
return -1;
}
System.arraycopy(buf,0,buffer,offset + 8,count);
update_crc(buffer, crc_offset, count + 4);
// for(int i = a ;i < a + count + 12;i++){
// System.out.print(" " + Integer.toHexString(buffer[i]));
// }
// System.out.println();
return (count + 12);
}
/**
* 还原PNG像素点的数据
*
* @param buffer
* @param offset
* @param is
* @return
*/
private int update_idata(byte[] buffer, int offset, InputStream is) {
byte[] buf = new byte[1];
int chunk = 0;
try {
is.read(buf);
chunk = buf[0];
} catch (IOException e) {
return -1;
}
int length = 0;
for (int i = 0; i < chunk; i++) {
buf = new byte[4];
int len = 0;
try {
is.read(buf);
len = get_int_from_bytes(buf);
buf = new byte[len];
is.read(buf);
} catch (IOException e) {
return -1;
}
update_length(buffer, offset, len);
offset += 4;
int crc_offset = offset;
System.arraycopy(MARK_IDAT, 0, buffer, offset, 4);
offset += 4;
System.arraycopy(buf, 0, buffer, offset, len);
update_crc(buffer, crc_offset, len + 4);
offset += (len + 4);
length += (len + 12);
}
return length;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -