KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > internal > image > WinBMPFileFormat


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.swt.internal.image;
12
13
14 import org.eclipse.swt.*;
15 import org.eclipse.swt.graphics.*;
16 import java.io.*;
17
18 final class WinBMPFileFormat extends FileFormat {
19     static final int BMPFileHeaderSize = 14;
20     static final int BMPHeaderFixedSize = 40;
21     int importantColors;
22     Point pelsPerMeter = new Point(0, 0);
23
24 /**
25  * Compress numBytes bytes of image data from src, storing in dest
26  * (starting at 0), using the technique specified by comp.
27  * If last is true, this indicates the last line of the image.
28  * Answer the size of the compressed data.
29  */

30 int compress(int comp, byte[] src, int srcOffset, int numBytes, byte[] dest, boolean last) {
31     if (comp == 1) { // BMP_RLE8_COMPRESSION
32
return compressRLE8Data(src, srcOffset, numBytes, dest, last);
33     }
34     if (comp == 2) { // BMP_RLE4_COMPRESSION
35
return compressRLE4Data(src, srcOffset, numBytes, dest, last);
36     }
37     SWT.error(SWT.ERROR_INVALID_IMAGE);
38     return 0;
39 }
40 int compressRLE4Data(byte[] src, int srcOffset, int numBytes, byte[] dest, boolean last) {
41     int sp = srcOffset, end = srcOffset + numBytes, dp = 0;
42     int size = 0, left, i, n;
43     byte theByte;
44     while (sp < end) {
45         /* find two consecutive bytes that are the same in the next 128 */
46         left = end - sp - 1;
47         if (left > 127)
48             left = 127;
49         for (n = 0; n < left; n++) {
50             if (src[sp + n] == src[sp + n + 1])
51                 break;
52         }
53         /* if there is only one more byte in the scan line, include it */
54         if (n < 127 && n == left)
55             n++;
56         /* store the intervening data */
57         switch (n) {
58             case 0:
59                 break;
60             case 1: /* handled separately because 0,2 is a command */
61                 dest[dp] = 2; dp++; /* 1 byte == 2 pixels */
62                 dest[dp] = src[sp];
63                 dp++; sp++;
64                 size += 2;
65                 break;
66             default:
67                 dest[dp] = 0; dp++;
68                 dest[dp] = (byte)(n + n); dp++; /* n bytes = n*2 pixels */
69                 for (i = n; i > 0; i--) {
70                     dest[dp] = src[sp];
71                     dp++; sp++;
72                 }
73                 size += 2 + n;
74                 if ((n & 1) != 0) { /* pad to word */
75                     dest[dp] = 0;
76                     dp++;
77                     size++;
78                 }
79                 break;
80         }
81         /* find the length of the next run (up to 127) and store it */
82         left = end - sp;
83         if (left > 0) {
84             if (left > 127)
85                 left = 127;
86             theByte = src[sp];
87             for (n = 1; n < left; n++) {
88                 if (src[sp + n] != theByte)
89                     break;
90             }
91             dest[dp] = (byte)(n + n); dp++; /* n bytes = n*2 pixels */
92             dest[dp] = theByte; dp++;
93             sp += n;
94             size += 2;
95         }
96     }
97
98     /* store the end of line or end of bitmap codes */
99     dest[dp] = 0; dp++;
100     if (last) {
101         dest[dp] = 1; dp++;
102     } else {
103         dest[dp] = 0; dp++;
104     }
105     size += 2;
106     
107     return size;
108 }
109 int compressRLE8Data(byte[] src, int srcOffset, int numBytes, byte[] dest, boolean last) {
110     int sp = srcOffset, end = srcOffset + numBytes, dp = 0;
111     int size = 0, left, i, n;
112     byte theByte;
113     while (sp < end) {
114         /* find two consecutive bytes that are the same in the next 256 */
115         left = end - sp - 1;
116         if (left > 254)
117             left = 254;
118         for (n = 0; n < left; n++) {
119             if (src[sp + n] == src[sp + n + 1])
120                 break;
121         }
122         /* if there is only one more byte in the scan line, include it */
123         if (n == left)
124             n++;
125         /* store the intervening data */
126         switch (n) {
127             case 0:
128                 break;
129             case 2: /* handled separately because 0,2 is a command */
130                 dest[dp] = 1; dp++;
131                 dest[dp] = src[sp];
132                 dp++; sp++;
133                 size += 2;
134                 /* don't break, fall through */
135             case 1: /* handled separately because 0,1 is a command */
136                 dest[dp] = 1; dp++;
137                 dest[dp] = src[sp];
138                 dp++; sp++;
139                 size += 2;
140                 break;
141             default:
142                 dest[dp] = 0; dp++;
143                 dest[dp] = (byte)n; dp++;
144                 for (i = n; i > 0; i--) {
145                     dest[dp] = src[sp];
146                     dp++; sp++;
147                 }
148                 size += 2 + n;
149                 if ((n & 1) != 0) { /* pad to word */
150                     dest[dp] = 0;
151                     dp++;
152                     size++;
153                 }
154                 break;
155         }
156         /* find the length of the next run (up to 255) and store it */
157         left = end - sp;
158         if (left > 0) {
159             if (left > 255)
160                 left = 255;
161             theByte = src[sp];
162             for (n = 1; n < left; n++) {
163                 if (src[sp + n] != theByte)
164                     break;
165             }
166             dest[dp] = (byte)n; dp++;
167             dest[dp] = theByte; dp++;
168             sp += n;
169             size += 2;
170         }
171     }
172
173     /* store the end of line or end of bitmap codes */
174     dest[dp] = 0; dp++;
175     if (last) {
176         dest[dp] = 1; dp++;
177     } else {
178         dest[dp] = 0; dp++;
179     }
180     size += 2;
181     
182     return size;
183 }
184 void decompressData(byte[] src, byte[] dest, int stride, int cmp) {
185     if (cmp == 1) { // BMP_RLE8_COMPRESSION
186
if (decompressRLE8Data(src, src.length, stride, dest, dest.length) <= 0)
187             SWT.error(SWT.ERROR_INVALID_IMAGE);
188         return;
189     }
190     if (cmp == 2) { // BMP_RLE4_COMPRESSION
191
if (decompressRLE4Data(src, src.length, stride, dest, dest.length) <= 0)
192             SWT.error(SWT.ERROR_INVALID_IMAGE);
193         return;
194     }
195     SWT.error(SWT.ERROR_INVALID_IMAGE);
196 }
197 int decompressRLE4Data(byte[] src, int numBytes, int stride, byte[] dest, int destSize) {
198     int sp = 0;
199     int se = numBytes;
200     int dp = 0;
201     int de = destSize;
202     int x = 0, y = 0;
203     while (sp < se) {
204         int len = src[sp] & 0xFF;
205         sp++;
206         if (len == 0) {
207             len = src[sp] & 0xFF;
208             sp++;
209             switch (len) {
210                 case 0: /* end of line */
211                     y++;
212                     x = 0;
213                     dp = y * stride;
214                     if (dp > de)
215                         return -1;
216                     break;
217                 case 1: /* end of bitmap */
218                     return 1;
219                 case 2: /* delta */
220                     x += src[sp] & 0xFF;
221                     sp++;
222                     y += src[sp] & 0xFF;
223                     sp++;
224                     dp = y * stride + x / 2;
225                     if (dp > de)
226                         return -1;
227                     break;
228                 default: /* absolute mode run */
229                     if ((len & 1) != 0) /* odd run lengths not currently supported */
230                         return -1;
231                     x += len;
232                     len = len / 2;
233                     if (len > (se - sp))
234                         return -1;
235                     if (len > (de - dp))
236                         return -1;
237                     for (int i = 0; i < len; i++) {
238                         dest[dp] = src[sp];
239                         dp++;
240                         sp++;
241                     }
242                     if ((sp & 1) != 0)
243                         sp++; /* word align sp? */
244                     break;
245             }
246         } else {
247             if ((len & 1) != 0)
248                 return -1;
249             x += len;
250             len = len / 2;
251             byte theByte = src[sp];
252             sp++;
253             if (len > (de - dp))
254                 return -1;
255             for (int i = 0; i < len; i++) {
256                 dest[dp] = theByte;
257                 dp++;
258             }
259         }
260     }
261     return 1;
262 }
263 int decompressRLE8Data(byte[] src, int numBytes, int stride, byte[] dest, int destSize) {
264     int sp = 0;
265     int se = numBytes;
266     int dp = 0;
267     int de = destSize;
268     int x = 0, y = 0;
269     while (sp < se) {
270         int len = src[sp] & 0xFF;
271         sp++;
272         if (len == 0) {
273             len = src[sp] & 0xFF;
274             sp++;
275             switch (len) {
276                 case 0: /* end of line */
277                     y++;
278                     x = 0;
279                     dp = y * stride;
280                     if (dp > de)
281                         return -1;
282                     break;
283                 case 1: /* end of bitmap */
284                     return 1;
285                 case 2: /* delta */
286                     x += src[sp] & 0xFF;
287                     sp++;
288                     y += src[sp] & 0xFF;
289                     sp++;
290                     dp = y * stride + x;
291                     if (dp > de)
292                         return -1;
293                     break;
294                 default: /* absolute mode run */
295                     if (len > (se - sp))
296                         return -1;
297                     if (len > (de - dp))
298                         return -1;
299                     for (int i = 0; i < len; i++) {
300                         dest[dp] = src[sp];
301                         dp++;
302                         sp++;
303                     }
304                     if ((sp & 1) != 0)
305                         sp++; /* word align sp? */
306                     x += len;
307                     break;
308             }
309         } else {
310             byte theByte = src[sp];
311             sp++;
312             if (len > (de - dp))
313                 return -1;
314             for (int i = 0; i < len; i++) {
315                 dest[dp] = theByte;
316                 dp++;
317             }
318             x += len;
319         }
320     }
321     return 1;
322 }
323 boolean isFileFormat(LEDataInputStream stream) {
324     try {
325         byte[] header = new byte[18];
326         stream.read(header);
327         stream.unread(header);
328         int infoHeaderSize = (header[14] & 0xFF) | ((header[15] & 0xFF) << 8) | ((header[16] & 0xFF) << 16) | ((header[17] & 0xFF) << 24);
329         return header[0] == 0x42 && header[1] == 0x4D && infoHeaderSize >= BMPHeaderFixedSize;
330     } catch (Exception JavaDoc e) {
331         return false;
332     }
333 }
334 byte[] loadData(byte[] infoHeader) {
335     int width = (infoHeader[4] & 0xFF) | ((infoHeader[5] & 0xFF) << 8) | ((infoHeader[6] & 0xFF) << 16) | ((infoHeader[7] & 0xFF) << 24);
336     int height = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24);
337     int bitCount = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8);
338     int stride = (width * bitCount + 7) / 8;
339     stride = (stride + 3) / 4 * 4; // Round up to 4 byte multiple
340
byte[] data = loadData(infoHeader, stride);
341     flipScanLines(data, stride, height);
342     return data;
343 }
344 byte[] loadData(byte[] infoHeader, int stride) {
345     int height = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24);
346     if (height < 0) height = -height;
347     int dataSize = height * stride;
348     byte[] data = new byte[dataSize];
349     int cmp = (infoHeader[16] & 0xFF) | ((infoHeader[17] & 0xFF) << 8) | ((infoHeader[18] & 0xFF) << 16) | ((infoHeader[19] & 0xFF) << 24);
350     if (cmp == 0 || cmp == 3) { // BMP_NO_COMPRESSION
351
try {
352             if (inputStream.read(data) != dataSize)
353                 SWT.error(SWT.ERROR_INVALID_IMAGE);
354         } catch (IOException e) {
355             SWT.error(SWT.ERROR_IO, e);
356         }
357     } else {
358         int compressedSize = (infoHeader[20] & 0xFF) | ((infoHeader[21] & 0xFF) << 8) | ((infoHeader[22] & 0xFF) << 16) | ((infoHeader[23] & 0xFF) << 24);
359         byte[] compressed = new byte[compressedSize];
360         try {
361             if (inputStream.read(compressed) != compressedSize)
362                 SWT.error(SWT.ERROR_INVALID_IMAGE);
363         } catch (IOException e) {
364             SWT.error(SWT.ERROR_IO, e);
365         }
366         decompressData(compressed, data, stride, cmp);
367     }
368     return data;
369 }
370 int[] loadFileHeader() {
371     int[] header = new int[5];
372     try {
373         header[0] = inputStream.readShort();
374         header[1] = inputStream.readInt();
375         header[2] = inputStream.readShort();
376         header[3] = inputStream.readShort();
377         header[4] = inputStream.readInt();
378     } catch (IOException e) {
379         SWT.error(SWT.ERROR_IO, e);
380     }
381     if (header[0] != 0x4D42)
382         SWT.error(SWT.ERROR_INVALID_IMAGE);
383     return header;
384 }
385 ImageData[] loadFromByteStream() {
386     int[] fileHeader = loadFileHeader();
387     byte[] infoHeader = new byte[BMPHeaderFixedSize];
388     try {
389         inputStream.read(infoHeader);
390     } catch (Exception JavaDoc e) {
391         SWT.error(SWT.ERROR_IO, e);
392     }
393     int width = (infoHeader[4] & 0xFF) | ((infoHeader[5] & 0xFF) << 8) | ((infoHeader[6] & 0xFF) << 16) | ((infoHeader[7] & 0xFF) << 24);
394     int height = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24);
395     if (height < 0) height = -height;
396     int bitCount = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8);
397     this.compression = (infoHeader[16] & 0xFF) | ((infoHeader[17] & 0xFF) << 8) | ((infoHeader[18] & 0xFF) << 16) | ((infoHeader[19] & 0xFF) << 24);
398     PaletteData palette = loadPalette(infoHeader);
399     if (inputStream.getPosition() < fileHeader[4]) {
400         // Seek to the specified offset
401
try {
402             inputStream.skip(fileHeader[4] - inputStream.getPosition());
403         } catch (IOException e) {
404             SWT.error(SWT.ERROR_IO, e);
405         }
406     }
407     byte[] data = loadData(infoHeader);
408     this.importantColors = (infoHeader[36] & 0xFF) | ((infoHeader[37] & 0xFF) << 8) | ((infoHeader[38] & 0xFF) << 16) | ((infoHeader[39] & 0xFF) << 24);
409     int xPelsPerMeter = (infoHeader[24] & 0xFF) | ((infoHeader[25] & 0xFF) << 8) | ((infoHeader[26] & 0xFF) << 16) | ((infoHeader[27] & 0xFF) << 24);
410     int yPelsPerMeter = (infoHeader[28] & 0xFF) | ((infoHeader[29] & 0xFF) << 8) | ((infoHeader[30] & 0xFF) << 16) | ((infoHeader[31] & 0xFF) << 24);
411     this.pelsPerMeter = new Point(xPelsPerMeter, yPelsPerMeter);
412     int type = (this.compression == 1 /*BMP_RLE8_COMPRESSION*/) || (this.compression == 2 /*BMP_RLE4_COMPRESSION*/) ? SWT.IMAGE_BMP_RLE : SWT.IMAGE_BMP;
413     return new ImageData[] {
414         ImageData.internal_new(
415             width,
416             height,
417             bitCount,
418             palette,
419             4,
420             data,
421             0,
422             null,
423             null,
424             -1,
425             -1,
426             type,
427             0,
428             0,
429             0,
430             0)
431     };
432 }
433 PaletteData loadPalette(byte[] infoHeader) {
434     int depth = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8);
435     if (depth <= 8) {
436         int numColors = (infoHeader[32] & 0xFF) | ((infoHeader[33] & 0xFF) << 8) | ((infoHeader[34] & 0xFF) << 16) | ((infoHeader[35] & 0xFF) << 24);
437         if (numColors == 0) {
438             numColors = 1 << depth;
439         } else {
440             if (numColors > 256)
441                 numColors = 256;
442         }
443         byte[] buf = new byte[numColors * 4];
444         try {
445             if (inputStream.read(buf) != buf.length)
446                 SWT.error(SWT.ERROR_INVALID_IMAGE);
447         } catch (IOException e) {
448             SWT.error(SWT.ERROR_IO, e);
449         }
450         return paletteFromBytes(buf, numColors);
451     }
452     if (depth == 16) {
453         if (this.compression == 3) {
454             try {
455                 return new PaletteData(inputStream.readInt(), inputStream.readInt(), inputStream.readInt());
456             } catch (IOException e) {
457                 SWT.error(SWT.ERROR_IO, e);
458             }
459         }
460         return new PaletteData(0x7C00, 0x3E0, 0x1F);
461     }
462     if (depth == 24) return new PaletteData(0xFF, 0xFF00, 0xFF0000);
463     if (this.compression == 3) {
464         try {
465             return new PaletteData(inputStream.readInt(), inputStream.readInt(), inputStream.readInt());
466         } catch (IOException e) {
467             SWT.error(SWT.ERROR_IO, e);
468         }
469     }
470     return new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
471 }
472 PaletteData paletteFromBytes(byte[] bytes, int numColors) {
473     int bytesOffset = 0;
474     RGB[] colors = new RGB[numColors];
475     for (int i = 0; i < numColors; i++) {
476         colors[i] = new RGB(bytes[bytesOffset + 2] & 0xFF,
477             bytes[bytesOffset + 1] & 0xFF,
478             bytes[bytesOffset] & 0xFF);
479         bytesOffset += 4;
480     }
481     return new PaletteData(colors);
482 }
483 /**
484  * Answer a byte array containing the BMP representation of
485  * the given device independent palette.
486  */

