Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / gnu / javax / imageio / bmp / EncodeRLE4.java
blob3674c4d78776b0bcabe50bdb4045591be8dd6ad1
1 /* EncodeRLE4.java --
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.javax.imageio.bmp;
41 import java.awt.image.BufferedImage;
42 import java.awt.image.PixelGrabber;
43 import java.io.IOException;
44 import java.nio.BufferUnderflowException;
45 import java.nio.ByteBuffer;
47 import javax.imageio.IIOImage;
48 import javax.imageio.ImageWriteParam;
49 import javax.imageio.metadata.IIOMetadata;
50 import javax.imageio.stream.ImageOutputStream;
52 public class EncodeRLE4
53 extends BMPEncoder
55 protected BMPInfoHeader infoHeader;
56 protected BMPFileHeader fileHeader;
57 protected long offset;
59 /**
60 * RLE control codes
62 private static final byte ESCAPE = (byte)0;
63 private static final byte EOL = (byte)0; // end of line
64 private static final byte EOB = (byte)1; // end of bitmap
65 private static final byte DELTA = (byte)2; // delta
67 /**
68 * Constructs an instance of this class.
70 * @param fh - the file header to use.
71 * @param ih - the info header to use.
73 public EncodeRLE4(BMPFileHeader fh, BMPInfoHeader ih)
75 super();
76 fileHeader = fh;
77 infoHeader = ih;
78 offset = BMPFileHeader.SIZE + BMPInfoHeader.SIZE;
81 /**
82 * The image encoder.
84 * @param o - the image output stream
85 * @param streamMetadata - metadata associated with this stream, or
86 * null
87 * @param image - an IIOImage containing image data.
88 * @param param - image writing parameters, or null
89 * @exception IOException if a write error occurs
91 public void encode(ImageOutputStream o, IIOMetadata streamMetadata,
92 IIOImage image, ImageWriteParam param) throws IOException
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);
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();
115 for (j = 0; j < size; j++)
117 value = bitmap[rowIndex];
118 buf.put((byte) (value & 0xFF));
120 if (rowCount == infoHeader.biWidth)
122 rowCount = 1;
123 rowIndex = lastRowIndex - infoHeader.biWidth;
124 lastRowIndex = rowIndex;
126 else
127 rowCount++;
128 rowIndex++;
131 buf.flip();
132 o.write(uncompress(infoHeader.biWidth, infoHeader.biHeight, buf));
134 catch (Exception wb)
136 wb.printStackTrace();
141 * Uncompresses the image stored in the buffer.
143 * @param w - the width of the image
144 * @param h - the height of the image
145 * @param buf - the ByteBuffer containing the pixel values.
146 * @return byte array containing the uncompressed image
147 * @throws IOException if an error is encountered while reading
148 * buffer.
150 private byte[] uncompress(int w, int h, ByteBuffer buf)
151 throws IOException
153 byte[] cmd = new byte[2];
154 byte[] data = new byte[w * h >> 1];
155 int offIn = 0;
156 int x = 0, y = 0;
158 w += (w & 1);
159 w = w >> 1;
163 while (((x >> 1) + y * w) < w * h)
167 buf.get(cmd);
169 catch (BufferUnderflowException e)
171 throw new IOException("Error reading compressed data.");
174 if (cmd[0] == ESCAPE)
176 switch (cmd[1])
178 case EOB:
179 return data;
180 case EOL:
181 x = 0;
182 y++;
183 break;
184 case DELTA:
187 buf.get(cmd);
189 catch (BufferUnderflowException e)
191 throw new IOException("Error reading compressed data.");
194 int dx = cmd[0] & (0xFF);
195 int dy = cmd[1] & (0xFF);
196 x += dx;
197 y += dy;
198 break;
200 default:
201 int length = cmd[1] & (0xFF);
203 int bytesize = length;
204 bytesize += (bytesize & 1);
205 bytesize >>= 1;
206 bytesize += (bytesize & 1);
208 byte[] run = new byte[bytesize];
211 buf.get(run);
213 catch (BufferUnderflowException e)
215 throw new IOException("Error reading compressed data.");
218 if ((x & 1) == 0)
220 length += (length & 1);
221 length >>= 1;
222 System.arraycopy(run, 0, data,
223 ((x >> 1) + w * (h - y - 1)), length);
225 else
227 for (int i = 0; i < length; i++)
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);
235 x += cmd[1] & (0xFF);
236 break;
239 else
241 int length = cmd[0] & (0xFF);
242 if ((x & 1) == 0)
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];
249 else
251 for (int i = 0; i < length; i++)
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);
259 x += cmd[0] & (0xFF);
262 return data;
264 catch (ArrayIndexOutOfBoundsException e)
266 throw new BMPException("Invalid RLE data.");