1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46:
47: import ;
48: import ;
49: import ;
50: import ;
51:
52: public class EncodeRLE4
53: extends BMPEncoder
54: {
55: protected BMPInfoHeader infoHeader;
56: protected BMPFileHeader fileHeader;
57: protected long offset;
58:
59:
62: private static final byte ESCAPE = (byte)0;
63: private static final byte EOL = (byte)0;
64: private static final byte EOB = (byte)1;
65: private static final byte DELTA = (byte)2;
66:
67:
73: public EncodeRLE4(BMPFileHeader fh, BMPInfoHeader ih)
74: {
75: super();
76: fileHeader = fh;
77: infoHeader = ih;
78: offset = BMPFileHeader.SIZE + BMPInfoHeader.SIZE;
79: }
80:
81:
91: public void encode(ImageOutputStream o, IIOMetadata streamMetadata,
92: IIOImage image, ImageWriteParam param) throws IOException
93: {
94: int size;
95: int value;
96: int j;
97: int rowCount;
98: int rowIndex;
99: int lastRowIndex;
100: int[] bitmap;
101: size = (infoHeader.biWidth * infoHeader.biHeight) - 1;
102: rowCount = 1;
103: rowIndex = size - infoHeader.biWidth;
104: lastRowIndex = rowIndex;
105: ByteBuffer buf = ByteBuffer.allocate(size);
106: try
107: {
108: bitmap = new int[infoHeader.biWidth * infoHeader.biHeight];
109: PixelGrabber pg = new PixelGrabber((BufferedImage) image.getRenderedImage(),
110: 0, 0, infoHeader.biWidth,
111: infoHeader.biHeight, bitmap, 0,
112: infoHeader.biWidth);
113: pg.grabPixels();
114:
115: for (j = 0; j < size; j++)
116: {
117: value = bitmap[rowIndex];
118: buf.put((byte) (value & 0xFF));
119:
120: if (rowCount == infoHeader.biWidth)
121: {
122: rowCount = 1;
123: rowIndex = lastRowIndex - infoHeader.biWidth;
124: lastRowIndex = rowIndex;
125: }
126: else
127: rowCount++;
128: rowIndex++;
129: }
130:
131: buf.flip();
132: o.write(uncompress(infoHeader.biWidth, infoHeader.biHeight, buf));
133: }
134: catch (Exception wb)
135: {
136: wb.printStackTrace();
137: }
138: }
139:
140:
150: private byte[] uncompress(int w, int h, ByteBuffer buf)
151: throws IOException
152: {
153: byte[] cmd = new byte[2];
154: byte[] data = new byte[w * h >> 1];
155: int offIn = 0;
156: int x = 0, y = 0;
157:
158: w += (w & 1);
159: w = w >> 1;
160:
161: try
162: {
163: while (((x >> 1) + y * w) < w * h)
164: {
165: try
166: {
167: buf.get(cmd);
168: }
169: catch (BufferUnderflowException e)
170: {
171: throw new IOException("Error reading compressed data.");
172: }
173:
174: if (cmd[0] == ESCAPE)
175: {
176: switch (cmd[1])
177: {
178: case EOB:
179: return data;
180: case EOL:
181: x = 0;
182: y++;
183: break;
184: case DELTA:
185: try
186: {
187: buf.get(cmd);
188: }
189: catch (BufferUnderflowException e)
190: {
191: throw new IOException("Error reading compressed data.");
192: }
193:
194: int dx = cmd[0] & (0xFF);
195: int dy = cmd[1] & (0xFF);
196: x += dx;
197: y += dy;
198: break;
199:
200: default:
201: int length = cmd[1] & (0xFF);
202:
203: int bytesize = length;
204: bytesize += (bytesize & 1);
205: bytesize >>= 1;
206: bytesize += (bytesize & 1);
207:
208: byte[] run = new byte[bytesize];
209: try
210: {
211: buf.get(run);
212: }
213: catch (BufferUnderflowException e)
214: {
215: throw new IOException("Error reading compressed data.");
216: }
217:
218: if ((x & 1) == 0)
219: {
220: length += (length & 1);
221: length >>= 1;
222: System.arraycopy(run, 0, data,
223: ((x >> 1) + w * (h - y - 1)), length);
224: }
225: else
226: {
227: for (int i = 0; i < length; i++)
228: {
229: if ((i & 1) == 0)
230: data[((x + i) >> 1) + w * (h - y - 1)] |= ((run[i >> 1] & 0xF0) >> 4);
231: else
232: data[((x + i) >> 1) + w * (h - y - 1)] |= ((run[i >> 1] & 0x0F) << 4);
233: }
234: }
235: x += cmd[1] & (0xFF);
236: break;
237: }
238: }
239: else
240: {
241: int length = cmd[0] & (0xFF);
242: if ((x & 1) == 0)
243: {
244: length += (length & 1);
245: length >>= 1;
246: for (int i = 0; i < length; i++)
247: data[(h - y - 1) * w + i + (x >> 1)] = cmd[1];
248: }
249: else
250: {
251: for (int i = 0; i < length; i++)
252: {
253: if ((i & 1) == 0)
254: data[((x + i) >> 1) + w * (h - y - 1)] |= ((cmd[1] & 0xF0) >> 4);
255: else
256: data[((x + i) >> 1) + w * (h - y - 1)] |= ((cmd[1] & 0x0F) << 4);
257: }
258: }
259: x += cmd[0] & (0xFF);
260: }
261: }
262: return data;
263: }
264: catch (ArrayIndexOutOfBoundsException e)
265: {
266: throw new BMPException("Invalid RLE data.");
267: }
268: }
269: }