487 static byte[] paletteToBytes(PaletteData pal) {
488     int n = pal.colors == null ? 0 : (pal.colors.length < 256 ? pal.colors.length : 256);
489     byte[] bytes = new byte[n * 4];
490     int offset = 0;
491     for (int i = 0; i < n; i++) {
492         RGB col = pal.colors[i];
493         bytes[offset] = (byte)col.blue;
494         bytes[offset + 1] = (byte)col.green;
495         bytes[offset + 2] = (byte)col.red;
496         offset += 4;
497     }
498     return bytes;
499 }
500 /**
501  * Unload the given image's data into the given byte stream
502  * using the given compression strategy.
503  * Answer the number of bytes written.
504  */

505 int unloadData(ImageData image, OutputStream out, int comp) {
506     int totalSize = 0;
507     try {
508         if (comp == 0)
509             return unloadDataNoCompression(image, out);
510         int bpl = (image.width * image.depth + 7) / 8;
511         int bmpBpl = (bpl + 3) / 4 * 4; // BMP pads scanlines to multiples of 4 bytes
512
int imageBpl = image.bytesPerLine;
513         // Compression can actually take twice as much space, in worst case
514
byte[] buf = new byte[bmpBpl * 2];
515         int srcOffset = imageBpl * (image.height - 1); // Start at last line
516
byte[] data = image.data;
517         totalSize = 0;
518         byte[] buf2 = new byte[32768];
519         int buf2Offset = 0;
520         for (int y = image.height - 1; y >= 0; y--) {
521             int lineSize = compress(comp, data, srcOffset, bpl, buf, y == 0);
522             if (buf2Offset + lineSize > buf2.length) {
523                 out.write(buf2, 0, buf2Offset);
524                 buf2Offset = 0;
525             }
526             System.arraycopy(buf, 0, buf2, buf2Offset, lineSize);
527             buf2Offset += lineSize;
528             totalSize += lineSize;
529             srcOffset -= imageBpl;
530         }
531         if (buf2Offset > 0)
532             out.write(buf2, 0, buf2Offset);
533     } catch (IOException e) {
534         SWT.error(SWT.ERROR_IO, e);
535     }
536     return totalSize;
537 }
538 /**
539  * Prepare the given image's data for unloading into a byte stream
540  * using no compression strategy.
541  * Answer the number of bytes written.
542  */

