001: /*
002: * $RCSfile: ForwCompTransfSpec.java,v $
003: * $Revision: 1.1 $
004: * $Date: 2005/02/11 05:02:13 $
005: * $State: Exp $
006: *
007: * Class: ForwCompTransfSpec
008: *
009: * Description: Component Transformation specification for encoder
010: *
011: *
012: *
013: * COPYRIGHT:
014: *
015: * This software module was originally developed by Raphaël Grosbois and
016: * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
017: * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
018: * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
019: * Centre France S.A) in the course of development of the JPEG2000
020: * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
021: * software module is an implementation of a part of the JPEG 2000
022: * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
023: * Systems AB and Canon Research Centre France S.A (collectively JJ2000
024: * Partners) agree not to assert against ISO/IEC and users of the JPEG
025: * 2000 Standard (Users) any of their rights under the copyright, not
026: * including other intellectual property rights, for this software module
027: * with respect to the usage by ISO/IEC and Users of this software module
028: * or modifications thereof for use in hardware or software products
029: * claiming conformance to the JPEG 2000 Standard. Those intending to use
030: * this software module in hardware or software products are advised that
031: * their use may infringe existing patents. The original developers of
032: * this software module, JJ2000 Partners and ISO/IEC assume no liability
033: * for use of this software module or modifications thereof. No license
034: * or right to this software module is granted for non JPEG 2000 Standard
035: * conforming products. JJ2000 Partners have full right to use this
036: * software module for his/her own purpose, assign or donate this
037: * software module to any third party and to inhibit third parties from
038: * using this software module for non JPEG 2000 Standard conforming
039: * products. This copyright notice must be included in all copies or
040: * derivative works of this software module.
041: *
042: * Copyright (c) 1999/2000 JJ2000 Partners.
043: * */
044: package jj2000.j2k.image.forwcomptransf;
045:
046: import jj2000.j2k.wavelet.analysis.*;
047: import jj2000.j2k.wavelet.*;
048: import jj2000.j2k.image.*;
049: import jj2000.j2k.util.*;
050: import jj2000.j2k.*;
051:
052: import java.util.*;
053:
054: import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriteParamJava;
055:
056: /**
057: * This class extends CompTransfSpec class in order to hold encoder specific
058: * aspects of CompTransfSpec.
059: *
060: * @see CompTransfSpec
061: * */
062: public class ForwCompTransfSpec extends CompTransfSpec implements
063: FilterTypes {
064: private String defaultValue = null;
065:
066: /**
067: * Constructs a new 'ForwCompTransfSpec' for the specified number of
068: * components and tiles and the arguments of <tt>optName</tt>
069: * option. This constructor is called by the encoder. It also
070: * checks that the arguments belongs to the recognized arguments
071: * list.
072: *
073: * <P>This constructor chose the component transformation type
074: * depending on the wavelet filters : RCT with w5x3 filter and ICT
075: * with w9x7 filter. Note: All filters must use the same data
076: * type.
077: *
078: * @param nt The number of tiles
079: *
080: * @param nc The number of components
081: *
082: * @param type the type of the specification module i.e. tile specific,
083: * component specific or both.
084: *
085: * @param wfs The wavelet filter specifications
086: * */
087: public ForwCompTransfSpec(int nt, int nc, byte type,
088: AnWTFilterSpec wfs, J2KImageWriteParamJava wp, String values) {
089: super (nt, nc, type);
090:
091: String param = values;
092: specified = values;
093: if (values == null) {
094: // If less than three component, do not use any component
095: // transformation
096: if (nc < 3) {
097: setDefault("none");
098: return;
099: }
100: // If the compression is lossless, uses RCT
101: else if (wp.getLossless()) {
102: setDefault("rct");
103: return;
104: } else {
105: AnWTFilter[][] anfilt;
106: int[] filtType = new int[nComp];
107: for (int c = 0; c < 3; c++) {
108: anfilt = (AnWTFilter[][]) wfs.getCompDef(c);
109: filtType[c] = anfilt[0][0].getFilterType();
110: }
111:
112: // Check that the three first components use the same filters
113: boolean reject = false;
114: for (int c = 1; c < 3; c++) {
115: if (filtType[c] != filtType[0])
116: reject = true;
117: }
118:
119: if (reject) {
120: setDefault("none");
121: } else {
122: anfilt = (AnWTFilter[][]) wfs.getCompDef(0);
123: if (anfilt[0][0].getFilterType() == W9X7) {
124: setDefault("ict");
125: } else {
126: setDefault("rct");
127: }
128: }
129: }
130:
131: // Each tile receives a component transform specification
132: // according the type of wavelet filters that are used by the
133: // three first components
134: for (int t = 0; t < nt; t++) {
135: AnWTFilter[][] anfilt;
136: int[] filtType = new int[nComp];
137: for (int c = 0; c < 3; c++) {
138: anfilt = (AnWTFilter[][]) wfs.getTileCompVal(t, c);
139: filtType[c] = anfilt[0][0].getFilterType();
140: }
141:
142: // Check that the three components use the same filters
143: boolean reject = false;
144: for (int c = 1; c < nComp; c++) {
145: if (filtType[c] != filtType[0])
146: reject = true;
147: }
148:
149: if (reject) {
150: setTileDef(t, "none");
151: } else {
152: anfilt = (AnWTFilter[][]) wfs.getTileCompVal(t, 0);
153: if (anfilt[0][0].getFilterType() == W9X7) {
154: setTileDef(t, "ict");
155: } else {
156: setTileDef(t, "rct");
157: }
158: }
159: }
160: return;
161: }
162:
163: if (param.equalsIgnoreCase("true"))
164: param = "on";
165: // Parse argument
166: StringTokenizer stk = new StringTokenizer(param);
167: String word; // current word
168: byte curSpecType = SPEC_DEF; // Specification type of the
169: // current parameter
170: boolean[] tileSpec = null; // Tiles concerned by the
171: // specification
172: Boolean value;
173:
174: while (stk.hasMoreTokens()) {
175: word = stk.nextToken();
176:
177: switch (word.charAt(0)) {
178: case 't': // Tiles specification
179: tileSpec = parseIdx(word, nTiles);
180: if (curSpecType == SPEC_COMP_DEF) {
181: curSpecType = SPEC_TILE_COMP;
182: } else {
183: curSpecType = SPEC_TILE_DEF;
184: }
185: break;
186: case 'c': // Components specification
187: throw new IllegalArgumentException(
188: "Component specific " + " parameters"
189: + " not allowed with "
190: + "'-Mct' option");
191: default:
192: if (word.equals("off")) {
193: if (curSpecType == SPEC_DEF) {
194: setDefault("none");
195: } else if (curSpecType == SPEC_TILE_DEF) {
196: for (int i = tileSpec.length - 1; i >= 0; i--)
197: if (tileSpec[i]) {
198: setTileDef(i, "none");
199: }
200: }
201: } else if (word.equals("on")) {
202: if (nc < 3) {
203: setDefault("none");
204: break;
205: }
206:
207: if (curSpecType == SPEC_DEF) { // Set arbitrarily the default
208: // value to RCT (later will be found the suitable
209: // component transform for each tile)
210: setDefault("rct");
211: } else if (curSpecType == SPEC_TILE_DEF) {
212: for (int i = tileSpec.length - 1; i >= 0; i--) {
213: if (tileSpec[i]) {
214: if (getFilterType(i, wfs) == W5X3) {
215: setTileDef(i, "rct");
216: } else {
217: setTileDef(i, "ict");
218: }
219: }
220: }
221: }
222: } else {
223: throw new IllegalArgumentException(
224: "Default parameter of " + "option Mct not"
225: + " recognized: " + param);
226: }
227:
228: // Re-initialize
229: curSpecType = SPEC_DEF;
230: tileSpec = null;
231: break;
232: }
233: }
234:
235: // Check that default value has been specified
236: if (getDefault() == null) {
237: // If not, set arbitrarily the default value to 'none' but
238: // specifies explicitely a default value for each tile depending
239: // on the wavelet transform that is used
240: setDefault("none");
241:
242: for (int t = 0; t < nt; t++) {
243: if (isTileSpecified(t)) {
244: continue;
245: }
246:
247: AnWTFilter[][] anfilt;
248: int[] filtType = new int[nComp];
249: for (int c = 0; c < 3; c++) {
250: anfilt = (AnWTFilter[][]) wfs.getTileCompVal(t, c);
251: filtType[c] = anfilt[0][0].getFilterType();
252: }
253:
254: // Check that the three components use the same filters
255: boolean reject = false;
256: for (int c = 1; c < nComp; c++) {
257: if (filtType[c] != filtType[0])
258: reject = true;
259: }
260:
261: if (reject) {
262: setTileDef(t, "none");
263: } else {
264: anfilt = (AnWTFilter[][]) wfs.getTileCompVal(t, 0);
265: if (anfilt[0][0].getFilterType() == W9X7) {
266: setTileDef(t, "ict");
267: } else {
268: setTileDef(t, "rct");
269: }
270: }
271: }
272: }
273:
274: // Check validity of component transformation of each tile compared to
275: // the filter used.
276: for (int t = nt - 1; t >= 0; t--) {
277:
278: if (((String) getTileDef(t)).equals("none")) {
279: // No comp. transf is used. No check is needed
280: continue;
281: } else if (((String) getTileDef(t)).equals("rct")) {
282: // Tile is using Reversible component transform
283: int filterType = getFilterType(t, wfs);
284: switch (filterType) {
285: case FilterTypes.W5X3: // OK
286: break;
287: case FilterTypes.W9X7: // Must use ICT
288: if (isTileSpecified(t)) {
289: // User has requested RCT -> Error
290: throw new IllegalArgumentException(
291: "Cannot use RCT " + "with 9x7 filter "
292: + "in tile " + t);
293: } else { // Specify ICT for this tile
294: setTileDef(t, "ict");
295: }
296: break;
297: default:
298: throw new IllegalArgumentException(
299: "Default filter is " + "not JPEG 2000 part"
300: + " I compliant");
301: }
302: } else { // ICT
303: int filterType = getFilterType(t, wfs);
304: switch (filterType) {
305: case FilterTypes.W5X3: // Must use RCT
306: if (isTileSpecified(t)) {
307: // User has requested ICT -> Error
308: throw new IllegalArgumentException(
309: "Cannot use ICT " + "with filter 5x3 "
310: + "in tile " + t);
311: } else {
312: setTileDef(t, "rct");
313: }
314: break;
315: case FilterTypes.W9X7: // OK
316: break;
317: default:
318: throw new IllegalArgumentException(
319: "Default filter is " + "not JPEG 2000 part"
320: + " I compliant");
321:
322: }
323: }
324: }
325: }
326:
327: /** Get the filter type common to all component of a given tile. If the
328: * tile index is -1, it searches common filter type of default
329: * specifications.
330: *
331: * @param t The tile index
332: *
333: * @param wfs The analysis filters specifications
334: *
335: * @return The filter type common to all the components
336: *
337: */
338: private int getFilterType(int t, AnWTFilterSpec wfs) {
339: AnWTFilter[][] anfilt;
340: int[] filtType = new int[nComp];
341: for (int c = 0; c < nComp; c++) {
342: if (t == -1)
343: anfilt = (AnWTFilter[][]) wfs.getCompDef(c);
344: else
345: anfilt = (AnWTFilter[][]) wfs.getTileCompVal(t, c);
346: filtType[c] = anfilt[0][0].getFilterType();
347: }
348:
349: // Check that all filters are the same one
350: boolean reject = false;
351: for (int c = 1; c < nComp; c++) {
352: if (filtType[c] != filtType[0])
353: reject = true;
354: }
355: if (reject) {
356: throw new IllegalArgumentException("Can not use component"
357: + " transformation when "
358: + "components do not use " + "the same filters");
359: }
360: return filtType[0];
361: }
362: }
|