Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/memoire/bu/BuBmpLoader.java


1   
2   
3   package com.memoire.bu;
4   
5   
6   
7   /**
8   
9    * This class implements a Bmp Loader.
10  
11   *
12  
13   *-----------------------------------------------------------------------
14  
15   *   This program is free software; you can redistribute it and/or modify
16  
17   *   it under the terms of the GNU Library General Public License as published
18  
19   *   by the Free Software Foundation; either version 2 of the License, or
20  
21   *   (at your option) any later version.
22  
23   *
24  
25   *   This program is distributed in the hope that it will be useful,
26  
27   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
28  
29   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  
31   *   GNU Library General Public License for more details.
32  
33   *
34  
35   *   You should have received a copy of the GNU Library General Public
36  
37   *   License along with this program; if not, write to the Free Software
38  
39   *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
40  
41   *----------------------------------------------------------------------
42  
43   */
44  
45  
46  
47  import java.awt.*;
48  
49  import java.awt.image.*;
50  
51  import java.io.*;
52  
53  
54  
55  /**
56  
57   * A decoder for Windows bitmap (.Bmp) files.
58  
59   * Compression not supported.
60  
61   * Source code provided by JavaZoom under the LGPL.
62  
63   */
64  
65  public class BuBmpLoader
66  
67  {
68  
69    private InputStream is;
70  
71    private int curPos = 0;
72  
73    
74  
75    private int bitmapOffset;    // starting position of image data
76  
77    
78  
79    private int width;        // image width in pixels
80  
81    private int height;        // image height in pixels
82  
83    private short bitsPerPixel;    // 1, 4, 8, or 24 (no color map)
84  
85    private int compression;    // 0 (none), 1 (8-bit RLE), or 2 (4-bit RLE)
86  
87    private int actualSizeOfBitmap;
88  
89    private int scanLineSize;
90  
91    private int actualColorsUsed;
92  
93    
94  
95    private byte r[], g[], b[];    // color palette
96  
97    private int noOfEntries;
98  
99    
100 
101   private byte[] byteData;    // Unpacked data
102 
103   private int[] intData;      // Unpacked data
104 
105   
106 
107   public BuBmpLoader()
108 
109   {
110 
111   }
112 
113   
114 
115   public Image getBmpImage(InputStream stream) throws Exception
116 
117   {
118 
119     read(stream);
120 
121     return Toolkit.getDefaultToolkit().createImage(getImageSource());
122 
123   }
124 
125   
126 
127   private int readInt() throws IOException {
128 
129     int b1 = is.read();
130 
131     int b2 = is.read();
132 
133     int b3 = is.read();
134 
135     int b4 = is.read();
136 
137     curPos += 4;
138 
139     return ((b4 << 24) + (b3 << 16) + (b2 << 8) + (b1 << 0));
140 
141   }
142 
143   
144 
145   
146 
147   private short readShort() throws IOException {
148 
149     int b1 = is.read();
150 
151     int b2 = is.read();
152 
153     curPos += 4;
154 
155     return (short)((b2 << 8) + b1);
156 
157   }
158 
159 
160 
161   
162 
163   void getFileHeader()  throws Exception {
164 
165     // Actual contents (14 bytes):
166 
167     short fileType = 0x4d42;// always "BM"
168 
169     int fileSize;      // size of file in bytes
170 
171     short reserved1 = 0;  // always 0
172 
173     short reserved2 = 0;  // always 0
174 
175     
176 
177     fileType = readShort();
178 
179     if (fileType != 0x4d42)
180 
181       throw new Exception("Not a BMP file");  // wrong file type
182 
183     fileSize = readInt();
184 
185     reserved1 = readShort();
186 
187     reserved2 = readShort();
188 
189     bitmapOffset = readInt();
190 
191   }
192 
193   
194 
195   void getBitmapHeader() throws IOException {
196 
197     
198 
199     // Actual contents (40 bytes):
200 
201     int size;        // size of this header in bytes
202 
203     short planes;      // no. of color planes: always 1
204 
205     int sizeOfBitmap;    // size of bitmap in bytes (may be 0: if so, calculate)
206 
207     int horzResolution;    // horizontal resolution, pixels/meter (may be 0)
208 
209     int vertResolution;    // vertical resolution, pixels/meter (may be 0)
210 
211     int colorsUsed;      // no. of colors in palette (if 0, calculate)
212 
213     int colorsImportant;  // no. of important colors (appear first in palette) (0 means all are important)
214 
215     boolean topDown;
216 
217     int noOfPixels;
218 
219     
220 
221     size = readInt();
222 
223     width = readInt();
224 
225     height = readInt();
226 
227     planes = readShort();
228 
229     bitsPerPixel = readShort();
230 
231     compression = readInt();
232 
233     sizeOfBitmap = readInt();
234 
235     horzResolution = readInt();
236 
237     vertResolution = readInt();
238 
239     colorsUsed = readInt();
240 
241     colorsImportant = readInt();
242 
243     
244 
245     topDown = (height < 0);
246 
247     noOfPixels = width * height;
248 
249     
250 
251     // Scan line is padded with zeroes to be a multiple of four bytes
252 
253     scanLineSize = ((width * bitsPerPixel + 31) / 32) * 4;
254 
255     
256 
257     if (sizeOfBitmap != 0)
258 
259       actualSizeOfBitmap = sizeOfBitmap;
260 
261     else
262 
263       // a value of 0 doesn't mean zero - it means we have to calculate it
264 
265       actualSizeOfBitmap = scanLineSize * height;
266 
267     
268 
269     if (colorsUsed != 0)
270 
271       actualColorsUsed = colorsUsed;
272 
273     else
274 
275       // a value of 0 means we determine this based on the bits per pixel
276 
277       if (bitsPerPixel < 16)
278 
279   actualColorsUsed = 1 << bitsPerPixel;
280 
281       else
282 
283   actualColorsUsed = 0;  // no palette
284 
285   }
286 
287   
288 
289   
290 
291   void getPalette() throws IOException {
292 
293     noOfEntries = actualColorsUsed;
294 
295     //IJ.write("noOfEntries: " + noOfEntries);
296 
297     if (noOfEntries>0) {
298 
299       r = new byte[noOfEntries];
300 
301       g = new byte[noOfEntries];
302 
303       b = new byte[noOfEntries];
304 
305       
306 
307       int reserved;
308 
309       for (int i = 0; i < noOfEntries; i++) {
310 
311   b[i] = (byte)is.read();
312 
313   g[i] = (byte)is.read();
314 
315   r[i] = (byte)is.read();
316 
317   reserved = is.read();
318 
319   curPos += 4;
320 
321       }
322 
323     }
324 
325   }
326 
327   
328 
329   void unpack(byte[] rawData, int rawOffset, int[] intData, int intOffset, int w) {
330 
331     int j = intOffset;
332 
333     int k = rawOffset;
334 
335     int mask = 0xff;
336 
337     for (int i = 0; i < w; i++) {
338 
339       int b0 = (((int)(rawData[k++])) & mask);
340 
341       int b1 = (((int)(rawData[k++])) & mask) << 8;
342 
343       int b2 = (((int)(rawData[k++])) & mask) << 16;
344 
345       intData[j] = 0xff000000 | b0 | b1 | b2;
346 
347       j++;
348 
349     }
350 
351   }
352 
353   
354 
355   
356 
357   void unpack(byte[] rawData, int rawOffset, int bpp,
358 
359         byte[] byteData, int byteOffset, int w) throws Exception {
360 
361     int j = byteOffset;
362 
363     int k = rawOffset;
364 
365     byte mask;
366 
367     int pixPerByte;
368 
369     
370 
371     switch (bpp) {
372 
373     case 1:  mask = (byte)0x01; pixPerByte = 8; break;
374 
375     case 4:  mask = (byte)0x0f; pixPerByte = 2; break;
376 
377     case 8:  mask = (byte)0xff; pixPerByte = 1; break;
378 
379     default:
380 
381       throw new Exception("Unsupported bits-per-pixel value");
382 
383     }
384 
385     
386 
387     for (int i = 0;;) {
388 
389       int shift = 8 - bpp;
390 
391       for (int ii = 0; ii < pixPerByte; ii++) {
392 
393   byte br = rawData[k];
394 
395   br >>= shift;
396 
397   byteData[j] = (byte)(br & mask);
398 
399   //System.out.println("Setting byteData[" + j + "]=" + Test.byteToHex(byteData[j]));
400 
401   j++;
402 
403   i++;
404 
405   if (i == w) return;
406 
407   shift -= bpp;
408 
409       }
410 
411       k++;
412 
413     }
414 
415   }
416 
417   
418 
419   
420 
421   void getPixelData() throws Exception {
422 
423     byte[] rawData;      // the raw unpacked data
424 
425     
426 
427     // Skip to the start of the bitmap data (if we are not already there)
428 
429     long skip = bitmapOffset - curPos;
430 
431     if (skip > 0) {
432 
433       is.skip(skip);
434 
435       curPos += skip;
436 
437     }
438 
439     
440 
441     int len = scanLineSize;
442 
443     if (bitsPerPixel > 8)
444 
445       intData = new int[width * height];
446 
447     else
448 
449       byteData = new byte[width * height];
450 
451     rawData = new byte[actualSizeOfBitmap];
452 
453     int rawOffset = 0;
454 
455     int offset = (height - 1) * width;
456 
457     for (int i = height - 1; i >= 0; i--) {
458 
459       int n = is.read(rawData, rawOffset, len);
460 
461       if (n < len) throw new Exception("Scan line ended prematurely after "
462 
463                + n + " bytes");
464 
465       if (bitsPerPixel > 8) {
466 
467   // Unpack and create one int per pixel
468 
469   unpack(rawData, rawOffset, intData, offset, width);
470 
471       }
472 
473       else {
474 
475   // Unpack and create one byte per pixel
476 
477   unpack(rawData, rawOffset, bitsPerPixel,
478 
479          byteData, offset, width);
480 
481       }
482 
483       rawOffset += len;
484 
485       offset -= width;
486 
487     }
488 
489   }
490 
491   
492 
493   public void read(InputStream is) throws Exception {
494 
495     this.is = is;
496 
497     getFileHeader();
498 
499     getBitmapHeader();
500 
501     if (compression!=0)
502 
503       throw new Exception(" BMP Compression not supported");
504 
505     getPalette();
506 
507     getPixelData();
508 
509   }
510 
511   
512 
513   
514 
515   public MemoryImageSource getImageSource() {
516 
517     ColorModel cm;
518 
519     MemoryImageSource mis;
520 
521     
522 
523     if (noOfEntries > 0) {
524 
525       // There is a color palette; create an IndexColorModel
526 
527       cm = new IndexColorModel(bitsPerPixel,
528 
529              noOfEntries, r, g, b);
530 
531     } else {
532 
533       // There is no palette; use the default RGB color model
534 
535       cm = ColorModel.getRGBdefault();
536 
537     }
538 
539     
540 
541     // Create MemoryImageSource
542 
543     
544 
545     if (bitsPerPixel > 8) {
546 
547       // use one int per pixel
548 
549       mis = new MemoryImageSource(width,
550 
551           height, cm, intData, 0, width);
552 
553     } else {
554 
555       // use one byte per pixel
556 
557       mis = new MemoryImageSource(width,
558 
559           height, cm, byteData, 0, width);
560 
561     }
562 
563     
564 
565     return mis;   // this can be used by Component.createImage()
566 
567   }
568 
569 }
570