543 int unloadDataNoCompression(ImageData image, OutputStream out) {
544     int bmpBpl = 0;
545     try {
546         int bpl = (image.width * image.depth + 7) / 8;
547         bmpBpl = (bpl + 3) / 4 * 4; // BMP pads scanlines to multiples of 4 bytes
548
int linesPerBuf = 32678 / bmpBpl;
549         byte[] buf = new byte[linesPerBuf * bmpBpl];
550         byte[] data = image.data;
551         int imageBpl = image.bytesPerLine;
552         int dataIndex = imageBpl * (image.height - 1); // Start at last line
553
if (image.depth == 16) {
554             for (int y = 0; y < image.height; y += linesPerBuf) {
555                 int count = image.height - y;
556                 if (linesPerBuf < count) count = linesPerBuf;
557                 int bufOffset = 0;
558                 for (int i = 0; i < count; i++) {
559                     for (int wIndex = 0; wIndex < bpl; wIndex += 2) {
560                         buf[bufOffset + wIndex + 1] = data[dataIndex + wIndex + 1];
561                         buf[bufOffset + wIndex] = data[dataIndex + wIndex];
562                     }
563                     bufOffset += bmpBpl;
564                     dataIndex -= imageBpl;
565                 }
566                 out.write(buf, 0, bufOffset);
567             }
568         } else {
569             for (int y = 0; y < image.height; y += linesPerBuf) {
570                 int tmp = image.height - y;
571                 int count = tmp < linesPerBuf ? tmp : linesPerBuf;
572                 int bufOffset = 0;
573                 for (int i = 0; i < count; i++) {
574                     System.arraycopy(data, dataIndex, buf, bufOffset, bpl);
575                     bufOffset += bmpBpl;
576                     dataIndex -= imageBpl;
577                 }
578                 out.write(buf, 0, bufOffset);
579             }
580         }
581     } catch (IOException e) {
582         SWT.error(SWT.ERROR_IO, e);
583     }
584     return bmpBpl * image.height;
585 }
586 /**
587  * Unload a DeviceIndependentImage using Windows .BMP format into the given
588  * byte stream.
589  */

