001: /*******************************************************************************
002: * Copyright (c) 2000, 2005 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.swt.internal.image;
011:
012: /**
013: * JPEGHuffmanTable class actually represents two types of object:
014: * 1) A DHT (Define Huffman Tables) segment, which may represent
015: * as many as 4 Huffman tables. In this case, the tables are
016: * stored in the allTables array.
017: * 2) A single Huffman table. In this case, the allTables array
018: * will be null.
019: * The 'reference' field is stored in both types of object, but
020: * 'initialize' is only called if the object represents a DHT.
021: */
022: final class JPEGHuffmanTable extends JPEGVariableSizeSegment {
023: JPEGHuffmanTable[] allTables;
024: int tableClass;
025: int tableIdentifier;
026: int[] dhMaxCodes;
027: int[] dhMinCodes;
028: int[] dhValPtrs;
029: int[] dhValues;
030: int[] ehCodes;
031: byte[] ehCodeLengths;
032: static byte[] DCLuminanceTable = { (byte) 255, (byte) 196, 0, 31,
033: 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
034: 3, 4, 5, 6, 7, 8, 9, 10, 11 };
035: static byte[] DCChrominanceTable = { (byte) 255, (byte) 196, 0, 31,
036: 1, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 2,
037: 3, 4, 5, 6, 7, 8, 9, 10, 11 };
038: static byte[] ACLuminanceTable = { (byte) 255, (byte) 196, 0,
039: (byte) 181, 16, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0,
040: 1, 125, 1, 2, 3, 0, 4, 17, 5, 18, 33, 49, 65, 6, 19, 81,
041: 97, 7, 34, 113, 20, 50, (byte) 129, (byte) 145, (byte) 161,
042: 8, 35, 66, (byte) 177, (byte) 193, 21, 82, (byte) 209,
043: (byte) 240, 36, 51, 98, 114, (byte) 130, 9, 10, 22, 23, 24,
044: 25, 26, 37, 38, 39, 40, 41, 42, 52, 53, 54, 55, 56, 57, 58,
045: 67, 68, 69, 70, 71, 72, 73, 74, 83, 84, 85, 86, 87, 88, 89,
046: 90, 99, 100, 101, 102, 103, 104, 105, 106, 115, 116, 117,
047: 118, 119, 120, 121, 122, (byte) 131, (byte) 132,
048: (byte) 133, (byte) 134, (byte) 135, (byte) 136, (byte) 137,
049: (byte) 138, (byte) 146, (byte) 147, (byte) 148, (byte) 149,
050: (byte) 150, (byte) 151, (byte) 152, (byte) 153, (byte) 154,
051: (byte) 162, (byte) 163, (byte) 164, (byte) 165, (byte) 166,
052: (byte) 167, (byte) 168, (byte) 169, (byte) 170, (byte) 178,
053: (byte) 179, (byte) 180, (byte) 181, (byte) 182, (byte) 183,
054: (byte) 184, (byte) 185, (byte) 186, (byte) 194, (byte) 195,
055: (byte) 196, (byte) 197, (byte) 198, (byte) 199, (byte) 200,
056: (byte) 201, (byte) 202, (byte) 210, (byte) 211, (byte) 212,
057: (byte) 213, (byte) 214, (byte) 215, (byte) 216, (byte) 217,
058: (byte) 218, (byte) 225, (byte) 226, (byte) 227, (byte) 228,
059: (byte) 229, (byte) 230, (byte) 231, (byte) 232, (byte) 233,
060: (byte) 234, (byte) 241, (byte) 242, (byte) 243, (byte) 244,
061: (byte) 245, (byte) 246, (byte) 247, (byte) 248, (byte) 249,
062: (byte) 250 };
063: static byte[] ACChrominanceTable = { (byte) 255, (byte) 196, 0,
064: (byte) 181, 17, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1,
065: 2, 119, 0, 1, 2, 3, 17, 4, 5, 33, 49, 6, 18, 65, 81, 7, 97,
066: 113, 19, 34, 50, (byte) 129, 8, 20, 66, (byte) 145,
067: (byte) 161, (byte) 177, (byte) 193, 9, 35, 51, 82,
068: (byte) 240, 21, 98, 114, (byte) 209, 10, 22, 36, 52,
069: (byte) 225, 37, (byte) 241, 23, 24, 25, 26, 38, 39, 40, 41,
070: 42, 53, 54, 55, 56, 57, 58, 67, 68, 69, 70, 71, 72, 73, 74,
071: 83, 84, 85, 86, 87, 88, 89, 90, 99, 100, 101, 102, 103,
072: 104, 105, 106, 115, 116, 117, 118, 119, 120, 121, 122,
073: (byte) 130, (byte) 131, (byte) 132, (byte) 133, (byte) 134,
074: (byte) 135, (byte) 136, (byte) 137, (byte) 138, (byte) 146,
075: (byte) 147, (byte) 148, (byte) 149, (byte) 150, (byte) 151,
076: (byte) 152, (byte) 153, (byte) 154, (byte) 162, (byte) 163,
077: (byte) 164, (byte) 165, (byte) 166, (byte) 167, (byte) 168,
078: (byte) 169, (byte) 170, (byte) 178, (byte) 179, (byte) 180,
079: (byte) 181, (byte) 182, (byte) 183, (byte) 184, (byte) 185,
080: (byte) 186, (byte) 194, (byte) 195, (byte) 196, (byte) 197,
081: (byte) 198, (byte) 199, (byte) 200, (byte) 201, (byte) 202,
082: (byte) 210, (byte) 211, (byte) 212, (byte) 213, (byte) 214,
083: (byte) 215, (byte) 216, (byte) 217, (byte) 218, (byte) 226,
084: (byte) 227, (byte) 228, (byte) 229, (byte) 230, (byte) 231,
085: (byte) 232, (byte) 233, (byte) 234, (byte) 242, (byte) 243,
086: (byte) 244, (byte) 245, (byte) 246, (byte) 247, (byte) 248,
087: (byte) 249, (byte) 250 };
088:
089: public JPEGHuffmanTable(byte[] reference) {
090: super (reference);
091: }
092:
093: public JPEGHuffmanTable(LEDataInputStream byteStream) {
094: super (byteStream);
095: initialize();
096: }
097:
098: public JPEGHuffmanTable[] getAllTables() {
099: return allTables;
100: }
101:
102: public static JPEGHuffmanTable getDefaultACChrominanceTable() {
103: JPEGHuffmanTable result = new JPEGHuffmanTable(
104: ACChrominanceTable);
105: result.initialize();
106: return result;
107: }
108:
109: public static JPEGHuffmanTable getDefaultACLuminanceTable() {
110: JPEGHuffmanTable result = new JPEGHuffmanTable(ACLuminanceTable);
111: result.initialize();
112: return result;
113: }
114:
115: public static JPEGHuffmanTable getDefaultDCChrominanceTable() {
116: JPEGHuffmanTable result = new JPEGHuffmanTable(
117: DCChrominanceTable);
118: result.initialize();
119: return result;
120: }
121:
122: public static JPEGHuffmanTable getDefaultDCLuminanceTable() {
123: JPEGHuffmanTable result = new JPEGHuffmanTable(DCLuminanceTable);
124: result.initialize();
125: return result;
126: }
127:
128: public int[] getDhMaxCodes() {
129: return dhMaxCodes;
130: }
131:
132: public int[] getDhMinCodes() {
133: return dhMinCodes;
134: }
135:
136: public int[] getDhValPtrs() {
137: return dhValPtrs;
138: }
139:
140: public int[] getDhValues() {
141: return dhValues;
142: }
143:
144: public int getTableClass() {
145: return tableClass;
146: }
147:
148: public int getTableIdentifier() {
149: return tableIdentifier;
150: }
151:
152: void initialize() {
153: int totalLength = getSegmentLength() - 2;
154: int ofs = 4;
155: int[] bits = new int[16];
156: JPEGHuffmanTable[] huffTables = new JPEGHuffmanTable[8]; // maximum is 4 AC + 4 DC
157: int huffTableCount = 0;
158: while (totalLength > 0) {
159: int tc = (reference[ofs] & 0xFF) >> 4; // table class: AC (1) or DC (0)
160: int tid = reference[ofs] & 0xF; // table id: 0-1 baseline, 0-3 prog/ext
161: ofs++;
162:
163: /* Read the 16 count bytes and add them together to get the table size. */
164: int count = 0;
165: for (int i = 0; i < bits.length; i++) {
166: int bCount = reference[ofs + i] & 0xFF;
167: bits[i] = bCount;
168: count += bCount;
169: }
170: ofs += 16;
171: totalLength -= 17;
172:
173: /* Read the table. */
174: int[] huffVals = new int[count];
175: for (int i = 0; i < count; i++) {
176: huffVals[i] = reference[ofs + i] & 0xFF;
177: }
178: ofs += count;
179: totalLength -= count;
180:
181: /* Calculate the lengths. */
182: int[] huffCodeLengths = new int[50]; // start with 50 and increment as needed
183: int huffCodeLengthsIndex = 0;
184: for (int i = 0; i < 16; i++) {
185: for (int j = 0; j < bits[i]; j++) {
186: if (huffCodeLengthsIndex >= huffCodeLengths.length) {
187: int[] newHuffCodeLengths = new int[huffCodeLengths.length + 50];
188: System.arraycopy(huffCodeLengths, 0,
189: newHuffCodeLengths, 0,
190: huffCodeLengths.length);
191: huffCodeLengths = newHuffCodeLengths;
192: }
193: huffCodeLengths[huffCodeLengthsIndex] = i + 1;
194: huffCodeLengthsIndex++;
195: }
196: }
197:
198: /* Truncate huffCodeLengths to the correct size. */
199: if (huffCodeLengthsIndex < huffCodeLengths.length) {
200: int[] newHuffCodeLengths = new int[huffCodeLengthsIndex];
201: System.arraycopy(huffCodeLengths, 0,
202: newHuffCodeLengths, 0, huffCodeLengthsIndex);
203: huffCodeLengths = newHuffCodeLengths;
204: }
205:
206: /* Calculate the Huffman codes. */
207: int[] huffCodes = new int[50]; // start with 50 and increment as needed
208: int huffCodesIndex = 0;
209: int k = 1;
210: int code = 0;
211: int si = huffCodeLengths[0];
212: int p = 0;
213: while (p < huffCodeLengthsIndex) {
214: while ((p < huffCodeLengthsIndex)
215: && (huffCodeLengths[p] == si)) {
216: if (huffCodesIndex >= huffCodes.length) {
217: int[] newHuffCodes = new int[huffCodes.length + 50];
218: System.arraycopy(huffCodes, 0, newHuffCodes, 0,
219: huffCodes.length);
220: huffCodes = newHuffCodes;
221: }
222: huffCodes[huffCodesIndex] = code;
223: huffCodesIndex++;
224: code++;
225: p++;
226: }
227: code *= 2;
228: si++;
229: }
230:
231: /* Truncate huffCodes to the correct size. */
232: if (huffCodesIndex < huffCodes.length) {
233: int[] newHuffCodes = new int[huffCodesIndex];
234: System.arraycopy(huffCodes, 0, newHuffCodes, 0,
235: huffCodesIndex);
236: huffCodes = newHuffCodes;
237: }
238:
239: /* Calculate the maximum and minimum codes */
240: k = 0;
241: int[] maxCodes = new int[16];
242: int[] minCodes = new int[16];
243: int[] valPtrs = new int[16];
244: for (int i = 0; i < 16; i++) {
245: int bSize = bits[i];
246: if (bSize == 0) {
247: maxCodes[i] = -1;
248: } else {
249: valPtrs[i] = k;
250: minCodes[i] = huffCodes[k];
251: k += bSize;
252: maxCodes[i] = huffCodes[k - 1];
253: }
254: }
255:
256: /* Calculate the eHuffman codes and lengths. */
257: int[] eHuffCodes = new int[256];
258: byte[] eHuffSize = new byte[256];
259: for (int i = 0; i < huffCodesIndex; i++) {
260: eHuffCodes[huffVals[i]] = huffCodes[i];
261: eHuffSize[huffVals[i]] = (byte) huffCodeLengths[i];
262: }
263:
264: /* Create the new JPEGHuffmanTable and add it to the allTables array. */
265: JPEGHuffmanTable dhtTable = new JPEGHuffmanTable(reference);
266: dhtTable.tableClass = tc;
267: dhtTable.tableIdentifier = tid;
268: dhtTable.dhValues = huffVals;
269: dhtTable.dhMinCodes = minCodes;
270: dhtTable.dhMaxCodes = maxCodes;
271: dhtTable.dhValPtrs = valPtrs;
272: dhtTable.ehCodes = eHuffCodes;
273: dhtTable.ehCodeLengths = eHuffSize;
274: huffTables[huffTableCount] = dhtTable;
275: huffTableCount++;
276: }
277: allTables = new JPEGHuffmanTable[huffTableCount];
278: System.arraycopy(huffTables, 0, allTables, 0, huffTableCount);
279: }
280:
281: public int signature() {
282: return JPEGFileFormat.DHT;
283: }
284: }
|