package com.javaxyq.util;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class MapDecoder {
private int width;
private int height;
private int[][] segmentsOffset;
private Object[][] jpegDatas;
private String filename;
private MyRandomAccessFile mapFile;
private int horSegmentCount;
private int verSegmentCount;
public MapDecoder(String filename) throws Exception {
this(new File(filename));
}
public MapDecoder(File file) throws Exception {
this.filename = file.getName();
mapFile = new MyRandomAccessFile(file, "r");
loadHeader();
}
/**
* ��������MAP
*
* @param is
*/
private void loadHeader() {
if (!isValidMapFile()) { throw new IllegalArgumentException("���λõ�ͼ��ʽ�ļ�!"); }
try {
// start decoding
width = mapFile.readInt2();
height = mapFile.readInt2();
horSegmentCount = (int) Math.ceil(width / 320.0);
verSegmentCount = (int) Math.ceil(height / 240.0);
// System.out.println("size: " + width + "*" + height);
// System.out.println("segment: " + horSegmentCount + "*" + horSegmentCount);
segmentsOffset = new int[horSegmentCount][verSegmentCount];
jpegDatas = new Object[horSegmentCount][verSegmentCount];
for (int v = 0; v < verSegmentCount; v++) {
for (int h = 0; h < horSegmentCount; h++) {
segmentsOffset[h][v] = mapFile.readInt2();
}
}
// int headerSize = sis.readInt2();// where need it?
} catch (Exception e) {
throw new IllegalArgumentException("��ͼ����ʧ��:" + e.getMessage());
// e.printStackTrace();
}
}
/**
* ��ȡָ����JPEG���ݿ�
*
* @param h
* ��
* @param v
* ��
* @return
*/
public byte[] getJpegData(int h, int v) {
try {
// read jpeg data
int len;
byte jpegBuf[] = null;
mapFile.seek(segmentsOffset[h][v]);// XXX offset
if (isJPEGData()) {
len = mapFile.readInt2();
jpegBuf = new byte[len];
mapFile.readFully(jpegBuf);
jpegDatas[h][v] = jpegBuf;
}
// modify jpeg data
ByteArrayOutputStream bos = new ByteArrayOutputStream(4096);
boolean isFilled = false;// �Ƿ�0xFF->0xFF 0x00
bos.reset();
jpegBuf = (byte[]) jpegDatas[h][v];
bos.write(jpegBuf, 0, 2);
// skip 2 bytes: FF A0
int p, start;
isFilled = false;
for (p = 4, start = 4; p < jpegBuf.length - 2; p++) {
if (!isFilled && jpegBuf[p] == (byte) 0xFF && jpegBuf[++p] == (byte) 0xDA) {
isFilled = true;
// 0xFF 0xDA ; SOS: Start Of Scan
// ch=jpegBuf[p+3];
// suppose always like this: FF DA 00 09 03...
jpegBuf[p + 2] = 12;
bos.write(jpegBuf, start, p + 10 - start);
// filled 00 3F 00
bos.write(0);
bos.write(0x3F);
bos.write(0);
start = p + 10;
p += 9;
}
if (isFilled && jpegBuf[p] == (byte) 0xFF) {
bos.write(jpegBuf, start, p + 1 - start);
bos.write(0);
start = p + 1;
}
}
bos.write(jpegBuf, start, jpegBuf.length - start);
jpegDatas[h][v] = bos.toByteArray();
} catch (Exception e) {
System.err.println("��ȡJPEG ���ݿ�ʧ�ܣ�" + e.getMessage());
}
return (byte[]) jpegDatas[h][v];
}
private boolean isJPEGData() {
byte[] buf = new byte[4];
try {
int len = mapFile.read();
mapFile.skipBytes(3 + len * 4);
mapFile.read(buf);// 47 45 50 4A; GEPJ
String str = new String(buf);
return str.equals("GEPJ");
} catch (IOException ex) {
ex.printStackTrace();
}
return false;
}
private boolean isValidMapFile() {
byte[] buf = new byte[4];
try {
mapFile.read(buf);
String str = new String(buf);
return str.equals("0.1M");
} catch (IOException ex) {
ex.printStackTrace();
}
return false;
}
public String getFilename() {
return filename;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
class MyRandomAccessFile extends RandomAccessFile {
public MyRandomAccessFile(String name, String mode) throws FileNotFoundException {
super(name, mode);
}
public MyRandomAccessFile(File file, String mode) throws FileNotFoundException {
super(file, mode);
}
public int readInt2() throws IOException {
int ch1 = this.read();
int ch2 = this.read();
int ch3 = this.read();
int ch4 = this.read();
if ((ch1 | ch2 | ch3 | ch4) < 0)
throw new EOFException();
return ((ch1 << 0) + (ch2 << 8) + (ch3 << 16) + (ch4 << 24));
}
}
public int getHorSegmentCount() {
return horSegmentCount;
}
public int getVerSegmentCount() {
return verSegmentCount;
}
}