package com.javaxyq.util;
import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import com.javaxyq.core.Toolkit;
import com.javaxyq.io.RandomAcessInputStream;
public class WASImage {
private RandomAcessInputStream in;
private static final int TYPE_ALPHA = 0x00;// ǰ2λ
private static final int TYPE_ALPHA_PIXEL = 0x20;// ǰ3λ 0010 0000
private static final int TYPE_ALPHA_REPEAT = 0x00;// ǰ3λ
private static final int TYPE_FLAG = 0xC0;// 2����ǰ2λ 1100 0000
private static final int TYPE_PIXELS = 0x40;// ����ǰ2λ 0100 0000
private static final int TYPE_REPEAT = 0x80;// 1000 0000
private static final int TYPE_SKIP = 0xC0; // 1100 0000
private static final int WAS_IMAGE_HEADER_SIZE = 12;
private static final String WAS_FILE_TAG = "SP";
public int centerX;
public int centerY;
int[] delayLine;
public int frameCount;
public WASFrame[][] frames;
public int height;
short imageHeaderSize;
String name;
short[] palette;
String path;
public int spriteCount;
public int width;
public WASImage() {
palette = new short[256];
}
public String getName() {
return name;
}
public Dimension getSize() {
return new Dimension(width, height);
}
/**
* ��ȡij֡����ʱ֡��
*/
public int getFrameDelay(int index) {
return delayLine[index];
}
/**
* �ļ���־ 2�ֽڣ� SP 53 50 / SP<br>
* �ļ�ͷ��С 2�ֽڣ� ������ǰ�ĸ��ֽ� 0C 00 / 12<br>
* ���������� 2�ֽ� 01 00 / 1<br>
* ÿ�����֡�� 2�ֽ� 01 00 / 1<br>
* �����Ŀ�� 2�ֽ� 80 02 / 640<br>
* �����ĸ߶� 2�ֽ� 29 00 / 41<br>
* ���������ĵ� X 2�ֽڣ� �з��� 00 00 / 0<br>
* ���������ĵ� Y 2�ֽ�, �з��� 00 00 / 0<br>
*
* @param filename
*/
public synchronized void loadWAS(String filename) {
//System.out.print("loading WAS file: " + filename + " ...");
//long startTime = System.currentTimeMillis();
InputStream fileIn = null;
try {
File file = new File(filename);
path = file.getAbsolutePath();
name = file.getName();
fileIn = Toolkit.getInputStream(filename);
byte[] buf = new byte[fileIn.available()];
int a = 0, count = 0;
while (fileIn.available() > 0) {
a = fileIn.read(buf, count, fileIn.available());
count += a;
}
// construct a new seekable stream
in = new RandomAcessInputStream(buf);
buf = new byte[2];
in.read(buf, 0, 2);
String flag = new String(buf, 0, 2);
if (!WAS_FILE_TAG.equals(flag)) { throw new Exception("�ļ�ͷ��־����:" + flag); }
// was ��Ϣ
imageHeaderSize = readUnsignedShort();
spriteCount = readUnsignedShort();
frameCount = readUnsignedShort();
width = readUnsignedShort();
height = readUnsignedShort();
centerX = readUnsignedShort();
centerY = readUnsignedShort();
// ��ȡ֡��ʱ��Ϣ
int len = imageHeaderSize - WAS_IMAGE_HEADER_SIZE;
if (len < 0) {
throw new Exception("֡��ʱ��Ϣ����");
} else if (len > 0) {
delayLine = new int[len];
for (int i = 0; i < delayLine.length; i++) {
delayLine[i] = in.read();
}
} else
delayLine = null;
// ��ȡ��ɫ��
in.seek(imageHeaderSize + 4);
for (int i = 0; i < 256; i++) {
palette[i] = readUnsignedShort();
}
frames = new WASFrame[spriteCount][];
in.seek(imageHeaderSize + 4 + 512);
for (int i = 0; i < spriteCount; i++) {
frames[i] = new WASFrame[frameCount];
for (int n = 0; n < frameCount; n++) {// ֡ƫ���б�
WASFrame frame = new WASFrame();
frames[i][n] = frame;
if (delayLine != null && n < delayLine.length) {
frames[i][n].setDelay(delayLine[n]);
}
frame.setFrameOffset(readInt());
}
}
for (int i = 0; i < spriteCount; i++) {// ֡��Ϣ
for (int n = 0; n < frameCount; n++) {
WASFrame frame = frames[i][n];
int offset = frame.getFrameOffset();
if (offset == 0)
continue;// blank frame
in.seek(offset + imageHeaderSize + 4);
frame.setX(readInt());
frame.setY(readInt());
frame.setWidth(readInt());
frame.setHeight(readInt());
frame.setLineOffsets(new int[frame.getHeight()]);
for (int l = 0; l < frame.getHeight(); l++) {// ����������ƫ��
frame.getLineOffsets()[l] = readInt();
}
parse(frame);// ����֡����
}
}
} catch (Exception e) {
System.err.println("load was file failed!");
e.printStackTrace();
} finally {
if (in != null)
in.close();
try {
if (fileIn != null)
fileIn.close();
} catch (IOException e) {
e.printStackTrace();
}
//System.out.println((System.currentTimeMillis() - startTime) + "ms");
}
}
/**
* ��ͼƬһ��RLE�����ʽ�����ݽ���,���������ݷŵ�pixels��<br>
* ��ʽ:��16λΪ[565]rgb��ɫֵ,16-20λΪalphaֵ(���Ϊ0x1F);
*
* @throws IOException
*/
public void parse(WASFrame frame) throws IOException {
int frameWidth = frame.getWidth();
int frameHeight = frame.getHeight();
int[] pixels = new int[frameHeight *frameWidth];
frame.setPixels(pixels);
int b;
int x;
int c;
int count;
for (int y = 0; y < frameHeight; y++) {
x = 0;
in.seek(frame.getLineOffsets()[y] + frame.getFrameOffset() + imageHeaderSize + 4);
while (x < frameWidth) {
b = in.read();
switch ((b & TYPE_FLAG)) {
case TYPE_ALPHA:
if ((b & TYPE_ALPHA_PIXEL) > 0) {
c = palette[in.read()];
pixels[y*width +x++] = c + ((b & 0x1F) << 16);
} else if (b != 0) {// ???
count = b & 0x1F;// count
b = in.read();// alpha
c = palette[in.read()];
for (int i = 0; i < count; i++) {
pixels[y*width +x++] = c + ((b & 0x1F) << 16);
}
} else {// block end
if (x > frameWidth) {
System.err.println("block end error: [" + y + "][" + x + "/" + frameWidth + "]");
continue;
} else if (x == 0) {
// System.err.println("x==0");
} else {
x = frameWidth;// set the x value to break the 'while' sentences
}
}
break;
case TYPE_PIXELS:
count = b & 0x3F;
for (int i = 0; i < count; i++) {
pixels[y*width +x++] = palette[in.read()] + (0x1F << 16);
}
break;
case TYPE_REPEAT:
count = b & 0x3F;
c = palette[in.read()];
for (int i = 0; i < count; i++) {
pixels[y*width +x++] = c + (0x1F << 16);
}
break;
case TYPE_SKIP:
count = b & 0x3F;
x += count;
break;
}
}
if (x > frameWidth)
System.err.println("block end error: [" + y + "][" + x + "/" + frameWidth + "]");
}
}
private int readInt() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
int ch3 = in.read();
int ch4 = in.read();
return (ch1 + (ch2 << 8) + (ch3 << 16) + (ch4 << 24));
}
private short readUnsignedShort() throws IOException {
int ch1 = in.read();
int ch2 = in.read();
return (short) ((ch2 << 8) + ch1);
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("�ļ�·��:\t");
buf.append(path);
buf.append("\r\n");
buf.append("�ļ���־:\t");
buf.append(WAS_FILE_TAG);
buf.append("\r\n");
buf.append("�ļ�ͷ��С:\t");
buf.append(imageHeaderSize);
buf.append("\r\n");
buf.append("����������:\t");
buf.append(spriteCount);
buf.append("\r\n");
buf.append("����֡��:\t");
buf.append(frameCount);
buf.append("\r\n");
buf.append("�����Ŀ��:\t");
buf.append(width);
buf.append("\r\n");
buf.append("�����ĸ߶�:\t");
buf.append(height);
buf.append("\r\n");
buf.append("����X���ĵ�:\t");
buf.append(centerX);
buf.append("\r\n");
buf.append("����Y���ĵ�:\t");
buf.append(centerY);
buf.append("\r\n");
return buf.toString();
}
}
// ��������ͼƬ��������Ϣ����ʽ���£�
// ������=����(8����)+����
//
// ���͵ĸ�ʽ���£�
// ������4�֣���2���ر�ʾ��
//
// 00����ʾalpha���أ�ʣ�µ�6����Ҳ��0ʱ�����ݶν�����
// �����3��������1ʱ��ʣ�µ�5����(0~31)Ϊalpha�㡣�����Ժ���ֽ�������������
// ����ʣ�µ�5����(0~31)��alpha�����ظ�����.�����Ժ��2�ֽ���alpha,����������
// 01����ʾ�����飬ʣ�µ�6����(0~63)Ϊ���ݶεij��ȡ�
// 10����ʾ�ظ����� n �Σ�n Ϊʣ�µ�6����(0~63)��ʾ��
// 11����ʾ�������� n ����n Ϊʣ�µ�6����(0~63)��ʾ��