1:
37:
38: package ;
39:
40: import ;
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51:
52: public class DecodeRLE8 extends BMPDecoder {
53:
54: public DecodeRLE8(BMPFileHeader fh, BMPInfoHeader ih){
55: super(fh, ih);
56: }
57:
58:
61: private static final byte ESCAPE = (byte)0;
62: private static final byte EOL = (byte)0;
63: private static final byte EOB = (byte)1;
64: private static final byte DELTA = (byte)2;
65:
66: public BufferedImage decode(ImageInputStream in) throws IOException, BMPException {
67: IndexColorModel palette = readPalette(in);
68: skipToImage(in);
69:
70: Dimension d = infoHeader.getSize();
71: int h = (int)d.getHeight();
72: int w = (int)d.getWidth();
73:
74: byte[] data = uncompress(w, h, in);
75: SampleModel sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_BYTE,
76: w, h,
77: new int[] {0xFF});
78: DataBuffer db = new DataBufferByte(data, w*h, 0);
79: WritableRaster raster = Raster.createWritableRaster(sm, db, null);
80:
81: return new BufferedImage(palette, raster, false, null);
82: }
83:
84: private byte[] uncompress(int w, int h, ImageInputStream in)
85: throws BMPException, IOException {
86: byte[] cmd = new byte[2];
87: byte[] data = new byte[w*h];
88: int offIn = 0;
89: int x=0,y=0;
90:
91: try {
92: while((x + y*w) < w*h){
93: if(in.read(cmd) != 2)
94: throw new IOException("Error reading compressed data.");
95:
96: if(cmd[0] == ESCAPE){
97: switch(cmd[1]){
98: case EOB:
99: return data;
100: case EOL:
101: x = 0;
102: y++;
103: break;
104: case DELTA:
105: if(in.read(cmd) != 2)
106: throw new IOException("Error reading compressed data.");
107: int dx = cmd[0] & (0xFF);
108: int dy = cmd[1] & (0xFF);
109: x += dx;
110: y += dy;
111: break;
112:
113: default:
114:
115: int length = cmd[1] & (0xFF);
116: int copylength = length;
117:
118:
119: length += (length & 1);
120:
121: byte[] run = new byte[length];
122: if(in.read(run) != length)
123: throw new IOException("Error reading compressed data.");
124:
125: System.arraycopy(run, 0, data, (x+w*(h-y-1)),
126: copylength);
127: x += copylength;
128: break;
129: }
130: } else {
131:
132: int length = cmd[0] & (0xFF);
133: for(int i=0;i<length;i++)
134: data[(h-y-1)*w + x++] = cmd[1];
135: }
136: }
137: return data;
138: } catch(ArrayIndexOutOfBoundsException e){
139: throw new BMPException("Invalid RLE data.");
140: }
141: }
142: }