Source Code Cross Referenced for JPEGFileFormat.java in  » IDE-Eclipse » swt » org » eclipse » swt » internal » image » 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 » swt » org.eclipse.swt.internal.image 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2000, 2006 IBM Corporation and others.
0003:         * All rights reserved.  This source file is made available under the terms contained in the README file
0004:         * accompanying this program.  The README file should be located in the about_files directory of the
0005:         * plug-in that contains this source file.
0006:         *
0007:         * Contributors:
0008:         *     IBM Corporation - initial API and implementation
0009:         *******************************************************************************/package org.eclipse.swt.internal.image;
0010:
0011:        import org.eclipse.swt.*;
0012:        import org.eclipse.swt.graphics.*;
0013:        import java.io.*;
0014:
0015:        final class JPEGFileFormat extends FileFormat {
0016:            int restartInterval;
0017:            JPEGFrameHeader frameHeader;
0018:            int imageWidth, imageHeight;
0019:            int interleavedMcuCols, interleavedMcuRows;
0020:            int maxV, maxH;
0021:            boolean progressive;
0022:            int samplePrecision;
0023:            int nComponents;
0024:            int[][] frameComponents;
0025:            int[] componentIds;
0026:            byte[][] imageComponents;
0027:            int[] dataUnit;
0028:            int[][][] dataUnits;
0029:            int[] precedingDCs;
0030:            JPEGScanHeader scanHeader;
0031:            byte[] dataBuffer;
0032:            int currentBitCount;
0033:            int bufferCurrentPosition;
0034:            int restartsToGo;
0035:            int nextRestartNumber;
0036:            JPEGHuffmanTable[] acHuffmanTables;
0037:            JPEGHuffmanTable[] dcHuffmanTables;
0038:            int[][] quantizationTables;
0039:            int currentByte;
0040:            int encoderQFactor = 75;
0041:            int eobrun = 0;
0042:            /* JPEGConstants */
0043:            public static final int DCTSIZE = 8;
0044:            public static final int DCTSIZESQR = 64;
0045:            /* JPEGFixedPointConstants */
0046:            public static final int FIX_0_899976223 = 7373;
0047:            public static final int FIX_1_961570560 = 16069;
0048:            public static final int FIX_2_053119869 = 16819;
0049:            public static final int FIX_0_298631336 = 2446;
0050:            public static final int FIX_1_847759065 = 15137;
0051:            public static final int FIX_1_175875602 = 9633;
0052:            public static final int FIX_3_072711026 = 25172;
0053:            public static final int FIX_0_765366865 = 6270;
0054:            public static final int FIX_2_562915447 = 20995;
0055:            public static final int FIX_0_541196100 = 4433;
0056:            public static final int FIX_0_390180644 = 3196;
0057:            public static final int FIX_1_501321110 = 12299;
0058:            /* JPEGMarkerCodes */
0059:            public static final int APP0 = 0xFFE0;
0060:            public static final int APP15 = 0xFFEF;
0061:            public static final int COM = 0xFFFE;
0062:            public static final int DAC = 0xFFCC;
0063:            public static final int DHP = 0xFFDE;
0064:            public static final int DHT = 0xFFC4;
0065:            public static final int DNL = 0xFFDC;
0066:            public static final int DRI = 0xFFDD;
0067:            public static final int DQT = 0xFFDB;
0068:            public static final int EOI = 0xFFD9;
0069:            public static final int EXP = 0xFFDF;
0070:            public static final int JPG = 0xFFC8;
0071:            public static final int JPG0 = 0xFFF0;
0072:            public static final int JPG13 = 0xFFFD;
0073:            public static final int RST0 = 0xFFD0;
0074:            public static final int RST1 = 0xFFD1;
0075:            public static final int RST2 = 0xFFD2;
0076:            public static final int RST3 = 0xFFD3;
0077:            public static final int RST4 = 0xFFD4;
0078:            public static final int RST5 = 0xFFD5;
0079:            public static final int RST6 = 0xFFD6;
0080:            public static final int RST7 = 0xFFD7;
0081:            public static final int SOF0 = 0xFFC0;
0082:            public static final int SOF1 = 0xFFC1;
0083:            public static final int SOF2 = 0xFFC2;
0084:            public static final int SOF3 = 0xFFC3;
0085:            public static final int SOF5 = 0xFFC5;
0086:            public static final int SOF6 = 0xFFC6;
0087:            public static final int SOF7 = 0xFFC7;
0088:            public static final int SOF9 = 0xFFC9;
0089:            public static final int SOF10 = 0xFFCA;
0090:            public static final int SOF11 = 0xFFCB;
0091:            public static final int SOF13 = 0xFFCD;
0092:            public static final int SOF14 = 0xFFCE;
0093:            public static final int SOF15 = 0xFFCF;
0094:            public static final int SOI = 0xFFD8;
0095:            public static final int SOS = 0xFFDA;
0096:            public static final int TEM = 0xFF01;
0097:            /* JPEGFrameComponentParameterConstants */
0098:            public static final int TQI = 0;
0099:            public static final int HI = 1;
0100:            public static final int VI = 2;
0101:            public static final int CW = 3;
0102:            public static final int CH = 4;
0103:            /* JPEGScanComponentParameterConstants */
0104:            public static final int DC = 0;
0105:            public static final int AC = 1;
0106:            /* JFIF Component Constants */
0107:            public static final int ID_Y = 1 - 1;
0108:            public static final int ID_CB = 2 - 1;
0109:            public static final int ID_CR = 3 - 1;
0110:            public static final RGB[] RGB16 = new RGB[] { new RGB(0, 0, 0),
0111:                    new RGB(0x80, 0, 0), new RGB(0, 0x80, 0),
0112:                    new RGB(0x80, 0x80, 0), new RGB(0, 0, 0x80),
0113:                    new RGB(0x80, 0, 0x80), new RGB(0, 0x80, 0x80),
0114:                    new RGB(0xC0, 0xC0, 0xC0), new RGB(0x80, 0x80, 0x80),
0115:                    new RGB(0xFF, 0, 0), new RGB(0, 0xFF, 0),
0116:                    new RGB(0xFF, 0xFF, 0), new RGB(0, 0, 0xFF),
0117:                    new RGB(0xFF, 0, 0xFF), new RGB(0, 0xFF, 0xFF),
0118:                    new RGB(0xFF, 0xFF, 0xFF), };
0119:            public static final int[] ExtendTest = { 0, 1, 2, 4, 8, 16, 32, 64,
0120:                    128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536,
0121:                    131072, 262144 };
0122:            public static final int[] ExtendOffset = new int[] { 0, -1, -3, -7,
0123:                    -15, -31, -63, -127, -255, -511, -1023, -2047, -4095,
0124:                    -8191, -16383, -32767, -65535, -131071, -262143 };
0125:            public static final int[] ZigZag8x8 = { 0, 1, 8, 16, 9, 2, 3, 10,
0126:                    17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41,
0127:                    34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50,
0128:                    43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38,
0129:                    31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 };
0130:
0131:            public static int[] CrRTable, CbBTable, CrGTable, CbGTable;
0132:            public static int[] RYTable, GYTable, BYTable, RCbTable, GCbTable,
0133:                    BCbTable, RCrTable, GCrTable, BCrTable, NBitsTable;
0134:            static {
0135:                initialize();
0136:            }
0137:
0138:            void compress(ImageData image, byte[] dataYComp, byte[] dataCbComp,
0139:                    byte[] dataCrComp) {
0140:                int srcWidth = image.width;
0141:                int srcHeight = image.height;
0142:                int vhFactor = maxV * maxH;
0143:                int[] frameComponent;
0144:                imageComponents = new byte[nComponents][];
0145:                for (int i = 0; i < nComponents; i++) {
0146:                    frameComponent = frameComponents[componentIds[i]];
0147:                    imageComponents[i] = new byte[frameComponent[CW]
0148:                            * frameComponent[CH]];
0149:                }
0150:                frameComponent = frameComponents[componentIds[ID_Y]];
0151:                for (int yPos = 0; yPos < srcHeight; yPos++) {
0152:                    int srcOfs = yPos * srcWidth;
0153:                    int dstOfs = yPos * frameComponent[CW];
0154:                    System.arraycopy(dataYComp, srcOfs, imageComponents[ID_Y],
0155:                            dstOfs, srcWidth);
0156:                }
0157:                frameComponent = frameComponents[componentIds[ID_CB]];
0158:                for (int yPos = 0; yPos < srcHeight / maxV; yPos++) {
0159:                    int destRowIndex = yPos * frameComponent[CW];
0160:                    for (int xPos = 0; xPos < srcWidth / maxH; xPos++) {
0161:                        int sum = 0;
0162:                        for (int iv = 0; iv < maxV; iv++) {
0163:                            int srcIndex = (yPos * maxV + iv) * srcWidth
0164:                                    + (xPos * maxH);
0165:                            for (int ih = 0; ih < maxH; ih++) {
0166:                                sum += dataCbComp[srcIndex + ih] & 0xFF;
0167:                            }
0168:                        }
0169:                        imageComponents[ID_CB][destRowIndex + xPos] = (byte) (sum / vhFactor);
0170:                    }
0171:                }
0172:                frameComponent = frameComponents[componentIds[ID_CR]];
0173:                for (int yPos = 0; yPos < srcHeight / maxV; yPos++) {
0174:                    int destRowIndex = yPos * frameComponent[CW];
0175:                    for (int xPos = 0; xPos < srcWidth / maxH; xPos++) {
0176:                        int sum = 0;
0177:                        for (int iv = 0; iv < maxV; iv++) {
0178:                            int srcIndex = (yPos * maxV + iv) * srcWidth
0179:                                    + (xPos * maxH);
0180:                            for (int ih = 0; ih < maxH; ih++) {
0181:                                sum += dataCrComp[srcIndex + ih] & 0xFF;
0182:                            }
0183:                        }
0184:                        imageComponents[ID_CR][destRowIndex + xPos] = (byte) (sum / vhFactor);
0185:                    }
0186:                }
0187:                for (int iComp = 0; iComp < nComponents; iComp++) {
0188:                    byte[] imageComponent = imageComponents[iComp];
0189:                    frameComponent = frameComponents[componentIds[iComp]];
0190:                    int hFactor = frameComponent[HI];
0191:                    int vFactor = frameComponent[VI];
0192:                    int componentWidth = frameComponent[CW];
0193:                    int componentHeight = frameComponent[CH];
0194:                    int compressedWidth = srcWidth / (maxH / hFactor);
0195:                    int compressedHeight = srcHeight / (maxV / vFactor);
0196:                    if (compressedWidth < componentWidth) {
0197:                        int delta = componentWidth - compressedWidth;
0198:                        for (int yPos = 0; yPos < compressedHeight; yPos++) {
0199:                            int dstOfs = ((yPos + 1) * componentWidth - delta);
0200:                            int dataValue = imageComponent[dstOfs - 1] & 0xFF;
0201:                            for (int i = 0; i < delta; i++) {
0202:                                imageComponent[dstOfs + i] = (byte) dataValue;
0203:                            }
0204:                        }
0205:                    }
0206:                    if (compressedHeight < componentHeight) {
0207:                        int srcOfs = (compressedHeight - 1) * componentWidth;
0208:                        for (int yPos = compressedHeight; yPos <= componentHeight; yPos++) {
0209:                            int dstOfs = (yPos - 1) * componentWidth;
0210:                            System.arraycopy(imageComponent, srcOfs,
0211:                                    imageComponent, dstOfs, componentWidth);
0212:                        }
0213:                    }
0214:                }
0215:            }
0216:
0217:            void convert4BitRGBToYCbCr(ImageData image) {
0218:                RGB[] rgbs = image.getRGBs();
0219:                int paletteSize = rgbs.length;
0220:                byte[] yComp = new byte[paletteSize];
0221:                byte[] cbComp = new byte[paletteSize];
0222:                byte[] crComp = new byte[paletteSize];
0223:                int srcWidth = image.width;
0224:                int srcHeight = image.height;
0225:                for (int i = 0; i < paletteSize; i++) {
0226:                    RGB color = rgbs[i];
0227:                    int r = color.red;
0228:                    int g = color.green;
0229:                    int b = color.blue;
0230:                    int n = RYTable[r] + GYTable[g] + BYTable[b];
0231:                    yComp[i] = (byte) (n >> 16);
0232:                    if ((n < 0) && ((n & 0xFFFF) != 0))
0233:                        yComp[i]--;
0234:                    n = RCbTable[r] + GCbTable[g] + BCbTable[b];
0235:                    cbComp[i] = (byte) (n >> 16);
0236:                    if ((n < 0) && ((n & 0xFFFF) != 0))
0237:                        cbComp[i]--;
0238:                    n = RCrTable[r] + GCrTable[g] + BCrTable[b];
0239:                    crComp[i] = (byte) (n >> 16);
0240:                    if ((n < 0) && ((n & 0xFFFF) != 0))
0241:                        crComp[i]--;
0242:                }
0243:                int bSize = srcWidth * srcHeight;
0244:                byte[] dataYComp = new byte[bSize];
0245:                byte[] dataCbComp = new byte[bSize];
0246:                byte[] dataCrComp = new byte[bSize];
0247:                byte[] origData = image.data;
0248:                int bytesPerLine = image.bytesPerLine;
0249:                int maxScanlineByte = srcWidth >> 1;
0250:                for (int yPos = 0; yPos < srcHeight; yPos++) {
0251:                    for (int xPos = 0; xPos < maxScanlineByte; xPos++) {
0252:                        int srcIndex = yPos * bytesPerLine + xPos;
0253:                        int dstIndex = yPos * srcWidth + (xPos * 2);
0254:                        int value2 = origData[srcIndex] & 0xFF;
0255:                        int value1 = value2 >> 4;
0256:                        value2 &= 0x0F;
0257:                        dataYComp[dstIndex] = yComp[value1];
0258:                        dataCbComp[dstIndex] = cbComp[value1];
0259:                        dataCrComp[dstIndex] = crComp[value1];
0260:                        dataYComp[dstIndex + 1] = yComp[value2];
0261:                        dataCbComp[dstIndex + 1] = cbComp[value2];
0262:                        dataCrComp[dstIndex + 1] = crComp[value2];
0263:                    }
0264:                }
0265:                compress(image, dataYComp, dataCbComp, dataCrComp);
0266:            }
0267:
0268:            void convert8BitRGBToYCbCr(ImageData image) {
0269:                RGB[] rgbs = image.getRGBs();
0270:                int paletteSize = rgbs.length;
0271:                byte[] yComp = new byte[paletteSize];
0272:                byte[] cbComp = new byte[paletteSize];
0273:                byte[] crComp = new byte[paletteSize];
0274:                int srcWidth = image.width;
0275:                int srcHeight = image.height;
0276:                for (int i = 0; i < paletteSize; i++) {
0277:                    RGB color = rgbs[i];
0278:                    int r = color.red;
0279:                    int g = color.green;
0280:                    int b = color.blue;
0281:                    int n = RYTable[r] + GYTable[g] + BYTable[b];
0282:                    yComp[i] = (byte) (n >> 16);
0283:                    if ((n < 0) && ((n & 0xFFFF) != 0))
0284:                        yComp[i]--;
0285:                    n = RCbTable[r] + GCbTable[g] + BCbTable[b];
0286:                    cbComp[i] = (byte) (n >> 16);
0287:                    if ((n < 0) && ((n & 0xFFFF) != 0))
0288:                        cbComp[i]--;
0289:                    n = RCrTable[r] + GCrTable[g] + BCrTable[b];
0290:                    crComp[i] = (byte) (n >> 16);
0291:                    if ((n < 0) && ((n & 0xFFFF) != 0))
0292:                        crComp[i]--;
0293:                }
0294:                int dstWidth = image.width;
0295:                int dstHeight = srcHeight;
0296:                int stride = ((srcWidth + 3) >> 2) << 2;
0297:                int bSize = dstWidth * dstHeight;
0298:                byte[] dataYComp = new byte[bSize];
0299:                byte[] dataCbComp = new byte[bSize];
0300:                byte[] dataCrComp = new byte[bSize];
0301:                byte[] origData = image.data;
0302:                for (int yPos = 0; yPos < srcHeight; yPos++) {
0303:                    int srcRowIndex = yPos * stride;
0304:                    int dstRowIndex = yPos * dstWidth;
0305:                    for (int xPos = 0; xPos < srcWidth; xPos++) {
0306:                        int value = origData[srcRowIndex + xPos] & 0xFF;
0307:                        int dstIndex = dstRowIndex + xPos;
0308:                        dataYComp[dstIndex] = yComp[value];
0309:                        dataCbComp[dstIndex] = cbComp[value];
0310:                        dataCrComp[dstIndex] = crComp[value];
0311:                    }
0312:                }
0313:                compress(image, dataYComp, dataCbComp, dataCrComp);
0314:            }
0315:
0316:            byte[] convertCMYKToRGB() {
0317:                /* Unsupported CMYK format. Answer an empty byte array. */
0318:                return new byte[0];
0319:            }
0320:
0321:            void convertImageToYCbCr(ImageData image) {
0322:                switch (image.depth) {
0323:                case 4:
0324:                    convert4BitRGBToYCbCr(image);
0325:                    return;
0326:                case 8:
0327:                    convert8BitRGBToYCbCr(image);
0328:                    return;
0329:                case 16:
0330:                case 24:
0331:                case 32:
0332:                    convertMultiRGBToYCbCr(image);
0333:                    return;
0334:                default:
0335:                    SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
0336:                }
0337:                return;
0338:            }
0339:
0340:            void convertMultiRGBToYCbCr(ImageData image) {
0341:                int srcWidth = image.width;
0342:                int srcHeight = image.height;
0343:                int bSize = srcWidth * srcHeight;
0344:                byte[] dataYComp = new byte[bSize];
0345:                byte[] dataCbComp = new byte[bSize];
0346:                byte[] dataCrComp = new byte[bSize];
0347:                PaletteData palette = image.palette;
0348:                int[] buffer = new int[srcWidth];
0349:                if (palette.isDirect) {
0350:                    int redMask = palette.redMask;
0351:                    int greenMask = palette.greenMask;
0352:                    int blueMask = palette.blueMask;
0353:                    int redShift = palette.redShift;
0354:                    int greenShift = palette.greenShift;
0355:                    int blueShift = palette.blueShift;
0356:                    for (int yPos = 0; yPos < srcHeight; yPos++) {
0357:                        image.getPixels(0, yPos, srcWidth, buffer, 0);
0358:                        int dstRowIndex = yPos * srcWidth;
0359:                        for (int xPos = 0; xPos < srcWidth; xPos++) {
0360:                            int pixel = buffer[xPos];
0361:                            int dstDataIndex = dstRowIndex + xPos;
0362:                            int r = pixel & redMask;
0363:                            r = (redShift < 0) ? r >>> -redShift
0364:                                    : r << redShift;
0365:                            int g = pixel & greenMask;
0366:                            g = (greenShift < 0) ? g >>> -greenShift
0367:                                    : g << greenShift;
0368:                            int b = pixel & blueMask;
0369:                            b = (blueShift < 0) ? b >>> -blueShift
0370:                                    : b << blueShift;
0371:                            dataYComp[dstDataIndex] = (byte) ((RYTable[r]
0372:                                    + GYTable[g] + BYTable[b]) >> 16);
0373:                            dataCbComp[dstDataIndex] = (byte) ((RCbTable[r]
0374:                                    + GCbTable[g] + BCbTable[b]) >> 16);
0375:                            dataCrComp[dstDataIndex] = (byte) ((RCrTable[r]
0376:                                    + GCrTable[g] + BCrTable[b]) >> 16);
0377:                        }
0378:                    }
0379:                } else {
0380:                    for (int yPos = 0; yPos < srcHeight; yPos++) {
0381:                        image.getPixels(0, yPos, srcWidth, buffer, 0);
0382:                        int dstRowIndex = yPos * srcWidth;
0383:                        for (int xPos = 0; xPos < srcWidth; xPos++) {
0384:                            int pixel = buffer[xPos];
0385:                            int dstDataIndex = dstRowIndex + xPos;
0386:                            RGB rgb = palette.getRGB(pixel);
0387:                            int r = rgb.red;
0388:                            int g = rgb.green;
0389:                            int b = rgb.blue;
0390:                            dataYComp[dstDataIndex] = (byte) ((RYTable[r]
0391:                                    + GYTable[g] + BYTable[b]) >> 16);
0392:                            dataCbComp[dstDataIndex] = (byte) ((RCbTable[r]
0393:                                    + GCbTable[g] + BCbTable[b]) >> 16);
0394:                            dataCrComp[dstDataIndex] = (byte) ((RCrTable[r]
0395:                                    + GCrTable[g] + BCrTable[b]) >> 16);
0396:                        }
0397:                    }
0398:                }
0399:                compress(image, dataYComp, dataCbComp, dataCrComp);
0400:            }
0401:
0402:            byte[] convertYToRGB() {
0403:                int compWidth = frameComponents[componentIds[ID_Y]][CW];
0404:                int bytesPerLine = (((imageWidth * 8 + 7) / 8) + 3) / 4 * 4;
0405:                byte[] data = new byte[bytesPerLine * imageHeight];
0406:                byte[] yComp = imageComponents[ID_Y];
0407:                int destIndex = 0;
0408:                for (int i = 0; i < imageHeight; i++) {
0409:                    int srcIndex = i * compWidth;
0410:                    for (int j = 0; j < bytesPerLine; j++) {
0411:                        int y = yComp[srcIndex] & 0xFF;
0412:                        if (y < 0) {
0413:                            y = 0;
0414:                        } else {
0415:                            if (y > 255)
0416:                                y = 255;
0417:                        }
0418:                        if (j >= imageWidth) {
0419:                            y = 0;
0420:                        }
0421:                        data[destIndex] = (byte) y;
0422:                        srcIndex++;
0423:                        destIndex++;
0424:                    }
0425:                }
0426:                return data;
0427:            }
0428:
0429:            byte[] convertYCbCrToRGB() {
0430:                /**
0431:                 * Convert existing image components into an RGB format.
0432:                 * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
0433:                 * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
0434:                 * The conversion equations to be implemented are therefore
0435:                 * 	R = Y                + 1.40200 * Cr
0436:                 * 	G = Y - 0.34414 * Cb - 0.71414 * Cr
0437:                 * 	B = Y + 1.77200 * Cb
0438:                 * where Cb and Cr represent the incoming values less MAXJSAMPLE/2.
0439:                 * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
0440:                 * 
0441:                 * To avoid floating-point arithmetic, we represent the fractional constants
0442:                 * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
0443:                 * the products by 2^16, with appropriate rounding, to get the correct answer.
0444:                 * Notice that Y, being an integral input, does not contribute any fraction
0445:                 * so it need not participate in the rounding.
0446:                 * 
0447:                 * For even more speed, we avoid doing any multiplications in the inner loop
0448:                 * by precalculating the constants times Cb and Cr for all possible values.
0449:                 * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
0450:                 * for 12-bit samples it is still acceptable.  It's not very reasonable for
0451:                 * 16-bit samples, but if you want lossless storage you shouldn't be changing
0452:                 * colorspace anyway.
0453:                 * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
0454:                 * values for the G calculation are left scaled up, since we must add them
0455:                 * together before rounding.
0456:                 */
0457:                int bSize = imageWidth * imageHeight * nComponents;
0458:                byte[] rgbData = new byte[bSize];
0459:                int destIndex = 0;
0460:                expandImageComponents();
0461:                byte[] yComp = imageComponents[ID_Y];
0462:                byte[] cbComp = imageComponents[ID_CB];
0463:                byte[] crComp = imageComponents[ID_CR];
0464:                int compWidth = frameComponents[componentIds[ID_Y]][CW];
0465:                for (int v = 0; v < imageHeight; v++) {
0466:                    int srcIndex = v * compWidth;
0467:                    for (int i = 0; i < imageWidth; i++) {
0468:                        int y = yComp[srcIndex] & 0xFF;
0469:                        int cb = cbComp[srcIndex] & 0xFF;
0470:                        int cr = crComp[srcIndex] & 0xFF;
0471:                        int r = y + CrRTable[cr];
0472:                        int g = y + ((CbGTable[cb] + CrGTable[cr]) >> 16);
0473:                        int b = y + CbBTable[cb];
0474:                        if (r < 0) {
0475:                            r = 0;
0476:                        } else {
0477:                            if (r > 255)
0478:                                r = 255;
0479:                        }
0480:                        if (g < 0) {
0481:                            g = 0;
0482:                        } else {
0483:                            if (g > 255)
0484:                                g = 255;
0485:                        }
0486:                        if (b < 0) {
0487:                            b = 0;
0488:                        } else {
0489:                            if (b > 255)
0490:                                b = 255;
0491:                        }
0492:                        rgbData[destIndex] = (byte) b;
0493:                        rgbData[destIndex + 1] = (byte) g;
0494:                        rgbData[destIndex + 2] = (byte) r;
0495:                        destIndex += 3;
0496:                        srcIndex++;
0497:                    }
0498:                }
0499:                return rgbData;
0500:            }
0501:
0502:            void decodeACCoefficients(int[] dataUnit, int iComp) {
0503:                int[] sParams = scanHeader.componentParameters[componentIds[iComp]];
0504:                JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
0505:                int k = 1;
0506:                while (k < 64) {
0507:                    int rs = decodeUsingTable(acTable);
0508:                    int r = rs >> 4;
0509:                    int s = rs & 0xF;
0510:                    if (s == 0) {
0511:                        if (r == 15) {
0512:                            k += 16;
0513:                        } else {
0514:                            break;
0515:                        }
0516:                    } else {
0517:                        k += r;
0518:                        int bits = receive(s);
0519:                        dataUnit[ZigZag8x8[k]] = extendBy(bits, s);
0520:                        k++;
0521:                    }
0522:                }
0523:            }
0524:
0525:            void decodeACFirstCoefficients(int[] dataUnit, int iComp,
0526:                    int start, int end, int approxBit) {
0527:                if (eobrun > 0) {
0528:                    eobrun--;
0529:                    return;
0530:                }
0531:                int[] sParams = scanHeader.componentParameters[componentIds[iComp]];
0532:                JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
0533:                int k = start;
0534:                while (k <= end) {
0535:                    int rs = decodeUsingTable(acTable);
0536:                    int r = rs >> 4;
0537:                    int s = rs & 0xF;
0538:                    if (s == 0) {
0539:                        if (r == 15) {
0540:                            k += 16;
0541:                        } else {
0542:                            eobrun = (1 << r) + receive(r) - 1;
0543:                            break;
0544:                        }
0545:                    } else {
0546:                        k += r;
0547:                        int bits = receive(s);
0548:                        dataUnit[ZigZag8x8[k]] = extendBy(bits, s) << approxBit;
0549:                        k++;
0550:                    }
0551:                }
0552:            }
0553:
0554:            void decodeACRefineCoefficients(int[] dataUnit, int iComp,
0555:                    int start, int end, int approxBit) {
0556:                int[] sParams = scanHeader.componentParameters[componentIds[iComp]];
0557:                JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
0558:                int k = start;
0559:                while (k <= end) {
0560:                    if (eobrun > 0) {
0561:                        while (k <= end) {
0562:                            int zzIndex = ZigZag8x8[k];
0563:                            if (dataUnit[zzIndex] != 0) {
0564:                                dataUnit[zzIndex] = refineAC(dataUnit[zzIndex],
0565:                                        approxBit);
0566:                            }
0567:                            k++;
0568:                        }
0569:                        eobrun--;
0570:                    } else {
0571:                        int rs = decodeUsingTable(acTable);
0572:                        int r = rs >> 4;
0573:                        int s = rs & 0xF;
0574:                        if (s == 0) {
0575:                            if (r == 15) {
0576:                                int zeros = 0;
0577:                                while (zeros < 16 && k <= end) {
0578:                                    int zzIndex = ZigZag8x8[k];
0579:                                    if (dataUnit[zzIndex] != 0) {
0580:                                        dataUnit[zzIndex] = refineAC(
0581:                                                dataUnit[zzIndex], approxBit);
0582:                                    } else {
0583:                                        zeros++;
0584:                                    }
0585:                                    k++;
0586:                                }
0587:                            } else {
0588:                                eobrun = (1 << r) + receive(r);
0589:                            }
0590:                        } else {
0591:                            int bit = receive(s);
0592:                            int zeros = 0;
0593:                            int zzIndex = ZigZag8x8[k];
0594:                            while ((zeros < r || dataUnit[zzIndex] != 0)
0595:                                    && k <= end) {
0596:                                if (dataUnit[zzIndex] != 0) {
0597:                                    dataUnit[zzIndex] = refineAC(
0598:                                            dataUnit[zzIndex], approxBit);
0599:                                } else {
0600:                                    zeros++;
0601:                                }
0602:                                k++;
0603:                                zzIndex = ZigZag8x8[k];
0604:                            }
0605:                            if (bit != 0) {
0606:                                dataUnit[zzIndex] = 1 << approxBit;
0607:                            } else {
0608:                                dataUnit[zzIndex] = -1 << approxBit;
0609:                            }
0610:                            k++;
0611:                        }
0612:                    }
0613:                }
0614:            }
0615:
0616:            int refineAC(int ac, int approxBit) {
0617:                if (ac > 0) {
0618:                    int bit = nextBit();
0619:                    if (bit != 0) {
0620:                        ac += 1 << approxBit;
0621:                    }
0622:                } else if (ac < 0) {
0623:                    int bit = nextBit();
0624:                    if (bit != 0) {
0625:                        ac += -1 << approxBit;
0626:                    }
0627:                }
0628:                return ac;
0629:            }
0630:
0631:            void decodeDCCoefficient(int[] dataUnit, int iComp, boolean first,
0632:                    int approxBit) {
0633:                int[] sParams = scanHeader.componentParameters[componentIds[iComp]];
0634:                JPEGHuffmanTable dcTable = dcHuffmanTables[sParams[DC]];
0635:                int lastDC = 0;
0636:                if (progressive && !first) {
0637:                    int bit = nextBit();
0638:                    lastDC = dataUnit[0] + (bit << approxBit);
0639:                } else {
0640:                    lastDC = precedingDCs[iComp];
0641:                    int nBits = decodeUsingTable(dcTable);
0642:                    if (nBits != 0) {
0643:                        int bits = receive(nBits);
0644:                        int diff = extendBy(bits, nBits);
0645:                        lastDC += diff;
0646:                        precedingDCs[iComp] = lastDC;
0647:                    }
0648:                    if (progressive) {
0649:                        lastDC = lastDC << approxBit;
0650:                    }
0651:                }
0652:                dataUnit[0] = lastDC;
0653:            }
0654:
0655:            void dequantize(int[] dataUnit, int iComp) {
0656:                int[] qTable = quantizationTables[frameComponents[componentIds[iComp]][TQI]];
0657:                for (int i = 0; i < dataUnit.length; i++) {
0658:                    int zzIndex = ZigZag8x8[i];
0659:                    dataUnit[zzIndex] = dataUnit[zzIndex] * qTable[i];
0660:                }
0661:            }
0662:
0663:            byte[] decodeImageComponents() {
0664:                if (nComponents == 3) { // compIds 1, 2, 3
0665:                    return convertYCbCrToRGB();
0666:                }
0667:                //	if (nComponents == 3) { // compIds 1, 4, 5
0668:                //		Unsupported CMYK format.
0669:                //		return convertYIQToRGB();
0670:                //	}
0671:                if (nComponents == 4) {
0672:                    return convertCMYKToRGB();
0673:                }
0674:                return convertYToRGB();
0675:            }
0676:
0677:            void decodeMCUAtXAndY(int xmcu, int ymcu, int nComponentsInScan,
0678:                    boolean first, int start, int end, int approxBit) {
0679:                for (int iComp = 0; iComp < nComponentsInScan; iComp++) {
0680:                    int scanComponent = iComp;
0681:                    while (scanHeader.componentParameters[componentIds[scanComponent]] == null) {
0682:                        scanComponent++;
0683:                    }
0684:                    int[] frameComponent = frameComponents[componentIds[scanComponent]];
0685:                    int hi = frameComponent[HI];
0686:                    int vi = frameComponent[VI];
0687:                    if (nComponentsInScan == 1) {
0688:                        hi = 1;
0689:                        vi = 1;
0690:                    }
0691:                    int compWidth = frameComponent[CW];
0692:                    for (int ivi = 0; ivi < vi; ivi++) {
0693:                        for (int ihi = 0; ihi < hi; ihi++) {
0694:                            if (progressive) {
0695:                                // Progressive: First scan - create a new data unit.
0696:                                // Subsequent scans - refine the existing data unit.
0697:                                int index = (ymcu * vi + ivi) * compWidth
0698:                                        + xmcu * hi + ihi;
0699:                                dataUnit = dataUnits[scanComponent][index];
0700:                                if (dataUnit == null) {
0701:                                    dataUnit = new int[64];
0702:                                    dataUnits[scanComponent][index] = dataUnit;
0703:                                }
0704:                            } else {
0705:                                // Sequential: Clear and reuse the data unit buffer.
0706:                                for (int i = 0; i < dataUnit.length; i++) {
0707:                                    dataUnit[i] = 0;
0708:                                }
0709:                            }
0710:                            if (!progressive
0711:                                    || scanHeader.isDCProgressiveScan()) {
0712:                                decodeDCCoefficient(dataUnit, scanComponent,
0713:                                        first, approxBit);
0714:                            }
0715:                            if (!progressive) {
0716:                                decodeACCoefficients(dataUnit, scanComponent);
0717:                            } else {
0718:                                if (scanHeader.isACProgressiveScan()) {
0719:                                    if (first) {
0720:                                        decodeACFirstCoefficients(dataUnit,
0721:                                                scanComponent, start, end,
0722:                                                approxBit);
0723:                                    } else {
0724:                                        decodeACRefineCoefficients(dataUnit,
0725:                                                scanComponent, start, end,
0726:                                                approxBit);
0727:                                    }
0728:                                }
0729:                                if (loader.hasListeners()) {
0730:                                    // Dequantization, IDCT, up-sampling and color conversion
0731:                                    // are done on a copy of the coefficient data in order to
0732:                                    // display the image incrementally.
0733:                                    int[] temp = dataUnit;
0734:                                    dataUnit = new int[64];
0735:                                    System.arraycopy(temp, 0, dataUnit, 0, 64);
0736:                                }
0737:                            }
0738:                            if (!progressive
0739:                                    || (progressive && loader.hasListeners())) {
0740:                                dequantize(dataUnit, scanComponent);
0741:                                inverseDCT(dataUnit);
0742:                                storeData(dataUnit, scanComponent, xmcu, ymcu,
0743:                                        hi, ihi, vi, ivi);
0744:                            }
0745:                        }
0746:                    }
0747:                }
0748:            }
0749:
0750:            void decodeScan() {
0751:                if (progressive && !scanHeader.verifyProgressiveScan()) {
0752:                    SWT.error(SWT.ERROR_INVALID_IMAGE);
0753:                }
0754:                int nComponentsInScan = scanHeader.getNumberOfImageComponents();
0755:                int mcuRowsInScan = interleavedMcuRows;
0756:                int mcusPerRow = interleavedMcuCols;
0757:                if (nComponentsInScan == 1) {
0758:                    // Non-interleaved.
0759:                    int scanComponent = 0;
0760:                    while (scanHeader.componentParameters[componentIds[scanComponent]] == null) {
0761:                        scanComponent++;
0762:                    }
0763:                    int[] frameComponent = frameComponents[componentIds[scanComponent]];
0764:                    int hi = frameComponent[HI];
0765:                    int vi = frameComponent[VI];
0766:                    int mcuWidth = DCTSIZE * maxH / hi;
0767:                    int mcuHeight = DCTSIZE * maxV / vi;
0768:                    mcusPerRow = (imageWidth + mcuWidth - 1) / mcuWidth;
0769:                    mcuRowsInScan = (imageHeight + mcuHeight - 1) / mcuHeight;
0770:                }
0771:                boolean first = scanHeader.isFirstScan();
0772:                int start = scanHeader.getStartOfSpectralSelection();
0773:                int end = scanHeader.getEndOfSpectralSelection();
0774:                int approxBit = scanHeader.getApproxBitPositionLow();
0775:                restartsToGo = restartInterval;
0776:                nextRestartNumber = 0;
0777:                for (int ymcu = 0; ymcu < mcuRowsInScan; ymcu++) {
0778:                    for (int xmcu = 0; xmcu < mcusPerRow; xmcu++) {
0779:                        if (restartInterval != 0) {
0780:                            if (restartsToGo == 0)
0781:                                processRestartInterval();
0782:                            restartsToGo--;
0783:                        }
0784:                        decodeMCUAtXAndY(xmcu, ymcu, nComponentsInScan, first,
0785:                                start, end, approxBit);
0786:                    }
0787:                }
0788:            }
0789:
0790:            int decodeUsingTable(JPEGHuffmanTable huffmanTable) {
0791:                int i = 0;
0792:                int[] maxCodes = huffmanTable.getDhMaxCodes();
0793:                int[] minCodes = huffmanTable.getDhMinCodes();
0794:                int[] valPtrs = huffmanTable.getDhValPtrs();
0795:                int[] huffVals = huffmanTable.getDhValues();
0796:                int code = nextBit();
0797:                while (code > maxCodes[i]) {
0798:                    code = code * 2 + nextBit();
0799:                    i++;
0800:                }
0801:                int j = valPtrs[i] + code - minCodes[i];
0802:                return huffVals[j];
0803:            }
0804:
0805:            void emit(int huffCode, int nBits) {
0806:                if (nBits == 0) {
0807:                    SWT.error(SWT.ERROR_INVALID_IMAGE);
0808:                }
0809:                int[] power2m1 = new int[] { 1, 3, 7, 15, 31, 63, 127, 255,
0810:                        511, 1023, 2047, 4095, 8191, 16383, 32767, 65535,
0811:                        131125 };
0812:                int code = (huffCode & power2m1[nBits - 1]) << (24 - nBits - currentBitCount);
0813:                byte[] codeBuffer = new byte[4];
0814:                codeBuffer[0] = (byte) (code & 0xFF);
0815:                codeBuffer[1] = (byte) ((code >> 8) & 0xFF);
0816:                codeBuffer[2] = (byte) ((code >> 16) & 0xFF);
0817:                codeBuffer[3] = (byte) ((code >> 24) & 0xFF);
0818:                int abs = nBits - (8 - currentBitCount);
0819:                if (abs < 0)
0820:                    abs = -abs;
0821:                if ((abs >> 3) > 0) {
0822:                    currentByte += codeBuffer[2];
0823:                    emitByte((byte) currentByte);
0824:                    emitByte(codeBuffer[1]);
0825:                    currentByte = codeBuffer[0];
0826:                    currentBitCount += nBits - 16;
0827:                } else {
0828:                    currentBitCount += nBits;
0829:                    if (currentBitCount >= 8) {
0830:                        currentByte += codeBuffer[2];
0831:                        emitByte((byte) currentByte);
0832:                        currentByte = codeBuffer[1];
0833:                        currentBitCount -= 8;
0834:                    } else {
0835:                        currentByte += codeBuffer[2];
0836:                    }
0837:                }
0838:            }
0839:
0840:            void emitByte(byte byteValue) {
0841:                if (bufferCurrentPosition >= 512) {
0842:                    resetOutputBuffer();
0843:                }
0844:                dataBuffer[bufferCurrentPosition] = byteValue;
0845:                bufferCurrentPosition++;
0846:                if (byteValue == -1) {
0847:                    emitByte((byte) 0);
0848:                }
0849:            }
0850:
0851:            void encodeACCoefficients(int[] dataUnit, int iComp) {
0852:                int[] sParams = scanHeader.componentParameters[iComp];
0853:                JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
0854:                int[] ehCodes = acTable.ehCodes;
0855:                byte[] ehSizes = acTable.ehCodeLengths;
0856:                int r = 0;
0857:                int k = 1;
0858:                while (k < 64) {
0859:                    k++;
0860:                    int acValue = dataUnit[ZigZag8x8[k - 1]];
0861:                    if (acValue == 0) {
0862:                        if (k == 64) {
0863:                            emit(ehCodes[0], ehSizes[0] & 0xFF);
0864:                        } else {
0865:                            r++;
0866:                        }
0867:                    } else {
0868:                        while (r > 15) {
0869:                            emit(ehCodes[0xF0], ehSizes[0xF0] & 0xFF);
0870:                            r -= 16;
0871:                        }
0872:                        if (acValue < 0) {
0873:                            int absACValue = acValue;
0874:                            if (absACValue < 0)
0875:                                absACValue = -absACValue;
0876:                            int nBits = NBitsTable[absACValue];
0877:                            int rs = r * 16 + nBits;
0878:                            emit(ehCodes[rs], ehSizes[rs] & 0xFF);
0879:                            emit(0xFFFFFF - absACValue, nBits);
0880:                        } else {
0881:                            int nBits = NBitsTable[acValue];
0882:                            int rs = r * 16 + nBits;
0883:                            emit(ehCodes[rs], ehSizes[rs] & 0xFF);
0884:                            emit(acValue, nBits);
0885:                        }
0886:                        r = 0;
0887:                    }
0888:                }
0889:            }
0890:
0891:            void encodeDCCoefficients(int[] dataUnit, int iComp) {
0892:                int[] sParams = scanHeader.componentParameters[iComp];
0893:                JPEGHuffmanTable dcTable = dcHuffmanTables[sParams[DC]];
0894:                int lastDC = precedingDCs[iComp];
0895:                int dcValue = dataUnit[0];
0896:                int diff = dcValue - lastDC;
0897:                precedingDCs[iComp] = dcValue;
0898:                if (diff < 0) {
0899:                    int absDiff = 0 - diff;
0900:                    int nBits = NBitsTable[absDiff];
0901:                    emit(dcTable.ehCodes[nBits], dcTable.ehCodeLengths[nBits]);
0902:                    emit(0xFFFFFF - absDiff, nBits);
0903:                } else {
0904:                    int nBits = NBitsTable[diff];
0905:                    emit(dcTable.ehCodes[nBits], dcTable.ehCodeLengths[nBits]);
0906:                    if (nBits != 0) {
0907:                        emit(diff, nBits);
0908:                    }
0909:                }
0910:            }
0911:
0912:            void encodeMCUAtXAndY(int xmcu, int ymcu) {
0913:                int nComponentsInScan = scanHeader.getNumberOfImageComponents();
0914:                dataUnit = new int[64];
0915:                for (int iComp = 0; iComp < nComponentsInScan; iComp++) {
0916:                    int[] frameComponent = frameComponents[componentIds[iComp]];
0917:                    int hi = frameComponent[HI];
0918:                    int vi = frameComponent[VI];
0919:                    for (int ivi = 0; ivi < vi; ivi++) {
0920:                        for (int ihi = 0; ihi < hi; ihi++) {
0921:                            extractData(dataUnit, iComp, xmcu, ymcu, ihi, ivi);
0922:                            forwardDCT(dataUnit);
0923:                            quantizeData(dataUnit, iComp);
0924:                            encodeDCCoefficients(dataUnit, iComp);
0925:                            encodeACCoefficients(dataUnit, iComp);
0926:                        }
0927:                    }
0928:                }
0929:            }
0930:
0931:            void encodeScan() {
0932:                for (int ymcu = 0; ymcu < interleavedMcuRows; ymcu++) {
0933:                    for (int xmcu = 0; xmcu < interleavedMcuCols; xmcu++) {
0934:                        encodeMCUAtXAndY(xmcu, ymcu);
0935:                    }
0936:                }
0937:                if (currentBitCount != 0) {
0938:                    emitByte((byte) currentByte);
0939:                }
0940:                resetOutputBuffer();
0941:            }
0942:
0943:            void expandImageComponents() {
0944:                for (int iComp = 0; iComp < nComponents; iComp++) {
0945:                    int[] frameComponent = frameComponents[componentIds[iComp]];
0946:                    int hi = frameComponent[HI];
0947:                    int vi = frameComponent[VI];
0948:                    int upH = maxH / hi;
0949:                    int upV = maxV / vi;
0950:                    if ((upH * upV) > 1) {
0951:                        byte[] component = imageComponents[iComp];
0952:                        int compWidth = frameComponent[CW];
0953:                        int compHeight = frameComponent[CH];
0954:                        int upCompWidth = compWidth * upH;
0955:                        int upCompHeight = compHeight * upV;
0956:                        ImageData src = new ImageData(compWidth, compHeight, 8,
0957:                                new PaletteData(RGB16), 4, component);
0958:                        ImageData dest = src
0959:                                .scaledTo(upCompWidth, upCompHeight);
0960:                        imageComponents[iComp] = dest.data;
0961:                    }
0962:                }
0963:            }
0964:
0965:            int extendBy(int diff, int t) {
0966:                if (diff < ExtendTest[t]) {
0967:                    return diff + ExtendOffset[t];
0968:                } else {
0969:                    return diff;
0970:                }
0971:            }
0972:
0973:            void extractData(int[] dataUnit, int iComp, int xmcu, int ymcu,
0974:                    int ihi, int ivi) {
0975:                byte[] compImage = imageComponents[iComp];
0976:                int[] frameComponent = frameComponents[componentIds[iComp]];
0977:                int hi = frameComponent[HI];
0978:                int vi = frameComponent[VI];
0979:                int compWidth = frameComponent[CW];
0980:                int srcIndex = ((ymcu * vi + ivi) * compWidth * DCTSIZE)
0981:                        + ((xmcu * hi + ihi) * DCTSIZE);
0982:                int destIndex = 0;
0983:                for (int i = 0; i < DCTSIZE; i++) {
0984:                    for (int col = 0; col < DCTSIZE; col++) {
0985:                        dataUnit[destIndex] = (compImage[srcIndex + col] & 0xFF) - 128;
0986:                        destIndex++;
0987:                    }
0988:                    srcIndex += compWidth;
0989:                }
0990:            }
0991:
0992:            void forwardDCT(int[] dataUnit) {
0993:                for (int row = 0; row < 8; row++) {
0994:                    int rIndex = row * DCTSIZE;
0995:                    int tmp0 = dataUnit[rIndex] + dataUnit[rIndex + 7];
0996:                    int tmp7 = dataUnit[rIndex] - dataUnit[rIndex + 7];
0997:                    int tmp1 = dataUnit[rIndex + 1] + dataUnit[rIndex + 6];
0998:                    int tmp6 = dataUnit[rIndex + 1] - dataUnit[rIndex + 6];
0999:                    int tmp2 = dataUnit[rIndex + 2] + dataUnit[rIndex + 5];
1000:                    int tmp5 = dataUnit[rIndex + 2] - dataUnit[rIndex + 5];
1001:                    int tmp3 = dataUnit[rIndex + 3] + dataUnit[rIndex + 4];
1002:                    int tmp4 = dataUnit[rIndex + 3] - dataUnit[rIndex + 4];
1003:
1004:                    /**
1005:                     * Even part per LL&M figure 1 --- note that published figure 
1006:                     * is faulty; rotator 'sqrt(2)*c1' should be 'sqrt(2)*c6'.
1007:                     */
1008:                    int tmp10 = tmp0 + tmp3;
1009:                    int tmp13 = tmp0 - tmp3;
1010:                    int tmp11 = tmp1 + tmp2;
1011:                    int tmp12 = tmp1 - tmp2;
1012:
1013:                    dataUnit[rIndex] = (tmp10 + tmp11) * 4;
1014:                    dataUnit[rIndex + 4] = (tmp10 - tmp11) * 4;
1015:
1016:                    int z1 = (tmp12 + tmp13) * FIX_0_541196100;
1017:                    int n = z1 + (tmp13 * FIX_0_765366865) + 1024;
1018:                    dataUnit[rIndex + 2] = n >> 11;
1019:                    if ((n < 0) && ((n & 0x07FF) != 0))
1020:                        dataUnit[rIndex + 2]--;
1021:                    n = z1 + (tmp12 * (0 - FIX_1_847759065)) + 1024;
1022:                    dataUnit[rIndex + 6] = n >> 11;
1023:                    if ((n < 0) && ((n & 0x07FF) != 0))
1024:                        dataUnit[rIndex + 6]--;
1025:
1026:                    /**
1027:                     * Odd part per figure 8 --- note paper omits factor of sqrt(2).
1028:                     * cK represents cos(K*pi/16).
1029:                     * i0..i3 in the paper are tmp4..tmp7 here.
1030:                     */
1031:                    z1 = tmp4 + tmp7;
1032:                    int z2 = tmp5 + tmp6;
1033:                    int z3 = tmp4 + tmp6;
1034:                    int z4 = tmp5 + tmp7;
1035:                    int z5 = (z3 + z4) * FIX_1_175875602; // sqrt(2) * c3
1036:
1037:                    tmp4 *= FIX_0_298631336; // sqrt(2) * (-c1+c3+c5-c7)
1038:                    tmp5 *= FIX_2_053119869; // sqrt(2) * ( c1+c3-c5+c7)
1039:                    tmp6 *= FIX_3_072711026; // sqrt(2) * ( c1+c3+c5-c7)
1040:                    tmp7 *= FIX_1_501321110; // sqrt(2) * ( c1+c3-c5-c7)
1041:                    z1 *= 0 - FIX_0_899976223; // sqrt(2) * (c7-c3)
1042:                    z2 *= 0 - FIX_2_562915447; // sqrt(2) * (-c1-c3)
1043:                    z3 *= 0 - FIX_1_961570560; // sqrt(2) * (-c3-c5)
1044:                    z4 *= 0 - FIX_0_390180644; // sqrt(2) * (c5-c3)
1045:
1046:                    z3 += z5;
1047:                    z4 += z5;
1048:
1049:                    n = tmp4 + z1 + z3 + 1024;
1050:                    dataUnit[rIndex + 7] = n >> 11;
1051:                    if ((n < 0) && ((n & 0x07FF) != 0))
1052:                        dataUnit[rIndex + 7]--;
1053:                    n = tmp5 + z2 + z4 + 1024;
1054:                    dataUnit[rIndex + 5] = n >> 11;
1055:                    if ((n < 0) && ((n & 0x07FF) != 0))
1056:                        dataUnit[rIndex + 5]--;
1057:                    n = tmp6 + z2 + z3 + 1024;
1058:                    dataUnit[rIndex + 3] = n >> 11;
1059:                    if ((n < 0) && ((n & 0x07FF) != 0))
1060:                        dataUnit[rIndex + 3]--;
1061:                    n = tmp7 + z1 + z4 + 1024;
1062:                    dataUnit[rIndex + 1] = n >> 11;
1063:                    if ((n < 0) && ((n & 0x07FF) != 0))
1064:                        dataUnit[rIndex + 1]--;
1065:                }
1066:
1067:                /**
1068:                 * Pass 2: process columns.
1069:                 * Note that we must descale the results by a factor of 8 == 2**3,
1070:                 * and also undo the PASS1_BITS scaling.
1071:                 */
1072:                for (int col = 0; col < 8; col++) {
1073:                    int c0 = col;
1074:                    int c1 = col + 8;
1075:                    int c2 = col + 16;
1076:                    int c3 = col + 24;
1077:                    int c4 = col + 32;
1078:                    int c5 = col + 40;
1079:                    int c6 = col + 48;
1080:                    int c7 = col + 56;
1081:                    int tmp0 = dataUnit[c0] + dataUnit[c7];
1082:                    int tmp7 = dataUnit[c0] - dataUnit[c7];
1083:                    int tmp1 = dataUnit[c1] + dataUnit[c6];
1084:                    int tmp6 = dataUnit[c1] - dataUnit[c6];
1085:                    int tmp2 = dataUnit[c2] + dataUnit[c5];
1086:                    int tmp5 = dataUnit[c2] - dataUnit[c5];
1087:                    int tmp3 = dataUnit[c3] + dataUnit[c4];
1088:                    int tmp4 = dataUnit[c3] - dataUnit[c4];
1089:
1090:                    /**
1091:                     * Even part per LL&M figure 1 --- note that published figure 
1092:                     * is faulty; rotator 'sqrt(2)*c1' should be 'sqrt(2)*c6'.
1093:                     */
1094:                    int tmp10 = tmp0 + tmp3;
1095:                    int tmp13 = tmp0 - tmp3;
1096:                    int tmp11 = tmp1 + tmp2;
1097:                    int tmp12 = tmp1 - tmp2;
1098:
1099:                    int n = tmp10 + tmp11 + 16;
1100:                    dataUnit[c0] = n >> 5;
1101:                    if ((n < 0) && ((n & 0x1F) != 0))
1102:                        dataUnit[c0]--;
1103:                    n = tmp10 - tmp11 + 16;
1104:                    dataUnit[c4] = n >> 5;
1105:                    if ((n < 0) && ((n & 0x1F) != 0))
1106:                        dataUnit[c4]--;
1107:
1108:                    int z1 = (tmp12 + tmp13) * FIX_0_541196100;
1109:                    n = z1 + (tmp13 * FIX_0_765366865) + 131072;
1110:                    dataUnit[c2] = n >> 18;
1111:                    if ((n < 0) && ((n & 0x3FFFF) != 0))
1112:                        dataUnit[c2]--;
1113:                    n = z1 + (tmp12 * (0 - FIX_1_847759065)) + 131072;
1114:                    dataUnit[c6] = n >> 18;
1115:                    if ((n < 0) && ((n & 0x3FFFF) != 0))
1116:                        dataUnit[c6]--;
1117:
1118:                    /**
1119:                     * Odd part per figure 8 --- note paper omits factor of sqrt(2).
1120:                     * cK represents cos(K*pi/16).
1121:                     * i0..i3 in the paper are tmp4..tmp7 here.
1122:                     */
1123:                    z1 = tmp4 + tmp7;
1124:                    int z2 = tmp5 + tmp6;
1125:                    int z3 = tmp4 + tmp6;
1126:                    int z4 = tmp5 + tmp7;
1127:                    int z5 = (z3 + z4) * FIX_1_175875602; // sqrt(2) * c3
1128:
1129:                    tmp4 *= FIX_0_298631336; // sqrt(2) * (-c1+c3+c5-c7)
1130:                    tmp5 *= FIX_2_053119869; // sqrt(2) * ( c1+c3-c5+c7)
1131:                    tmp6 *= FIX_3_072711026; // sqrt(2) * ( c1+c3+c5-c7)
1132:                    tmp7 *= FIX_1_501321110; // sqrt(2) * ( c1+c3-c5-c7)
1133:                    z1 *= 0 - FIX_0_899976223; // sqrt(2) * (c7-c3)
1134:                    z2 *= 0 - FIX_2_562915447; // sqrt(2) * (-c1-c3)
1135:                    z3 *= 0 - FIX_1_961570560; // sqrt(2) * (-c3-c5)
1136:                    z4 *= 0 - FIX_0_390180644; // sqrt(2) * (c5-c3)
1137:
1138:                    z3 += z5;
1139:                    z4 += z5;
1140:
1141:                    n = tmp4 + z1 + z3 + 131072;
1142:                    dataUnit[c7] = n >> 18;
1143:                    if ((n < 0) && ((n & 0x3FFFF) != 0))
1144:                        dataUnit[c7]--;
1145:                    n = tmp5 + z2 + z4 + 131072;
1146:                    dataUnit[c5] = n >> 18;
1147:                    if ((n < 0) && ((n & 0x3FFFF) != 0))
1148:                        dataUnit[c5]--;
1149:                    n = tmp6 + z2 + z3 + 131072;
1150:                    dataUnit[c3] = n >> 18;
1151:                    if ((n < 0) && ((n & 0x3FFFF) != 0))
1152:                        dataUnit[c3]--;
1153:                    n = tmp7 + z1 + z4 + 131072;
1154:                    dataUnit[c1] = n >> 18;
1155:                    if ((n < 0) && ((n & 0x3FFFF) != 0))
1156:                        dataUnit[c1]--;
1157:                }
1158:            }
1159:
1160:            void getAPP0() {
1161:                JPEGAppn appn = new JPEGAppn(inputStream);
1162:                if (!appn.verify()) {
1163:                    SWT.error(SWT.ERROR_INVALID_IMAGE);
1164:                }
1165:            }
1166:
1167:            void getCOM() {
1168:                new JPEGComment(inputStream);
1169:            }
1170:
1171:            void getDAC() {
1172:                new JPEGArithmeticConditioningTable(inputStream);
1173:            }
1174:
1175:            void getDHT() {
1176:                JPEGHuffmanTable dht = new JPEGHuffmanTable(inputStream);
1177:                if (!dht.verify()) {
1178:                    SWT.error(SWT.ERROR_INVALID_IMAGE);
1179:                }
1180:                if (acHuffmanTables == null) {
1181:                    acHuffmanTables = new JPEGHuffmanTable[4];
1182:                }
1183:                if (dcHuffmanTables == null) {
1184:                    dcHuffmanTables = new JPEGHuffmanTable[4];
1185:                }
1186:                JPEGHuffmanTable[] dhtTables = dht.getAllTables();
1187:                for (int i = 0; i < dhtTables.length; i++) {
1188:                    JPEGHuffmanTable dhtTable = dhtTables[i];
1189:                    if (dhtTable.getTableClass() == 0) {
1190:                        dcHuffmanTables[dhtTable.getTableIdentifier()] = dhtTable;
1191:                    } else {
1192:                        acHuffmanTables[dhtTable.getTableIdentifier()] = dhtTable;
1193:                    }
1194:                }
1195:            }
1196:
1197:            void getDNL() {
1198:                new JPEGRestartInterval(inputStream);
1199:            }
1200:
1201:            void getDQT() {
1202:                JPEGQuantizationTable dqt = new JPEGQuantizationTable(
1203:                        inputStream);
1204:                int[][] currentTables = quantizationTables;
1205:                if (currentTables == null) {
1206:                    currentTables = new int[4][];
1207:                }
1208:                int[] dqtTablesKeys = dqt.getQuantizationTablesKeys();
1209:                int[][] dqtTablesValues = dqt.getQuantizationTablesValues();
1210:                for (int i = 0; i < dqtTablesKeys.length; i++) {
1211:                    int index = dqtTablesKeys[i];
1212:                    currentTables[index] = dqtTablesValues[i];
1213:                }
1214:                quantizationTables = currentTables;
1215:            }
1216:
1217:            void getDRI() {
1218:                JPEGRestartInterval dri = new JPEGRestartInterval(inputStream);
1219:                if (!dri.verify()) {
1220:                    SWT.error(SWT.ERROR_INVALID_IMAGE);
1221:                }
1222:                restartInterval = dri.getRestartInterval();
1223:            }
1224:
1225:            static void initialize() {
1226:                initializeRGBYCbCrTables();
1227:                initializeYCbCrRGBTables();
1228:                initializeBitCountTable();
1229:            }
1230:
1231:            static void initializeBitCountTable() {
1232:                int nBits = 1;
1233:                int power2 = 2;
1234:                NBitsTable = new int[2048];
1235:                NBitsTable[0] = 0;
1236:                for (int i = 1; i < NBitsTable.length; i++) {
1237:                    if (!(i < power2)) {
1238:                        nBits++;
1239:                        power2 *= 2;
1240:                    }
1241:                    NBitsTable[i] = nBits;
1242:                }
1243:            }
1244:
1245:            static void initializeRGBYCbCrTables() {
1246:                RYTable = new int[256];
1247:                GYTable = new int[256];
1248:                BYTable = new int[256];
1249:                RCbTable = new int[256];
1250:                GCbTable = new int[256];
1251:                BCbTable = new int[256];
1252:                RCrTable = BCbTable;
1253:                GCrTable = new int[256];
1254:                BCrTable = new int[256];
1255:                for (int i = 0; i < 256; i++) {
1256:                    RYTable[i] = i * 19595;
1257:                    GYTable[i] = i * 38470;
1258:                    BYTable[i] = i * 7471 + 32768;
1259:                    RCbTable[i] = i * -11059;
1260:                    GCbTable[i] = i * -21709;
1261:                    BCbTable[i] = i * 32768 + 8388608;
1262:                    GCrTable[i] = i * -27439;
1263:                    BCrTable[i] = i * -5329;
1264:                }
1265:            }
1266:
1267:            static void initializeYCbCrRGBTables() {
1268:                CrRTable = new int[256];
1269:                CbBTable = new int[256];
1270:                CrGTable = new int[256];
1271:                CbGTable = new int[256];
1272:                for (int i = 0; i < 256; i++) {
1273:                    int x2 = 2 * i - 255;
1274:                    CrRTable[i] = (45941 * x2 + 32768) >> 16;
1275:                    CbBTable[i] = (58065 * x2 + 32768) >> 16;
1276:                    CrGTable[i] = -23401 * x2;
1277:                    CbGTable[i] = -11277 * x2 + 32768;
1278:                }
1279:            }
1280:
1281:            void inverseDCT(int[] dataUnit) {
1282:                for (int row = 0; row < 8; row++) {
1283:                    int rIndex = row * DCTSIZE;
1284:                    /**
1285:                     * Due to quantization, we will usually find that many of the input
1286:                     * coefficients are zero, especially the AC terms.  We can exploit this
1287:                     * by short-circuiting the IDCT calculation for any row in which all
1288:                     * the AC terms are zero.  In that case each output is equal to the
1289:                     * DC coefficient (with scale factor as needed).
1290:                     * With typical images and quantization tables, half or more of the
1291:                     * row DCT calculations can be simplified this way.
1292:                     */
1293:                    if (isZeroInRow(dataUnit, rIndex)) {
1294:                        int dcVal = dataUnit[rIndex] << 2;
1295:                        for (int i = rIndex + 7; i >= rIndex; i--) {
1296:                            dataUnit[i] = dcVal;
1297:                        }
1298:                    } else {
1299:                        /**
1300:                         * Even part: reverse the even part of the forward DCT.
1301:                         * The rotator is sqrt(2)*c(-6).
1302:                         */
1303:                        int z2 = dataUnit[rIndex + 2];
1304:                        int z3 = dataUnit[rIndex + 6];
1305:                        int z1 = (z2 + z3) * FIX_0_541196100;
1306:                        int tmp2 = z1 + (z3 * (0 - FIX_1_847759065));
1307:                        int tmp3 = z1 + (z2 * FIX_0_765366865);
1308:                        int tmp0 = (dataUnit[rIndex] + dataUnit[rIndex + 4]) << 13;
1309:                        int tmp1 = (dataUnit[rIndex] - dataUnit[rIndex + 4]) << 13;
1310:                        int tmp10 = tmp0 + tmp3;
1311:                        int tmp13 = tmp0 - tmp3;
1312:                        int tmp11 = tmp1 + tmp2;
1313:                        int tmp12 = tmp1 - tmp2;
1314:                        /**
1315:                         * Odd part per figure 8; the matrix is unitary and hence its
1316:                         * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
1317:                         */
1318:                        tmp0 = dataUnit[rIndex + 7];
1319:                        tmp1 = dataUnit[rIndex + 5];
1320:                        tmp2 = dataUnit[rIndex + 3];
1321:                        tmp3 = dataUnit[rIndex + 1];
1322:                        z1 = tmp0 + tmp3;
1323:                        z2 = tmp1 + tmp2;
1324:                        z3 = tmp0 + tmp2;
1325:                        int z4 = tmp1 + tmp3;
1326:                        int z5 = (z3 + z4) * FIX_1_175875602; /* sqrt(2) * c3 */
1327:
1328:                        tmp0 *= FIX_0_298631336; /* sqrt(2) * (-c1+c3+c5-c7) */
1329:                        tmp1 *= FIX_2_053119869; /* sqrt(2) * ( c1+c3-c5+c7) */
1330:                        tmp2 *= FIX_3_072711026; /* sqrt(2) * ( c1+c3+c5-c7) */
1331:                        tmp3 *= FIX_1_501321110; /* sqrt(2) * ( c1+c3-c5-c7) */
1332:                        z1 *= 0 - FIX_0_899976223; /* sqrt(2) * (c7-c3) */
1333:                        z2 *= 0 - FIX_2_562915447; /* sqrt(2) * (-c1-c3) */
1334:                        z3 *= 0 - FIX_1_961570560; /* sqrt(2) * (-c3-c5) */
1335:                        z4 *= 0 - FIX_0_390180644; /* sqrt(2) * (c5-c3) */
1336:
1337:                        z3 += z5;
1338:                        z4 += z5;
1339:                        tmp0 += z1 + z3;
1340:                        tmp1 += z2 + z4;
1341:                        tmp2 += z2 + z3;
1342:                        tmp3 += z1 + z4;
1343:
1344:                        dataUnit[rIndex] = (tmp10 + tmp3 + 1024) >> 11;
1345:                        dataUnit[rIndex + 7] = (tmp10 - tmp3 + 1024) >> 11;
1346:                        dataUnit[rIndex + 1] = (tmp11 + tmp2 + 1024) >> 11;
1347:                        dataUnit[rIndex + 6] = (tmp11 - tmp2 + 1024) >> 11;
1348:                        dataUnit[rIndex + 2] = (tmp12 + tmp1 + 1024) >> 11;
1349:                        dataUnit[rIndex + 5] = (tmp12 - tmp1 + 1024) >> 11;
1350:                        dataUnit[rIndex + 3] = (tmp13 + tmp0 + 1024) >> 11;
1351:                        dataUnit[rIndex + 4] = (tmp13 - tmp0 + 1024) >> 11;
1352:                    }
1353:                }
1354:                /**
1355:                 * Pass 2: process columns.
1356:                 * Note that we must descale the results by a factor of 8 == 2**3,
1357:                 * and also undo the PASS1_BITS scaling.
1358:                 */
1359:                for (int col = 0; col < 8; col++) {
1360:                    int c0 = col;
1361:                    int c1 = col + 8;
1362:                    int c2 = col + 16;
1363:                    int c3 = col + 24;
1364:                    int c4 = col + 32;
1365:                    int c5 = col + 40;
1366:                    int c6 = col + 48;
1367:                    int c7 = col + 56;
1368:                    if (isZeroInColumn(dataUnit, col)) {
1369:                        int dcVal = (dataUnit[c0] + 16) >> 5;
1370:                        dataUnit[c0] = dcVal;
1371:                        dataUnit[c1] = dcVal;
1372:                        dataUnit[c2] = dcVal;
1373:                        dataUnit[c3] = dcVal;
1374:                        dataUnit[c4] = dcVal;
1375:                        dataUnit[c5] = dcVal;
1376:                        dataUnit[c6] = dcVal;
1377:                        dataUnit[c7] = dcVal;
1378:                    } else {
1379:                        /**
1380:                         * Even part: reverse the even part of the forward DCT.
1381:                         * The rotator is sqrt(2)*c(-6).
1382:                         */
1383:                        int z0 = dataUnit[c0];
1384:                        int z2 = dataUnit[c2];
1385:                        int z3 = dataUnit[c6];
1386:                        int z4 = dataUnit[c4];
1387:                        int z1 = (z2 + z3) * FIX_0_541196100;
1388:                        int tmp2 = z1 + (z3 * (0 - FIX_1_847759065));
1389:                        int tmp3 = z1 + (z2 * FIX_0_765366865);
1390:                        int tmp0 = (z0 + z4) << 13;
1391:                        int tmp1 = (z0 - z4) << 13;
1392:                        int tmp10 = tmp0 + tmp3;
1393:                        int tmp13 = tmp0 - tmp3;
1394:                        int tmp11 = tmp1 + tmp2;
1395:                        int tmp12 = tmp1 - tmp2;
1396:                        /**
1397:                         * Odd part per figure 8; the matrix is unitary and hence its
1398:                         * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
1399:                         */
1400:                        tmp0 = dataUnit[c7];
1401:                        tmp1 = dataUnit[c5];
1402:                        tmp2 = dataUnit[c3];
1403:                        tmp3 = dataUnit[c1];
1404:                        z1 = tmp0 + tmp3;
1405:                        z2 = tmp1 + tmp2;
1406:                        z3 = tmp0 + tmp2;
1407:                        z4 = tmp1 + tmp3;
1408:                        z0 = (z3 + z4) * FIX_1_175875602; /* sqrt(2) * c3 */
1409:
1410:                        tmp0 *= FIX_0_298631336; /* sqrt(2) * (-c1+c3+c5-c7) */
1411:                        tmp1 *= FIX_2_053119869; /* sqrt(2) * ( c1+c3-c5+c7) */
1412:                        tmp2 *= FIX_3_072711026; /* sqrt(2) * ( c1+c3+c5-c7) */
1413:                        tmp3 *= FIX_1_501321110; /* sqrt(2) * ( c1+c3-c5-c7) */
1414:                        z1 *= 0 - FIX_0_899976223; /* sqrt(2) * (c7-c3) */
1415:                        z2 *= 0 - FIX_2_562915447; /* sqrt(2) * (-c1-c3) */
1416:                        z3 *= 0 - FIX_1_961570560; /* sqrt(2) * (-c3-c5) */
1417:                        z4 *= 0 - FIX_0_390180644; /* sqrt(2) * (c5-c3) */
1418:
1419:                        z3 += z0;
1420:                        z4 += z0;
1421:
1422:                        tmp0 += z1 + z3;
1423:                        tmp1 += z2 + z4;
1424:                        tmp2 += z2 + z3;
1425:                        tmp3 += z1 + z4;
1426:
1427:                        /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
1428:                        dataUnit[c0] = (tmp10 + tmp3 + 131072) >> 18;
1429:                        dataUnit[c7] = (tmp10 - tmp3 + 131072) >> 18;
1430:                        dataUnit[c1] = (tmp11 + tmp2 + 131072) >> 18;
1431:                        dataUnit[c6] = (tmp11 - tmp2 + 131072) >> 18;
1432:                        dataUnit[c2] = (tmp12 + tmp1 + 131072) >> 18;
1433:                        dataUnit[c5] = (tmp12 - tmp1 + 131072) >> 18;
1434:                        dataUnit[c3] = (tmp13 + tmp0 + 131072) >> 18;
1435:                        dataUnit[c4] = (tmp13 - tmp0 + 131072) >> 18;
1436:                    }
1437:                }
1438:            }
1439:
1440:            boolean isFileFormat(LEDataInputStream stream) {
1441:                try {
1442:                    JPEGStartOfImage soi = new JPEGStartOfImage(stream);
1443:                    stream.unread(soi.reference);
1444:                    return soi.verify(); // we no longer check for appN
1445:                } catch (Exception e) {
1446:                    return false;
1447:                }
1448:            }
1449:
1450:            boolean isZeroInColumn(int[] dataUnit, int col) {
1451:                return dataUnit[col + 8] == 0 && dataUnit[col + 16] == 0
1452:                        && dataUnit[col + 24] == 0 && dataUnit[col + 32] == 0
1453:                        && dataUnit[col + 40] == 0 && dataUnit[col + 48] == 0
1454:                        && dataUnit[col + 56] == 0;
1455:            }
1456:
1457:            boolean isZeroInRow(int[] dataUnit, int rIndex) {
1458:                return dataUnit[rIndex + 1] == 0 && dataUnit[rIndex + 2] == 0
1459:                        && dataUnit[rIndex + 3] == 0
1460:                        && dataUnit[rIndex + 4] == 0
1461:                        && dataUnit[rIndex + 5] == 0
1462:                        && dataUnit[rIndex + 6] == 0
1463:                        && dataUnit[rIndex + 7] == 0;
1464:            }
1465:
1466:            ImageData[] loadFromByteStream() {
1467:                //TEMPORARY CODE
1468:                if (System
1469:                        .getProperty("org.eclipse.swt.internal.image.JPEGFileFormat_3.2") == null) {
1470:                    return JPEGDecoder.loadFromByteStream(inputStream, loader);
1471:                }
1472:                JPEGStartOfImage soi = new JPEGStartOfImage(inputStream);
1473:                if (!soi.verify())
1474:                    SWT.error(SWT.ERROR_INVALID_IMAGE);
1475:                restartInterval = 0;
1476:
1477:                /* Process the tables preceding the frame header. */
1478:                processTables();
1479:
1480:                /* Start of Frame. */
1481:                frameHeader = new JPEGFrameHeader(inputStream);
1482:                if (!frameHeader.verify())
1483:                    SWT.error(SWT.ERROR_INVALID_IMAGE);
1484:                imageWidth = frameHeader.getSamplesPerLine();
1485:                imageHeight = frameHeader.getNumberOfLines();
1486:                maxH = frameHeader.getMaxHFactor();
1487:                maxV = frameHeader.getMaxVFactor();
1488:                int mcuWidth = maxH * DCTSIZE;
1489:                int mcuHeight = maxV * DCTSIZE;
1490:                interleavedMcuCols = (imageWidth + mcuWidth - 1) / mcuWidth;
1491:                interleavedMcuRows = (imageHeight + mcuHeight - 1) / mcuHeight;
1492:                progressive = frameHeader.isProgressive();
1493:                samplePrecision = frameHeader.getSamplePrecision();
1494:                nComponents = frameHeader.getNumberOfImageComponents();
1495:                frameComponents = frameHeader.componentParameters;
1496:                componentIds = frameHeader.componentIdentifiers;
1497:                imageComponents = new byte[nComponents][];
1498:                if (progressive) {
1499:                    // Progressive jpeg: need to keep all of the data units.
1500:                    dataUnits = new int[nComponents][][];
1501:                } else {
1502:                    // Sequential jpeg: only need one data unit.
1503:                    dataUnit = new int[8 * 8];
1504:                }
1505:                for (int i = 0; i < nComponents; i++) {
1506:                    int[] frameComponent = frameComponents[componentIds[i]];
1507:                    int bufferSize = frameComponent[CW] * frameComponent[CH];
1508:                    imageComponents[i] = new byte[bufferSize];
1509:                    if (progressive) {
1510:                        dataUnits[i] = new int[bufferSize][];
1511:                    }
1512:                }
1513:
1514:                /* Process the tables preceding the scan header. */
1515:                processTables();
1516:
1517:                /* Start of Scan. */
1518:                scanHeader = new JPEGScanHeader(inputStream);
1519:                if (!scanHeader.verify())
1520:                    SWT.error(SWT.ERROR_INVALID_IMAGE);
1521:
1522:                /* Process scan(s) and further tables until EOI. */
1523:                int progressiveScanCount = 0;
1524:                boolean done = false;
1525:                while (!done) {
1526:                    resetInputBuffer();
1527:                    precedingDCs = new int[4];
1528:                    decodeScan();
1529:                    if (progressive && loader.hasListeners()) {
1530:                        ImageData imageData = createImageData();
1531:                        loader.notifyListeners(new ImageLoaderEvent(loader,
1532:                                imageData, progressiveScanCount, false));
1533:                        progressiveScanCount++;
1534:                    }
1535:
1536:                    /* Unread any buffered data before looking for tables again. */
1537:                    int delta = 512 - bufferCurrentPosition - 1;
1538:                    if (delta > 0) {
1539:                        byte[] unreadBuffer = new byte[delta];
1540:                        System.arraycopy(dataBuffer, bufferCurrentPosition + 1,
1541:                                unreadBuffer, 0, delta);
1542:                        try {
1543:                            inputStream.unread(unreadBuffer);
1544:                        } catch (IOException e) {
1545:                            SWT.error(SWT.ERROR_IO, e);
1546:                        }
1547:                    }
1548:
1549:                    /* Process the tables preceding the next scan header. */
1550:                    JPEGSegment jpegSegment = processTables();
1551:                    if (jpegSegment == null
1552:                            || jpegSegment.getSegmentMarker() == EOI) {
1553:                        done = true;
1554:                    } else {
1555:                        scanHeader = new JPEGScanHeader(inputStream);
1556:                        if (!scanHeader.verify())
1557:                            SWT.error(SWT.ERROR_INVALID_IMAGE);
1558:                    }
1559:                }
1560:
1561:                if (progressive) {
1562:                    for (int ymcu = 0; ymcu < interleavedMcuRows; ymcu++) {
1563:                        for (int xmcu = 0; xmcu < interleavedMcuCols; xmcu++) {
1564:                            for (int iComp = 0; iComp < nComponents; iComp++) {
1565:                                int[] frameComponent = frameComponents[componentIds[iComp]];
1566:                                int hi = frameComponent[HI];
1567:                                int vi = frameComponent[VI];
1568:                                int compWidth = frameComponent[CW];
1569:                                for (int ivi = 0; ivi < vi; ivi++) {
1570:                                    for (int ihi = 0; ihi < hi; ihi++) {
1571:                                        int index = (ymcu * vi + ivi)
1572:                                                * compWidth + xmcu * hi + ihi;
1573:                                        dataUnit = dataUnits[iComp][index];
1574:                                        dequantize(dataUnit, iComp);
1575:                                        inverseDCT(dataUnit);
1576:                                        storeData(dataUnit, iComp, xmcu, ymcu,
1577:                                                hi, ihi, vi, ivi);
1578:                                    }
1579:                                }
1580:                            }
1581:                        }
1582:                    }
1583:                    dataUnits = null; // release memory
1584:                }
1585:                ImageData imageData = createImageData();
1586:                if (progressive && loader.hasListeners()) {
1587:                    loader.notifyListeners(new ImageLoaderEvent(loader,
1588:                            imageData, progressiveScanCount, true));
1589:                }
1590:                return new ImageData[] { imageData };
1591:            }
1592:
1593:            ImageData createImageData() {
1594:                return ImageData.internal_new(imageWidth, imageHeight,
1595:                        nComponents * samplePrecision, setUpPalette(),
1596:                        nComponents == 1 ? 4 : 1, decodeImageComponents(), 0,
1597:                        null, null, -1, -1, SWT.IMAGE_JPEG, 0, 0, 0, 0);
1598:            }
1599:
1600:            int nextBit() {
1601:                if (currentBitCount != 0) {
1602:                    currentBitCount--;
1603:                    currentByte *= 2;
1604:                    if (currentByte > 255) {
1605:                        currentByte -= 256;
1606:                        return 1;
1607:                    } else {
1608:                        return 0;
1609:                    }
1610:                }
1611:                bufferCurrentPosition++;
1612:                if (bufferCurrentPosition >= 512) {
1613:                    resetInputBuffer();
1614:                    bufferCurrentPosition = 0;
1615:                }
1616:                currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
1617:                currentBitCount = 8;
1618:                byte nextByte;
1619:                if (bufferCurrentPosition == 511) {
1620:                    resetInputBuffer();
1621:                    currentBitCount = 8;
1622:                    nextByte = dataBuffer[0];
1623:                } else {
1624:                    nextByte = dataBuffer[bufferCurrentPosition + 1];
1625:                }
1626:                if (currentByte == 0xFF) {
1627:                    if (nextByte == 0) {
1628:                        bufferCurrentPosition++;
1629:                        currentBitCount--;
1630:                        currentByte *= 2;
1631:                        if (currentByte > 255) {
1632:                            currentByte -= 256;
1633:                            return 1;
1634:                        } else {
1635:                            return 0;
1636:                        }
1637:                    } else {
1638:                        if ((nextByte & 0xFF) + 0xFF00 == DNL) {
1639:                            getDNL();
1640:                            return 0;
1641:                        } else {
1642:                            SWT.error(SWT.ERROR_INVALID_IMAGE);
1643:                            return 0;
1644:                        }
1645:                    }
1646:                } else {
1647:                    currentBitCount--;
1648:                    currentByte *= 2;
1649:                    if (currentByte > 255) {
1650:                        currentByte -= 256;
1651:                        return 1;
1652:                    } else {
1653:                        return 0;
1654:                    }
1655:                }
1656:            }
1657:
1658:            void processRestartInterval() {
1659:                do {
1660:                    bufferCurrentPosition++;
1661:                    if (bufferCurrentPosition > 511) {
1662:                        resetInputBuffer();
1663:                        bufferCurrentPosition = 0;
1664:                    }
1665:                    currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
1666:                } while (currentByte != 0xFF);
1667:                while (currentByte == 0xFF) {
1668:                    bufferCurrentPosition++;
1669:                    if (bufferCurrentPosition > 511) {
1670:                        resetInputBuffer();
1671:                        bufferCurrentPosition = 0;
1672:                    }
1673:                    currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
1674:                }
1675:                if (currentByte != ((RST0 + nextRestartNumber) & 0xFF)) {
1676:                    SWT.error(SWT.ERROR_INVALID_IMAGE);
1677:                }
1678:                bufferCurrentPosition++;
1679:                if (bufferCurrentPosition > 511) {
1680:                    resetInputBuffer();
1681:                    bufferCurrentPosition = 0;
1682:                }
1683:                currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
1684:                currentBitCount = 8;
1685:                restartsToGo = restartInterval;
1686:                nextRestartNumber = (nextRestartNumber + 1) & 0x7;
1687:                precedingDCs = new int[4];
1688:                eobrun = 0;
1689:            }
1690:
1691:            /* Process all markers until a frame header, scan header, or EOI is found. */
1692:            JPEGSegment processTables() {
1693:                while (true) {
1694:                    JPEGSegment jpegSegment = seekUnspecifiedMarker(inputStream);
1695:                    if (jpegSegment == null)
1696:                        return null;
1697:                    JPEGFrameHeader sof = new JPEGFrameHeader(
1698:                            jpegSegment.reference);
1699:                    if (sof.verify()) {
1700:                        return jpegSegment;
1701:                    }
1702:                    int marker = jpegSegment.getSegmentMarker();
1703:                    switch (marker) {
1704:                    case SOI: // there should only be one SOI per file
1705:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
1706:                    case EOI:
1707:                    case SOS:
1708:                        return jpegSegment;
1709:                    case DQT:
1710:                        getDQT();
1711:                        break;
1712:                    case DHT:
1713:                        getDHT();
1714:                        break;
1715:                    case DAC:
1716:                        getDAC();
1717:                        break;
1718:                    case DRI:
1719:                        getDRI();
1720:                        break;
1721:                    case APP0:
1722:                        getAPP0();
1723:                        break;
1724:                    case COM:
1725:                        getCOM();
1726:                        break;
1727:                    default:
1728:                        skipSegmentFrom(inputStream);
1729:
1730:                    }
1731:                }
1732:            }
1733:
1734:            void quantizeData(int[] dataUnit, int iComp) {
1735:                int[] qTable = quantizationTables[frameComponents[componentIds[iComp]][TQI]];
1736:                for (int i = 0; i < dataUnit.length; i++) {
1737:                    int zzIndex = ZigZag8x8[i];
1738:                    int data = dataUnit[zzIndex];
1739:                    int absData = data < 0 ? 0 - data : data;
1740:                    int qValue = qTable[i];
1741:                    int q2 = qValue >> 1;
1742:                    absData += q2;
1743:                    if (absData < qValue) {
1744:                        dataUnit[zzIndex] = 0;
1745:                    } else {
1746:                        absData /= qValue;
1747:                        if (data >= 0) {
1748:                            dataUnit[zzIndex] = absData;
1749:                        } else {
1750:                            dataUnit[zzIndex] = 0 - absData;
1751:                        }
1752:                    }
1753:                }
1754:            }
1755:
1756:            int receive(int nBits) {
1757:                int v = 0;
1758:                for (int i = 0; i < nBits; i++) {
1759:                    v = v * 2 + nextBit();
1760:                }
1761:                return v;
1762:            }
1763:
1764:            void resetInputBuffer() {
1765:                if (dataBuffer == null) {
1766:                    dataBuffer = new byte[512];
1767:                }
1768:                try {
1769:                    inputStream.read(dataBuffer);
1770:                } catch (IOException e) {
1771:                    SWT.error(SWT.ERROR_IO, e);
1772:                }
1773:                currentBitCount = 0;
1774:                bufferCurrentPosition = -1;
1775:            }
1776:
1777:            void resetOutputBuffer() {
1778:                if (dataBuffer == null) {
1779:                    dataBuffer = new byte[512];
1780:                } else {
1781:                    try {
1782:                        outputStream
1783:                                .write(dataBuffer, 0, bufferCurrentPosition);
1784:                    } catch (IOException e) {
1785:                        SWT.error(SWT.ERROR_IO, e);
1786:                    }
1787:                }
1788:                bufferCurrentPosition = 0;
1789:            }
1790:
1791:            static JPEGSegment seekUnspecifiedMarker(
1792:                    LEDataInputStream byteStream) {
1793:                byte[] byteArray = new byte[2];
1794:                try {
1795:                    while (true) {
1796:                        if (byteStream.read(byteArray, 0, 1) != 1)
1797:                            return null;
1798:                        if (byteArray[0] == (byte) 0xFF) {
1799:                            if (byteStream.read(byteArray, 1, 1) != 1)
1800:                                return null;
1801:                            if (byteArray[1] != (byte) 0xFF
1802:                                    && byteArray[1] != 0) {
1803:                                byteStream.unread(byteArray);
1804:                                return new JPEGSegment(byteArray);
1805:                            }
1806:                        }
1807:                    }
1808:                } catch (IOException e) {
1809:                    SWT.error(SWT.ERROR_IO, e);
1810:                }
1811:                return null;
1812:            }
1813:
1814:            PaletteData setUpPalette() {
1815:                if (nComponents == 1) {
1816:                    RGB[] entries = new RGB[256];
1817:                    for (int i = 0; i < 256; i++) {
1818:                        entries[i] = new RGB(i, i, i);
1819:                    }
1820:                    return new PaletteData(entries);
1821:                }
1822:                return new PaletteData(0xFF, 0xFF00, 0xFF0000);
1823:            }
1824:
1825:            static void skipSegmentFrom(LEDataInputStream byteStream) {
1826:                try {
1827:                    byte[] byteArray = new byte[4];
1828:                    JPEGSegment jpegSegment = new JPEGSegment(byteArray);
1829:
1830:                    if (byteStream.read(byteArray) != byteArray.length) {
1831:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
1832:                    }
1833:                    if (!(byteArray[0] == -1 && byteArray[1] != 0 && byteArray[1] != -1)) {
1834:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
1835:                    }
1836:                    int delta = jpegSegment.getSegmentLength() - 2;
1837:                    byteStream.skip(delta);
1838:                } catch (Exception e) {
1839:                    SWT.error(SWT.ERROR_IO, e);
1840:                }
1841:            }
1842:
1843:            void storeData(int[] dataUnit, int iComp, int xmcu, int ymcu,
1844:                    int hi, int ihi, int vi, int ivi) {
1845:                byte[] compImage = imageComponents[iComp];
1846:                int[] frameComponent = frameComponents[componentIds[iComp]];
1847:                int compWidth = frameComponent[CW];
1848:                int destIndex = ((ymcu * vi + ivi) * compWidth * DCTSIZE)
1849:                        + ((xmcu * hi + ihi) * DCTSIZE);
1850:                int srcIndex = 0;
1851:                for (int i = 0; i < DCTSIZE; i++) {
1852:                    for (int col = 0; col < DCTSIZE; col++) {
1853:                        int x = dataUnit[srcIndex] + 128;
1854:                        if (x < 0) {
1855:                            x = 0;
1856:                        } else {
1857:                            if (x > 255)
1858:                                x = 255;
1859:                        }
1860:                        compImage[destIndex + col] = (byte) x;
1861:                        srcIndex++;
1862:                    }
1863:                    destIndex += compWidth;
1864:                }
1865:            }
1866:
1867:            void unloadIntoByteStream(ImageLoader loader) {
1868:                ImageData image = loader.data[0];
1869:                if (!new JPEGStartOfImage().writeToStream(outputStream)) {
1870:                    SWT.error(SWT.ERROR_IO);
1871:                }
1872:                JPEGAppn appn = new JPEGAppn(new byte[] { (byte) 0xFF,
1873:                        (byte) 0xE0, 0, 0x10, 0x4A, 0x46, 0x49, 0x46, 0, 1, 1,
1874:                        0, 0, 1, 0, 1, 0, 0 });
1875:                if (!appn.writeToStream(outputStream)) {
1876:                    SWT.error(SWT.ERROR_IO);
1877:                }
1878:                quantizationTables = new int[4][];
1879:                JPEGQuantizationTable chromDQT = JPEGQuantizationTable
1880:                        .defaultChrominanceTable();
1881:                chromDQT.scaleBy(encoderQFactor);
1882:                int[] jpegDQTKeys = chromDQT.getQuantizationTablesKeys();
1883:                int[][] jpegDQTValues = chromDQT.getQuantizationTablesValues();
1884:                for (int i = 0; i < jpegDQTKeys.length; i++) {
1885:                    quantizationTables[jpegDQTKeys[i]] = jpegDQTValues[i];
1886:                }
1887:                JPEGQuantizationTable lumDQT = JPEGQuantizationTable
1888:                        .defaultLuminanceTable();
1889:                lumDQT.scaleBy(encoderQFactor);
1890:                jpegDQTKeys = lumDQT.getQuantizationTablesKeys();
1891:                jpegDQTValues = lumDQT.getQuantizationTablesValues();
1892:                for (int i = 0; i < jpegDQTKeys.length; i++) {
1893:                    quantizationTables[jpegDQTKeys[i]] = jpegDQTValues[i];
1894:                }
1895:                if (!lumDQT.writeToStream(outputStream)) {
1896:                    SWT.error(SWT.ERROR_IO);
1897:                }
1898:                if (!chromDQT.writeToStream(outputStream)) {
1899:                    SWT.error(SWT.ERROR_IO);
1900:                }
1901:                int frameLength, scanLength, precision;
1902:                int[][] frameParams, scanParams;
1903:                if (image.depth == 1) {
1904:                    frameLength = 11;
1905:                    frameParams = new int[1][];
1906:                    frameParams[0] = new int[] { 1, 1, 1, 0, 0 };
1907:                    scanParams = new int[1][];
1908:                    scanParams[0] = new int[] { 0, 0 };
1909:                    scanLength = 8;
1910:                    nComponents = 1;
1911:                    precision = 1;
1912:                } else {
1913:                    frameLength = 17;
1914:                    frameParams = new int[3][];
1915:                    frameParams[0] = new int[] { 0, 2, 2, 0, 0 };
1916:                    frameParams[1] = new int[] { 1, 1, 1, 0, 0 };
1917:                    frameParams[2] = new int[] { 1, 1, 1, 0, 0 };
1918:                    scanParams = new int[3][];
1919:                    scanParams[0] = new int[] { 0, 0 };
1920:                    scanParams[1] = new int[] { 1, 1 };
1921:                    scanParams[2] = new int[] { 1, 1 };
1922:                    scanLength = 12;
1923:                    nComponents = 3;
1924:                    precision = 8;
1925:                }
1926:                imageWidth = image.width;
1927:                imageHeight = image.height;
1928:                frameHeader = new JPEGFrameHeader(new byte[19]);
1929:                frameHeader.setSegmentMarker(SOF0);
1930:                frameHeader.setSegmentLength(frameLength);
1931:                frameHeader.setSamplePrecision(precision);
1932:                frameHeader.setSamplesPerLine(imageWidth);
1933:                frameHeader.setNumberOfLines(imageHeight);
1934:                frameHeader.setNumberOfImageComponents(nComponents);
1935:                frameHeader.componentParameters = frameParams;
1936:                frameHeader.componentIdentifiers = new int[] { 0, 1, 2 };
1937:                frameHeader.initializeContents();
1938:                if (!frameHeader.writeToStream(outputStream)) {
1939:                    SWT.error(SWT.ERROR_IO);
1940:                }
1941:                frameComponents = frameParams;
1942:                componentIds = frameHeader.componentIdentifiers;
1943:                maxH = frameHeader.getMaxHFactor();
1944:                maxV = frameHeader.getMaxVFactor();
1945:                int mcuWidth = maxH * DCTSIZE;
1946:                int mcuHeight = maxV * DCTSIZE;
1947:                interleavedMcuCols = (imageWidth + mcuWidth - 1) / mcuWidth;
1948:                interleavedMcuRows = (imageHeight + mcuHeight - 1) / mcuHeight;
1949:                acHuffmanTables = new JPEGHuffmanTable[4];
1950:                dcHuffmanTables = new JPEGHuffmanTable[4];
1951:                JPEGHuffmanTable[] dhtTables = new JPEGHuffmanTable[] {
1952:                        JPEGHuffmanTable.getDefaultDCLuminanceTable(),
1953:                        JPEGHuffmanTable.getDefaultDCChrominanceTable(),
1954:                        JPEGHuffmanTable.getDefaultACLuminanceTable(),
1955:                        JPEGHuffmanTable.getDefaultACChrominanceTable() };
1956:                for (int i = 0; i < dhtTables.length; i++) {
1957:                    JPEGHuffmanTable dhtTable = dhtTables[i];
1958:                    if (!dhtTable.writeToStream(outputStream)) {
1959:                        SWT.error(SWT.ERROR_IO);
1960:                    }
1961:                    JPEGHuffmanTable[] allTables = dhtTable.getAllTables();
1962:                    for (int j = 0; j < allTables.length; j++) {
1963:                        JPEGHuffmanTable huffmanTable = allTables[j];
1964:                        if (huffmanTable.getTableClass() == 0) {
1965:                            dcHuffmanTables[huffmanTable.getTableIdentifier()] = huffmanTable;
1966:                        } else {
1967:                            acHuffmanTables[huffmanTable.getTableIdentifier()] = huffmanTable;
1968:                        }
1969:                    }
1970:                }
1971:                precedingDCs = new int[4];
1972:                scanHeader = new JPEGScanHeader(new byte[14]);
1973:                scanHeader.setSegmentMarker(SOS);
1974:                scanHeader.setSegmentLength(scanLength);
1975:                scanHeader.setNumberOfImageComponents(nComponents);
1976:                scanHeader.setStartOfSpectralSelection(0);
1977:                scanHeader.setEndOfSpectralSelection(63);
1978:                scanHeader.componentParameters = scanParams;
1979:                scanHeader.initializeContents();
1980:                if (!scanHeader.writeToStream(outputStream)) {
1981:                    SWT.error(SWT.ERROR_IO);
1982:                }
1983:                convertImageToYCbCr(image);
1984:                resetOutputBuffer();
1985:                currentByte = 0;
1986:                currentBitCount = 0;
1987:                encodeScan();
1988:                if (!new JPEGEndOfImage().writeToStream(outputStream)) {
1989:                    SWT.error(SWT.ERROR_IO);
1990:                }
1991:            }
1992:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.