Source Code Cross Referenced for IconExe.java in  » IDE-Eclipse » Eclipse-plug-in-development » org » eclipse » pde » internal » swt » tools » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » Eclipse plug in development » org.eclipse.pde.internal.swt.tools 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2000, 2006 IBM Corporation and others.
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         * 
0008:         * Contributors:
0009:         *     IBM Corporation - initial API and implementation
0010:         *******************************************************************************/package org.eclipse.pde.internal.swt.tools;
0011:
0012:        import java.io.*;
0013:        import java.util.*;
0014:
0015:        /**
0016:         * Customize the icon of a Windows exe
0017:         * 
0018:         * WARNING! This class is not part of SWT API. It is NOT API. It is an internal
0019:         * tool that may be changed or removed at anytime.
0020:         * 
0021:         * Based on MSDN "An In-Depth Look into the Win32 Portable Executable File Format"
0022:         */
0023:        public class IconExe {
0024:
0025:            /**
0026:             * Replace the Desktop icons provided in the Windows executable program
0027:             * with matching icons provided by the user.
0028:             *
0029:             * Takes 2 arguments
0030:             * argument 0: the Windows executable e.g c:/eclipse/eclipse.exe
0031:             * argument 1: The .ico file to write to the given executable e.g. c:/myApp.ico
0032:             *
0033:             * Note 1. Write access to the executable program is required. As a result, that
0034:             * program must not be currently running or edited elsewhere.
0035:             * 
0036:             * Note 2.  The Eclipse 3.1 launcher requires a .ico file with the following 6 images
0037:             * 1. 32x32, 4 bit (Windows 16 colors palette)
0038:             * 2. 16x16, 4 bit (Windows 16 colors palette)
0039:             * 3. 16x16, 8 bit (256 colors)
0040:             * 4. 32x32, 8 bit (256 colors)
0041:             * 5. 48x48, 4 bit (Windows 16 colors palette)
0042:             * 6. 48x48, 8 bit (256 colors)
0043:             * A user icon matching exactly the width/height/depth of an executable icon will be written
0044:             * to the executable and will replace that executable icon. If an executable icon
0045:             * does not match a user icon, it is silently left as is.
0046:             * 
0047:             * Note 3. This function modifies the content of the executable program and may cause
0048:             * its corruption.
0049:             */
0050:            public static void main(String[] args) throws Exception {
0051:                if (args.length < 2) {
0052:                    System.err
0053:                            .println("Usage: IconExe <windows executable> <ico file>"); //$NON-NLS-1$
0054:                    return;
0055:                }
0056:                ImageLoader loader = new ImageLoader();
0057:
0058:                List images = new ArrayList();
0059:                for (int i = 1; i < args.length; i++) {
0060:                    try {
0061:                        //An ICO should contain 7 images, a BMP will contain 1
0062:                        ImageData[] current = loader.load(args[i]);
0063:                        for (int j = 0; j < current.length; j++) {
0064:                            images.add(current[j]);
0065:                        }
0066:                    } catch (RuntimeException e) {
0067:                        //ignore so that we process the other images
0068:                    }
0069:                }
0070:                ImageData[] data = new ImageData[images.size()];
0071:                data = (ImageData[]) images.toArray(data);
0072:
0073:                int nMissing = unloadIcons(args[0], data);
0074:                if (nMissing != 0)
0075:                    System.err
0076:                            .println("Error - " + nMissing + " icon(s) not replaced in " + args[0] + " using " + args[1]); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
0077:            }
0078:
0079:            /* Implementation */
0080:
0081:            /** 
0082:             * Retrieve the Desktop icons provided in the Windows executable program.
0083:             * These icons are typically shown in various places of the Windows desktop.
0084:             * 
0085:             * Note.  The Eclipse 3.1 launcher returns the following 6 images
0086:             * 1. 32x32, 4 bit (Windows 16 colors palette)
0087:             * 2. 16x16, 4 bit (Windows 16 colors palette)
0088:             * 3. 16x16, 8 bit (256 colors)
0089:             * 4. 32x32, 8 bit (256 colors)
0090:             * 5. 48x48, 4 bit (Windows 16 colors palette)
0091:             * 6. 48x48, 8 bit (256 colors)
0092:             * 
0093:             * @param program the Windows executable e.g c:/eclipse/eclipse.exe
0094:             */
0095:            static ImageData[] loadIcons(String program)
0096:                    throws FileNotFoundException, IOException {
0097:                RandomAccessFile raf = new RandomAccessFile(program, "r"); //$NON-NLS-1$
0098:                IconExe iconExe = new IconExe();
0099:                IconResInfo[] iconInfo = iconExe.getIcons(raf);
0100:                ImageData[] data = new ImageData[iconInfo.length];
0101:                for (int i = 0; i < data.length; i++)
0102:                    data[i] = iconInfo[i].data;
0103:                raf.close();
0104:                return data;
0105:            }
0106:
0107:            /** 
0108:             * Replace the Desktop icons provided in the Windows executable program
0109:             * with icons provided by the user.
0110:             * 
0111:             * Note 1. Write access to the executable program is required. As a result, that
0112:             * program must not be currently running or edited elsewhere.
0113:             * 
0114:             * Note 2. Use loadIcons to determine which set of icons (width, height, depth)
0115:             * is required to replace the icons in the executable program. A user icon
0116:             * matching exactly the width/height/depth of an executable icon will be written
0117:             * to the executable and will replace that executable icon. If an executable icon
0118:             * does not match a user icon, it is left as is. Verify the return value matches
0119:             * the number of icons to write. Finally, use loadIcons after this operation
0120:             * to verify the icons have changed as expected.
0121:             * 
0122:             * Note 3. The Eclipse 3.1 launcher requires the following 6 images (in any order).
0123:             * 1. 32x32, 4 bit (Windows 16 colors palette)
0124:             * 2. 16x16, 4 bit (Windows 16 colors palette)
0125:             * 3. 16x16, 8 bit (256 colors)
0126:             * 4. 32x32, 8 bit (256 colors)
0127:             * 5. 48x48, 4 bit (Windows 16 colors palette)
0128:             * 6. 48x48, 8 bit (256 colors)
0129:             * 
0130:             * Note 4. This function modifies the content of the executable program and may cause
0131:             * its corruption. 
0132:             * 
0133:             * @param program the Windows executable e.g c:/eclipse/eclipse.exe
0134:             * @param icons to write to the given executable
0135:             * @return the number of icons from the original program that were not successfully replaced (0 if success)
0136:             */
0137:            static int unloadIcons(String program, ImageData[] icons)
0138:                    throws FileNotFoundException, IOException {
0139:                RandomAccessFile raf = new RandomAccessFile(program, "rw"); //$NON-NLS-1$
0140:                IconExe iconExe = new IconExe();
0141:                IconResInfo[] iconInfo = iconExe.getIcons(raf);
0142:                int cnt = 0;
0143:                for (int i = 0; i < iconInfo.length; i++) {
0144:                    for (int j = 0; j < icons.length; j++) {
0145:                        if (icons[j] == null)
0146:                            continue;
0147:                        if (iconInfo[i].data.width == icons[j].width
0148:                                && iconInfo[i].data.height == icons[j].height
0149:                                && iconInfo[i].data.depth == icons[j].depth) {
0150:                            raf.seek(iconInfo[i].offset);
0151:                            unloadIcon(raf, icons[j]);
0152:                            cnt++;
0153:                            break;
0154:                        }
0155:                    }
0156:                }
0157:                raf.close();
0158:                return iconInfo.length - cnt;
0159:            }
0160:
0161:            public static final String VERSION = "20050124"; //$NON-NLS-1$
0162:
0163:            static final boolean DEBUG = false;
0164:
0165:            public static class IconResInfo {
0166:                ImageData data;
0167:                int offset;
0168:                int size;
0169:            }
0170:
0171:            IconResInfo[] iconInfo = null;
0172:            int iconCnt;
0173:
0174:            IconResInfo[] getIcons(RandomAccessFile raf) throws IOException {
0175:                iconInfo = new IconResInfo[4];
0176:                iconCnt = 0;
0177:                IMAGE_DOS_HEADER imageDosHeader = new IMAGE_DOS_HEADER();
0178:                read(raf, imageDosHeader);
0179:                if (imageDosHeader.e_magic != IMAGE_DOS_SIGNATURE)
0180:                    return null;
0181:                int imageNtHeadersOffset = imageDosHeader.e_lfanew;
0182:                raf.seek(imageNtHeadersOffset);
0183:                IMAGE_NT_HEADERS imageNtHeaders = new IMAGE_NT_HEADERS();
0184:                read(raf, imageNtHeaders);
0185:                if (imageNtHeaders.Signature != IMAGE_NT_SIGNATURE)
0186:                    return null;
0187:
0188:                // DumpResources
0189:                int resourcesRVA = imageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
0190:                if (resourcesRVA == 0)
0191:                    return null;
0192:                if (DEBUG)
0193:                    System.out
0194:                            .println("* Resources (RVA= " + resourcesRVA + ")"); //$NON-NLS-1$ //$NON-NLS-2$
0195:                IMAGE_SECTION_HEADER imageSectionHeader = new IMAGE_SECTION_HEADER();
0196:                int firstSectionOffset = imageNtHeadersOffset
0197:                        + IMAGE_NT_HEADERS.FIELD_OFFSET_OptionalHeader
0198:                        + imageNtHeaders.FileHeader.SizeOfOptionalHeader;
0199:                raf.seek(firstSectionOffset);
0200:                boolean found = false;
0201:                for (int i = 0; i < imageNtHeaders.FileHeader.NumberOfSections; i++) {
0202:                    read(raf, imageSectionHeader);
0203:                    if (resourcesRVA >= imageSectionHeader.VirtualAddress
0204:                            && resourcesRVA < imageSectionHeader.VirtualAddress
0205:                                    + imageSectionHeader.Misc_VirtualSize) {
0206:                        // could check the imageSectionHeader name is .rsrc
0207:                        found = true;
0208:                        break;
0209:                    }
0210:                }
0211:                if (!found)
0212:                    return null;
0213:                int delta = imageSectionHeader.VirtualAddress
0214:                        - imageSectionHeader.PointerToRawData;
0215:                int imageResourceDirectoryOffset = resourcesRVA - delta;
0216:                dumpResourceDirectory(raf, imageResourceDirectoryOffset,
0217:                        imageResourceDirectoryOffset, delta, 0, 0, false);
0218:                if (iconCnt < iconInfo.length) {
0219:                    IconResInfo[] newArray = new IconResInfo[iconCnt];
0220:                    System.arraycopy(iconInfo, 0, newArray, 0, iconCnt);
0221:                    iconInfo = newArray;
0222:                }
0223:                return iconInfo;
0224:            }
0225:
0226:            void dumpResourceDirectory(RandomAccessFile raf,
0227:                    int imageResourceDirectoryOffset, int resourceBase,
0228:                    int delta, int type, int level, boolean rt_icon_root)
0229:                    throws IOException {
0230:                if (DEBUG)
0231:                    System.out.println("** LEVEL " + level); //$NON-NLS-1$
0232:
0233:                IMAGE_RESOURCE_DIRECTORY imageResourceDirectory = new IMAGE_RESOURCE_DIRECTORY();
0234:                raf.seek(imageResourceDirectoryOffset);
0235:                read(raf, imageResourceDirectory);
0236:
0237:                if (DEBUG) {
0238:                    String sType = "" + type; //$NON-NLS-1$
0239:                    // level 1 resources are resource types
0240:                    if (level == 1) {
0241:                        System.out.println("___________________________"); //$NON-NLS-1$
0242:                        if (type == RT_ICON)
0243:                            sType = "RT_ICON"; //$NON-NLS-1$
0244:                        if (type == RT_GROUP_ICON)
0245:                            sType = "RT_GROUP_ICON"; //$NON-NLS-1$
0246:                    }
0247:                    System.out
0248:                            .println("Resource Directory [" + sType + "]" + " (Named " + imageResourceDirectory.NumberOfNamedEntries + ", ID " + imageResourceDirectory.NumberOfIdEntries + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
0249:                }
0250:
0251:                IMAGE_RESOURCE_DIRECTORY_ENTRY[] imageResourceDirectoryEntries = new IMAGE_RESOURCE_DIRECTORY_ENTRY[imageResourceDirectory.NumberOfIdEntries];
0252:                for (int i = 0; i < imageResourceDirectoryEntries.length; i++) {
0253:                    imageResourceDirectoryEntries[i] = new IMAGE_RESOURCE_DIRECTORY_ENTRY();
0254:                    read(raf, imageResourceDirectoryEntries[i]);
0255:                }
0256:                for (int i = 0; i < imageResourceDirectoryEntries.length; i++) {
0257:                    if (imageResourceDirectoryEntries[i].DataIsDirectory) {
0258:                        dumpResourceDirectory(
0259:                                raf,
0260:                                imageResourceDirectoryEntries[i].OffsetToDirectory
0261:                                        + resourceBase, resourceBase, delta,
0262:                                imageResourceDirectoryEntries[i].Id, level + 1,
0263:                                rt_icon_root ? true : type == RT_ICON);
0264:                    } else {
0265:                        // Resource found
0266:                        /// pResDirEntry->Name
0267:                        IMAGE_RESOURCE_DIRECTORY_ENTRY irde = imageResourceDirectoryEntries[i];
0268:                        IMAGE_RESOURCE_DATA_ENTRY data = new IMAGE_RESOURCE_DATA_ENTRY();
0269:                        raf.seek(imageResourceDirectoryEntries[i].OffsetToData
0270:                                + resourceBase);
0271:                        read(raf, data);
0272:                        if (DEBUG)
0273:                            System.out
0274:                                    .println("Resource Id " + irde.Id + " Data Offset RVA " + data.OffsetToData + ", Size " + data.Size); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
0275:                        if (rt_icon_root) {
0276:                            if (DEBUG)
0277:                                System.out
0278:                                        .println("iconcnt " + iconCnt + " |" + iconInfo.length); //$NON-NLS-1$ //$NON-NLS-2$
0279:                            iconInfo[iconCnt] = new IconResInfo();
0280:                            iconInfo[iconCnt].data = parseIcon(raf,
0281:                                    data.OffsetToData - delta, data.Size);
0282:                            iconInfo[iconCnt].offset = data.OffsetToData
0283:                                    - delta;
0284:                            iconInfo[iconCnt].size = data.Size;
0285:                            iconCnt++;
0286:                            if (iconCnt == iconInfo.length) {
0287:                                IconResInfo[] newArray = new IconResInfo[iconInfo.length + 4];
0288:                                System.arraycopy(iconInfo, 0, newArray, 0,
0289:                                        iconInfo.length);
0290:                                iconInfo = newArray;
0291:                            }
0292:                        }
0293:                    }
0294:                }
0295:            }
0296:
0297:            static ImageData parseIcon(RandomAccessFile raf, int offset,
0298:                    int size) throws IOException {
0299:                raf.seek(offset);
0300:                BITMAPINFO bitmapInfo = new BITMAPINFO();
0301:                read(raf, bitmapInfo);
0302:                bitmapInfo.bmiHeader.biHeight /= 2;
0303:                int width = bitmapInfo.bmiHeader.biWidth;
0304:                int height = bitmapInfo.bmiHeader.biHeight;
0305:                int depth = bitmapInfo.bmiHeader.biBitCount;
0306:
0307:                PaletteData palette = loadPalette(bitmapInfo.bmiHeader, raf);
0308:                byte[] shapeData = loadData(bitmapInfo.bmiHeader, raf);
0309:                bitmapInfo.bmiHeader.biBitCount = 1;
0310:                byte[] maskData = loadData(bitmapInfo.bmiHeader, raf);
0311:                maskData = convertPad(maskData, width, height, 1, 4, 2);
0312:                bitInvertData(maskData, 0, maskData.length);
0313:                return ImageData.internal_new(width, height, depth, palette, 4,
0314:                        shapeData, 2, maskData, null, -1, -1, SWT.IMAGE_ICO, 0,
0315:                        0, 0, 0);
0316:            }
0317:
0318:            static byte[] bitInvertData(byte[] data, int startIndex,
0319:                    int endIndex) {
0320:                // Destructively bit invert data in the given byte array.
0321:                for (int i = startIndex; i < endIndex; i++) {
0322:                    data[i] = (byte) (255 - data[i - startIndex]);
0323:                }
0324:                return data;
0325:            }
0326:
0327:            static final byte[] convertPad(byte[] data, int width, int height,
0328:                    int depth, int pad, int newPad) {
0329:                if (pad == newPad)
0330:                    return data;
0331:                int stride = (width * depth + 7) / 8;
0332:                int bpl = (stride + (pad - 1)) / pad * pad;
0333:                int newBpl = (stride + (newPad - 1)) / newPad * newPad;
0334:                byte[] newData = new byte[height * newBpl];
0335:                int srcIndex = 0, destIndex = 0;
0336:                for (int y = 0; y < height; y++) {
0337:                    System
0338:                            .arraycopy(data, srcIndex, newData, destIndex,
0339:                                    newBpl);
0340:                    srcIndex += bpl;
0341:                    destIndex += newBpl;
0342:                }
0343:                return newData;
0344:            }
0345:
0346:            static PaletteData loadPalette(BITMAPINFOHEADER bih,
0347:                    RandomAccessFile raf) throws IOException {
0348:                int depth = bih.biBitCount;
0349:                if (depth <= 8) {
0350:                    int numColors = bih.biClrUsed;
0351:                    if (numColors == 0) {
0352:                        numColors = 1 << depth;
0353:                    } else {
0354:                        if (numColors > 256)
0355:                            numColors = 256;
0356:                    }
0357:                    byte[] buf = new byte[numColors * 4];
0358:                    raf.read(buf);
0359:                    return paletteFromBytes(buf, numColors);
0360:                }
0361:                if (depth == 16)
0362:                    return new PaletteData(0x7C00, 0x3E0, 0x1F);
0363:                if (depth == 24)
0364:                    return new PaletteData(0xFF, 0xFF00, 0xFF0000);
0365:                return new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
0366:            }
0367:
0368:            static PaletteData paletteFromBytes(byte[] bytes, int numColors) {
0369:                int bytesOffset = 0;
0370:                RGB[] colors = new RGB[numColors];
0371:                for (int i = 0; i < numColors; i++) {
0372:                    colors[i] = new RGB(bytes[bytesOffset + 2] & 0xFF,
0373:                            bytes[bytesOffset + 1] & 0xFF,
0374:                            bytes[bytesOffset] & 0xFF);
0375:                    bytesOffset += 4;
0376:                }
0377:                return new PaletteData(colors);
0378:            }
0379:
0380:            static byte[] loadData(BITMAPINFOHEADER bih, RandomAccessFile raf)
0381:                    throws IOException {
0382:                int stride = (bih.biWidth * bih.biBitCount + 7) / 8;
0383:                stride = (stride + 3) / 4 * 4; // Round up to 4 byte multiple
0384:                byte[] data = loadData(bih, raf, stride);
0385:                flipScanLines(data, stride, bih.biHeight);
0386:                return data;
0387:            }
0388:
0389:            static void flipScanLines(byte[] data, int stride, int height) {
0390:                int i1 = 0;
0391:                int i2 = (height - 1) * stride;
0392:                for (int i = 0; i < height / 2; i++) {
0393:                    for (int index = 0; index < stride; index++) {
0394:                        byte b = data[index + i1];
0395:                        data[index + i1] = data[index + i2];
0396:                        data[index + i2] = b;
0397:                    }
0398:                    i1 += stride;
0399:                    i2 -= stride;
0400:                }
0401:            }
0402:
0403:            static byte[] loadData(BITMAPINFOHEADER bih, RandomAccessFile raf,
0404:                    int stride) throws IOException {
0405:                int dataSize = bih.biHeight * stride;
0406:                byte[] data = new byte[dataSize];
0407:                int cmp = bih.biCompression;
0408:                if (cmp == 0) { // BMP_NO_COMPRESSION
0409:                    raf.read(data);
0410:                } else {
0411:                    if (DEBUG)
0412:                        System.out.println("ICO cannot be compressed?"); //$NON-NLS-1$
0413:                }
0414:                return data;
0415:            }
0416:
0417:            static void unloadIcon(RandomAccessFile raf, ImageData icon)
0418:                    throws IOException {
0419:                int sizeImage = (((icon.width * icon.depth + 31) / 32 * 4) + ((icon.width + 31) / 32 * 4))
0420:                        * icon.height;
0421:                write4(raf, BMPHeaderFixedSize);
0422:                write4(raf, icon.width);
0423:                write4(raf, icon.height * 2);
0424:                writeU2(raf, 1);
0425:                writeU2(raf, icon.depth);
0426:                write4(raf, 0);
0427:                write4(raf, sizeImage);
0428:                write4(raf, 0);
0429:                write4(raf, 0);
0430:                write4(
0431:                        raf,
0432:                        icon.palette.colors != null ? icon.palette.colors.length
0433:                                : 0);
0434:                write4(raf, 0);
0435:
0436:                byte[] rgbs = paletteToBytes(icon.palette);
0437:                raf.write(rgbs);
0438:                unloadShapeData(raf, icon);
0439:                unloadMaskData(raf, icon);
0440:            }
0441:
0442:            static byte[] paletteToBytes(PaletteData pal) {
0443:                int n = pal.colors == null ? 0
0444:                        : (pal.colors.length < 256 ? pal.colors.length : 256);
0445:                byte[] bytes = new byte[n * 4];
0446:                int offset = 0;
0447:                for (int i = 0; i < n; i++) {
0448:                    RGB col = pal.colors[i];
0449:                    bytes[offset] = (byte) col.blue;
0450:                    bytes[offset + 1] = (byte) col.green;
0451:                    bytes[offset + 2] = (byte) col.red;
0452:                    offset += 4;
0453:                }
0454:                return bytes;
0455:            }
0456:
0457:            static void unloadMaskData(RandomAccessFile raf, ImageData icon) {
0458:                ImageData mask = icon.getTransparencyMask();
0459:                int bpl = (icon.width + 7) / 8;
0460:                int pad = mask.scanlinePad;
0461:                int srcBpl = (bpl + pad - 1) / pad * pad;
0462:                int destBpl = (bpl + 3) / 4 * 4;
0463:                byte[] buf = new byte[destBpl];
0464:                int offset = (icon.height - 1) * srcBpl;
0465:                byte[] data = mask.data;
0466:                try {
0467:                    for (int i = 0; i < icon.height; i++) {
0468:                        System.arraycopy(data, offset, buf, 0, bpl);
0469:                        bitInvertData(buf, 0, bpl);
0470:                        raf.write(buf, 0, destBpl);
0471:                        offset -= srcBpl;
0472:                    }
0473:                } catch (IOException e) {
0474:                    SWT.error(SWT.ERROR_IO, e);
0475:                }
0476:            }
0477:
0478:            static void unloadShapeData(RandomAccessFile raf, ImageData icon) {
0479:                int bpl = (icon.width * icon.depth + 7) / 8;
0480:                int pad = icon.scanlinePad;
0481:                int srcBpl = (bpl + pad - 1) / pad * pad;
0482:                int destBpl = (bpl + 3) / 4 * 4;
0483:                byte[] buf = new byte[destBpl];
0484:                int offset = (icon.height - 1) * srcBpl;
0485:                byte[] data = icon.data;
0486:                try {
0487:                    for (int i = 0; i < icon.height; i++) {
0488:                        System.arraycopy(data, offset, buf, 0, bpl);
0489:                        raf.write(buf, 0, destBpl);
0490:                        offset -= srcBpl;
0491:                    }
0492:                } catch (IOException e) {
0493:                    SWT.error(SWT.ERROR_IO, e);
0494:                }
0495:            }
0496:
0497:            static boolean readIconGroup(RandomAccessFile raf, int offset,
0498:                    int size) throws IOException {
0499:                raf.seek(offset);
0500:                NEWHEADER newHeader = new NEWHEADER();
0501:                read(raf, newHeader);
0502:                if (newHeader.ResType != RES_ICON)
0503:                    return false;
0504:                RESDIR[] resDir = new RESDIR[newHeader.ResCount];
0505:                for (int i = 0; i < newHeader.ResCount; i++) {
0506:                    resDir[i] = new RESDIR();
0507:                    read(raf, resDir[i]);
0508:                }
0509:                return true;
0510:            }
0511:
0512:            static void copyFile(String src, String dst)
0513:                    throws FileNotFoundException, IOException {
0514:                File srcFile = new File(src);
0515:                File dstFile = new File(dst);
0516:                InputStream in = new BufferedInputStream(new FileInputStream(
0517:                        srcFile));
0518:                OutputStream out = new BufferedOutputStream(
0519:                        new FileOutputStream(dstFile));
0520:                int c;
0521:                while ((c = in.read()) != -1)
0522:                    out.write(c);
0523:                in.close();
0524:                out.close();
0525:            }
0526:
0527:            /* IO utilities to parse Windows executable */
0528:            static final int IMAGE_DOS_SIGNATURE = 0x5a4d;
0529:            static final int IMAGE_NT_SIGNATURE = 0x00004550;
0530:            static final int IMAGE_DIRECTORY_ENTRY_RESOURCE = 2;
0531:            static final int RES_ICON = 1;
0532:            static final int RT_ICON = 3;
0533:            static final int RT_GROUP_ICON = 14;
0534:            static final int BMPHeaderFixedSize = 40;
0535:
0536:            public static class IMAGE_DOS_HEADER {
0537:                int e_magic; // WORD
0538:                int e_cblp; // WORD
0539:                int e_cp; // WORD
0540:                int e_crlc; // WORD
0541:                int e_cparhdr; // WORD
0542:                int e_minalloc; // WORD
0543:                int e_maxalloc; // WORD
0544:                int e_ss; // WORD
0545:                int e_sp; // WORD
0546:                int e_csum; // WORD
0547:                int e_ip; // WORD
0548:                int e_cs; // WORD
0549:                int e_lfarlc; // WORD
0550:                int e_ovno; // WORD
0551:                int[] e_res = new int[4]; // WORD[4]
0552:                int e_oemid; // WORD
0553:                int e_oeminfo; // WORD
0554:                int[] e_res2 = new int[10]; // WORD[10]
0555:                int e_lfanew; // LONG
0556:            }
0557:
0558:            public static class IMAGE_FILE_HEADER {
0559:                int Machine; // WORD
0560:                int NumberOfSections; // WORD
0561:                int TimeDateStamp; // DWORD
0562:                int PointerToSymbolTable; // DWORD
0563:                int NumberOfSymbols; // DWORD
0564:                int SizeOfOptionalHeader; // WORD
0565:                int Characteristics; // WORD
0566:            }
0567:
0568:            public static class IMAGE_DATA_DIRECTORY {
0569:                int VirtualAddress; // DWORD
0570:                int Size; // DWORD
0571:            }
0572:
0573:            public static class IMAGE_OPTIONAL_HEADER {
0574:                int Magic; // WORD
0575:                int MajorLinkerVersion; // BYTE
0576:                int MinorLinkerVersion; // BYTE
0577:                int SizeOfCode; // DWORD
0578:                int SizeOfInitializedData; // DWORD
0579:                int SizeOfUninitializedData; // DWORD
0580:                int AddressOfEntryPoint; // DWORD
0581:                int BaseOfCode; // DWORD
0582:                int BaseOfData; // DWORD
0583:                int ImageBase; // DWORD
0584:                int SectionAlignment; // DWORD
0585:                int FileAlignment; // DWORD
0586:                int MajorOperatingSystemVersion; // WORD
0587:                int MinorOperatingSystemVersion; // WORD
0588:                int MajorImageVersion; // WORD
0589:                int MinorImageVersion; // WORD
0590:                int MajorSubsystemVersion; // WORD
0591:                int MinorSubsystemVersion; // WORD
0592:                int Win32VersionValue; // DWORD
0593:                int SizeOfImage; // DWORD
0594:                int SizeOfHeaders; // DWORD
0595:                int CheckSum; // DWORD
0596:                int Subsystem; // WORD
0597:                int DllCharacteristics; // WORD
0598:                int SizeOfStackReserve; // DWORD
0599:                int SizeOfStackCommit; // DWORD
0600:                int SizeOfHeapReserve; // DWORD
0601:                int SizeOfHeapCommit; // DWORD
0602:                int LoaderFlags; // DWORD
0603:                int NumberOfRvaAndSizes; // DWORD
0604:                IMAGE_DATA_DIRECTORY[] DataDirectory = new IMAGE_DATA_DIRECTORY[16];
0605:            }
0606:
0607:            public static class IMAGE_NT_HEADERS {
0608:                int Signature; // DWORD
0609:                IMAGE_FILE_HEADER FileHeader = new IMAGE_FILE_HEADER();
0610:                IMAGE_OPTIONAL_HEADER OptionalHeader = new IMAGE_OPTIONAL_HEADER();
0611:                final static int FIELD_OFFSET_OptionalHeader = 24;
0612:            }
0613:
0614:            public static class IMAGE_SECTION_HEADER {
0615:                int[] Name = new int[8]; // BYTE[8]
0616:                int Misc_VirtualSize; // DWORD (union Misc { DWORD PhysicalAddress; DWORD VirtualSize }
0617:                int VirtualAddress; // DWORD
0618:                int SizeOfRawData; // DWORD
0619:                int PointerToRawData; // DWORD
0620:                int PointerToRelocations; // DWORD
0621:                int PointerToLinenumbers; // DWORD
0622:                int NumberOfRelocations; // WORD
0623:                int NumberOfLinenumbers; // WORD
0624:                int Characteristics; // DWORD
0625:            }
0626:
0627:            public static class IMAGE_RESOURCE_DIRECTORY {
0628:                int Characteristics; // DWORD
0629:                int TimeDateStamp; // DWORD
0630:                int MajorVersion; // WORD
0631:                int MinorVersion; // WORD
0632:                int NumberOfNamedEntries; // WORD - used
0633:                int NumberOfIdEntries; // WORD - used
0634:                final static int SIZEOF = 16;
0635:            }
0636:
0637:            public static class IMAGE_RESOURCE_DIRECTORY_ENTRY {
0638:                // union
0639:                int NameOffset; // DWORD 31 bits
0640:                boolean NameIsString; // DWORD 1 bit
0641:                int Name; // DWORD
0642:                int Id; // WORD
0643:                // union
0644:                int OffsetToData; // DWORD
0645:                int OffsetToDirectory; // DWORD 31 bits
0646:                boolean DataIsDirectory; // DWORD 1 bit
0647:            }
0648:
0649:            public static class IMAGE_RESOURCE_DATA_ENTRY {
0650:                int OffsetToData; // DWORD
0651:                int Size; // DWORD
0652:                int CodePage; // DWORD
0653:                int Reserved; // DWORD
0654:            }
0655:
0656:            public static class NEWHEADER {
0657:                int Reserved; // WORD
0658:                int ResType; // WORD
0659:                int ResCount; // WORD
0660:            }
0661:
0662:            public static class ICONRESDIR {
0663:                int Width; // BYTE
0664:                int Height; // BYTE
0665:                int ColorCount; // BYTE
0666:                int reserved; // BYTE
0667:            }
0668:
0669:            public static class CURSORDIR {
0670:                int Width; // WORD
0671:                int Height; // WORD
0672:            }
0673:
0674:            public static class RESDIR {
0675:                // union
0676:                ICONRESDIR Icon = new ICONRESDIR();
0677:                CURSORDIR Cursor = new CURSORDIR();
0678:                int Planes; // WORD
0679:                int BitCount; // WORD
0680:                int BytesInRes; // DWORD
0681:                int IconCursorId; // WORD
0682:            }
0683:
0684:            public static class BITMAPINFOHEADER {
0685:                int biSize; // DWORD
0686:                int biWidth; // LONG
0687:                int biHeight; // LONG
0688:                int biPlanes; // WORD
0689:                int biBitCount; // WORD
0690:                int biCompression; // DWORD
0691:                int biSizeImage; // DWORD
0692:                int biXPelsPerMeter; // LONG
0693:                int biYPelsPerMeter; // LONG
0694:                int biClrUsed; // DWORD
0695:                int biClrImportant; // DWORD
0696:            }
0697:
0698:            static class RGBQUAD {
0699:                int rgBlue; // BYTE
0700:                int rgbGreen; // BYTE
0701:                int rgbRed; // BYTE
0702:                int rgbReserved; // BYTE
0703:            }
0704:
0705:            static class BITMAPINFO {
0706:                BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
0707:                RGBQUAD[] bmiColors = null;
0708:            }
0709:
0710:            static void read(RandomAccessFile raf, BITMAPINFOHEADER bih)
0711:                    throws IOException {
0712:                bih.biSize = read4(raf);
0713:                bih.biWidth = read4(raf);
0714:                bih.biHeight = read4(raf);
0715:                bih.biPlanes = readU2(raf);
0716:                bih.biBitCount = readU2(raf);
0717:                bih.biCompression = read4(raf);
0718:                bih.biSizeImage = read4(raf);
0719:                bih.biXPelsPerMeter = read4(raf);
0720:                bih.biYPelsPerMeter = read4(raf);
0721:                bih.biClrUsed = read4(raf);
0722:                bih.biClrImportant = read4(raf);
0723:            }
0724:
0725:            static void read(RandomAccessFile raf, BITMAPINFO bi)
0726:                    throws IOException {
0727:                read(raf, bi.bmiHeader);
0728:            }
0729:
0730:            /* Little Endian helpers */
0731:            static int readU2(RandomAccessFile raf) throws IOException {
0732:                int b0 = raf.readByte() & 0xFF;
0733:                int b1 = raf.readByte() & 0xFF;
0734:                return (b1 << 8 | b0);
0735:            }
0736:
0737:            static int read4(RandomAccessFile raf) throws IOException {
0738:                int b0 = raf.readByte() & 0xFF;
0739:                int b1 = raf.readByte() & 0xFF;
0740:                int b2 = raf.readByte() & 0xFF;
0741:                int b3 = raf.readByte() & 0xFF;
0742:                return b3 << 24 | b2 << 16 | b1 << 8 | b0;
0743:            }
0744:
0745:            static void write4(RandomAccessFile raf, int value)
0746:                    throws IOException {
0747:                raf.write(value & 0xFF);
0748:                raf.write((value >> 8) & 0xFF);
0749:                raf.write((value >> 16) & 0xFF);
0750:                raf.write((value >> 24) & 0xFF);
0751:            }
0752:
0753:            static void writeU2(RandomAccessFile raf, int value)
0754:                    throws IOException {
0755:                raf.write(value & 0xFF);
0756:                raf.write((value >> 8) & 0xFF);
0757:            }
0758:
0759:            static void read(RandomAccessFile raf, IMAGE_DOS_HEADER idh)
0760:                    throws IOException {
0761:                idh.e_magic = readU2(raf);
0762:                idh.e_cblp = readU2(raf);
0763:                idh.e_cp = readU2(raf);
0764:                idh.e_crlc = readU2(raf);
0765:                idh.e_cparhdr = readU2(raf);
0766:                idh.e_minalloc = readU2(raf);
0767:                idh.e_maxalloc = readU2(raf);
0768:                idh.e_ss = readU2(raf);
0769:                idh.e_sp = readU2(raf);
0770:                idh.e_csum = readU2(raf);
0771:                idh.e_ip = readU2(raf);
0772:                idh.e_cs = readU2(raf);
0773:                idh.e_lfarlc = readU2(raf);
0774:                idh.e_ovno = readU2(raf);
0775:                for (int i = 0; i < idh.e_res.length; i++)
0776:                    idh.e_res[i] = readU2(raf);
0777:                idh.e_oemid = readU2(raf);
0778:                idh.e_oeminfo = readU2(raf);
0779:                for (int i = 0; i < idh.e_res2.length; i++)
0780:                    idh.e_res2[i] = readU2(raf);
0781:                idh.e_lfanew = read4(raf);
0782:            }
0783:
0784:            static void read(RandomAccessFile raf, IMAGE_FILE_HEADER ifh)
0785:                    throws IOException {
0786:                ifh.Machine = readU2(raf);
0787:                ifh.NumberOfSections = readU2(raf);
0788:                ifh.TimeDateStamp = read4(raf);
0789:                ifh.PointerToSymbolTable = read4(raf);
0790:                ifh.NumberOfSymbols = read4(raf);
0791:                ifh.SizeOfOptionalHeader = readU2(raf);
0792:                ifh.Characteristics = readU2(raf);
0793:            }
0794:
0795:            static void read(RandomAccessFile raf, IMAGE_DATA_DIRECTORY idd)
0796:                    throws IOException {
0797:                idd.VirtualAddress = read4(raf);
0798:                idd.Size = read4(raf);
0799:            }
0800:
0801:            static void read(RandomAccessFile raf, IMAGE_OPTIONAL_HEADER ioh)
0802:                    throws IOException {
0803:                ioh.Magic = readU2(raf);
0804:                ioh.MajorLinkerVersion = raf.read();
0805:                ioh.MinorLinkerVersion = raf.read();
0806:                ioh.SizeOfCode = read4(raf);
0807:                ioh.SizeOfInitializedData = read4(raf);
0808:                ioh.SizeOfUninitializedData = read4(raf);
0809:                ioh.AddressOfEntryPoint = read4(raf);
0810:                ioh.BaseOfCode = read4(raf);
0811:                ioh.BaseOfData = read4(raf);
0812:                ioh.ImageBase = read4(raf);
0813:                ioh.SectionAlignment = read4(raf);
0814:                ioh.FileAlignment = read4(raf);
0815:                ioh.MajorOperatingSystemVersion = readU2(raf);
0816:                ioh.MinorOperatingSystemVersion = readU2(raf);
0817:                ioh.MajorImageVersion = readU2(raf);
0818:                ioh.MinorImageVersion = readU2(raf);
0819:                ioh.MajorSubsystemVersion = readU2(raf);
0820:                ioh.MinorSubsystemVersion = readU2(raf);
0821:                ioh.Win32VersionValue = read4(raf);
0822:                ioh.SizeOfImage = read4(raf);
0823:                ioh.SizeOfHeaders = read4(raf);
0824:                ioh.CheckSum = read4(raf);
0825:                ioh.Subsystem = readU2(raf);
0826:                ioh.DllCharacteristics = readU2(raf);
0827:                ioh.SizeOfStackReserve = read4(raf);
0828:                ioh.SizeOfStackCommit = read4(raf);
0829:                ioh.SizeOfHeapReserve = read4(raf);
0830:                ioh.SizeOfHeapCommit = read4(raf);
0831:                ioh.LoaderFlags = read4(raf);
0832:                ioh.NumberOfRvaAndSizes = read4(raf);
0833:                for (int i = 0; i < ioh.DataDirectory.length; i++) {
0834:                    ioh.DataDirectory[i] = new IMAGE_DATA_DIRECTORY();
0835:                    read(raf, ioh.DataDirectory[i]);
0836:                }
0837:            }
0838:
0839:            static void read(RandomAccessFile raf, IMAGE_NT_HEADERS inh)
0840:                    throws IOException {
0841:                inh.Signature = read4(raf);
0842:                read(raf, inh.FileHeader);
0843:                read(raf, inh.OptionalHeader);
0844:            }
0845:
0846:            static void read(RandomAccessFile raf, IMAGE_SECTION_HEADER ish)
0847:                    throws IOException {
0848:                for (int i = 0; i < ish.Name.length; i++)
0849:                    ish.Name[i] = raf.read();
0850:                ish.Misc_VirtualSize = read4(raf);
0851:                ish.VirtualAddress = read4(raf);
0852:                ish.SizeOfRawData = read4(raf);
0853:                ish.PointerToRawData = read4(raf);
0854:                ish.PointerToRelocations = read4(raf);
0855:                ish.PointerToLinenumbers = read4(raf);
0856:                ish.NumberOfRelocations = readU2(raf);
0857:                ish.NumberOfLinenumbers = readU2(raf);
0858:                ish.Characteristics = read4(raf);
0859:            }
0860:
0861:            static void read(RandomAccessFile raf, IMAGE_RESOURCE_DIRECTORY ird)
0862:                    throws IOException {
0863:                ird.Characteristics = read4(raf);
0864:                ird.TimeDateStamp = read4(raf);
0865:                ird.MajorVersion = readU2(raf);
0866:                ird.MinorVersion = readU2(raf);
0867:                ird.NumberOfNamedEntries = readU2(raf);
0868:                ird.NumberOfIdEntries = readU2(raf);
0869:            }
0870:
0871:            static void read(RandomAccessFile raf,
0872:                    IMAGE_RESOURCE_DIRECTORY_ENTRY irde) throws IOException {
0873:                irde.Name = read4(raf);
0874:                irde.OffsetToData = read4(raf);
0875:                // construct other union members
0876:                irde.NameOffset = irde.Name & ~(1 << 31);
0877:                irde.NameIsString = (irde.Name & (1 << 31)) != 0;
0878:                irde.Id = irde.Name & 0xFFFF;
0879:                irde.OffsetToDirectory = irde.OffsetToData & ~(1 << 31);
0880:                irde.DataIsDirectory = (irde.OffsetToData & (1 << 31)) != 0;
0881:            }
0882:
0883:            static void read(RandomAccessFile raf,
0884:                    IMAGE_RESOURCE_DATA_ENTRY irde) throws IOException {
0885:                irde.OffsetToData = read4(raf);
0886:                irde.Size = read4(raf);
0887:                irde.CodePage = read4(raf);
0888:                irde.Reserved = read4(raf);
0889:            }
0890:
0891:            static void read(RandomAccessFile raf, NEWHEADER nh)
0892:                    throws IOException {
0893:                nh.Reserved = readU2(raf);
0894:                nh.ResType = readU2(raf);
0895:                nh.ResCount = readU2(raf);
0896:            }
0897:
0898:            static void read(RandomAccessFile raf, ICONRESDIR i)
0899:                    throws IOException {
0900:                i.Width = raf.read();
0901:                i.Height = raf.read();
0902:                i.ColorCount = raf.read();
0903:                i.reserved = raf.read();
0904:            }
0905:
0906:            static void read(RandomAccessFile raf, CURSORDIR c)
0907:                    throws IOException {
0908:                c.Width = readU2(raf);
0909:                c.Height = readU2(raf);
0910:            }
0911:
0912:            static void read(RandomAccessFile raf, RESDIR rs)
0913:                    throws IOException {
0914:                long start = raf.getFilePointer();
0915:                read(raf, rs.Icon);
0916:                raf.seek(start);
0917:                read(raf, rs.Cursor);
0918:                rs.Planes = readU2(raf);
0919:                rs.BitCount = readU2(raf);
0920:                rs.BytesInRes = read4(raf);
0921:                rs.IconCursorId = readU2(raf);
0922:            }
0923:
0924:            /* ImageData and Image Decoder inlining to avoid dependency on SWT 
0925:             * The following section can be entirely removed if SWT can be used.
0926:             */
0927:
0928:            static class RGB {
0929:
0930:                /**
0931:                 * the red component of the RGB
0932:                 */
0933:                public int red;
0934:
0935:                /**
0936:                 * the green component of the RGB
0937:                 */
0938:                public int green;
0939:
0940:                /**
0941:                 * the blue component of the RGB
0942:                 */
0943:                public int blue;
0944:
0945:                static final long serialVersionUID = 3258415023461249074L;
0946:
0947:                /**
0948:                 * Constructs an instance of this class with the given
0949:                 * red, green and blue values.
0950:                 *
0951:                 * @param red the red component of the new instance
0952:                 * @param green the green component of the new instance
0953:                 * @param blue the blue component of the new instance
0954:                 *
0955:                 * @exception IllegalArgumentException <ul>
0956:                 *    <li>ERROR_INVALID_ARGUMENT - if the red, green or blue argument is not between 0 and 255</li>
0957:                 * </ul>
0958:                 */
0959:                public RGB(int red, int green, int blue) {
0960:                    if ((red > 255) || (red < 0) || (green > 255)
0961:                            || (green < 0) || (blue > 255) || (blue < 0))
0962:                        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
0963:                    this .red = red;
0964:                    this .green = green;
0965:                    this .blue = blue;
0966:                }
0967:
0968:                /**
0969:                 * Compares the argument to the receiver, and returns true
0970:                 * if they represent the <em>same</em> object using a class
0971:                 * specific comparison.
0972:                 *
0973:                 * @param object the object to compare with this object
0974:                 * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
0975:                 *
0976:                 * @see #hashCode()
0977:                 */
0978:                public boolean equals(Object object) {
0979:                    if (object == this )
0980:                        return true;
0981:                    if (!(object instanceof  RGB))
0982:                        return false;
0983:                    RGB rgb = (RGB) object;
0984:                    return (rgb.red == this .red) && (rgb.green == this .green)
0985:                            && (rgb.blue == this .blue);
0986:                }
0987:
0988:                /**
0989:                 * Returns an integer hash code for the receiver. Any two 
0990:                 * objects which return <code>true</code> when passed to 
0991:                 * <code>equals</code> must return the same value for this
0992:                 * method.
0993:                 *
0994:                 * @return the receiver's hash
0995:                 *
0996:                 * @see #equals(Object)
0997:                 */
0998:                public int hashCode() {
0999:                    return (blue << 16) | (green << 8) | red;
1000:                }
1001:
1002:                /**
1003:                 * Returns a string containing a concise, human-readable
1004:                 * description of the receiver.
1005:                 *
1006:                 * @return a string representation of the <code>RGB</code>
1007:                 */
1008:                public String toString() {
1009:                    return "RGB {" + red + ", " + green + ", " + blue + "}"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 
1010:
1011:                    //$NON-NLS-4$
1012:                }
1013:
1014:            }
1015:
1016:            static class PaletteData {
1017:
1018:                /**
1019:                 * true if the receiver is a direct palette, 
1020:                 * and false otherwise
1021:                 */
1022:                public boolean isDirect;
1023:
1024:                /**
1025:                 * the RGB values for an indexed palette, where the
1026:                 * indices of the array correspond to pixel values
1027:                 */
1028:                public RGB[] colors;
1029:
1030:                /**
1031:                 * the red mask for a direct palette
1032:                 */
1033:                public int redMask;
1034:
1035:                /**
1036:                 * the green mask for a direct palette
1037:                 */
1038:                public int greenMask;
1039:
1040:                /**
1041:                 * the blue mask for a direct palette
1042:                 */
1043:                public int blueMask;
1044:
1045:                /**
1046:                 * the red shift for a direct palette
1047:                 */
1048:                public int redShift;
1049:
1050:                /**
1051:                 * the green shift for a direct palette
1052:                 */
1053:                public int greenShift;
1054:
1055:                /**
1056:                 * the blue shift for a direct palette
1057:                 */
1058:                public int blueShift;
1059:
1060:                /**
1061:                 * Constructs a new indexed palette given an array of RGB values.
1062:                 *
1063:                 * @param colors the array of <code>RGB</code>s for the palette
1064:                 *
1065:                 * @exception IllegalArgumentException <ul>
1066:                 *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
1067:                 * </ul>
1068:                 */
1069:                public PaletteData(RGB[] colors) {
1070:                    if (colors == null)
1071:                        SWT.error(SWT.ERROR_NULL_ARGUMENT);
1072:                    this .colors = colors;
1073:                    this .isDirect = false;
1074:                }
1075:
1076:                /**
1077:                 * Constructs a new direct palette given the red, green and blue masks.
1078:                 *
1079:                 * @param redMask the red mask
1080:                 * @param greenMask the green mask
1081:                 * @param blueMask the blue mask
1082:                 */
1083:                public PaletteData(int redMask, int greenMask, int blueMask) {
1084:                    this .redMask = redMask;
1085:                    this .greenMask = greenMask;
1086:                    this .blueMask = blueMask;
1087:                    this .isDirect = true;
1088:                    this .redShift = shiftForMask(redMask);
1089:                    this .greenShift = shiftForMask(greenMask);
1090:                    this .blueShift = shiftForMask(blueMask);
1091:                }
1092:
1093:                /**
1094:                 * Returns the pixel value corresponding to the given <code>RBG</code>.
1095:                 *
1096:                 * @param rgb the RGB to get the pixel value for
1097:                 * @return the pixel value for the given RGB
1098:                 * 
1099:                 * @exception IllegalArgumentException <ul>
1100:                 *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
1101:                 *    <li>ERROR_INVALID_ARGUMENT - if the RGB is not found in the palette</li>
1102:                 * </ul>
1103:                 */
1104:                public int getPixel(RGB rgb) {
1105:                    if (rgb == null)
1106:                        SWT.error(SWT.ERROR_NULL_ARGUMENT);
1107:                    if (isDirect) {
1108:                        int pixel = 0;
1109:                        pixel |= (redShift < 0 ? rgb.red << -redShift
1110:                                : rgb.red >>> redShift)
1111:                                & redMask;
1112:                        pixel |= (greenShift < 0 ? rgb.green << -greenShift
1113:                                : rgb.green >>> greenShift)
1114:                                & greenMask;
1115:                        pixel |= (blueShift < 0 ? rgb.blue << -blueShift
1116:                                : rgb.blue >>> blueShift)
1117:                                & blueMask;
1118:                        return pixel;
1119:                    }
1120:
1121:                    for (int i = 0; i < colors.length; i++) {
1122:                        if (colors[i].equals(rgb))
1123:                            return i;
1124:                    }
1125:                    /* The RGB did not exist in the palette */
1126:                    SWT.error(SWT.ERROR_INVALID_ARGUMENT);
1127:                    return 0;
1128:                }
1129:
1130:                /**
1131:                 * Returns an <code>RGB</code> corresponding to the given pixel value.
1132:                 *
1133:                 * @param pixel the pixel to get the RGB value for
1134:                 * @return the RGB value for the given pixel
1135:                 *
1136:                 * @exception IllegalArgumentException <ul>
1137:                 *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
1138:                 *    <li>ERROR_INVALID_ARGUMENT - if the pixel does not exist in the palette</li>
1139:                 * </ul>
1140:                 */
1141:                public RGB getRGB(int pixel) {
1142:                    if (isDirect) {
1143:                        int r = pixel & redMask;
1144:                        r = (redShift < 0) ? r >>> -redShift : r << redShift;
1145:                        int g = pixel & greenMask;
1146:                        g = (greenShift < 0) ? g >>> -greenShift
1147:                                : g << greenShift;
1148:                        int b = pixel & blueMask;
1149:                        b = (blueShift < 0) ? b >>> -blueShift : b << blueShift;
1150:                        return new RGB(r, g, b);
1151:                    }
1152:                    if (pixel < 0 || pixel >= colors.length) {
1153:                        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
1154:                    }
1155:                    return colors[pixel];
1156:                }
1157:
1158:                /**
1159:                 * Returns all the RGB values in the receiver if it is an
1160:                 * indexed palette, or null if it is a direct palette.
1161:                 *
1162:                 * @return the <code>RGB</code>s for the receiver or null
1163:                 */
1164:                public RGB[] getRGBs() {
1165:                    return colors;
1166:                }
1167:
1168:                /**
1169:                 * Computes the shift value for a given mask.
1170:                 *
1171:                 * @param mask the mask to compute the shift for
1172:                 * @return the shift amount
1173:                 *
1174:                 * @see PaletteData
1175:                 */
1176:                int shiftForMask(int mask) {
1177:                    for (int i = 31; i >= 0; i--) {
1178:                        if (((mask >> i) & 0x1) != 0)
1179:                            return 7 - i;
1180:                    }
1181:                    return 32;
1182:                }
1183:
1184:            }
1185:
1186:            static class ImageLoader {
1187:
1188:                /**
1189:                 * the array of ImageData objects in this ImageLoader.
1190:                 * This array is read in when the load method is called,
1191:                 * and it is written out when the save method is called
1192:                 */
1193:                public ImageData[] data;
1194:
1195:                /**
1196:                 * the width of the logical screen on which the images
1197:                 * reside, in pixels (this corresponds to the GIF89a
1198:                 * Logical Screen Width value)
1199:                 */
1200:                public int logicalScreenWidth;
1201:
1202:                /**
1203:                 * the height of the logical screen on which the images
1204:                 * reside, in pixels (this corresponds to the GIF89a
1205:                 * Logical Screen Height value)
1206:                 */
1207:                public int logicalScreenHeight;
1208:
1209:                /**
1210:                 * the background pixel for the logical screen (this 
1211:                 * corresponds to the GIF89a Background Color Index value).
1212:                 * The default is -1 which means 'unspecified background'
1213:                 * 
1214:                 */
1215:                public int backgroundPixel;
1216:
1217:                /**
1218:                 * the number of times to repeat the display of a sequence
1219:                 * of animated images (this corresponds to the commonly-used
1220:                 * GIF application extension for "NETSCAPE 2.0 01")
1221:                 */
1222:                public int repeatCount;
1223:
1224:                /*
1225:                 * the set of ImageLoader event listeners, created on demand
1226:                 */
1227:                Vector imageLoaderListeners;
1228:
1229:                /**
1230:                 * Construct a new empty ImageLoader.
1231:                 */
1232:                public ImageLoader() {
1233:                    reset();
1234:                }
1235:
1236:                /**
1237:                 * Resets the fields of the ImageLoader, except for the
1238:                 * <code>imageLoaderListeners</code> field.
1239:                 */
1240:                void reset() {
1241:                    data = null;
1242:                    logicalScreenWidth = 0;
1243:                    logicalScreenHeight = 0;
1244:                    backgroundPixel = -1;
1245:                    repeatCount = 1;
1246:                }
1247:
1248:                /**
1249:                 * Loads an array of <code>ImageData</code> objects from the
1250:                 * specified input stream. Throws an error if either an error
1251:                 * occurs while loading the images, or if the images are not
1252:                 * of a supported type. Returns the loaded image data array.
1253:                 *
1254:                 * @param stream the input stream to load the images from
1255:                 * @return an array of <code>ImageData</code> objects loaded from the specified input stream
1256:                 *
1257:                 * @exception IllegalArgumentException <ul>
1258:                 *    <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
1259:                 * </ul>
1260:                 * @exception SWTException <ul>
1261:                 *    <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
1262:                 *    <li>ERROR_IO - if an input/output error occurs while reading data</li>
1263:                 *    <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
1264:                 * </ul>
1265:                 */
1266:                public ImageData[] load(InputStream stream) {
1267:                    if (stream == null)
1268:                        SWT.error(SWT.ERROR_NULL_ARGUMENT);
1269:                    reset();
1270:                    data = FileFormat.load(stream, this );
1271:                    return data;
1272:                }
1273:
1274:                /**
1275:                 * Loads an array of <code>ImageData</code> objects from the
1276:                 * file with the specified name. Throws an error if either
1277:                 * an error occurs while loading the images, or if the images are
1278:                 * not of a supported type. Returns the loaded image data array.
1279:                 *
1280:                 * @param filename the name of the file to load the images from
1281:                 * @return an array of <code>ImageData</code> objects loaded from the specified file
1282:                 *
1283:                 * @exception IllegalArgumentException <ul>
1284:                 *    <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
1285:                 * </ul>
1286:                 * @exception SWTException <ul>
1287:                 *    <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
1288:                 *    <li>ERROR_IO - if an IO error occurs while reading data</li>
1289:                 *    <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
1290:                 * </ul>
1291:                 */
1292:                public ImageData[] load(String filename) {
1293:                    if (filename == null)
1294:                        SWT.error(SWT.ERROR_NULL_ARGUMENT);
1295:                    InputStream stream = null;
1296:                    try {
1297:                        stream = new BufferedInputStream(new FileInputStream(
1298:                                filename));
1299:                        return load(stream);
1300:                    } catch (IOException e) {
1301:                        SWT.error(SWT.ERROR_IO, e);
1302:                    } finally {
1303:                        try {
1304:                            if (stream != null)
1305:                                stream.close();
1306:                        } catch (IOException e) {
1307:                            // Ignore error
1308:                        }
1309:                    }
1310:                    return null;
1311:                }
1312:            }
1313:
1314:            static class ImageData {
1315:
1316:                /**
1317:                 * The width of the image, in pixels.
1318:                 */
1319:                public int width;
1320:
1321:                /**
1322:                 * The height of the image, in pixels.
1323:                 */
1324:                public int height;
1325:
1326:                /**
1327:                 * The color depth of the image, in bits per pixel.
1328:                 * <p>
1329:                 * Note that a depth of 8 or less does not necessarily
1330:                 * mean that the image is palette indexed, or
1331:                 * conversely that a depth greater than 8 means that
1332:                 * the image is direct color.  Check the associated
1333:                 * PaletteData's isDirect field for such determinations.
1334:                 */
1335:                public int depth;
1336:
1337:                /**
1338:                 * The scanline padding.
1339:                 * <p>
1340:                 * If one scanline of the image is not a multiple of
1341:                 * this number, it will be padded with zeros until it is.
1342:                 * </p>
1343:                 */
1344:                public int scanlinePad;
1345:
1346:                /**
1347:                 * The number of bytes per scanline.
1348:                 * <p>
1349:                 * This is a multiple of the scanline padding.
1350:                 * </p>
1351:                 */
1352:                public int bytesPerLine;
1353:
1354:                /**
1355:                 * The pixel data of the image.
1356:                 * <p>
1357:                 * Note that for 16 bit depth images the pixel data is stored
1358:                 * in least significant byte order; however, for 24bit and
1359:                 * 32bit depth images the pixel data is stored in most
1360:                 * significant byte order.
1361:                 * </p>
1362:                 */
1363:                public byte[] data;
1364:
1365:                /**
1366:                 * The color table for the image.
1367:                 */
1368:                public PaletteData palette;
1369:
1370:                /**
1371:                 * The transparent pixel.
1372:                 * <p>
1373:                 * Pixels with this value are transparent.
1374:                 * </p><p>
1375:                 * The default is -1 which means 'no transparent pixel'.
1376:                 * </p>
1377:                 */
1378:                public int transparentPixel;
1379:
1380:                /**
1381:                 * An icon-specific field containing the data from the icon mask.
1382:                 * <p>
1383:                 * This is a 1 bit bitmap stored with the most significant
1384:                 * bit first.  The number of bytes per scanline is
1385:                 * '((width + 7) / 8 + (maskPad - 1)) / maskPad * maskPad'.
1386:                 * </p><p>
1387:                 * The default is null which means 'no transparency mask'.
1388:                 * </p>
1389:                 */
1390:                public byte[] maskData;
1391:
1392:                /**
1393:                 * An icon-specific field containing the scanline pad of the mask.
1394:                 * <p>
1395:                 * If one scanline of the transparency mask is not a
1396:                 * multiple of this number, it will be padded with zeros until
1397:                 * it is.
1398:                 * </p>
1399:                 */
1400:                public int maskPad;
1401:
1402:                /**
1403:                 * The alpha data of the image.
1404:                 * <p>
1405:                 * Every pixel can have an <em>alpha blending</em> value that
1406:                 * varies from 0, meaning fully transparent, to 255 meaning
1407:                 * fully opaque.  The number of bytes per scanline is
1408:                 * 'width'.
1409:                 * </p>
1410:                 */
1411:                public byte[] alphaData;
1412:
1413:                /**
1414:                 * The global alpha value to be used for every pixel.
1415:                 * <p>
1416:                 * If this value is set, the <code>alphaData</code> field
1417:                 * is ignored and when the image is rendered each pixel
1418:                 * will be blended with the background an amount
1419:                 * proportional to this value.
1420:                 * </p><p>
1421:                 * The default is -1 which means 'no global alpha value'
1422:                 * </p>
1423:                 */
1424:                public int alpha;
1425:
1426:                /**
1427:                 * The type of file from which the image was read.
1428:                 * 
1429:                 * It is expressed as one of the following values:
1430:                 * <dl>
1431:                 * <dt><code>IMAGE_BMP</code></dt>
1432:                 * <dd>Windows BMP file format, no compression</dd>
1433:                 * <dt><code>IMAGE_BMP_RLE</code></dt>
1434:                 * <dd>Windows BMP file format, RLE compression if appropriate</dd>
1435:                 * <dt><code>IMAGE_GIF</code></dt>
1436:                 * <dd>GIF file format</dd>
1437:                 * <dt><code>IMAGE_ICO</code></dt>
1438:                 * <dd>Windows ICO file format</dd>
1439:                 * <dt><code>IMAGE_JPEG</code></dt>
1440:                 * <dd>JPEG file format</dd>
1441:                 * <dt><code>IMAGE_PNG</code></dt>
1442:                 * <dd>PNG file format</dd>
1443:                 * </dl>
1444:                 */
1445:                public int type;
1446:
1447:                /**
1448:                 * The x coordinate of the top left corner of the image
1449:                 * within the logical screen (this field corresponds to
1450:                 * the GIF89a Image Left Position value).
1451:                 */
1452:                public int x;
1453:
1454:                /**
1455:                 * The y coordinate of the top left corner of the image
1456:                 * within the logical screen (this field corresponds to
1457:                 * the GIF89a Image Top Position value).
1458:                 */
1459:                public int y;
1460:
1461:                /**
1462:                 * A description of how to dispose of the current image
1463:                 * before displaying the next.
1464:                 * 
1465:                 * It is expressed as one of the following values:
1466:                 * <dl>
1467:                 * <dt><code>DM_UNSPECIFIED</code></dt>
1468:                 * <dd>disposal method not specified</dd>
1469:                 * <dt><code>DM_FILL_NONE</code></dt>
1470:                 * <dd>do nothing - leave the image in place</dd>
1471:                 * <dt><code>DM_FILL_BACKGROUND</code></dt>
1472:                 * <dd>fill with the background color</dd>
1473:                 * <dt><code>DM_FILL_PREVIOUS</code></dt>
1474:                 * <dd>restore the previous picture</dd>
1475:                 * </dl>
1476:                 * (this field corresponds to the GIF89a Disposal Method value)
1477:                 */
1478:                public int disposalMethod;
1479:
1480:                /**
1481:                 * The time to delay before displaying the next image
1482:                 * in an animation (this field corresponds to the GIF89a
1483:                 * Delay Time value).
1484:                 */
1485:                public int delayTime;
1486:
1487:                /**
1488:                 * Arbitrary channel width data to 8-bit conversion table.
1489:                 */
1490:                static final byte[][] ANY_TO_EIGHT = new byte[9][];
1491:                static {
1492:                    for (int b = 0; b < 9; ++b) {
1493:                        byte[] data = ANY_TO_EIGHT[b] = new byte[1 << b];
1494:                        if (b == 0)
1495:                            continue;
1496:                        int inc = 0;
1497:                        for (int bit = 0x10000; (bit >>= b) != 0;)
1498:                            inc |= bit;
1499:                        for (int v = 0, p = 0; v < 0x10000; v += inc)
1500:                            data[p++] = (byte) (v >> 8);
1501:                    }
1502:                }
1503:                static final byte[] ONE_TO_ONE_MAPPING = ANY_TO_EIGHT[8];
1504:
1505:                /**
1506:                 * Scaled 8x8 Bayer dither matrix.
1507:                 */
1508:                static final int[][] DITHER_MATRIX = {
1509:                        { 0xfc0000, 0x7c0000, 0xdc0000, 0x5c0000, 0xf40000,
1510:                                0x740000, 0xd40000, 0x540000 },
1511:                        { 0x3c0000, 0xbc0000, 0x1c0000, 0x9c0000, 0x340000,
1512:                                0xb40000, 0x140000, 0x940000 },
1513:                        { 0xcc0000, 0x4c0000, 0xec0000, 0x6c0000, 0xc40000,
1514:                                0x440000, 0xe40000, 0x640000 },
1515:                        { 0x0c0000, 0x8c0000, 0x2c0000, 0xac0000, 0x040000,
1516:                                0x840000, 0x240000, 0xa40000 },
1517:                        { 0xf00000, 0x700000, 0xd00000, 0x500000, 0xf80000,
1518:                                0x780000, 0xd80000, 0x580000 },
1519:                        { 0x300000, 0xb00000, 0x100000, 0x900000, 0x380000,
1520:                                0xb80000, 0x180000, 0x980000 },
1521:                        { 0xc00000, 0x400000, 0xe00000, 0x600000, 0xc80000,
1522:                                0x480000, 0xe80000, 0x680000 },
1523:                        { 0x000000, 0x800000, 0x200000, 0xa00000, 0x080000,
1524:                                0x880000, 0x280000, 0xa80000 } };
1525:
1526:                /**
1527:                 * Constructs a new, empty ImageData with the given width, height,
1528:                 * depth and palette. The data will be initialized to an (all zero)
1529:                 * array of the appropriate size.
1530:                 *
1531:                 * @param width the width of the image
1532:                 * @param height the height of the image
1533:                 * @param depth the depth of the image
1534:                 * @param palette the palette of the image (must not be null)
1535:                 *
1536:                 * @exception IllegalArgumentException <ul>
1537:                 *    <li>ERROR_INVALID_ARGUMENT - if the width or height is negative, or if the depth is not
1538:                 *        	one of 1, 2, 4, 8, 16, 24 or 32</li>
1539:                 *    <li>ERROR_NULL_ARGUMENT - if the palette is null</li>
1540:                 * </ul>
1541:                 */
1542:                public ImageData(int width, int height, int depth,
1543:                        PaletteData palette) {
1544:                    this (width, height, depth, palette, 4, null, 0, null, null,
1545:                            -1, -1, SWT.IMAGE_UNDEFINED, 0, 0, 0, 0);
1546:                }
1547:
1548:                /**
1549:                 * Constructs a new, empty ImageData with the given width, height,
1550:                 * depth, palette, scanlinePad and data.
1551:                 *
1552:                 * @param width the width of the image
1553:                 * @param height the height of the image
1554:                 * @param depth the depth of the image
1555:                 * @param palette the palette of the image
1556:                 * @param scanlinePad the padding of each line, in bytes
1557:                 * @param data the data of the image
1558:                 *
1559:                 * @exception IllegalArgumentException <ul>
1560:                 *    <li>ERROR_INVALID_ARGUMENT - if the width or height is negative, or if the depth is not
1561:                 *        	one of 1, 2, 4, 8, 16, 24 or 32</li>
1562:                 *    <li>ERROR_NULL_ARGUMENT - if the palette or data is null</li>
1563:                 *    <li>ERROR_CANNOT_BE_ZERO - if the scanlinePad is zero</li>
1564:                 * </ul>
1565:                 */
1566:                public ImageData(int width, int height, int depth,
1567:                        PaletteData palette, int scanlinePad, byte[] data) {
1568:                    this (width, height, depth, palette, scanlinePad,
1569:                            checkData(data), 0, null, null, -1, -1,
1570:                            SWT.IMAGE_UNDEFINED, 0, 0, 0, 0);
1571:                }
1572:
1573:                /**
1574:                 * Constructs an <code>ImageData</code> loaded from a file with the
1575:                 * specified name. Throws an error if an error occurs loading the
1576:                 * image, or if the image has an unsupported type.
1577:                 * <p>
1578:                 * This constructor is provided for convenience when loading a single
1579:                 * image only. If the file contains multiple images, only the first
1580:                 * one will be loaded. To load multiple images, use 
1581:                 * <code>ImageLoader.load()</code>.
1582:                 * </p>
1583:                 *
1584:                 * @param filename the name of the file to load the image from (must not be null)
1585:                 *
1586:                 * @exception IllegalArgumentException <ul>
1587:                 *    <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
1588:                 * </ul>
1589:                 * @exception SWTException <ul>
1590:                 *    <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
1591:                 *    <li>ERROR_IO if an IO error occurs while reading data</li>
1592:                 *    <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
1593:                 * </ul>
1594:                 */
1595:                public ImageData(String filename) {
1596:                    ImageData[] data = new ImageLoader().load(filename);
1597:                    if (data.length < 1)
1598:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
1599:                    ImageData i = data[0];
1600:                    setAllFields(i.width, i.height, i.depth, i.scanlinePad,
1601:                            i.bytesPerLine, i.data, i.palette,
1602:                            i.transparentPixel, i.maskData, i.maskPad,
1603:                            i.alphaData, i.alpha, i.type, i.x, i.y,
1604:                            i.disposalMethod, i.delayTime);
1605:                }
1606:
1607:                /**
1608:                 * Prevents uninitialized instances from being created outside the package.
1609:                 */
1610:                ImageData() {
1611:                    //empty constructor
1612:                }
1613:
1614:                /**
1615:                 * Constructs an image data by giving values for all non-computable fields.
1616:                 * <p>
1617:                 * This method is for internal use, and is not described further.
1618:                 * </p>
1619:                 */
1620:                ImageData(int width, int height, int depth,
1621:                        PaletteData palette, int scanlinePad, byte[] data,
1622:                        int maskPad, byte[] maskData, byte[] alphaData,
1623:                        int alpha, int transparentPixel, int type, int x,
1624:                        int y, int disposalMethod, int delayTime) {
1625:
1626:                    if (palette == null)
1627:                        SWT.error(SWT.ERROR_NULL_ARGUMENT);
1628:                    if (!(depth == 1 || depth == 2 || depth == 4 || depth == 8
1629:                            || depth == 16 || depth == 24 || depth == 32)) {
1630:                        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
1631:                    }
1632:                    if (width <= 0 || height <= 0) {
1633:                        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
1634:                    }
1635:                    if (scanlinePad == 0)
1636:                        SWT.error(SWT.ERROR_CANNOT_BE_ZERO);
1637:
1638:                    int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1))
1639:                            / scanlinePad * scanlinePad;
1640:                    setAllFields(width, height, depth, scanlinePad,
1641:                            bytesPerLine, data != null ? data
1642:                                    : new byte[bytesPerLine * height], palette,
1643:                            transparentPixel, maskData, maskPad, alphaData,
1644:                            alpha, type, x, y, disposalMethod, delayTime);
1645:                }
1646:
1647:                /**
1648:                 * Initializes all fields in the receiver. This method must be called
1649:                 * by all public constructors to ensure that all fields are initialized
1650:                 * for a new ImageData object. If a new field is added to the class,
1651:                 * then it must be added to this method.
1652:                 * <p>
1653:                 * This method is for internal use, and is not described further.
1654:                 * </p>
1655:                 */
1656:                void setAllFields(int width, int height, int depth,
1657:                        int scanlinePad, int bytesPerLine, byte[] data,
1658:                        PaletteData palette, int transparentPixel,
1659:                        byte[] maskData, int maskPad, byte[] alphaData,
1660:                        int alpha, int type, int x, int y, int disposalMethod,
1661:                        int delayTime) {
1662:
1663:                    this .width = width;
1664:                    this .height = height;
1665:                    this .depth = depth;
1666:                    this .scanlinePad = scanlinePad;
1667:                    this .bytesPerLine = bytesPerLine;
1668:                    this .data = data;
1669:                    this .palette = palette;
1670:                    this .transparentPixel = transparentPixel;
1671:                    this .maskData = maskData;
1672:                    this .maskPad = maskPad;
1673:                    this .alphaData = alphaData;
1674:                    this .alpha = alpha;
1675:                    this .type = type;
1676:                    this .x = x;
1677:                    this .y = y;
1678:                    this .disposalMethod = disposalMethod;
1679:                    this .delayTime = delayTime;
1680:                }
1681:
1682:                /**	 
1683:                 * Invokes internal SWT functionality to create a new instance of
1684:                 * this class.
1685:                 * <p>
1686:                 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
1687:                 * API for <code>ImageData</code>. It is marked public only so that it
1688:                 * can be shared within the packages provided by SWT. It is subject
1689:                 * to change without notice, and should never be called from
1690:                 * application code.
1691:                 * </p>
1692:                 * <p>
1693:                 * This method is for internal use, and is not described further.
1694:                 * </p>
1695:                 */
1696:                public static ImageData internal_new(int width, int height,
1697:                        int depth, PaletteData palette, int scanlinePad,
1698:                        byte[] data, int maskPad, byte[] maskData,
1699:                        byte[] alphaData, int alpha, int transparentPixel,
1700:                        int type, int x, int y, int disposalMethod,
1701:                        int delayTime) {
1702:                    return new ImageData(width, height, depth, palette,
1703:                            scanlinePad, data, maskPad, maskData, alphaData,
1704:                            alpha, transparentPixel, type, x, y,
1705:                            disposalMethod, delayTime);
1706:                }
1707:
1708:                ImageData colorMaskImage(int pixel) {
1709:                    ImageData mask = new ImageData(width, height, 1,
1710:                            bwPalette(), 2, null, 0, null, null, -1, -1,
1711:                            SWT.IMAGE_UNDEFINED, 0, 0, 0, 0);
1712:                    int[] row = new int[width];
1713:                    for (int y = 0; y < height; y++) {
1714:                        getPixels(0, y, width, row, 0);
1715:                        for (int i = 0; i < width; i++) {
1716:                            if (pixel != -1 && row[i] == pixel) {
1717:                                row[i] = 0;
1718:                            } else {
1719:                                row[i] = 1;
1720:                            }
1721:                        }
1722:                        mask.setPixels(0, y, width, row, 0);
1723:                    }
1724:                    return mask;
1725:                }
1726:
1727:                static byte[] checkData(byte[] data) {
1728:                    if (data == null)
1729:                        SWT.error(SWT.ERROR_NULL_ARGUMENT);
1730:                    return data;
1731:                }
1732:
1733:                /**
1734:                 * Returns <code>getWidth</code> pixel values starting at offset
1735:                 * <code>x</code> in scanline <code>y</code> in the receiver's
1736:                 * data starting at <code>startIndex</code>.
1737:                 *
1738:                 * @param x the x position of the first pixel to get
1739:                 * @param y the y position of the first pixel to get
1740:                 * @param getWidth the width of the data to get
1741:                 * @param pixels the buffer in which to put the pixels
1742:                 * @param startIndex the offset into the byte array to begin storing pixels
1743:                 *
1744:                 * @exception IndexOutOfBoundsException if getWidth is too large
1745:                 * @exception IllegalArgumentException <ul>
1746:                 *    <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
1747:                 *    <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
1748:                 *    <li>ERROR_INVALID_ARGUMENT - if getWidth is negative</li>
1749:                 * </ul>
1750:                 * @exception SWTException <ul>
1751:                 *    <li>ERROR_UNSUPPORTED_DEPTH - if the depth is not one of 1, 2, 4 or 8
1752:                 *        (For higher depths, use the int[] version of this method.)</li>
1753:                 * </ul>
1754:                 */
1755:                public void getPixels(int x, int y, int getWidth,
1756:                        byte[] pixels, int startIndex) {
1757:                    if (pixels == null)
1758:                        SWT.error(SWT.ERROR_NULL_ARGUMENT);
1759:                    if (getWidth < 0 || x >= width || y >= height || x < 0
1760:                            || y < 0)
1761:                        SWT.error
1762:
1763:                        (SWT.ERROR_INVALID_ARGUMENT);
1764:                    if (getWidth == 0)
1765:                        return;
1766:                    int index;
1767:                    int theByte;
1768:                    int mask = 0;
1769:                    int n = getWidth;
1770:                    int i = startIndex;
1771:                    int srcX = x, srcY = y;
1772:                    if (depth == 1) {
1773:                        index = (y * bytesPerLine) + (x >> 3);
1774:                        theByte = data[index] & 0xFF;
1775:                        while (n > 0) {
1776:                            mask = 1 << (7 - (srcX & 0x7));
1777:                            if ((theByte & mask) == 0) {
1778:                                pixels[i] = 0;
1779:                            } else {
1780:                                pixels[i] = 1;
1781:                            }
1782:                            i++;
1783:                            n--;
1784:                            srcX++;
1785:                            if (srcX >= width) {
1786:                                srcY++;
1787:                                index = srcY * bytesPerLine;
1788:                                if (n > 0)
1789:                                    theByte = data[index] & 0xFF;
1790:                                srcX = 0;
1791:                            } else {
1792:                                if (mask == 1) {
1793:                                    index++;
1794:                                    if (n > 0)
1795:                                        theByte = data[index] & 0xFF;
1796:                                }
1797:                            }
1798:                        }
1799:                        return;
1800:                    }
1801:                    if (depth == 2) {
1802:                        index = (y * bytesPerLine) + (x >> 2);
1803:                        theByte = data[index] & 0xFF;
1804:                        int offset;
1805:                        while (n > 0) {
1806:                            offset = 3 - (srcX % 4);
1807:                            mask = 3 << (offset * 2);
1808:                            pixels[i] = (byte) ((theByte & mask) >> (offset * 2));
1809:                            i++;
1810:                            n--;
1811:                            srcX++;
1812:                            if (srcX >= width) {
1813:                                srcY++;
1814:                                index = srcY * bytesPerLine;
1815:                                if (n > 0)
1816:                                    theByte = data[index] & 0xFF;
1817:                                srcX = 0;
1818:                            } else {
1819:                                if (offset == 0) {
1820:                                    index++;
1821:                                    theByte = data[index] & 0xFF;
1822:                                }
1823:                            }
1824:                        }
1825:                        return;
1826:                    }
1827:                    if (depth == 4) {
1828:                        index = (y * bytesPerLine) + (x >> 1);
1829:                        if ((x & 0x1) == 1) {
1830:                            theByte = data[index] & 0xFF;
1831:                            pixels[i] = (byte) (theByte & 0x0F);
1832:                            i++;
1833:                            n--;
1834:                            srcX++;
1835:                            if (srcX >= width) {
1836:                                srcY++;
1837:                                index = srcY * bytesPerLine;
1838:                                srcX = 0;
1839:                            } else {
1840:                                index++;
1841:                            }
1842:                        }
1843:                        while (n > 1) {
1844:                            theByte = data[index] & 0xFF;
1845:                            pixels[i] = (byte) (theByte >> 4);
1846:                            i++;
1847:                            n--;
1848:                            srcX++;
1849:                            if (srcX >= width) {
1850:                                srcY++;
1851:                                index = srcY * bytesPerLine;
1852:                                srcX = 0;
1853:                            } else {
1854:                                pixels[i] = (byte) (theByte & 0x0F);
1855:                                i++;
1856:                                n--;
1857:                                srcX++;
1858:                                if (srcX >= width) {
1859:                                    srcY++;
1860:                                    index = srcY * bytesPerLine;
1861:                                    srcX = 0;
1862:                                } else {
1863:                                    index++;
1864:                                }
1865:                            }
1866:                        }
1867:                        if (n > 0) {
1868:                            theByte = data[index] & 0xFF;
1869:                            pixels[i] = (byte) (theByte >> 4);
1870:                        }
1871:                        return;
1872:                    }
1873:                    if (depth == 8) {
1874:                        index = (y * bytesPerLine) + x;
1875:                        for (int j = 0; j < getWidth; j++) {
1876:                            pixels[i] = data[index];
1877:                            i++;
1878:                            srcX++;
1879:                            if (srcX >= width) {
1880:                                srcY++;
1881:                                index = srcY * bytesPerLine;
1882:                                srcX = 0;
1883:                            } else {
1884:                                index++;
1885:                            }
1886:                        }
1887:                        return;
1888:                    }
1889:                    SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
1890:                }
1891:
1892:                /**
1893:                 * Returns <code>getWidth</code> pixel values starting at offset
1894:                 * <code>x</code> in scanline <code>y</code> in the receiver's
1895:                 * data starting at <code>startIndex</code>.
1896:                 *
1897:                 * @param x the x position of the first pixel to get
1898:                 * @param y the y position of the first pixel to get
1899:                 * @param getWidth the width of the data to get
1900:                 * @param pixels the buffer in which to put the pixels
1901:                 * @param startIndex the offset into the buffer to begin storing pixels
1902:                 *
1903:                 * @exception IndexOutOfBoundsException if getWidth is too large
1904:                 * @exception IllegalArgumentException <ul>
1905:                 *    <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
1906:                 *    <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
1907:                 *    <li>ERROR_INVALID_ARGUMENT - if getWidth is negative</li>
1908:                 * </ul>
1909:                 * @exception SWTException <ul>
1910:                 *    <li>ERROR_UNSUPPORTED_DEPTH - if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
1911:                 * </ul>
1912:                 */
1913:                public void getPixels(int x, int y, int getWidth, int[] pixels,
1914:                        int startIndex) {
1915:                    if (pixels == null)
1916:                        SWT.error(SWT.ERROR_NULL_ARGUMENT);
1917:                    if (getWidth < 0 || x >= width || y >= height || x < 0
1918:                            || y < 0)
1919:                        SWT.error
1920:
1921:                        (SWT.ERROR_INVALID_ARGUMENT);
1922:                    if (getWidth == 0)
1923:                        return;
1924:                    int index;
1925:                    int theByte;
1926:                    int mask;
1927:                    int n = getWidth;
1928:                    int i = startIndex;
1929:                    int srcX = x, srcY = y;
1930:                    if (depth == 1) {
1931:                        index = (y * bytesPerLine) + (x >> 3);
1932:                        theByte = data[index] & 0xFF;
1933:                        while (n > 0) {
1934:                            mask = 1 << (7 - (srcX & 0x7));
1935:                            if ((theByte & mask) == 0) {
1936:                                pixels[i] = 0;
1937:                            } else {
1938:                                pixels[i] = 1;
1939:                            }
1940:                            i++;
1941:                            n--;
1942:                            srcX++;
1943:                            if (srcX >= width) {
1944:                                srcY++;
1945:                                index = srcY * bytesPerLine;
1946:                                if (n > 0)
1947:                                    theByte = data[index] & 0xFF;
1948:                                srcX = 0;
1949:                            } else {
1950:                                if (mask == 1) {
1951:                                    index++;
1952:                                    if (n > 0)
1953:                                        theByte = data[index] & 0xFF;
1954:                                }
1955:                            }
1956:                        }
1957:                        return;
1958:                    }
1959:                    if (depth == 2) {
1960:                        index = (y * bytesPerLine) + (x >> 2);
1961:                        theByte = data[index] & 0xFF;
1962:                        int offset;
1963:                        while (n > 0) {
1964:                            offset = 3 - (srcX % 4);
1965:                            mask = 3 << (offset * 2);
1966:                            pixels[i] = (byte) ((theByte & mask) >> (offset * 2));
1967:                            i++;
1968:                            n--;
1969:                            srcX++;
1970:                            if (srcX >= width) {
1971:                                srcY++;
1972:                                index = srcY * bytesPerLine;
1973:                                if (n > 0)
1974:                                    theByte = data[index] & 0xFF;
1975:                                srcX = 0;
1976:                            } else {
1977:                                if (offset == 0) {
1978:                                    index++;
1979:                                    theByte = data[index] & 0xFF;
1980:                                }
1981:                            }
1982:                        }
1983:                        return;
1984:                    }
1985:                    if (depth == 4) {
1986:                        index = (y * bytesPerLine) + (x >> 1);
1987:                        if ((x & 0x1) == 1) {
1988:                            theByte = data[index] & 0xFF;
1989:                            pixels[i] = theByte & 0x0F;
1990:                            i++;
1991:                            n--;
1992:                            srcX++;
1993:                            if (srcX >= width) {
1994:                                srcY++;
1995:                                index = srcY * bytesPerLine;
1996:                                srcX = 0;
1997:                            } else {
1998:                                index++;
1999:                            }
2000:                        }
2001:                        while (n > 1) {
2002:                            theByte = data[index] & 0xFF;
2003:                            pixels[i] = theByte >> 4;
2004:                            i++;
2005:                            n--;
2006:                            srcX++;
2007:                            if (srcX >= width) {
2008:                                srcY++;
2009:                                index = srcY * bytesPerLine;
2010:                                srcX = 0;
2011:                            } else {
2012:                                pixels[i] = theByte & 0x0F;
2013:                                i++;
2014:                                n--;
2015:                                srcX++;
2016:                                if (srcX >= width) {
2017:                                    srcY++;
2018:                                    index = srcY * bytesPerLine;
2019:                                    srcX = 0;
2020:                                } else {
2021:                                    index++;
2022:                                }
2023:                            }
2024:                        }
2025:                        if (n > 0) {
2026:                            theByte = data[index] & 0xFF;
2027:                            pixels[i] = theByte >> 4;
2028:                        }
2029:                        return;
2030:                    }
2031:                    if (depth == 8) {
2032:                        index = (y * bytesPerLine) + x;
2033:                        for (int j = 0; j < getWidth; j++) {
2034:                            pixels[i] = data[index] & 0xFF;
2035:                            i++;
2036:                            srcX++;
2037:                            if (srcX >= width) {
2038:                                srcY++;
2039:                                index = srcY * bytesPerLine;
2040:                                srcX = 0;
2041:                            } else {
2042:                                index++;
2043:                            }
2044:                        }
2045:                        return;
2046:                    }
2047:                    if (depth == 16) {
2048:                        index = (y * bytesPerLine) + (x * 2);
2049:                        for (int j = 0; j < getWidth; j++) {
2050:                            pixels[i] = ((data[index + 1] & 0xFF) << 8)
2051:                                    + (data[index] & 0xFF);
2052:                            i++;
2053:                            srcX++;
2054:                            if (srcX >= width) {
2055:                                srcY++;
2056:                                index = srcY * bytesPerLine;
2057:                                srcX = 0;
2058:                            } else {
2059:                                index += 2;
2060:                            }
2061:                        }
2062:                        return;
2063:                    }
2064:                    if (depth == 24) {
2065:                        index = (y * bytesPerLine) + (x * 3);
2066:                        for (int j = 0; j < getWidth; j++) {
2067:                            pixels[i] = ((data[index] & 0xFF) << 16)
2068:                                    | ((data[index + 1] & 0xFF) << 8)
2069:                                    | (data[index + 2] & 0xFF);
2070:                            i++;
2071:                            srcX++;
2072:                            if (srcX >= width) {
2073:                                srcY++;
2074:                                index = srcY * bytesPerLine;
2075:                                srcX = 0;
2076:                            } else {
2077:                                index += 3;
2078:                            }
2079:                        }
2080:                        return;
2081:                    }
2082:                    if (depth == 32) {
2083:                        index = (y * bytesPerLine) + (x * 4);
2084:                        i = startIndex;
2085:                        for (int j = 0; j < getWidth; j++) {
2086:                            pixels[i] = ((data[index] & 0xFF) << 24)
2087:                                    | ((data[index + 1] & 0xFF) << 16)
2088:                                    | ((data[index + 2] & 0xFF) << 8)
2089:                                    | (data[index + 3] & 0xFF);
2090:                            i++;
2091:                            srcX++;
2092:                            if (srcX >= width) {
2093:                                srcY++;
2094:                                index = srcY * bytesPerLine;
2095:                                srcX = 0;
2096:                            } else {
2097:                                index += 4;
2098:                            }
2099:                        }
2100:                        return;
2101:                    }
2102:                    SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
2103:                }
2104:
2105:                /**
2106:                 * Returns an array of <code>RGB</code>s which comprise the
2107:                 * indexed color table of the receiver, or null if the receiver
2108:                 * has a direct color model.
2109:                 *
2110:                 * @return the RGB values for the image or null if direct color
2111:                 *
2112:                 * @see PaletteData#getRGBs()
2113:                 */
2114:                public RGB[] getRGBs() {
2115:                    return palette.getRGBs();
2116:                }
2117:
2118:                /**
2119:                 * Returns an <code>ImageData</code> which specifies the
2120:                 * transparency mask information for the receiver, or null if the
2121:                 * receiver has no transparency and is not an icon.
2122:                 *
2123:                 * @return the transparency mask or null if none exists
2124:                 */
2125:                public ImageData getTransparencyMask() {
2126:                    if (getTransparencyType() == SWT.TRANSPARENCY_MASK) {
2127:                        return new ImageData(width, height, 1, bwPalette(),
2128:                                maskPad, maskData);
2129:                    }
2130:                    return colorMaskImage(transparentPixel);
2131:                }
2132:
2133:                /**
2134:                 * Returns the image transparency type.
2135:                 *
2136:                 * @return the receiver's transparency type
2137:                 */
2138:                public int getTransparencyType() {
2139:                    if (maskData != null)
2140:                        return SWT.TRANSPARENCY_MASK;
2141:                    if (transparentPixel != -1)
2142:                        return SWT.TRANSPARENCY_PIXEL;
2143:                    if (alphaData != null)
2144:                        return SWT.TRANSPARENCY_ALPHA;
2145:                    return SWT.TRANSPARENCY_NONE;
2146:                }
2147:
2148:                /**
2149:                 * Returns the byte order of the receiver.
2150:                 * 
2151:                 * @return MSB_FIRST or LSB_FIRST
2152:                 */
2153:                int getByteOrder() {
2154:                    return depth != 16 ? MSB_FIRST : LSB_FIRST;
2155:                }
2156:
2157:                /**
2158:                 * Sets the pixel values starting at offset <code>x</code> in
2159:                 * scanline <code>y</code> in the receiver's data to the
2160:                 * values from the array <code>pixels</code> starting at
2161:                 * <code>startIndex</code>.
2162:                 *
2163:                 * @param x the x position of the pixel to set
2164:                 * @param y the y position of the pixel to set
2165:                 * @param putWidth the width of the pixels to set
2166:                 * @param pixels the pixels to set
2167:                 * @param startIndex the index at which to begin setting
2168:                 *
2169:                 * @exception IndexOutOfBoundsException if putWidth is too large
2170:                 * @exception IllegalArgumentException <ul>
2171:                 *    <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
2172:                 *    <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
2173:                 *    <li>ERROR_INVALID_ARGUMENT - if putWidth is negative</li>
2174:                 * </ul>
2175:                 * @exception SWTException <ul>
2176:                 *    <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8
2177:                 *        (For higher depths, use the int[] version of this method.)</li>
2178:                 * </ul>
2179:                 */
2180:                public void setPixels(int x, int y, int putWidth,
2181:                        byte[] pixels, int startIndex) {
2182:                    if (pixels == null)
2183:                        SWT.error(SWT.ERROR_NULL_ARGUMENT);
2184:                    if (putWidth < 0 || x >= width || y >= height || x < 0
2185:                            || y < 0)
2186:                        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
2187:                    if (putWidth == 0)
2188:                        return;
2189:                    int index;
2190:                    int theByte;
2191:                    int mask;
2192:                    int n = putWidth;
2193:                    int i = startIndex;
2194:                    int srcX = x, srcY = y;
2195:                    if (depth == 1) {
2196:                        index = (y * bytesPerLine) + (x >> 3);
2197:                        while (n > 0) {
2198:                            mask = 1 << (7 - (srcX & 0x7));
2199:                            if ((pixels[i] & 0x1) == 1) {
2200:                                data[index] = (byte) ((data[index] & 0xFF) | mask);
2201:                            } else {
2202:                                data[index] = (byte) ((data[index] & 0xFF) & (mask ^ -1));
2203:                            }
2204:                            i++;
2205:                            n--;
2206:                            srcX++;
2207:                            if (srcX >= width) {
2208:                                srcY++;
2209:                                index = srcY * bytesPerLine;
2210:                                srcX = 0;
2211:                            } else {
2212:                                if (mask == 1) {
2213:                                    index++;
2214:                                }
2215:                            }
2216:                        }
2217:                        return;
2218:                    }
2219:                    if (depth == 2) {
2220:                        byte[] masks = { (byte) 0xFC, (byte) 0xF3, (byte) 0xCF,
2221:                                (byte) 0x3F };
2222:                        index = (y * bytesPerLine) + (x >> 2);
2223:                        int offset = 3 - (x % 4);
2224:                        while (n > 0) {
2225:                            theByte = pixels[i] & 0x3;
2226:                            data[index] = (byte) ((data[index] & masks[offset]) | (theByte << (offset * 2)));
2227:                            i++;
2228:                            n--;
2229:                            srcX++;
2230:                            if (srcX >= width) {
2231:                                srcY++;
2232:                                index = srcY * bytesPerLine;
2233:                                offset = 0;
2234:                                srcX = 0;
2235:                            } else {
2236:                                if (offset == 0) {
2237:                                    index++;
2238:                                    offset = 3;
2239:                                } else {
2240:                                    offset--;
2241:                                }
2242:                            }
2243:                        }
2244:                        return;
2245:                    }
2246:                    if (depth == 4) {
2247:                        index = (y * bytesPerLine) + (x >> 1);
2248:                        boolean high = (x & 0x1) == 0;
2249:                        while (n > 0) {
2250:                            theByte = pixels[i] & 0x0F;
2251:                            if (high) {
2252:                                data[index] = (byte) ((data[index] & 0x0F) | (theByte << 4));
2253:                            } else {
2254:                                data[index] = (byte) ((data[index] & 0xF0) | theByte);
2255:                            }
2256:                            i++;
2257:                            n--;
2258:                            srcX++;
2259:                            if (srcX >= width) {
2260:                                srcY++;
2261:                                index = srcY * bytesPerLine;
2262:                                high = true;
2263:                                srcX = 0;
2264:                            } else {
2265:                                if (!high)
2266:                                    index++;
2267:                                high = !high;
2268:                            }
2269:                        }
2270:                        return;
2271:                    }
2272:                    if (depth == 8) {
2273:                        index = (y * bytesPerLine) + x;
2274:                        for (int j = 0; j < putWidth; j++) {
2275:                            data[index] = (byte) (pixels[i] & 0xFF);
2276:                            i++;
2277:                            srcX++;
2278:                            if (srcX >= width) {
2279:                                srcY++;
2280:                                index = srcY * bytesPerLine;
2281:                                srcX = 0;
2282:                            } else {
2283:                                index++;
2284:                            }
2285:                        }
2286:                        return;
2287:                    }
2288:                    SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
2289:                }
2290:
2291:                /**
2292:                 * Sets the pixel values starting at offset <code>x</code> in
2293:                 * scanline <code>y</code> in the receiver's data to the
2294:                 * values from the array <code>pixels</code> starting at
2295:                 * <code>startIndex</code>.
2296:                 *
2297:                 * @param x the x position of the pixel to set
2298:                 * @param y the y position of the pixel to set
2299:                 * @param putWidth the width of the pixels to set
2300:                 * @param pixels the pixels to set
2301:                 * @param startIndex the index at which to begin setting
2302:                 *
2303:                 * @exception IndexOutOfBoundsException if putWidth is too large
2304:                 * @exception IllegalArgumentException <ul>
2305:                 *    <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
2306:                 *    <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
2307:                 *    <li>ERROR_INVALID_ARGUMENT - if putWidth is negative</li>
2308:                 * </ul>
2309:                 * @exception SWTException <ul>
2310:                 *    <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
2311:                 * </ul>
2312:                 */
2313:                public void setPixels(int x, int y, int putWidth, int[] pixels,
2314:                        int startIndex) {
2315:                    if (pixels == null)
2316:                        SWT.error(SWT.ERROR_NULL_ARGUMENT);
2317:                    if (putWidth < 0 || x >= width || y >= height || x < 0
2318:                            || y < 0)
2319:                        SWT.error(SWT.ERROR_INVALID_ARGUMENT);
2320:                    if (putWidth == 0)
2321:                        return;
2322:                    int index;
2323:                    int theByte;
2324:                    int mask;
2325:                    int n = putWidth;
2326:                    int i = startIndex;
2327:                    int pixel;
2328:                    int srcX = x, srcY = y;
2329:                    if (depth == 1) {
2330:                        index = (y * bytesPerLine) + (x >> 3);
2331:                        while (n > 0) {
2332:                            mask = 1 << (7 - (srcX & 0x7));
2333:                            if ((pixels[i] & 0x1) == 1) {
2334:                                data[index] = (byte) ((data[index] & 0xFF) | mask);
2335:                            } else {
2336:                                data[index] = (byte) ((data[index] & 0xFF) & (mask ^ -1));
2337:                            }
2338:                            i++;
2339:                            n--;
2340:                            srcX++;
2341:                            if (srcX >= width) {
2342:                                srcY++;
2343:                                index = srcY * bytesPerLine;
2344:                                srcX = 0;
2345:                            } else {
2346:                                if (mask == 1) {
2347:                                    index++;
2348:                                }
2349:                            }
2350:                        }
2351:                        return;
2352:                    }
2353:                    if (depth == 2) {
2354:                        byte[] masks = { (byte) 0xFC, (byte) 0xF3, (byte) 0xCF,
2355:                                (byte) 0x3F };
2356:                        index = (y * bytesPerLine) + (x >> 2);
2357:                        int offset = 3 - (x % 4);
2358:                        while (n > 0) {
2359:                            theByte = pixels[i] & 0x3;
2360:                            data[index] = (byte) ((data[index] & masks[offset]) | (theByte << (offset * 2)));
2361:                            i++;
2362:                            n--;
2363:                            srcX++;
2364:                            if (srcX >= width) {
2365:                                srcY++;
2366:                                index = srcY * bytesPerLine;
2367:                                offset = 3;
2368:                                srcX = 0;
2369:                            } else {
2370:                                if (offset == 0) {
2371:                                    index++;
2372:                                    offset = 3;
2373:                                } else {
2374:                                    offset--;
2375:                                }
2376:                            }
2377:                        }
2378:                        return;
2379:                    }
2380:                    if (depth == 4) {
2381:                        index = (y * bytesPerLine) + (x >> 1);
2382:                        boolean high = (x & 0x1) == 0;
2383:                        while (n > 0) {
2384:                            theByte = pixels[i] & 0x0F;
2385:                            if (high) {
2386:                                data[index] = (byte) ((data[index] & 0x0F) | (theByte << 4));
2387:                            } else {
2388:                                data[index] = (byte) ((data[index] & 0xF0) | theByte);
2389:                            }
2390:                            i++;
2391:                            n--;
2392:                            srcX++;
2393:                            if (srcX >= width) {
2394:                                srcY++;
2395:                                index = srcY * bytesPerLine;
2396:                                high = true;
2397:                                srcX = 0;
2398:                            } else {
2399:                                if (!high)
2400:                                    index++;
2401:                                high = !high;
2402:                            }
2403:                        }
2404:                        return;
2405:                    }
2406:                    if (depth == 8) {
2407:                        index = (y * bytesPerLine) + x;
2408:                        for (int j = 0; j < putWidth; j++) {
2409:                            data[index] = (byte) (pixels[i] & 0xFF);
2410:                            i++;
2411:                            srcX++;
2412:                            if (srcX >= width) {
2413:                                srcY++;
2414:                                index = srcY * bytesPerLine;
2415:                                srcX = 0;
2416:                            } else {
2417:                                index++;
2418:                            }
2419:                        }
2420:                        return;
2421:
2422:                    }
2423:                    if (depth == 16) {
2424:                        index = (y * bytesPerLine) + (x * 2);
2425:                        for (int j = 0; j < putWidth; j++) {
2426:                            pixel = pixels[i];
2427:                            data[index] = (byte) (pixel & 0xFF);
2428:                            data[index + 1] = (byte) ((pixel >> 8) & 0xFF);
2429:                            i++;
2430:                            srcX++;
2431:                            if (srcX >= width) {
2432:                                srcY++;
2433:                                index = srcY * bytesPerLine;
2434:                                srcX = 0;
2435:                            } else {
2436:                                index += 2;
2437:                            }
2438:                        }
2439:                        return;
2440:                    }
2441:                    if (depth == 24) {
2442:                        index = (y * bytesPerLine) + (x * 3);
2443:                        for (int j = 0; j < putWidth; j++) {
2444:                            pixel = pixels[i];
2445:                            data[index] = (byte) ((pixel >> 16) & 0xFF);
2446:                            data[index + 1] = (byte) ((pixel >> 8) & 0xFF);
2447:                            data[index + 2] = (byte) (pixel & 0xFF);
2448:                            i++;
2449:                            srcX++;
2450:                            if (srcX >= width) {
2451:                                srcY++;
2452:                                index = srcY * bytesPerLine;
2453:                                srcX = 0;
2454:                            } else {
2455:                                index += 3;
2456:                            }
2457:                        }
2458:                        return;
2459:                    }
2460:                    if (depth == 32) {
2461:                        index = (y * bytesPerLine) + (x * 4);
2462:                        for (int j = 0; j < putWidth; j++) {
2463:                            pixel = pixels[i];
2464:                            data[index] = (byte) ((pixel >> 24) & 0xFF);
2465:                            data[index + 1] = (byte) ((pixel >> 16) & 0xFF);
2466:                            data[index + 2] = (byte) ((pixel >> 8) & 0xFF);
2467:                            data[index + 3] = (byte) (pixel & 0xFF);
2468:                            i++;
2469:                            srcX++;
2470:                            if (srcX >= width) {
2471:                                srcY++;
2472:                                index = srcY * bytesPerLine;
2473:                                srcX = 0;
2474:                            } else {
2475:                                index += 4;
2476:                            }
2477:                        }
2478:                        return;
2479:                    }
2480:                    SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
2481:                }
2482:
2483:                /**
2484:                 * Returns a palette with 2 colors: black & white.
2485:                 */
2486:                static PaletteData bwPalette() {
2487:                    return new PaletteData(new RGB[] { new RGB(0, 0, 0),
2488:                            new RGB(255, 255, 255) });
2489:                }
2490:
2491:                /**
2492:                 * Gets the offset of the most significant bit for
2493:                 * the given mask.
2494:                 */
2495:                static int getMSBOffset(int mask) {
2496:                    for (int i = 31; i >= 0; i--) {
2497:                        if (((mask >> i) & 0x1) != 0)
2498:                            return i + 1;
2499:                    }
2500:                    return 0;
2501:                }
2502:
2503:                /**
2504:                 * Finds the closest match.
2505:                 */
2506:                static int closestMatch(int depth, byte red, byte green,
2507:                        byte blue, int redMask, int greenMask, int blueMask,
2508:                        byte[] reds, byte[] greens, byte[] blues) {
2509:                    if (depth > 8) {
2510:                        int rshift = 32 - getMSBOffset(redMask);
2511:                        int gshift = 32 - getMSBOffset(greenMask);
2512:                        int bshift = 32 - getMSBOffset(blueMask);
2513:                        return (((red << 24) >>> rshift) & redMask)
2514:                                | (((green << 24) >>> gshift) & greenMask)
2515:                                | (((blue << 24) >>> bshift) & blueMask);
2516:                    }
2517:                    int r, g, b;
2518:                    int minDistance = 0x7fffffff;
2519:                    int nearestPixel = 0;
2520:                    int n = reds.length;
2521:                    for (int j = 0; j < n; j++) {
2522:                        r = (reds[j] & 0xFF) - (red & 0xFF);
2523:                        g = (greens[j] & 0xFF) - (green & 0xFF);
2524:                        b = (blues[j] & 0xFF) - (blue & 0xFF);
2525:                        int distance = r * r + g * g + b * b;
2526:                        if (distance < minDistance) {
2527:                            nearestPixel = j;
2528:                            if (distance == 0)
2529:                                break;
2530:                            minDistance = distance;
2531:                        }
2532:                    }
2533:                    return nearestPixel;
2534:                }
2535:
2536:                static final ImageData convertMask(ImageData mask) {
2537:                    if (mask.depth == 1)
2538:                        return mask;
2539:                    PaletteData palette = new PaletteData(new RGB[] {
2540:                            new RGB(0, 0, 0), new RGB(255, 255, 255) });
2541:                    ImageData newMask = new ImageData(mask.width, mask.height,
2542:                            1, palette);
2543:                    /* Find index of black in mask palette */
2544:                    int blackIndex = 0;
2545:                    RGB[] rgbs = mask.getRGBs();
2546:                    if (rgbs != null) {
2547:                        while (blackIndex < rgbs.length) {
2548:                            if (rgbs[blackIndex].equals(palette.colors[0]))
2549:                                break;
2550:                            blackIndex++;
2551:                        }
2552:                    }
2553:                    int[] pixels = new int[mask.width];
2554:                    for (int y = 0; y < mask.height; y++) {
2555:                        mask.getPixels(0, y, mask.width, pixels, 0);
2556:                        for (int i = 0; i < pixels.length; i++) {
2557:                            if (pixels[i] == blackIndex) {
2558:                                pixels[i] = 0;
2559:                            } else {
2560:                                pixels[i] = 1;
2561:                            }
2562:                        }
2563:                        newMask.setPixels(0, y, mask.width, pixels, 0);
2564:                    }
2565:                    return newMask;
2566:                }
2567:
2568:                static final byte[] convertPad(byte[] data, int width,
2569:                        int height, int depth, int pad, int newPad) {
2570:                    if (pad == newPad)
2571:                        return data;
2572:                    int stride = (width * depth + 7) / 8;
2573:                    int bpl = (stride + (pad - 1)) / pad * pad;
2574:                    int newBpl = (stride + (newPad - 1)) / newPad * newPad;
2575:                    byte[] newData = new byte[height * newBpl];
2576:                    int srcIndex = 0, destIndex = 0;
2577:                    for (int y = 0; y < height; y++) {
2578:                        System.arraycopy(data, srcIndex, newData, destIndex,
2579:                                stride);
2580:                        srcIndex += bpl;
2581:                        destIndex += newBpl;
2582:                    }
2583:                    return newData;
2584:                }
2585:
2586:                /**
2587:                 * Blit operation bits to be OR'ed together to specify the desired operation.
2588:                 */
2589:                static final int BLIT_SRC = 1, // copy source directly, else applies logic operations
2590:                        BLIT_ALPHA = 2, // enable alpha blending
2591:                        BLIT_DITHER = 4; // enable dithering in low color modes
2592:
2593:                /**
2594:                 * Alpha mode, values 0 - 255 specify global alpha level
2595:                 */
2596:                static final int ALPHA_OPAQUE = 255, // Fully opaque (ignores any alpha data)
2597:                        ALPHA_TRANSPARENT = 0, // Fully transparent (ignores any alpha data)
2598:                        ALPHA_CHANNEL_SEPARATE = -1, // Use alpha channel from separate alphaData
2599:                        ALPHA_CHANNEL_SOURCE = -2, // Use alpha channel embedded in sourceData
2600:                        ALPHA_MASK_UNPACKED = -3, // Use transparency mask formed by bytes in alphaData (non-zero is opaque)
2601:                        ALPHA_MASK_PACKED = -4, // Use transparency mask formed by packed bits in alphaData
2602:                        ALPHA_MASK_INDEX = -5, // Consider source palette indices transparent if in alphaData array
2603:                        ALPHA_MASK_RGB = -6; // Consider source RGBs transparent if in RGB888 format alphaData array
2604:
2605:                /**
2606:                 * Byte and bit order constants.
2607:                 */
2608:                static final int LSB_FIRST = 0;
2609:                static final int MSB_FIRST = 1;
2610:
2611:                /**
2612:                 * Data types (internal)
2613:                 */
2614:                /*
2615:                 private static final int
2616:                 // direct / true color formats with arbitrary masks & shifts
2617:                 TYPE_GENERIC_8 = 0,
2618:                 TYPE_GENERIC_16_MSB = 1,
2619:                 TYPE_GENERIC_16_LSB = 2,
2620:                 TYPE_GENERIC_24 = 3,
2621:                 TYPE_GENERIC_32_MSB = 4,
2622:                 TYPE_GENERIC_32_LSB = 5,
2623:                 // palette indexed color formats
2624:                 TYPE_INDEX_8 = 6,
2625:                 TYPE_INDEX_4 = 7,
2626:                 TYPE_INDEX_2 = 8,
2627:                 TYPE_INDEX_1_MSB = 9,
2628:                 TYPE_INDEX_1_LSB = 10;
2629:                 */
2630:                /**
2631:                 * Computes the required channel shift from a mask.
2632:                 */
2633:                static int getChannelShift(int mask) {
2634:                    if (mask == 0)
2635:                        return 0;
2636:                    int i;
2637:                    for (i = 0; ((mask & 1) == 0) && (i < 32); ++i) {
2638:                        mask >>>= 1;
2639:                    }
2640:                    return i;
2641:                }
2642:
2643:                /**
2644:                 * Computes the required channel width (depth) from a mask.
2645:                 */
2646:                static int getChannelWidth(int mask, int shift) {
2647:                    if (mask == 0)
2648:                        return 0;
2649:                    int i;
2650:                    mask >>>= shift;
2651:                    for (i = shift; ((mask & 1) != 0) && (i < 32); ++i) {
2652:                        mask >>>= 1;
2653:                    }
2654:                    return i - shift;
2655:                }
2656:
2657:                /**
2658:                 * Extracts a field from packed RGB data given a mask for that field.
2659:                 */
2660:                static byte getChannelField(int data, int mask) {
2661:                    final int shift = getChannelShift(mask);
2662:                    return ANY_TO_EIGHT[getChannelWidth(mask, shift)][(data & mask) >>> shift];
2663:                }
2664:
2665:                /* 
2666:                 * Fill in dithered gradated values for a color channel
2667:                 */
2668:                static final void buildDitheredGradientChannel(int from,
2669:                        int to, int steps, int bandWidth, int bandHeight,
2670:                        boolean vertical, byte[] bitmapData, int dp,
2671:                        int bytesPerLine, int bits) {
2672:                    final int mask = 0xff00 >>> bits;
2673:                    int val = from << 16;
2674:                    final int inc = ((to << 16) - val) / steps + 1;
2675:                    if (vertical) {
2676:                        for (int dy = 0; dy < bandHeight; ++dy, dp += bytesPerLine) {
2677:                            for (int dx = 0, dptr = dp; dx < bandWidth; ++dx, dptr += 4) {
2678:                                final int thresh = DITHER_MATRIX[dy & 7][dx] >>> bits;
2679:                                int temp = val + thresh;
2680:                                if (temp > 0xffffff)
2681:                                    bitmapData[dptr] = -1;
2682:                                else
2683:                                    bitmapData[dptr] = (byte) ((temp >>> 16) & mask);
2684:                            }
2685:                            val += inc;
2686:                        }
2687:                    } else {
2688:                        for (int dx = 0; dx < bandWidth; ++dx, dp += 4) {
2689:                            for (int dy = 0, dptr = dp; dy < bandHeight; ++dy, dptr += bytesPerLine) {
2690:                                final int thresh = DITHER_MATRIX[dy][dx & 7] >>> bits;
2691:                                int temp = val + thresh;
2692:                                if (temp > 0xffffff)
2693:                                    bitmapData[dptr] = -1;
2694:                                else
2695:                                    bitmapData[dptr] = (byte) ((temp >>> 16) & mask);
2696:                            }
2697:                            val += inc;
2698:                        }
2699:                    }
2700:                }
2701:            }
2702:
2703:            static class LEDataInputStream extends InputStream {
2704:                int position;
2705:                InputStream in;
2706:
2707:                /**
2708:                 * The byte array containing the bytes to read.
2709:                 */
2710:                protected byte[] buf;
2711:
2712:                /**
2713:                 * The current position within the byte array <code>buf</code>. A value
2714:                 * equal to buf.length indicates no bytes available.  A value of
2715:                 * 0 indicates the buffer is full.
2716:                 */
2717:                protected int pos;
2718:
2719:                public LEDataInputStream(InputStream input) {
2720:                    this (input, 512);
2721:                }
2722:
2723:                public LEDataInputStream(InputStream input, int bufferSize) {
2724:                    this .in = input;
2725:                    if (bufferSize > 0) {
2726:                        buf = new byte[bufferSize];
2727:                        pos = bufferSize;
2728:                    } else
2729:                        throw new IllegalArgumentException();
2730:                }
2731:
2732:                public void close() throws IOException {
2733:                    buf = null;
2734:                    if (in != null) {
2735:                        in.close();
2736:                        in = null;
2737:                    }
2738:                }
2739:
2740:                /**
2741:                 * Answer how many bytes were read.
2742:                 */
2743:                public int getPosition() {
2744:                    return position;
2745:                }
2746:
2747:                /**
2748:                 * Answers how many bytes are available for reading without blocking
2749:                 */
2750:                public int available() throws IOException {
2751:                    if (buf == null)
2752:                        throw new IOException();
2753:                    return (buf.length - pos) + in.available();
2754:                }
2755:
2756:                /**
2757:                 * Answer the next byte of the input stream.
2758:                 */
2759:                public int read() throws IOException {
2760:                    if (buf == null)
2761:                        throw new IOException();
2762:                    position++;
2763:                    if (pos < buf.length)
2764:                        return (buf[pos++] & 0xFF);
2765:                    return in.read();
2766:                }
2767:
2768:                /**
2769:                 * Don't imitate the JDK behaviour of reading a random number
2770:                 * of bytes when you can actually read them all.
2771:                 */
2772:                public int read(byte b[], int off, int len) throws IOException {
2773:                    int result;
2774:                    int left = len;
2775:                    result = readData(b, off, len);
2776:                    while (true) {
2777:                        if (result == -1)
2778:                            return -1;
2779:                        position += result;
2780:                        if (result == left)
2781:                            return len;
2782:                        left -= result;
2783:                        off += result;
2784:                        result = readData(b, off, left);
2785:                    }
2786:                }
2787:
2788:                /**
2789:                 * Reads at most <code>length</code> bytes from this LEDataInputStream and 
2790:                 * stores them in byte array <code>buffer</code> starting at <code>offset</code>.
2791:                 * <p>
2792:                 * Answer the number of bytes actually read or -1 if no bytes were read and 
2793:                 * end of stream was encountered.  This implementation reads bytes from 
2794:                 * the pushback buffer first, then the target stream if more bytes are required
2795:                 * to satisfy <code>count</code>.
2796:                 * </p>
2797:                 * @param buffer the byte array in which to store the read bytes.
2798:                 * @param offset the offset in <code>buffer</code> to store the read bytes.
2799:                 * @param length the maximum number of bytes to store in <code>buffer</code>.
2800:                 *
2801:                 * @return int the number of bytes actually read or -1 if end of stream.
2802:                 *
2803:                 * @exception java.io.IOException if an IOException occurs.
2804:                 */
2805:                private int readData(byte[] buffer, int offset, int length)
2806:                        throws IOException {
2807:                    if (buf == null)
2808:                        throw new IOException();
2809:                    if (offset < 0 || offset > buffer.length || length < 0
2810:                            || (length > buffer.length - offset)) {
2811:                        throw new ArrayIndexOutOfBoundsException();
2812:                    }
2813:
2814:                    int cacheCopied = 0;
2815:                    int newOffset = offset;
2816:
2817:                    // Are there pushback bytes available?
2818:                    int available = buf.length - pos;
2819:                    if (available > 0) {
2820:                        cacheCopied = (available >= length) ? length
2821:                                : available;
2822:                        System.arraycopy(buf, pos, buffer, newOffset,
2823:                                cacheCopied);
2824:                        newOffset += cacheCopied;
2825:                        pos += cacheCopied;
2826:                    }
2827:
2828:                    // Have we copied enough?
2829:                    if (cacheCopied == length)
2830:                        return length;
2831:
2832:                    int inCopied = in.read(buffer, newOffset, length
2833:                            - cacheCopied);
2834:
2835:                    if (inCopied > 0)
2836:                        return inCopied + cacheCopied;
2837:                    if (cacheCopied == 0)
2838:                        return inCopied;
2839:                    return cacheCopied;
2840:                }
2841:
2842:                /**
2843:                 * Answer an integer comprised of the next
2844:                 * four bytes of the input stream.
2845:                 */
2846:                public int readInt() throws IOException {
2847:                    byte[] buf = new byte[4];
2848:                    read(buf);
2849:                    return ((((((buf[3] & 0xFF) << 8) | (buf[2] & 0xFF)) << 8) | (buf[1] & 0xFF)) << 8)
2850:                            | (buf[0] & 0xFF);
2851:                }
2852:
2853:                /**
2854:                 * Answer a short comprised of the next
2855:                 * two bytes of the input stream.
2856:                 */
2857:                public short readShort() throws IOException {
2858:                    byte[] buf = new byte[2];
2859:                    read(buf);
2860:                    return (short) (((buf[1] & 0xFF) << 8) | (buf[0] & 0xFF));
2861:                }
2862:
2863:                /**
2864:                 * Push back the entire content of the given buffer <code>b</code>.
2865:                 * <p>
2866:                 * The bytes are pushed so that they would be read back b[0], b[1], etc. 
2867:                 * If the push back buffer cannot handle the bytes copied from <code>b</code>, 
2868:                 * an IOException will be thrown and no byte will be pushed back.
2869:                 * </p>
2870:                 * 
2871:                 * @param b the byte array containing bytes to push back into the stream
2872:                 *
2873:                 * @exception 	java.io.IOException if the pushback buffer is too small
2874:                 */
2875:                public void unread(byte[] b) throws IOException {
2876:                    int length = b.length;
2877:                    if (length > pos)
2878:                        throw new IOException();
2879:                    position -= length;
2880:                    pos -= length;
2881:                    System.arraycopy(b, 0, buf, pos, length);
2882:                }
2883:            }
2884:
2885:            public static abstract class FileFormat {
2886:                LEDataInputStream inputStream;
2887:                ImageLoader loader;
2888:                int compression;
2889:
2890:                byte[] bitInvertData(byte[] data, int startIndex, int endIndex) {
2891:                    // Destructively bit invert data in the given byte array.
2892:                    for (int i = startIndex; i < endIndex; i++) {
2893:                        data[i] = (byte) (255 - data[i - startIndex]);
2894:                    }
2895:                    return data;
2896:                }
2897:
2898:                /**
2899:                 * Return whether or not the specified input stream
2900:                 * represents a supported file format.
2901:                 */
2902:                abstract boolean isFileFormat(LEDataInputStream stream);
2903:
2904:                abstract ImageData[] loadFromByteStream();
2905:
2906:                public ImageData[] loadFromStream(LEDataInputStream stream) {
2907:                    try {
2908:                        inputStream = stream;
2909:                        return loadFromByteStream();
2910:                    } catch (Exception e) {
2911:                        SWT.error(SWT.ERROR_IO, e);
2912:                        return null;
2913:                    }
2914:                }
2915:
2916:                public static ImageData[] load(InputStream is,
2917:                        ImageLoader loader) {
2918:                    LEDataInputStream stream = new LEDataInputStream(is);
2919:                    boolean isSupported = false;
2920:                    FileFormat fileFormat = new WinICOFileFormat();
2921:                    if (fileFormat.isFileFormat(stream))
2922:                        isSupported = true;
2923:                    else {
2924:                        fileFormat = new WinBMPFileFormat();
2925:                        if (fileFormat.isFileFormat(stream))
2926:                            isSupported = true;
2927:                    }
2928:                    if (!isSupported)
2929:                        SWT.error(SWT.ERROR_UNSUPPORTED_FORMAT);
2930:                    fileFormat.loader = loader;
2931:                    return fileFormat.loadFromStream(stream);
2932:                }
2933:            }
2934:
2935:            static class WinBMPFileFormat extends FileFormat {
2936:                static final int BMPFileHeaderSize = 14;
2937:                static final int BMPHeaderFixedSize = 40;
2938:                int importantColors;
2939:
2940:                void decompressData(byte[] src, byte[] dest, int stride, int cmp) {
2941:                    if (cmp == 1) { // BMP_RLE8_COMPRESSION
2942:                        if (decompressRLE8Data(src, src.length, stride, dest,
2943:                                dest.length) <= 0)
2944:                            SWT.error(SWT.ERROR_INVALID_IMAGE);
2945:                        return;
2946:                    }
2947:                    if (cmp == 2) { // BMP_RLE4_COMPRESSION
2948:                        if (decompressRLE4Data(src, src.length, stride, dest,
2949:                                dest.length) <= 0)
2950:                            SWT.error(SWT.ERROR_INVALID_IMAGE);
2951:                        return;
2952:                    }
2953:                    SWT.error(SWT.ERROR_INVALID_IMAGE);
2954:                }
2955:
2956:                int decompressRLE4Data(byte[] src, int numBytes, int stride,
2957:                        byte[] dest, int destSize) {
2958:                    int sp = 0;
2959:                    int se = numBytes;
2960:                    int dp = 0;
2961:                    int de = destSize;
2962:                    int x = 0, y = 0;
2963:                    while (sp < se) {
2964:                        int len = src[sp] & 0xFF;
2965:                        sp++;
2966:                        if (len == 0) {
2967:                            len = src[sp] & 0xFF;
2968:                            sp++;
2969:                            switch (len) {
2970:                            case 0: /* end of line */
2971:                                y++;
2972:                                x = 0;
2973:                                dp = y * stride;
2974:                                if (dp >= de)
2975:                                    return -1;
2976:                                break;
2977:                            case 1: /* end of bitmap */
2978:                                return 1;
2979:                            case 2: /* delta */
2980:                                x += src[sp] & 0xFF;
2981:                                sp++;
2982:                                y += src[sp] & 0xFF;
2983:                                sp++;
2984:                                dp = y * stride + x / 2;
2985:                                if (dp >= de)
2986:                                    return -1;
2987:                                break;
2988:                            default: /* absolute mode run */
2989:                                if ((len & 1) != 0) /* odd run lengths not currently supported */
2990:                                    return -1;
2991:                                x += len;
2992:                                len = len / 2;
2993:                                if (len > (se - sp))
2994:                                    return -1;
2995:                                if (len > (de - dp))
2996:                                    return -1;
2997:                                for (int i = 0; i < len; i++) {
2998:                                    dest[dp] = src[sp];
2999:                                    dp++;
3000:                                    sp++;
3001:                                }
3002:                                if ((sp & 1) != 0)
3003:                                    sp++; /* word align sp? */
3004:                                break;
3005:                            }
3006:                        } else {
3007:                            if ((len & 1) != 0)
3008:                                return -1;
3009:                            x += len;
3010:                            len = len / 2;
3011:                            byte theByte = src[sp];
3012:                            sp++;
3013:                            if (len > (de - dp))
3014:                                return -1;
3015:                            for (int i = 0; i < len; i++) {
3016:                                dest[dp] = theByte;
3017:                                dp++;
3018:                            }
3019:                        }
3020:                    }
3021:                    return 1;
3022:                }
3023:
3024:                int decompressRLE8Data(byte[] src, int numBytes, int stride,
3025:                        byte[] dest, int destSize) {
3026:                    int sp = 0;
3027:                    int se = numBytes;
3028:                    int dp = 0;
3029:                    int de = destSize;
3030:                    int x = 0, y = 0;
3031:                    while (sp < se) {
3032:                        int len = src[sp] & 0xFF;
3033:                        sp++;
3034:                        if (len == 0) {
3035:                            len = src[sp] & 0xFF;
3036:                            sp++;
3037:                            switch (len) {
3038:                            case 0: /* end of line */
3039:                                y++;
3040:                                x = 0;
3041:                                dp = y * stride;
3042:                                if (dp >= de)
3043:                                    return -1;
3044:                                break;
3045:                            case 1: /* end of bitmap */
3046:                                return 1;
3047:                            case 2: /* delta */
3048:                                x += src[sp] & 0xFF;
3049:                                sp++;
3050:                                y += src[sp] & 0xFF;
3051:                                sp++;
3052:                                dp = y * stride + x;
3053:                                if (dp >= de)
3054:                                    return -1;
3055:                                break;
3056:                            default: /* absolute mode run */
3057:                                if (len > (se - sp))
3058:                                    return -1;
3059:                                if (len > (de - dp))
3060:                                    return -1;
3061:                                for (int i = 0; i < len; i++) {
3062:                                    dest[dp] = src[sp];
3063:                                    dp++;
3064:                                    sp++;
3065:                                }
3066:                                if ((sp & 1) != 0)
3067:                                    sp++; /* word align sp? */
3068:                                x += len;
3069:                                break;
3070:                            }
3071:                        } else {
3072:                            byte theByte = src[sp];
3073:                            sp++;
3074:                            if (len > (de - dp))
3075:                                return -1;
3076:                            for (int i = 0; i < len; i++) {
3077:                                dest[dp] = theByte;
3078:                                dp++;
3079:                            }
3080:                            x += len;
3081:                        }
3082:                    }
3083:                    return 1;
3084:                }
3085:
3086:                boolean isFileFormat(LEDataInputStream stream) {
3087:                    try {
3088:                        byte[] header = new byte[18];
3089:                        stream.read(header);
3090:                        stream.unread(header);
3091:                        int infoHeaderSize = (header[14] & 0xFF)
3092:                                | ((header[15] & 0xFF) << 8)
3093:                                | ((header[16] & 0xFF) << 16)
3094:                                | ((header[17] & 0xFF) << 24);
3095:                        return header[0] == 0x42 && header[1] == 0x4D
3096:                                && infoHeaderSize >= BMPHeaderFixedSize;
3097:                    } catch (Exception e) {
3098:                        return false;
3099:                    }
3100:                }
3101:
3102:                byte[] loadData(byte[] infoHeader) {
3103:                    int width = (infoHeader[4] & 0xFF)
3104:                            | ((infoHeader[5] & 0xFF) << 8)
3105:                            | ((infoHeader[6] & 0xFF) << 16)
3106:                            | ((infoHeader[7] & 0xFF) << 24);
3107:                    int height = (infoHeader[8] & 0xFF)
3108:                            | ((infoHeader[9] & 0xFF) << 8)
3109:                            | ((infoHeader[10] & 0xFF) << 16)
3110:                            | ((infoHeader[11] & 0xFF) << 24);
3111:                    int bitCount = (infoHeader[14] & 0xFF)
3112:                            | ((infoHeader[15] & 0xFF) << 8);
3113:                    int stride = (width * bitCount + 7) / 8;
3114:                    stride = (stride + 3) / 4 * 4; // Round up to 4 byte multiple
3115:                    byte[] data = loadData(infoHeader, stride);
3116:                    flipScanLines(data, stride, height);
3117:                    return data;
3118:                }
3119:
3120:                byte[] loadData(byte[] infoHeader, int stride) {
3121:                    int height = (infoHeader[8] & 0xFF)
3122:                            | ((infoHeader[9] & 0xFF) << 8)
3123:                            | ((infoHeader[10] & 0xFF) << 16)
3124:                            | ((infoHeader[11] & 0xFF) << 24);
3125:                    int dataSize = height * stride;
3126:                    byte[] data = new byte[dataSize];
3127:                    int cmp = (infoHeader[16] & 0xFF)
3128:                            | ((infoHeader[17] & 0xFF) << 8)
3129:                            | ((infoHeader[18] & 0xFF) << 16)
3130:                            | ((infoHeader[19] & 0xFF) << 24);
3131:                    if (cmp == 0) { // BMP_NO_COMPRESSION
3132:                        try {
3133:                            if (inputStream.read(data) != dataSize)
3134:                                SWT.error(SWT.ERROR_INVALID_IMAGE);
3135:                        } catch (IOException e) {
3136:                            SWT.error(SWT.ERROR_IO, e);
3137:                        }
3138:                    } else {
3139:                        int compressedSize = (infoHeader[20] & 0xFF)
3140:                                | ((infoHeader[21] & 0xFF) << 8)
3141:                                | ((infoHeader[22] & 0xFF) << 16)
3142:                                | ((infoHeader[23] & 0xFF) << 24);
3143:                        byte[] compressed = new byte[compressedSize];
3144:                        try {
3145:                            if (inputStream.read(compressed) != compressedSize)
3146:                                SWT.error(SWT.ERROR_INVALID_IMAGE);
3147:                        } catch (IOException e) {
3148:                            SWT.error(SWT.ERROR_IO, e);
3149:                        }
3150:                        decompressData(compressed, data, stride, cmp);
3151:                    }
3152:                    return data;
3153:                }
3154:
3155:                int[] loadFileHeader() {
3156:                    int[] header = new int[5];
3157:                    try {
3158:                        header[0] = inputStream.readShort();
3159:                        header[1] = inputStream.readInt();
3160:                        header[2] = inputStream.readShort();
3161:                        header[3] = inputStream.readShort();
3162:                        header[4] = inputStream.readInt();
3163:                    } catch (IOException e) {
3164:                        SWT.error(SWT.ERROR_IO, e);
3165:                    }
3166:                    if (header[0] != 0x4D42)
3167:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
3168:                    return header;
3169:                }
3170:
3171:                ImageData[] loadFromByteStream() {
3172:                    int[] fileHeader = loadFileHeader();
3173:                    byte[] infoHeader = new byte[BMPHeaderFixedSize];
3174:                    try {
3175:                        inputStream.read(infoHeader);
3176:                    } catch (Exception e) {
3177:                        SWT.error(SWT.ERROR_IO, e);
3178:                    }
3179:                    int width = (infoHeader[4] & 0xFF)
3180:                            | ((infoHeader[5] & 0xFF) << 8)
3181:                            | ((infoHeader[6] & 0xFF) << 16)
3182:                            | ((infoHeader[7] & 0xFF) << 24);
3183:                    int height = (infoHeader[8] & 0xFF)
3184:                            | ((infoHeader[9] & 0xFF) << 8)
3185:                            | ((infoHeader[10] & 0xFF) << 16)
3186:                            | ((infoHeader[11] & 0xFF) << 24);
3187:                    int bitCount = (infoHeader[14] & 0xFF)
3188:                            | ((infoHeader[15] & 0xFF) << 8);
3189:                    PaletteData palette = loadPalette(infoHeader);
3190:                    if (inputStream.getPosition() < fileHeader[4]) {
3191:                        // Seek to the specified offset
3192:                        try {
3193:                            inputStream.skip(fileHeader[4]
3194:                                    - inputStream.getPosition());
3195:                        } catch (IOException e) {
3196:                            SWT.error(SWT.ERROR_IO, e);
3197:                        }
3198:                    }
3199:                    byte[] data = loadData(infoHeader);
3200:                    this .compression = (infoHeader[16] & 0xFF)
3201:                            | ((infoHeader[17] & 0xFF) << 8)
3202:                            | ((infoHeader[18] & 0xFF) << 16)
3203:                            | ((infoHeader[19] & 0xFF) << 24);
3204:                    this .importantColors = (infoHeader[36] & 0xFF)
3205:                            | ((infoHeader[37] & 0xFF) << 8)
3206:                            | ((infoHeader[38] & 0xFF) << 16)
3207:                            | ((infoHeader[39] & 0xFF) << 24);
3208:                    //	int xPelsPerMeter = (infoHeader[24] & 0xFF) | ((infoHeader[25] & 0xFF) << 8) | ((infoHeader[26] & 0xFF) << 16) | ((infoHeader[27] & 0xFF) << 24);
3209:                    //	int yPelsPerMeter = (infoHeader[28] & 0xFF) | ((infoHeader[29] & 0xFF) << 8) | ((infoHeader[30] & 0xFF) << 16) | ((infoHeader[31] & 0xFF) << 24);
3210:                    int type = (this .compression == 1 /*BMP_RLE8_COMPRESSION*/)
3211:                            || (this .compression == 2 /*BMP_RLE4_COMPRESSION*/) ? SWT.IMAGE_BMP_RLE
3212:                            : SWT.IMAGE_BMP;
3213:                    return new ImageData[] { ImageData.internal_new(width,
3214:                            height, bitCount, palette, 4, data, 0, null, null,
3215:                            -1, -1, type, 0, 0, 0, 0) };
3216:                }
3217:
3218:                PaletteData loadPalette(byte[] infoHeader) {
3219:                    int depth = (infoHeader[14] & 0xFF)
3220:                            | ((infoHeader[15] & 0xFF) << 8);
3221:                    if (depth <= 8) {
3222:                        int numColors = (infoHeader[32] & 0xFF)
3223:                                | ((infoHeader[33] & 0xFF) << 8)
3224:                                | ((infoHeader[34] & 0xFF) << 16)
3225:                                | ((infoHeader[35] & 0xFF) << 24);
3226:                        if (numColors == 0) {
3227:                            numColors = 1 << depth;
3228:                        } else {
3229:                            if (numColors > 256)
3230:                                numColors = 256;
3231:                        }
3232:                        byte[] buf = new byte[numColors * 4];
3233:                        try {
3234:                            if (inputStream.read(buf) != buf.length)
3235:                                SWT.error(SWT.ERROR_INVALID_IMAGE);
3236:                        } catch (IOException e) {
3237:                            SWT.error(SWT.ERROR_IO, e);
3238:                        }
3239:                        return paletteFromBytes(buf, numColors);
3240:                    }
3241:                    if (depth == 16)
3242:                        return new PaletteData(0x7C00, 0x3E0, 0x1F);
3243:                    if (depth == 24)
3244:                        return new PaletteData(0xFF, 0xFF00, 0xFF0000);
3245:                    return new PaletteData(0xFF00, 0xFF0000, 0xFF000000);
3246:                }
3247:
3248:                PaletteData paletteFromBytes(byte[] bytes, int numColors) {
3249:                    int bytesOffset = 0;
3250:                    RGB[] colors = new RGB[numColors];
3251:                    for (int i = 0; i < numColors; i++) {
3252:                        colors[i] = new RGB(bytes[bytesOffset + 2] & 0xFF,
3253:                                bytes[bytesOffset + 1] & 0xFF,
3254:                                bytes[bytesOffset] & 0xFF);
3255:                        bytesOffset += 4;
3256:                    }
3257:                    return new PaletteData(colors);
3258:                }
3259:
3260:                /**
3261:                 * Answer a byte array containing the BMP representation of
3262:                 * the given device independent palette.
3263:                 */
3264:                static byte[] paletteToBytes(PaletteData pal) {
3265:                    int n = pal.colors == null ? 0
3266:                            : (pal.colors.length < 256 ? pal.colors.length
3267:                                    : 256);
3268:                    byte[] bytes = new byte[n * 4];
3269:                    int offset = 0;
3270:                    for (int i = 0; i < n; i++) {
3271:                        RGB col = pal.colors[i];
3272:                        bytes[offset] = (byte) col.blue;
3273:                        bytes[offset + 1] = (byte) col.green;
3274:                        bytes[offset + 2] = (byte) col.red;
3275:                        offset += 4;
3276:                    }
3277:                    return bytes;
3278:                }
3279:
3280:                void flipScanLines(byte[] data, int stride, int height) {
3281:                    int i1 = 0;
3282:                    int i2 = (height - 1) * stride;
3283:                    for (int i = 0; i < height / 2; i++) {
3284:                        for (int index = 0; index < stride; index++) {
3285:                            byte b = data[index + i1];
3286:                            data[index + i1] = data[index + i2];
3287:                            data[index + i2] = b;
3288:                        }
3289:                        i1 += stride;
3290:                        i2 -= stride;
3291:                    }
3292:                }
3293:
3294:            }
3295:
3296:            static class WinICOFileFormat extends FileFormat {
3297:
3298:                static final byte[] convertPad(byte[] data, int width,
3299:                        int height, int depth, int pad, int newPad) {
3300:                    if (pad == newPad)
3301:                        return data;
3302:                    int stride = (width * depth + 7) / 8;
3303:                    int bpl = (stride + (pad - 1)) / pad * pad;
3304:                    int newBpl = (stride + (newPad - 1)) / newPad * newPad;
3305:                    byte[] newData = new byte[height * newBpl];
3306:                    int srcIndex = 0, destIndex = 0;
3307:                    for (int y = 0; y < height; y++) {
3308:                        System.arraycopy(data, srcIndex, newData, destIndex,
3309:                                newBpl);
3310:                        srcIndex += bpl;
3311:                        destIndex += newBpl;
3312:                    }
3313:                    return newData;
3314:                }
3315:
3316:                /**
3317:                 * Answer the size in bytes of the file representation of the given
3318:                 * icon
3319:                 */
3320:                int iconSize(ImageData i) {
3321:                    int shapeDataStride = (i.width * i.depth + 31) / 32 * 4;
3322:                    int maskDataStride = (i.width + 31) / 32 * 4;
3323:                    int dataSize = (shapeDataStride + maskDataStride)
3324:                            * i.height;
3325:                    int paletteSize = i.palette.colors != null ? i.palette.colors.length * 4
3326:                            : 0;
3327:                    return WinBMPFileFormat.BMPHeaderFixedSize + paletteSize
3328:                            + dataSize;
3329:                }
3330:
3331:                boolean isFileFormat(LEDataInputStream stream) {
3332:                    try {
3333:                        byte[] header = new byte[4];
3334:                        stream.read(header);
3335:                        stream.unread(header);
3336:                        return header[0] == 0 && header[1] == 0
3337:                                && header[2] == 1 && header[3] == 0;
3338:                    } catch (Exception e) {
3339:                        return false;
3340:                    }
3341:                }
3342:
3343:                boolean isValidIcon(ImageData i) {
3344:                    switch (i.depth) {
3345:                    case 1:
3346:                    case 4:
3347:                    case 8:
3348:                        if (i.palette.isDirect)
3349:                            return false;
3350:                        int size = i.palette.colors.length;
3351:                        return size == 2 || size == 16 || size == 32
3352:                                || size == 256;
3353:                    case 24:
3354:                    case 32:
3355:                        return i.palette.isDirect;
3356:                    }
3357:                    return false;
3358:                }
3359:
3360:                int loadFileHeader(LEDataInputStream byteStream) {
3361:                    int[] fileHeader = new int[3];
3362:                    try {
3363:                        fileHeader[0] = byteStream.readShort();
3364:                        fileHeader[1] = byteStream.readShort();
3365:                        fileHeader[2] = byteStream.readShort();
3366:                    } catch (IOException e) {
3367:                        SWT.error(SWT.ERROR_IO, e);
3368:                    }
3369:                    if ((fileHeader[0] != 0) || (fileHeader[1] != 1))
3370:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
3371:                    int numIcons = fileHeader[2];
3372:                    if (numIcons <= 0)
3373:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
3374:                    return numIcons;
3375:                }
3376:
3377:                int loadFileHeader(LEDataInputStream byteStream,
3378:                        boolean hasHeader) {
3379:                    int[] fileHeader = new int[3];
3380:                    try {
3381:                        if (hasHeader) {
3382:                            fileHeader[0] = byteStream.readShort();
3383:                            fileHeader[1] = byteStream.readShort();
3384:                        } else {
3385:                            fileHeader[0] = 0;
3386:                            fileHeader[1] = 1;
3387:                        }
3388:                        fileHeader[2] = byteStream.readShort();
3389:                    } catch (IOException e) {
3390:                        SWT.error(SWT.ERROR_IO, e);
3391:                    }
3392:                    if ((fileHeader[0] != 0) || (fileHeader[1] != 1))
3393:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
3394:                    int numIcons = fileHeader[2];
3395:                    if (numIcons <= 0)
3396:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
3397:                    return numIcons;
3398:                }
3399:
3400:                ImageData[] loadFromByteStream() {
3401:                    int numIcons = loadFileHeader(inputStream);
3402:                    int[][] headers = loadIconHeaders(numIcons);
3403:                    ImageData[] icons = new ImageData[headers.length];
3404:                    for (int i = 0; i < icons.length; i++) {
3405:                        icons[i] = loadIcon(headers[i]);
3406:                    }
3407:                    return icons;
3408:                }
3409:
3410:                /**
3411:                 * Load one icon from the byte stream.
3412:                 */
3413:                ImageData loadIcon(int[] iconHeader) {
3414:                    byte[] infoHeader = loadInfoHeader(iconHeader);
3415:                    WinBMPFileFormat bmpFormat = new WinBMPFileFormat();
3416:                    bmpFormat.inputStream = inputStream;
3417:                    PaletteData palette = bmpFormat.loadPalette(infoHeader);
3418:                    byte[] shapeData = bmpFormat.loadData(infoHeader);
3419:                    int width = (infoHeader[4] & 0xFF)
3420:                            | ((infoHeader[5] & 0xFF) << 8)
3421:                            | ((infoHeader[6] & 0xFF) << 16)
3422:                            | ((infoHeader[7] & 0xFF) << 24);
3423:                    int height = (infoHeader[8] & 0xFF)
3424:                            | ((infoHeader[9] & 0xFF) << 8)
3425:                            | ((infoHeader[10] & 0xFF) << 16)
3426:                            | ((infoHeader[11] & 0xFF) << 24);
3427:                    int depth = (infoHeader[14] & 0xFF)
3428:                            | ((infoHeader[15] & 0xFF) << 8);
3429:                    infoHeader[14] = 1;
3430:                    infoHeader[15] = 0;
3431:                    byte[] maskData = bmpFormat.loadData(infoHeader);
3432:                    maskData = convertPad(maskData, width, height, 1, 4, 2);
3433:                    bitInvertData(maskData, 0, maskData.length);
3434:                    return ImageData.internal_new(width, height, depth,
3435:                            palette, 4, shapeData, 2, maskData, null, -1, -1,
3436:                            SWT.IMAGE_ICO, 0, 0, 0, 0);
3437:                }
3438:
3439:                int[][] loadIconHeaders(int numIcons) {
3440:                    int[][] headers = new int[numIcons][7];
3441:                    try {
3442:                        for (int i = 0; i < numIcons; i++) {
3443:                            headers[i][0] = inputStream.read();
3444:                            headers[i][1] = inputStream.read();
3445:                            headers[i][2] = inputStream.readShort();
3446:                            headers[i][3] = inputStream.readShort();
3447:                            headers[i][4] = inputStream.readShort();
3448:                            headers[i][5] = inputStream.readInt();
3449:                            headers[i][6] = inputStream.readInt();
3450:                        }
3451:                    } catch (IOException e) {
3452:                        SWT.error(SWT.ERROR_IO, e);
3453:                    }
3454:                    return headers;
3455:                }
3456:
3457:                byte[] loadInfoHeader(int[] iconHeader) {
3458:                    int width = iconHeader[0];
3459:                    int height = iconHeader[1];
3460:                    int numColors = iconHeader[2]; // the number of colors is in the low byte, but the high byte must be 0
3461:                    if (numColors == 0)
3462:                        numColors = 256; // this is specified: '00' represents '256' (0x100) colors
3463:                    if ((numColors != 2) && (numColors != 8)
3464:                            && (numColors != 16) && (numColors != 32)
3465:                            && (numColors != 256))
3466:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
3467:                    if (inputStream.getPosition() < iconHeader[6]) {
3468:                        // Seek to the specified offset
3469:                        try {
3470:                            inputStream.skip(iconHeader[6]
3471:                                    - inputStream.getPosition());
3472:                        } catch (IOException e) {
3473:                            SWT.error(SWT.ERROR_IO, e);
3474:                            return null;
3475:                        }
3476:                    }
3477:                    byte[] infoHeader = new byte[WinBMPFileFormat.BMPHeaderFixedSize];
3478:                    try {
3479:                        inputStream.read(infoHeader);
3480:                    } catch (IOException e) {
3481:                        SWT.error(SWT.ERROR_IO, e);
3482:                    }
3483:                    if (((infoHeader[12] & 0xFF) | ((infoHeader[13] & 0xFF) << 8)) != 1)
3484:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
3485:                    int infoWidth = (infoHeader[4] & 0xFF)
3486:                            | ((infoHeader[5] & 0xFF) << 8)
3487:                            | ((infoHeader[6] & 0xFF) << 16)
3488:                            | ((infoHeader[7] & 0xFF) << 24);
3489:                    int infoHeight = (infoHeader[8] & 0xFF)
3490:                            | ((infoHeader[9] & 0xFF) << 8)
3491:                            | ((infoHeader[10] & 0xFF) << 16)
3492:                            | ((infoHeader[11] & 0xFF) << 24);
3493:                    int bitCount = (infoHeader[14] & 0xFF)
3494:                            | ((infoHeader[15] & 0xFF) << 8);
3495:                    if (height == infoHeight && bitCount == 1)
3496:                        height /= 2;
3497:                    if (!((width == infoWidth) && (height * 2 == infoHeight) && (bitCount == 1
3498:                            || bitCount == 4 || bitCount == 8 || bitCount == 24 || bitCount == 32)))
3499:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
3500:                    infoHeader[8] = (byte) (height & 0xFF);
3501:                    infoHeader[9] = (byte) ((height >> 8) & 0xFF);
3502:                    infoHeader[10] = (byte) ((height >> 16) & 0xFF);
3503:                    infoHeader[11] = (byte) ((height >> 24) & 0xFF);
3504:                    return infoHeader;
3505:                }
3506:            }
3507:
3508:            static class SWT {
3509:                public static final int IMAGE_ICO = 3;
3510:                public static final int ERROR_IO = 39;
3511:                public static final int ERROR_INVALID_IMAGE = 40;
3512:                public static final int ERROR_NULL_ARGUMENT = 4;
3513:                public static final int ERROR_INVALID_ARGUMENT = 5;
3514:                public static final int ERROR_CANNOT_BE_ZERO = 7;
3515:                public static final int IMAGE_UNDEFINED = -1;
3516:                public static final int ERROR_UNSUPPORTED_DEPTH = 38;
3517:                public static final int TRANSPARENCY_MASK = 1 << 1;
3518:                public static final int ERROR_UNSUPPORTED_FORMAT = 42;
3519:                public static final int TRANSPARENCY_ALPHA = 1 << 0;
3520:                public static final int TRANSPARENCY_NONE = 0x0;
3521:                public static final int TRANSPARENCY_PIXEL = 1 << 2;
3522:                public static final int IMAGE_BMP = 0;
3523:                public static final int IMAGE_BMP_RLE = 1;
3524:
3525:                public static void error(int code) {
3526:                    throw new RuntimeException("Error " + code); //$NON-NLS-1$
3527:                }
3528:
3529:                public static void error(int code, Throwable t) {
3530:                    throw new RuntimeException(t);
3531:                }
3532:            }
3533:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.