001: /**
002: * Caption: Zaval Java Resource Editor
003: * $Revision: 0.37 $
004: * $Date: 2002/03/28 9:24:42 $
005: *
006: * @author: Victor Krapivin
007: * @version: 1.3
008: *
009: * Zaval JRC Editor is a visual editor which allows you to manipulate
010: * localization strings for all Java based software with appropriate
011: * support embedded.
012: *
013: * For more info on this product read Zaval Java Resource Editor User's Guide
014: * (It comes within this package).
015: * The latest product version is always available from the product's homepage:
016: * http://www.zaval.org/products/jrc-editor/
017: * and from the SourceForge:
018: * http://sourceforge.net/projects/zaval0002/
019: *
020: * Contacts:
021: * Support : support@zaval.org
022: * Change Requests : change-request@zaval.org
023: * Feedback : feedback@zaval.org
024: * Other : info@zaval.org
025: *
026: * Copyright (C) 2001-2002 Zaval Creative Engineering Group (http://www.zaval.org)
027: *
028: * This program is free software; you can redistribute it and/or
029: * modify it under the terms of the GNU General Public License
030: * (version 2) as published by the Free Software Foundation.
031: *
032: * This program is distributed in the hope that it will be useful,
033: * but WITHOUT ANY WARRANTY; without even the implied warranty of
034: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
035: * GNU General Public License for more details.
036: *
037: * You should have received a copy of the GNU General Public License
038: * along with this program; if not, write to the Free Software
039: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
040: *
041: */package org.zaval.awt.image;
042:
043: import java.io.*;
044: import java.lang.*;
045: import java.awt.*;
046: import java.awt.image.*;
047:
048: public class BmpFileDecoder {
049: public static int BmpHints = 30;
050:
051: BMP_Header header;
052: BMP_Info_Header info_header;
053: BMP_Palette palette;
054:
055: public int[][] bmp_image;
056: private BMP_InputStream is;
057:
058: public int[][] getMatrix() {
059: return bmp_image;
060: }
061:
062: public BmpFileDecoder(InputStream is) throws IOException {
063: init(is);
064: }
065:
066: public void init(InputStream is_in) throws IOException {
067: this .is = new BMP_InputStream(is_in);
068: header = new BMP_Header(is);
069: info_header = new BMP_Info_Header(is);
070:
071: if (info_header.NumOfColors != 0) {
072: palette = new BMP_Palette(info_header.NumOfColors, is,
073: info_header.BitsPerPixel);
074: } else {
075: // MS Bug workaround.
076: // I have to guess how long the Color Table is.
077: long at = header.readBytes + info_header.readBytes;
078: info_header.NumOfColors = (int) (header.dataOffset - at) / 4;
079: palette = new BMP_Palette(info_header.NumOfColors, is,
080: info_header.BitsPerPixel);
081: }
082:
083: // Now we have all the information. Extract the data itself.
084:
085: bmp_image = new int[getHeight()][getWidth()];
086: int ByteWidth = getByteWidth();
087: int pad = ByteWidth % 4;
088:
089: // If the file is compress, I decompress immediatly into
090: // bmp_image. If not, I first read into tmp_buffer and then
091: // transle into bmp_image, if needed.
092:
093: if (info_header.CompressionMethod != BMP_Header.COMPRESS_RGB) {
094: if (info_header.BitsPerPixel == 8
095: || info_header.BitsPerPixel == 4)
096: readRLE(ByteWidth, pad, is,
097: 8 / (info_header.CompressionMethod));
098: else
099: throw new IllegalArgumentException("Can't uncompress "
100: + info_header.BitsPerPixel + "bit files");
101: } else { // No compression
102: int tmp_buffer[][] = new int[getHeight()][ByteWidth];
103: readRegular(ByteWidth, pad, tmp_buffer, is);
104: int w, h, bb;
105:
106: // put data into image_data
107:
108: int ands[] = { 128, 64, 32, 16, 8, 4, 2, 1 };
109:
110: if (info_header.BitsPerPixel == 8)
111: for (h = 0; h < getHeight(); h++)
112: for (w = 0; w < ByteWidth; w++)
113: bmp_image[h][w] = tmp_buffer[h][w];
114: else if (info_header.BitsPerPixel == 4)
115: for (h = 0; h < getHeight(); h++)
116: for (w = 0; w < ByteWidth; w++) {
117: bmp_image[h][w * 2] = MSN(tmp_buffer[h][w]);
118: bmp_image[h][w * 2 + 1] = LSN(tmp_buffer[h][w]);
119: }
120: else if (info_header.BitsPerPixel == 1) {
121: for (h = 0; h < getHeight(); h++)
122: for (w = 0; w < ByteWidth; w++)
123: for (bb = 0; bb < 8; bb++)
124: if (w * 8 + bb < getWidth())
125: if (((tmp_buffer[h][w]) & (ands[bb])) == ands[bb])
126: bmp_image[h][w * 8 + bb] = 1;
127: else
128: bmp_image[h][w * 8 + bb] = 0;
129: } else if (info_header.BitsPerPixel == 24)
130: for (h = 0; h < getHeight(); h++)
131: for (w = 0; w < getWidth(); w++)
132: bmp_image[h][w] = 0xff000000
133: + (tmp_buffer[h][w * 3] << 16)
134: + (tmp_buffer[h][w * 3 + 1] << 8)
135: + tmp_buffer[h][w * 3 + 2];
136: else if (info_header.BitsPerPixel == 16)
137: for (h = 0; h < getHeight(); h++)
138: for (w = 0; w < getWidth(); w++) {
139: int pixel = (tmp_buffer[h][w * 2])
140: + (tmp_buffer[h][w * 2 + 1] << 8);
141: int r = ((pixel & 0x7c00) >> 10) * 255 / 31;
142: int g = ((pixel & 0x03e0) >> 5) * 255 / 31;
143: int b = (pixel & 0x1f) * 255 / 31;
144: bmp_image[h][w] = 0xff000000 + (b << 16)
145: + (g << 8) + r;
146: }
147: else
148: throw new IllegalArgumentException(
149: "Illegal BitsPerPixel "
150: + info_header.BitsPerPixel);
151: }
152: }
153:
154: protected void readRegular(int ByteWidth, int pad,
155: int tmp_buffer[][], InputStream iss) throws IOException {
156: for (int h = 0; h < getHeight(); h++) {
157: for (int w = 0; w < ByteWidth; w++)
158: tmp_buffer[h][w] = iss.read();
159: if (pad != 0)
160: for (int ppad = 0; ppad < (4 - pad); ppad++)
161: iss.read();
162: }
163: }
164:
165: public int getWidth() {
166: return info_header.Width;
167: }
168:
169: public int getHeight() {
170: return info_header.Height;
171: }
172:
173: // 0,0 is top-left, unlike in BMP
174: public int getPixel(int x, int y) {
175: return bmp_image[getHeight() - y - 1][x];
176: }
177:
178: public void setPixel(int x, int y, int c) {
179: bmp_image[getHeight() - y - 1][x] = c;
180: }
181:
182: public ColorModel getColorModel() {
183: return palette.getColorModel();
184: }
185:
186: private int LSN(int value) {
187: return ((value) & 0x0f);
188: }
189:
190: private int MSN(int value) {
191: return (((value) & 0xf0) >> 4);
192: }
193:
194: private int getByteWidth() {
195: int ByteWidth = 0;
196: if (info_header.BitsPerPixel == 8)
197: ByteWidth = getWidth();
198: else if (info_header.BitsPerPixel == 4) {
199: ByteWidth = getWidth() / 2;
200: if (ByteWidth * 2 < getWidth())
201: ByteWidth++;
202: } else if (info_header.BitsPerPixel == 1) {
203: ByteWidth = getWidth() / 8;
204: if (ByteWidth * 8 < getWidth())
205: ByteWidth++;
206: } else if (info_header.BitsPerPixel == 24)
207: ByteWidth = getWidth() * 3;
208: else if (info_header.BitsPerPixel == 16)
209: ByteWidth = getWidth() * 2;
210: else
211: throw new IllegalArgumentException("Illegal BitsPerPixel "
212: + info_header.BitsPerPixel);
213: return ByteWidth;
214: }
215:
216: protected void readRLE(int ByteWidth, int pad, BMP_InputStream in,
217: int pixelSize) throws java.io.IOException {
218: int x = 0;
219: int y = 0;
220:
221: for (int i = 0; i < header.FileSize; i++) {
222: int byte1 = in.read();
223: int byte2 = in.read();
224: i += 2;
225:
226: // If byte 0 == 0, this is an escape code
227: if (byte1 == 0) {
228: // If escaped, byte 2 == 0 means you are at end of line
229: if (byte2 == 0) {
230: x = 0;
231: y++;
232: // If escaped, byte 2 == 1 means end of bitmap
233: } else if (byte2 == 1)
234: return;
235: // if escaped, byte 2 == 2 adjusts the current x and y by
236: // an offset stored in the next two words
237: else if (byte2 == 2) {
238: int xoff = (char) in.readShort();
239: i += 2;
240: int yoff = (char) in.readShort();
241: i += 2;
242: x += xoff;
243: y += yoff;
244: // Any other value for byte 2 is the number of bytes that you
245: // should read as pixel values (these pixels are not run-length
246: // encoded ).
247: } else {
248: int whichBit = 0;
249: int currByte = in.read();
250: i++;
251:
252: for (int j = 0; j < byte2; j++) {
253: if (pixelSize == 4) {
254: if (whichBit == 0)
255: bmp_image[y][x] = (currByte >> 4) & 0xf;
256: else {
257: bmp_image[y][x] = currByte & 0xf;
258: currByte = in.read();
259: i++;
260: }
261: whichBit = (whichBit == 0) ? 1 : 0;
262: } else {
263: bmp_image[y][x] = currByte;
264: currByte = in.read();
265: i++;
266: }
267: x++;
268: if (x >= getWidth()) {
269: x = 0;
270: y++;
271: }
272: }
273:
274: if ((byte2 & 1) == 1) {
275: in.read();
276: i++;
277: }
278: }
279: // If the first byte was not 0, it is the number of pixels that
280: // are encoded by byte 2
281: } else {
282: for (int j = 0; j < byte1; j++) {
283: if (pixelSize == 4) {
284: if ((j & 1) == 0)
285: bmp_image[y][x] = (byte2 >> 4) & 0xf;
286: else
287: bmp_image[y][x] = byte2 & 0xf;
288: } else
289: bmp_image[y][x] = byte2;
290: x++;
291: if (x >= getWidth()) {
292: x = 0;
293: y++;
294: }
295: }
296: }
297: }
298: }
299: }
|