KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > tools > internal > IconExe


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.tools.internal;
12
13 import java.io.*;
14 import java.util.*;
15
16 /**
17  * Customize the icon of a Windows exe
18  *
19  * WARNING! This class is not part of SWT API. It is NOT API. It is an internal
20  * tool that may be changed or removed at anytime.
21  *
22  * Based on MSDN "An In-Depth Look into the Win32 Portable Executable File Format"
23  */

24 public class IconExe {
25     
26      /**
27      * Replace the Desktop icons provided in the Windows executable program
28      * with matching icons provided by the user.
29      *
30      * Takes 2 arguments
31      * argument 0: the Windows executable e.g c:/eclipse/eclipse.exe
32      * argument 1: The .ico file to write to the given executable e.g. c:/myApp.ico
33      *
34      * Note 1. Write access to the executable program is required. As a result, that
35      * program must not be currently running or edited elsewhere.
36      *
37      * Note 2. The Eclipse 3.1 launcher requires a .ico file with the following 6 images
38      * 1. 32x32, 4 bit (Windows 16 colors palette)
39      * 2. 16x16, 4 bit (Windows 16 colors palette)
40      * 3. 16x16, 8 bit (256 colors)
41      * 4. 32x32, 8 bit (256 colors)
42      * 5. 48x48, 4 bit (Windows 16 colors palette)
43      * 6. 48x48, 8 bit (256 colors)
44      * A user icon matching exactly the width/height/depth of an executable icon will be written
45      * to the executable and will replace that executable icon. If an executable icon
46      * does not match a user icon, it is silently left as is.
47      *
48      * Note 3. This function modifies the content of the executable program and may cause
49      * its corruption.
50      */

51     public static void main(String JavaDoc[] args) throws Exception JavaDoc {
52         if (args.length < 2) {
53             System.err.println("Usage: IconExe <windows executable> <ico file>");
54             return;
55         }
56         ImageLoader loader = new ImageLoader();
57
58         List images = new ArrayList();
59         for (int i = 1; i < args.length; i++) {
60             try {
61                 //An ICO should contain 7 images, a BMP will contain 1
62
ImageData[] current = loader.load(args[i]);
63                 for (int j = 0; j < current.length; j++) {
64                     images.add(current[j]);
65                 }
66             } catch (RuntimeException JavaDoc e) {
67                 //ignore so that we process the other images
68
}
69         }
70         ImageData[] data = new ImageData[images.size()];
71         data = (ImageData[]) images.toArray(data);
72         
73         int nMissing = unloadIcons(args[0], data);
74         if (nMissing != 0)
75             System.err.println("Error - " + nMissing + " icon(s) not replaced in " + args[0] + " using " + args[1]);
76     }
77     
78     /* Implementation */
79
80     /**
81      * Retrieve the Desktop icons provided in the Windows executable program.
82      * These icons are typically shown in various places of the Windows desktop.
83      *
84      * Note. The Eclipse 3.1 launcher returns the following 6 images
85      * 1. 32x32, 4 bit (Windows 16 colors palette)
86      * 2. 16x16, 4 bit (Windows 16 colors palette)
87      * 3. 16x16, 8 bit (256 colors)
88      * 4. 32x32, 8 bit (256 colors)
89      * 5. 48x48, 4 bit (Windows 16 colors palette)
90      * 6. 48x48, 8 bit (256 colors)
91      *
92      * @param program the Windows executable e.g c:/eclipse/eclipse.exe
93      */

94     static ImageData[] loadIcons(String JavaDoc program) throws FileNotFoundException, IOException {
95         RandomAccessFile raf = new RandomAccessFile(program, "r");
96         IconExe iconExe = new IconExe();
97         IconResInfo[] iconInfo = iconExe.getIcons(raf);
98         ImageData[] data = new ImageData[iconInfo.length];
99         for (int i = 0; i < data.length; i++) data[i] = iconInfo[i].data;
100         raf.close();
101         return data;
102     }
103     
104     /**
105      * Replace the Desktop icons provided in the Windows executable program
106      * with icons provided by the user.
107      *
108      * Note 1. Write access to the executable program is required. As a result, that
109      * program must not be currently running or edited elsewhere.
110      *
111      * Note 2. Use loadIcons to determine which set of icons (width, height, depth)
112      * is required to replace the icons in the executable program. A user icon
113      * matching exactly the width/height/depth of an executable icon will be written
114      * to the executable and will replace that executable icon. If an executable icon
115      * does not match a user icon, it is left as is. Verify the return value matches
116      * the number of icons to write. Finally, use loadIcons after this operation
117      * to verify the icons have changed as expected.
118      *
119      * Note 3. The Eclipse 3.1 launcher requires the following 6 images (in any order).
120      * 1. 32x32, 4 bit (Windows 16 colors palette)
121      * 2. 16x16, 4 bit (Windows 16 colors palette)
122      * 3. 16x16, 8 bit (256 colors)
123      * 4. 32x32, 8 bit (256 colors)
124      * 5. 48x48, 4 bit (Windows 16 colors palette)
125      * 6. 48x48, 8 bit (256 colors)
126      *
127      * Note 4. This function modifies the content of the executable program and may cause
128      * its corruption.
129      *
130      * @param program the Windows executable e.g c:/eclipse/eclipse.exe
131      * @param icons to write to the given executable
132      * @return the number of icons from the original program that were not successfully replaced (0 if success)
133      */

134     static int unloadIcons(String JavaDoc program, ImageData[] icons) throws FileNotFoundException, IOException {
135         RandomAccessFile raf = new RandomAccessFile(program, "rw");
136         IconExe iconExe = new IconExe();
137         IconResInfo[] iconInfo = iconExe.getIcons(raf);
138         int cnt = 0;
139         for (int i = 0; i < iconInfo.length; i++) {
140             for (int j = 0; j < icons.length; j++) {
141                 if (icons[j] == null)
142                     continue;
143                 if (iconInfo[i].data.width == icons[j].width && iconInfo[i].data.height == icons[j].height && iconInfo[i].data.depth == icons[j].depth) {
144                     raf.seek(iconInfo[i].offset);
145                     unloadIcon(raf, icons[j]);
146                     cnt++;
147                     break;
148                 }
149             }
150         }
151         raf.close();
152         return iconInfo.length - cnt;
153     }
154     
155     public static final String JavaDoc VERSION = "20050124";
156     
157     static final boolean DEBUG = false;
158     public static class IconResInfo {
159         ImageData data;
160         int offset;
161         int size;
162     }
163     
164     IconResInfo[] iconInfo = null;
165     int iconCnt;
166     
167     IconResInfo[] getIcons(RandomAccessFile raf) throws IOException {
168         iconInfo = new IconResInfo[4];
169         iconCnt = 0;
170         IMAGE_DOS_HEADER imageDosHeader = new IMAGE_DOS_HEADER();
171         read(raf, imageDosHeader);
172         if (imageDosHeader.e_magic != IMAGE_DOS_SIGNATURE) return null;
173         int imageNtHeadersOffset = imageDosHeader.e_lfanew;
174         raf.seek(imageNtHeadersOffset);
175         IMAGE_NT_HEADERS imageNtHeaders = new IMAGE_NT_HEADERS();
176         read(raf, imageNtHeaders);
177         if (imageNtHeaders.Signature != IMAGE_NT_SIGNATURE) return null;
178         
179         // DumpResources
180
int resourcesRVA = imageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
181         if (resourcesRVA == 0) return null;
182         if (DEBUG) System.out.println("* Resources (RVA= "+resourcesRVA+")");
183         IMAGE_SECTION_HEADER imageSectionHeader = new IMAGE_SECTION_HEADER();
184         int firstSectionOffset = imageNtHeadersOffset + IMAGE_NT_HEADERS.FIELD_OFFSET_OptionalHeader + imageNtHeaders.FileHeader.SizeOfOptionalHeader;
185         raf.seek(firstSectionOffset);
186         boolean found = false;
187         for (int i = 0; i < imageNtHeaders.FileHeader.NumberOfSections; i++) {
188             read(raf, imageSectionHeader);
189             if (resourcesRVA >= imageSectionHeader.VirtualAddress && resourcesRVA < imageSectionHeader.VirtualAddress + imageSectionHeader.Misc_VirtualSize) {
190                 // could check the imageSectionHeader name is .rsrc
191
found = true;
192                 break;
193             }
194         }
195         if (!found) return null;
196         int delta = imageSectionHeader.VirtualAddress - imageSectionHeader.PointerToRawData;
197         int imageResourceDirectoryOffset = resourcesRVA - delta;
198         dumpResourceDirectory(raf, imageResourceDirectoryOffset, imageResourceDirectoryOffset, delta, 0, 0, false);
199         if (iconCnt < iconInfo.length) {
200             IconResInfo[] newArray = new IconResInfo[iconCnt];
201             System.arraycopy(iconInfo, 0, newArray, 0, iconCnt);
202             iconInfo = newArray;
203         }
204         return iconInfo;
205     }
206
207 void dumpResourceDirectory(RandomAccessFile raf, int imageResourceDirectoryOffset, int resourceBase, int delta, int type, int level, boolean rt_icon_root) throws IOException {
208     if (DEBUG) System.out.println("** LEVEL "+level);
209
210     IMAGE_RESOURCE_DIRECTORY imageResourceDirectory = new IMAGE_RESOURCE_DIRECTORY();
211     raf.seek(imageResourceDirectoryOffset);
212     read(raf, imageResourceDirectory);
213
214     if (DEBUG) {
215         String JavaDoc sType = ""+type;
216         // level 1 resources are resource types
217
if (level == 1) {
218             System.out.println("___________________________");
219             if (type == RT_ICON) sType = "RT_ICON";
220             if (type == RT_GROUP_ICON) sType = "RT_GROUP_ICON";
221         }
222         System.out.println("Resource Directory ["+sType+"]"+" (Named "+imageResourceDirectory.NumberOfNamedEntries+", ID "+imageResourceDirectory.NumberOfIdEntries+")");
223     }
224     int IRDE_StartOffset = imageResourceDirectoryOffset + IMAGE_RESOURCE_DIRECTORY.SIZEOF;
225     IMAGE_RESOURCE_DIRECTORY_ENTRY[] imageResourceDirectoryEntries = new IMAGE_RESOURCE_DIRECTORY_ENTRY[imageResourceDirectory.NumberOfIdEntries];
226     for (int i = 0; i < imageResourceDirectoryEntries.length; i++) {
227         imageResourceDirectoryEntries[i] = new IMAGE_RESOURCE_DIRECTORY_ENTRY();
228         read(raf, imageResourceDirectoryEntries[i]);
229     }
230     for (int i = 0; i < imageResourceDirectoryEntries.length; i++) {
231         if (imageResourceDirectoryEntries[i].DataIsDirectory) {
232             dumpResourceDirectory(raf, imageResourceDirectoryEntries[i].OffsetToDirectory + resourceBase, resourceBase, delta, imageResourceDirectoryEntries[i].Id, level + 1, rt_icon_root ? true : type == RT_ICON);
233         } else {
234             // Resource found
235
/// pResDirEntry->Name
236
IMAGE_RESOURCE_DIRECTORY_ENTRY irde = imageResourceDirectoryEntries[i];
237             IMAGE_RESOURCE_DATA_ENTRY data = new IMAGE_RESOURCE_DATA_ENTRY();
238             raf.seek(imageResourceDirectoryEntries[i].OffsetToData + resourceBase);
239             read(raf, data);
240             if (DEBUG) System.out.println("Resource Id "+irde.Id+" Data Offset RVA "+data.OffsetToData+", Size "+data.Size);
241             if (rt_icon_root) {
242                 if (DEBUG) System.out.println("iconcnt "+iconCnt+" |"+iconInfo.length);
243                 iconInfo[iconCnt] = new IconResInfo();
244                 iconInfo[iconCnt].data = parseIcon(raf, data.OffsetToData - delta, data.Size);
245                 iconInfo[iconCnt].offset = data.OffsetToData - delta;
246                 iconInfo[iconCnt].size = data.Size;
247                 iconCnt++;
248                 if (iconCnt == iconInfo.length) {
249                     IconResInfo[] newArray = new IconResInfo[iconInfo.length + 4];
250                     System.arraycopy(iconInfo, 0, newArray, 0, iconInfo.length);
251                     iconInfo = newArray;
252                 }
253             }
254         }
255     }
256 }
257
258 static ImageData parseIcon(RandomAccessFile raf, int offset, int size) throws IOException {
259     raf.seek(offset);
260     BITMAPINFO bitmapInfo = new BITMAPINFO();
261     read(raf, bitmapInfo);
262     bitmapInfo.bmiHeader.biHeight /= 2;
263     int width = bitmapInfo.bmiHeader.biWidth;
264     int height = bitmapInfo.bmiHeader.biHeight;
265     int depth = bitmapInfo.bmiHeader.biBitCount;
266
267     PaletteData palette = loadPalette(bitmapInfo.bmiHeader, raf);
268     byte[] shapeData = loadData(bitmapInfo.bmiHeader, raf);
269     bitmapInfo.bmiHeader.biBitCount = 1;
270     byte[] maskData = loadData(bitmapInfo.bmiHeader, raf);
271     maskData = convertPad(maskData, width, height, 1, 4, 2);
272     bitInvertData(maskData, 0, maskData.length);
273     return ImageData.internal_new(
274         width,
275         height,
276         depth,
277         palette,
278         4,
279         shapeData,
280         2,
281         maskData,
282         null,
283         -1,
284         -1,
285         SWT.IMAGE_ICO,
286         0,
287         0,
288         0,
289         0);
290 }
291
292 static byte[] bitInvertData(byte[] data, int startIndex, int endIndex) {
293     // Destructively bit invert data in the given byte array.
294
for (int i = startIndex; i < endIndex; i++) {
295         data[i] = (byte)(255 - data[i - startIndex]);
296     }
297     return data;
298 }
299
300 static final byte[] convertPad(byte[] data, int width, int height, int depth, int pad, int newPad) {
301     if (pad == newPad) return data;
302     int stride = (width * depth + 7) / 8;
303     int bpl = (stride + (pad - 1)) / pad * pad;
304     int newBpl = (stride + (newPad - 1)) / newPad * newPad;
305     byte[] newData = new byte[height * newBpl];
306     int srcIndex = 0, destIndex = 0;
307     for (int y = 0; y < height; y++) {
308         System.arraycopy(data, srcIndex, newData, destIndex, newBpl);
309         srcIndex += bpl;
310         destIndex += newBpl;
311     }
312     return newData;
313 }
314 static PaletteData loadPalette(BITMAPINFOHEADER bih, RandomAccessFile raf) throws IOException {
315     int depth = bih.biBitCount;
316     if (depth <= 8) {
317         int numColors = bih.biClrUsed;
318         if (numColors == 0) {
319             numColors = 1 << depth;
320         } else {
321             if (numColors > 256)
322                 numColors = 256;
323         }
324         byte[] buf = new byte[numColors * 4];
325         raf.read(buf);
326         return paletteFromBytes(buf, numColors);
327     }
328     if (depth == 16) return new PaletteData(0x7C00, 0x3E0, 0x1F);
329     if (depth == 24) return new PaletteData(0xFF, 0xFF00, 0xFF0000);
330     return new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
331 }
332 static PaletteData paletteFromBytes(byte[] bytes, int numColors) {
333     int bytesOffset = 0;
334     RGB[] colors = new RGB[numColors];
335     for (int i = 0; i < numColors; i++) {
336         colors[i] = new RGB(bytes[bytesOffset + 2] & 0xFF,
337             bytes[bytesOffset + 1] & 0xFF,
338             bytes[bytesOffset] & 0xFF);
339         bytesOffset += 4;
340     }
341     return new PaletteData(colors);
342 }
343 static byte[] loadData(BITMAPINFOHEADER bih, RandomAccessFile raf) throws IOException {
344     int stride = (bih.biWidth * bih.biBitCount + 7) / 8;
345     stride = (stride + 3) / 4 * 4; // Round up to 4 byte multiple
346
byte[] data = loadData(bih, raf, stride);
347     flipScanLines(data, stride, bih.biHeight);
348     return data;
349 }
350 static void flipScanLines(byte[] data, int stride, int height) {
351     int i1 = 0;
352     int i2 = (height - 1) * stride;
353     for (int i = 0; i < height / 2; i++) {
354         for (int index = 0; index < stride; index++) {
355             byte b = data[index + i1];
356             data[index + i1] = data[index + i2];
357             data[index + i2] = b;
358         }
359         i1 += stride;
360         i2 -= stride;
361     }
362 }
363 static byte[] loadData(BITMAPINFOHEADER bih, RandomAccessFile raf, int stride) throws IOException {
364     int dataSize = bih.biHeight * stride;
365     byte[] data = new byte[dataSize];
366     int cmp = bih.biCompression;
367     if (cmp == 0) { // BMP_NO_COMPRESSION
368
raf.read(data);
369     } else {
370         if (DEBUG) System.out.println("ICO cannot be compressed?");
371     }
372     return data;
373 }
374
375 static void unloadIcon(RandomAccessFile raf, ImageData icon) throws IOException {
376     int sizeImage = (((icon.width * icon.depth + 31) / 32 * 4) +
377         ((icon.width + 31) / 32 * 4)) * icon.height;
378     write4(raf, BMPHeaderFixedSize);
379     write4(raf, icon.width);
380     write4(raf, icon.height * 2);
381     writeU2(raf, 1);
382     writeU2(raf, icon.depth);
383     write4(raf, 0);
384     write4(raf, sizeImage);
385     write4(raf, 0);
386     write4(raf, 0);
387     write4(raf, icon.palette.colors != null ? icon.palette.colors.length : 0);
388     write4(raf, 0);
389     
390     byte[] rgbs = paletteToBytes(icon.palette);
391     raf.write(rgbs);
392     unloadShapeData(raf, icon);
393     unloadMaskData(raf, icon);
394 }
395 static byte[] paletteToBytes(PaletteData pal) {
396     int n = pal.colors == null ? 0 : (pal.colors.length < 256 ? pal.colors.length : 256);
397     byte[] bytes = new byte[n * 4];
398     int offset = 0;
399     for (int i = 0; i < n; i++) {
400         RGB col = pal.colors[i];
401         bytes[offset] = (byte)col.blue;
402         bytes[offset + 1] = (byte)col.green;
403         bytes[offset + 2] = (byte)col.red;
404         offset += 4;
405     }
406     return bytes;
407 }
408 static void unloadMaskData(RandomAccessFile raf, ImageData icon) {
409     ImageData mask = icon.getTransparencyMask();
410     int bpl = (icon.width + 7) / 8;
411     int pad = mask.scanlinePad;
412     int srcBpl = (bpl + pad - 1) / pad * pad;
413     int destBpl = (bpl + 3) / 4 * 4;
414     byte[] buf = new byte[destBpl];
415     int offset = (icon.height - 1) * srcBpl;
416     byte[] data = mask.data;
417     try {
418         for (int i = 0; i < icon.height; i++) {
419             System.arraycopy(data, offset, buf, 0, bpl);
420             bitInvertData(buf, 0, bpl);
421             raf.write(buf, 0, destBpl);
422             offset -= srcBpl;
423         }
424     } catch (IOException e) {
425         SWT.error(SWT.ERROR_IO, e);
426     }
427 }
428 static void unloadShapeData(RandomAccessFile raf, ImageData icon) {
429     int bpl = (icon.width * icon.depth + 7) / 8;
430     int pad = icon.scanlinePad;
431     int srcBpl = (bpl + pad - 1) / pad * pad;
432     int destBpl = (bpl + 3) / 4 * 4;
433     byte[] buf = new byte[destBpl];
434     int offset = (icon.height - 1) * srcBpl;
435     byte[] data = icon.data;
436     try {
437         for (int i = 0; i < icon.height; i++) {
438             System.arraycopy(data, offset, buf, 0, bpl);
439             raf.write(buf, 0, destBpl);
440             offset -= srcBpl;
441         }
442     } catch (IOException e) {
443         SWT.error(SWT.ERROR_IO, e);
444     }
445 }
446 static boolean readIconGroup(RandomAccessFile raf, int offset, int size) throws IOException {
447     raf.seek(offset);
448     NEWHEADER newHeader = new NEWHEADER();
449     read(raf, newHeader);
450     if (newHeader.ResType != RES_ICON) return false;
451     RESDIR[] resDir = new RESDIR[newHeader.ResCount];
452     for (int i = 0; i < newHeader.ResCount; i++) {
453         resDir[i] = new RESDIR();
454         read(raf, resDir[i]);
455     }
456     return true;
457 }
458
459 static void copyFile(String JavaDoc src, String JavaDoc dst) throws FileNotFoundException, IOException {
460     File srcFile = new File(src);
461     File dstFile = new File(dst);
462     FileInputStream in = new FileInputStream(srcFile);
463     FileOutputStream out = new FileOutputStream(dstFile);
464     int c;
465     while ((c = in.read()) != -1) out.write(c);
466     in.close();
467     out.close();
468 }
469
470 /* IO utilities to parse Windows executable */
471 static final int IMAGE_DOS_SIGNATURE = 0x5a4d;
472 static final int IMAGE_NT_SIGNATURE = 0x00004550;
473 static final int IMAGE_DIRECTORY_ENTRY_RESOURCE = 2;
474 static final int RES_ICON = 1;
475 static final int RT_ICON = 3;
476 static final int RT_GROUP_ICON = 14;
477 static final int BMPHeaderFixedSize = 40;
478     
479 public static class IMAGE_DOS_HEADER {
480     int e_magic; // WORD
481
int e_cblp; // WORD
482
int e_cp; // WORD
483
int e_crlc; // WORD
484
int e_cparhdr; // WORD
485
int e_minalloc; // WORD
486
int e_maxalloc; // WORD
487
int e_ss; // WORD
488
int e_sp; // WORD
489
int e_csum; // WORD
490
int e_ip; // WORD
491
int e_cs; // WORD
492
int e_lfarlc; // WORD
493
int e_ovno; // WORD
494
int[] e_res = new int[4]; // WORD[4]
495
int e_oemid; // WORD
496
int e_oeminfo; // WORD
497
int[] e_res2 = new int[10]; // WORD[10]
498
int e_lfanew; // LONG
499
}
500
501 public static class IMAGE_FILE_HEADER {
502     int Machine; // WORD
503
int NumberOfSections; // WORD
504
int TimeDateStamp; // DWORD
505
int PointerToSymbolTable; // DWORD
506
int NumberOfSymbols; // DWORD
507
int SizeOfOptionalHeader; // WORD
508
int Characteristics; // WORD
509
}
510
511 public static class IMAGE_DATA_DIRECTORY {
512     int VirtualAddress; // DWORD
513
int Size; // DWORD
514
}
515
516 public static class IMAGE_OPTIONAL_HEADER {
517     int Magic; // WORD
518
int MajorLinkerVersion; // BYTE
519
int MinorLinkerVersion; // BYTE
520
int SizeOfCode; // DWORD
521
int SizeOfInitializedData; // DWORD
522
int SizeOfUninitializedData; // DWORD
523
int AddressOfEntryPoint; // DWORD
524
int BaseOfCode; // DWORD
525
int BaseOfData; // DWORD
526
int ImageBase; // DWORD
527
int SectionAlignment; // DWORD
528
int FileAlignment; // DWORD
529
int MajorOperatingSystemVersion; // WORD
530
int MinorOperatingSystemVersion; // WORD
531
int MajorImageVersion; // WORD
532
int MinorImageVersion; // WORD
533
int MajorSubsystemVersion; // WORD
534
int MinorSubsystemVersion; // WORD
535
int Win32VersionValue; // DWORD
536
int SizeOfImage; // DWORD
537
int SizeOfHeaders; // DWORD
538
int CheckSum; // DWORD
539
int Subsystem; // WORD
540
int DllCharacteristics; // WORD
541
int SizeOfStackReserve; // DWORD
542
int SizeOfStackCommit; // DWORD
543
int SizeOfHeapReserve; // DWORD
544
int SizeOfHeapCommit; // DWORD
545
int LoaderFlags; // DWORD
546
int NumberOfRvaAndSizes; // DWORD
547
IMAGE_DATA_DIRECTORY[] DataDirectory = new IMAGE_DATA_DIRECTORY[16];
548 }
549 public static class IMAGE_NT_HEADERS {
550     int Signature; // DWORD
551
IMAGE_FILE_HEADER FileHeader = new IMAGE_FILE_HEADER();
552     IMAGE_OPTIONAL_HEADER OptionalHeader = new IMAGE_OPTIONAL_HEADER();
553     final static int FIELD_OFFSET_OptionalHeader = 24;
554 }
555     
556 public static class IMAGE_SECTION_HEADER {
557     int[] Name = new int[8]; // BYTE[8]
558
int Misc_VirtualSize; // DWORD (union Misc { DWORD PhysicalAddress; DWORD VirtualSize }
559
int VirtualAddress; // DWORD
560
int SizeOfRawData; // DWORD
561
int PointerToRawData; // DWORD
562
int PointerToRelocations; // DWORD
563
int PointerToLinenumbers; // DWORD
564
int NumberOfRelocations; // WORD
565
int NumberOfLinenumbers; // WORD
566
int Characteristics; // DWORD
567
}
568
569 public static class IMAGE_RESOURCE_DIRECTORY {
570     int Characteristics; // DWORD
571
int TimeDateStamp; // DWORD
572
int MajorVersion; // WORD
573
int MinorVersion; // WORD
574
int NumberOfNamedEntries; // WORD - used
575
int NumberOfIdEntries; // WORD - used
576
final static int SIZEOF = 16;
577 }
578
579 public static class IMAGE_RESOURCE_DIRECTORY_ENTRY {
580     // union
581
int NameOffset; // DWORD 31 bits
582
boolean NameIsString; // DWORD 1 bit
583
int Name; // DWORD
584
int Id; // WORD
585
// union
586
int OffsetToData; // DWORD
587
int OffsetToDirectory; // DWORD 31 bits
588
boolean DataIsDirectory; // DWORD 1 bit
589
}
590
591 public static class IMAGE_RESOURCE_DATA_ENTRY {
592     int OffsetToData; // DWORD
593
int Size; // DWORD
594
int CodePage; // DWORD
595
int Reserved; // DWORD
596
}
597
598 public static class NEWHEADER {
599     int Reserved; // WORD
600
int ResType; // WORD
601
int ResCount; // WORD
602
}
603
604 public static class ICONRESDIR {
605     int Width; // BYTE
606
int Height; // BYTE
607
int ColorCount; // BYTE
608
int reserved; // BYTE
609
}
610
611 public static class CURSORDIR {
612     int Width; // WORD
613
int Height; // WORD
614
}
615
616 public static class RESDIR {
617     // union
618
ICONRESDIR Icon = new ICONRESDIR();
619     CURSORDIR Cursor = new CURSORDIR();
620     int Planes; // WORD
621
int BitCount; // WORD
622
int BytesInRes; // DWORD
623
int IconCursorId; // WORD
624
}
625
626 public static class BITMAPINFOHEADER {
627     int biSize; // DWORD
628
int biWidth; // LONG
629
int biHeight; // LONG
630
int biPlanes; // WORD
631
int biBitCount; // WORD
632
int biCompression; // DWORD
633
int biSizeImage; // DWORD
634
int biXPelsPerMeter; // LONG
635
int biYPelsPerMeter; // LONG
636
int biClrUsed; // DWORD
637
int biClrImportant; // DWORD
638
}
639
640 static class RGBQUAD {
641     int rgBlue; // BYTE
642
int rgbGreen; // BYTE
643
int rgbRed; // BYTE
644
int rgbReserved; // BYTE
645
}
646 static class BITMAPINFO {
647     BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
648     RGBQUAD[] bmiColors = null;
649 }
650 static void read(RandomAccessFile raf, BITMAPINFOHEADER bih) throws IOException {
651     bih.biSize = read4(raf);
652     bih.biWidth = read4(raf);
653     bih.biHeight = read4(raf);
654     bih.biPlanes = readU2(raf);
655     bih.biBitCount = readU2(raf);
656     bih.biCompression = read4(raf);
657     bih.biSizeImage = read4(raf);
658     bih.biXPelsPerMeter = read4(raf);
659     bih.biYPelsPerMeter = read4(raf);
660     bih.biClrUsed = read4(raf);
661     bih.biClrImportant = read4(raf);
662 }
663 static void read(RandomAccessFile raf, BITMAPINFO bi) throws IOException {
664     read(raf, bi.bmiHeader);
665 }
666 /* Little Endian helpers */
667 static int readU2(RandomAccessFile raf) throws IOException {
668     int b0 = raf.readByte() & 0xFF;
669     int b1 = raf.readByte() & 0xFF;
670     return (b1 << 8 | b0);
671 }
672 static int read4(RandomAccessFile raf) throws IOException {
673     int b0 = raf.readByte() & 0xFF;
674     int b1 = raf.readByte() & 0xFF;
675     int b2 = raf.readByte() & 0xFF;
676     int b3 = raf.readByte() & 0xFF;
677     return b3 << 24 | b2 << 16 | b1 << 8 | b0;
678 }
679 static void write4(RandomAccessFile raf, int value) throws IOException {
680     raf.write(value & 0xFF);
681     raf.write((value >> 8) & 0xFF);
682     raf.write((value >> 16) & 0xFF);
683     raf.write((value >> 24) & 0xFF);
684 }
685 static void writeU2(RandomAccessFile raf, int value) throws IOException {
686     raf.write(value & 0xFF);
687     raf.write((value >> 8) & 0xFF);
688 }
689 static void read(RandomAccessFile raf, IMAGE_DOS_HEADER idh) throws IOException {
690     idh.e_magic = readU2(raf);
691     idh.e_cblp = readU2(raf);
692     idh.e_cp = readU2(raf);
693     idh.e_crlc = readU2(raf);
694     idh.e_cparhdr = readU2(raf);
695     idh.e_minalloc = readU2(raf);
696     idh.e_maxalloc = readU2(raf);
697     idh.e_ss = readU2(raf);
698     idh.e_sp = readU2(raf);
699     idh.e_csum = readU2(raf);
700     idh.e_ip = readU2(raf);
701     idh.e_cs = readU2(raf);
702     idh.e_lfarlc = readU2(raf);
703     idh.e_ovno = readU2(raf);
704     for (int i = 0; i < idh.e_res.length; i++) idh.e_res[i] = readU2(raf);
705     idh.e_oemid = readU2(raf);
706     idh.e_oeminfo = readU2(raf);
707     for (int i = 0; i < idh.e_res2.length; i++) idh.e_res2[i] = readU2(raf);
708     idh.e_lfanew = read4(raf);
709 }
710 static void read(RandomAccessFile raf, IMAGE_FILE_HEADER ifh) throws IOException {
711     ifh.Machine = readU2(raf);
712     ifh.NumberOfSections = readU2(raf);
713     ifh.TimeDateStamp = read4(raf);
714     ifh.PointerToSymbolTable = read4(raf);
715     ifh.NumberOfSymbols = read4(raf);
716     ifh.SizeOfOptionalHeader = readU2(raf);
717     ifh.Characteristics = readU2(raf);
718 }
719 static void read(RandomAccessFile raf, IMAGE_DATA_DIRECTORY idd) throws IOException {
720     idd.VirtualAddress = read4(raf);
721     idd.Size = read4(raf);
722 }
723 static void read(RandomAccessFile raf, IMAGE_OPTIONAL_HEADER ioh) throws IOException {
724     ioh.Magic = readU2(raf);
725     ioh.MajorLinkerVersion = raf.read();
726     ioh.MinorLinkerVersion = raf.read();
727     ioh.SizeOfCode = read4(raf);
728     ioh.SizeOfInitializedData = read4(raf);
729     ioh.SizeOfUninitializedData = read4(raf);
730     ioh.AddressOfEntryPoint = read4(raf);
731     ioh.BaseOfCode = read4(raf);
732     ioh.BaseOfData = read4(raf);
733     ioh.ImageBase = read4(raf);
734     ioh.SectionAlignment = read4(raf);
735     ioh.FileAlignment = read4(raf);
736     ioh.MajorOperatingSystemVersion = readU2(raf);
737     ioh.MinorOperatingSystemVersion = readU2(raf);
738     ioh.MajorImageVersion = readU2(raf);
739     ioh.MinorImageVersion = readU2(raf);
740     ioh.MajorSubsystemVersion = readU2(raf);
741     ioh.MinorSubsystemVersion = readU2(raf);
742     ioh.Win32VersionValue = read4(raf);
743     ioh.SizeOfImage = read4(raf);
744     ioh.SizeOfHeaders = read4(raf);
745     ioh.CheckSum = read4(raf);
746     ioh.Subsystem = readU2(raf);
747     ioh.DllCharacteristics = readU2(raf);
748     ioh.SizeOfStackReserve = read4(raf);
749     ioh.SizeOfStackCommit = read4(raf);
750     ioh.SizeOfHeapReserve = read4(raf);
751     ioh.SizeOfHeapCommit = read4(raf);
752     ioh.LoaderFlags = read4(raf);
753     ioh.NumberOfRvaAndSizes = read4(raf);
754     for (int i = 0 ; i < ioh.DataDirectory.length; i++) {
755         ioh.DataDirectory[i] = new IMAGE_DATA_DIRECTORY();
756         read(raf, ioh.DataDirectory[i]);
757     }
758 }
759 static void read(RandomAccessFile raf, IMAGE_NT_HEADERS inh) throws IOException {
760     inh.Signature = read4(raf);
761     read(raf, inh.FileHeader);
762     read(raf, inh.OptionalHeader);
763 }
764 static void read(RandomAccessFile raf, IMAGE_SECTION_HEADER ish) throws IOException {
765     for (int i = 0 ; i < ish.Name.length; i++) ish.Name[i] = raf.read();
766     ish.Misc_VirtualSize = read4(raf);
767     ish.VirtualAddress = read4(raf);
768     ish.SizeOfRawData = read4(raf);
769     ish.PointerToRawData = read4(raf);
770     ish.PointerToRelocations = read4(raf);
771     ish.PointerToLinenumbers = read4(raf);
772     ish.NumberOfRelocations = readU2(raf);
773     ish.NumberOfLinenumbers = readU2(raf);
774     ish.Characteristics = read4(raf);
775 }
776 static void read(RandomAccessFile raf, IMAGE_RESOURCE_DIRECTORY ird) throws IOException {
777     ird.Characteristics = read4(raf);
778     ird.TimeDateStamp = read4(raf);
779     ird.MajorVersion = readU2(raf);
780     ird.MinorVersion = readU2(raf);
781     ird.NumberOfNamedEntries = readU2(raf);
782     ird.NumberOfIdEntries = readU2(raf);
783 }
784 static void read(RandomAccessFile raf, IMAGE_RESOURCE_DIRECTORY_ENTRY irde) throws IOException {
785     irde.Name = read4(raf);
786     irde.OffsetToData = read4(raf);
787     // construct other union members
788
irde.NameOffset = irde.Name & ~ (1 << 31);
789     irde.NameIsString = (irde.Name & (1 << 31)) != 0;
790     irde.Id = irde.Name & 0xFFFF;
791     irde.OffsetToDirectory = irde.OffsetToData & ~ (1 << 31);
792     irde.DataIsDirectory = (irde.OffsetToData & (1 << 31)) != 0;
793 }
794 static void read(RandomAccessFile raf, IMAGE_RESOURCE_DATA_ENTRY irde) throws IOException {
795     irde.OffsetToData = read4(raf);
796     irde.Size = read4(raf);
797     irde.CodePage = read4(raf);
798     irde.Reserved = read4(raf);
799 }
800 static void read(RandomAccessFile raf, NEWHEADER nh) throws IOException {
801     nh.Reserved = readU2(raf);
802     nh.ResType = readU2(raf);
803     nh.ResCount = readU2(raf);
804 }
805 static void read(RandomAccessFile raf, ICONRESDIR i) throws IOException {
806     i.Width = raf.read();
807     i.Height = raf.read();
808     i.ColorCount = raf.read();
809     i.reserved = raf.read();
810 }
811 static void read(RandomAccessFile raf, CURSORDIR c) throws IOException {
812     c.Width = readU2(raf);
813     c.Height = readU2(raf);
814 }
815 static void read(RandomAccessFile raf, RESDIR rs) throws IOException {
816     long start = raf.getFilePointer();
817     read(raf, rs.Icon);
818     raf.seek(start);
819     read(raf, rs.Cursor);
820     rs.Planes = readU2(raf);
821     rs.BitCount = readU2(raf);
822     rs.BytesInRes = read4(raf);
823     rs.IconCursorId = readU2(raf);
824 }
825
826 /* ImageData and Image Decoder inlining to avoid dependency on SWT
827  * The following section can be entirely removed if SWT can be used.
828  */

829
830 static class RGB {
831     
832     /**
833      * the red component of the RGB
834      */

835     public int red;
836     
837     /**
838      * the green component of the RGB
839      */

840     public int green;
841     
842     /**
843      * the blue component of the RGB
844      */

845     public int blue;
846     
847     static final long serialVersionUID = 3258415023461249074L;
848     
849 /**
850  * Constructs an instance of this class with the given
851  * red, green and blue values.
852  *
853  * @param red the red component of the new instance
854  * @param green the green component of the new instance
855  * @param blue the blue component of the new instance
856  *
857  * @exception IllegalArgumentException <ul>
858  * <li>ERROR_INVALID_ARGUMENT - if the red, green or blue argument is not between 0 and 255</li>
859  * </ul>
860  */

861 public RGB(int red, int green, int blue) {
862     if ((red > 255) || (red < 0) ||
863         (green > 255) || (green < 0) ||
864         (blue > 255) || (blue < 0))
865             SWT.error(SWT.ERROR_INVALID_ARGUMENT);
866     this.red = red;
867     this.green = green;
868     this.blue = blue;
869 }
870
871 /**
872  * Compares the argument to the receiver, and returns true
873  * if they represent the <em>same</em> object using a class
874  * specific comparison.
875  *
876  * @param object the object to compare with this object
877  * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
878  *
879  * @see #hashCode()
880  */

881 public boolean equals (Object JavaDoc object) {
882     if (object == this) return true;
883     if (!(object instanceof RGB)) return false;
884     RGB rgb = (RGB)object;
885     return (rgb.red == this.red) && (rgb.green == this.green) && (rgb.blue == this.blue);
886 }
887
888 /**
889  * Returns an integer hash code for the receiver. Any two
890  * objects which return <code>true</code> when passed to
891  * <code>equals</code> must return the same value for this
892  * method.
893  *
894  * @return the receiver's hash
895  *
896  * @see #equals(Object)
897  */

898 public int hashCode () {
899     return (blue << 16) | (green << 8) | red;
900 }
901
902 /**
903  * Returns a string containing a concise, human-readable
904  * description of the receiver.
905  *
906  * @return a string representation of the <code>RGB</code>
907  */

908 public String JavaDoc toString () {
909     return "RGB {" + red + ", " + green + ", " + blue + "}"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
910

911 //$NON-NLS-4$
912
}
913
914 }
915 static class PaletteData {
916     
917     /**
918      * true if the receiver is a direct palette,
919      * and false otherwise
920      */

921     public boolean isDirect;
922     
923     /**
924      * the RGB values for an indexed palette, where the
925      * indices of the array correspond to pixel values
926      */

927     public RGB[] colors;
928     
929     /**
930      * the red mask for a direct palette
931      */

932     public int redMask;
933     
934     /**
935      * the green mask for a direct palette
936      */

937     public int greenMask;
938     
939     /**
940      * the blue mask for a direct palette
941      */

942     public int blueMask;
943     
944     /**
945      * the red shift for a direct palette
946      */

947     public int redShift;
948     
949     /**
950      * the green shift for a direct palette
951      */

952     public int greenShift;
953     
954     /**
955      * the blue shift for a direct palette
956      */

95