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: }
|