590 void unloadIntoByteStream(ImageLoader loader) {
591     ImageData image = loader.data[0];
592     byte[] rgbs;
593     int numCols;
594     if (!((image.depth == 1) || (image.depth == 4) || (image.depth == 8) ||
595           (image.depth == 16) || (image.depth == 24) || (image.depth == 32)))
596             SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
597     int comp = this.compression;
598     if (!((comp == 0) || ((comp == 1) && (image.depth == 8)) ||
599           ((comp == 2) && (image.depth == 4))))
600             SWT.error(SWT.ERROR_INVALID_IMAGE);
601     PaletteData pal = image.palette;
602     if ((image.depth == 16) || (image.depth == 24) || (image.depth == 32)) {
603         if (!pal.isDirect)
604             SWT.error(SWT.ERROR_INVALID_IMAGE);
605         numCols = 0;
606         rgbs = null;
607     } else {
608         if (pal.isDirect)
609             SWT.error(SWT.ERROR_INVALID_IMAGE);
610         numCols = pal.colors.length;
611         rgbs = paletteToBytes(pal);
612     }
613     // Fill in file header, except for bfsize, which is done later.
614
int headersSize = BMPFileHeaderSize + BMPHeaderFixedSize;
615     int[] fileHeader = new int[5];
616     fileHeader[0] = 0x4D42; // Signature
617
fileHeader[1] = 0; // File size - filled in later
618
fileHeader[2] = 0; // Reserved 1
619
fileHeader[3] = 0; // Reserved 2
620
fileHeader[4] = headersSize; // Offset to data
621
if (rgbs != null) {
622         fileHeader[4] += rgbs.length;
623     }
624
625     // Prepare data. This is done first so we don't have to try to rewind
626
// the stream and fill in the details later.
627
ByteArrayOutputStream out = new ByteArrayOutputStream();
628     unloadData(image, out, comp);
629     byte[] data = out.toByteArray();
630     
631     // Calculate file size
632
fileHeader[1] = fileHeader[4] + data.length;
633
634     // Write the headers
635
try {
636         outputStream.writeShort(fileHeader[0]);
637         outputStream.writeInt(fileHeader[1]);
638         outputStream.writeShort(fileHeader[2]);
639         outputStream.writeShort(fileHeader[3]);
640         outputStream.writeInt(fileHeader[4]);
641     } catch (IOException e) {
642         SWT.error(SWT.ERROR_IO, e);
643     }
644     try {
645         outputStream.writeInt(BMPHeaderFixedSize);
646         outputStream.writeInt(image.width);
647         outputStream.writeInt(image.height);
648         outputStream.writeShort(1);
649         outputStream.writeShort((short)image.depth);
650         outputStream.writeInt(comp);
651         outputStream.writeInt(data.length);
652         outputStream.writeInt(pelsPerMeter.x);
653         outputStream.writeInt(pelsPerMeter.y);
654         outputStream.writeInt(numCols);
655         outputStream.writeInt(importantColors);
656     } catch (IOException e) {
657         SWT.error(SWT.ERROR_IO, e);
658     }
659     
660     // Unload palette
661
if (numCols > 0) {
662         try {
663             outputStream.write(rgbs);
664         } catch (IOException e) {
665             SWT.error(SWT.ERROR_IO, e);
666         }
667     }
668
669     // Unload the data
670
try {
671         outputStream.write(data);
672     } catch (IOException e) {
673         SWT.error(SWT.ERROR_IO, e);
674     }
675 }
676 void flipScanLines(byte[] data, int stride, int height) {
677     int i1 = 0;
678     int i2 = (height - 1) * stride;
679     for (int i = 0; i < height / 2; i++) {
680         for (int index = 0; index < stride; index++) {
681             byte b = data[index + i1];
682             data[index + i1] = data[index + i2];
683             data[index + i2] = b;
684         }
685         i1 += stride;
686         i2 -= stride;
687     }
688 }
689
690 }
691
Popular Tags