001/*
002 * $RCSfile: J2KImageWriteParamJava.java,v $
003 *
004 * 
005 * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
006 * 
007 * Redistribution and use in source and binary forms, with or without
008 * modification, are permitted provided that the following conditions
009 * are met: 
010 * 
011 * - Redistribution of source code must retain the above copyright 
012 *   notice, this  list of conditions and the following disclaimer.
013 * 
014 * - Redistribution in binary form must reproduce the above copyright
015 *   notice, this list of conditions and the following disclaimer in 
016 *   the documentation and/or other materials provided with the
017 *   distribution.
018 * 
019 * Neither the name of Sun Microsystems, Inc. or the names of 
020 * contributors may be used to endorse or promote products derived 
021 * from this software without specific prior written permission.
022 * 
023 * This software is provided "AS IS," without a warranty of any 
024 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
025 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
026 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027 * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
028 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
029 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
031 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035 * POSSIBILITY OF SUCH DAMAGES. 
036 * 
037 * You acknowledge that this software is not designed or intended for 
038 * use in the design, construction, operation or maintenance of any 
039 * nuclear facility. 
040 *
041 * $Revision: 1.2 $
042 * $Date: 2006/09/20 23:23:30 $
043 * $State: Exp $
044 */
045package com.sun.media.imageioimpl.plugins.jpeg2000;
046
047import java.awt.Rectangle;
048import java.awt.image.Raster;
049import java.awt.image.RenderedImage;
050import java.util.Collections;
051import java.util.Locale;
052import java.util.Iterator;
053import javax.imageio.IIOImage;
054import javax.imageio.ImageWriteParam;
055import jj2000.j2k.*;
056import jj2000.j2k.roi.*;
057import jj2000.j2k.quantization.*;
058import jj2000.j2k.wavelet.analysis.AnWTFilterSpec;
059import jj2000.j2k.image.forwcomptransf.ForwCompTransfSpec;
060import jj2000.j2k.entropy.CBlkSizeSpec;
061import jj2000.j2k.entropy.PrecinctSizeSpec;
062import jj2000.j2k.entropy.ProgressionSpec;
063import jj2000.j2k.image.BlkImgDataSrc;
064import jj2000.j2k.entropy.encoder.LayersInfo;
065import com.sun.media.imageio.plugins.jpeg2000.J2KImageWriteParam;
066
067/**
068 * A subclass of <code>ImageWriteParam</code> for writing images in
069 * the JPEG 2000 format.
070 *
071 * <p>JPEG 2000 plugin supports to losslessly or lossy compress gray-scale,
072 * RGB, and RGBA images with byte, unsigned short or short data type.  It also
073 * supports losslessly compress bilevel, and 8-bit indexed.  The result data
074 * is in the format of JP2 (JPEG 2000 Part 1 or baseline format).
075 *
076 * <p>Many encoding parameters for JPEG 2000 can be tile-component specific.
077 * These parameters are marked as <code>Yes</code> in the column <code>
078 * TC_SPEC</code> in the following parameter table.
079 * They must be provided according to the pattern:
080 * [&lt;tile-component idx>] &lt;param&gt; (repeated as many time as needed),
081 * where &lt;tile-component idx&gt; respect the following policy according to
082 * the degree of priority:
083 * <table>
084 * <tr><td>(1) t&lt;idx&gt; c&lt;idx&gt; : Tile-component specification.</td></tr>
085 * <tr><td>(2) t&lt;idx&gt; : Tile specification.</td></tr>
086 * <tr><td>(3) c&lt;idx&gt; : Component specification.</td></tr>
087 * <tr><td>(4) &lt;void&gt; : Default specification.</td></tr>
088 * </table>
089 * <p>Where the priorities of the specifications are:
090 * (1) > (2) > (3) > (4), (">" means "overrides")
091 *  &lt;idx&gt;: "," separates indexes, "-" separates bounds of indexes list.
092 *  (for example, 0,2-4 means indexes 0,2,3 and  4).
093 *
094 * <p>The parameters for encoding JPEG 2000 are listed in the following table:
095 *
096 *  * <p><table border=1>
097 * <caption><b>JPEG 2000 Plugin Decoding Parameters</b></caption>
098 * <tr><th>Parameter Name</th> <th>Description</th><th>TC_SPEC</th></tr>
099 * <tr>
100 *    <td>encodingRate</td>
101 *    <td> The bitrate in bits-per-pixel for encoding.  Should be set when
102 *    lossy compression scheme is used.  With the default value
103 *    <code>Double.MAX_VALUE</code>, a lossless compression will be done.
104 *    </td>
105 *    <td>No</td>
106 * </tr>
107 * <tr>
108 *    <td>lossless</td>
109 *    <td> Indicates using the loseless scheme or not.  It is equivalent to
110 *    use reversible quantization and 5x3 integer wavelet filters.  The
111 *    default is <code>true</code>.
112 *    </td>
113 *    <td>No</td>
114 * </tr>
115 * <tr>
116 *    <td>componentTransformation</td>
117 *    <td> Specifies to utilize the component transformation on some tiles.
118 *    If the wavelet transform is reversible (w5x3 filter), the Reversible
119 *    Component Transformation (RCT) is applied. If not reversible
120 *    (w9x7 filter), the Irreversible Component Transformation (ICT) is used.
121 *    </td>
122 *    <td>Yes, Tile_Specific</td>
123 * </tr>
124 * <tr>
125 *    <td>filters</td>
126 *    <td> Specifies which wavelet filters to use for the specified
127 *    tile-components.  JPEG 2000 part I only supports w5x3 and w9x7 filters.
128 *    </td>
129 *    <td>Yes</td>
130 * </tr>
131 * <tr>
132 *    <td>decompositionLevel</td>
133 *    <td> Specifies the wavelet decomposition levels to apply to
134 *    the image.  If it is 0, no wavelet transform is performed, in which
135 *    case the original image data will be sent to the encoder and an example
136 *    is the binary data.  All components and all tiles have the same number
137 *    of decomposition levels.  The default value is 5.
138 *    </td>
139 *    <td>No</td>
140 * </tr>
141 * <tr>
142 *    <td>guardBits</td>
143 *    <td> The number of bits used for each tile-component in the quantizer
144 *    to avoid overflow.  It takes values in the range 0 through 7.  The
145 *    default value is 2.
146 *    </td>
147 *    <td>Yes</td>
148 * </tr>
149 * <tr>
150 *    <td>quantizationStep</td>
151 *    <td> This parameter specifies the base normalized quantization step
152 *    size for the tiles/components.  It is normalized to a dynamic range
153 *    of 1 in the image domain.  This parameter is ignored in reversible
154 *    coding.  The default value is 0.0078125.
155 *    </td>
156 *    <td>Yes</td>
157 * </tr>
158 * <tr>
159 *    <td>quantizationType</td>
160 *    <td> Specifies which quantization type to use for specified
161 *    tiles/components.  Not specified for lossless compression.  By default,
162 *    the quantization step size is "expounded".  Supported quantization
163 *    types specification are : "reversible" (no quantization), "derived"
164 *    (derived quantization step size) and "expounded".
165 *    </td>
166 *    <td>Yes</td>
167 * </tr>
168 * <tr>
169 *    <td>codeBlockSize</td>
170 *    <td> Specifies the maximum code-block size to use for tile-component.
171 *    The maximum width and height is 1024, however the block size
172 *    (i.e. width x height) must not exceed 4096.  The minimum width and
173 *    height is 4.  The default values are (64, 64).
174 *    </td>
175 *    <td>Yes</td>
176 * </tr>
177 * <tr>
178 *    <td>progressionType</td>
179 *    <td> Specifies which type of progression should be used when generating
180 *    the codestream.
181 *    <p> The format is [&lt;tile index&gt;]
182 *    res|layer|res-pos|pos-comp|comp-pos [res_start comp_start layer_end
183 *    res_end comp_end prog] [[res_start comp_start layer_end res_end
184 *    comp_end prog]...] [[&lt;tile-component idx]...].
185 *    <p>The value "res" generates a resolution progressive
186 *    codestream with the number of layers specified by "layers" parameter.
187 *    The value "layer" generates a layer progressive codestream with
188 *    multiple layers.  In any case, the rate-allocation algorithm optimizes
189 *    for best quality in each layer.  The quality measure is mean squared
190 *    error (MSE) or a weighted version of it (WMSE).  If no progression
191 *    type is specified or imposed by other parameters, the default value
192 *    is "layer".  It is also possible to describe progression order
193 *    changes.  In this case, "res_start" is the index (from 0) of the
194 *    first resolution level, "comp_start" is the index (from 0) of the
195 *    first component, "layer_end" is the index (from 0) of the first layer
196 *    not included, "res_end" is the index (from 0) of the first
197 *    resolution level not included, "comp_end" is index (from 0) of
198 *    the first component not included and "prog" is the progression type
199 *    to be used for the rest of the tile/image.  Several progression
200 *    order changes can be specified, one after the other.
201 *    </td>
202 *    <td>Yes</td>
203 * </tr>
204 * <tr>
205 *    <td>packPacketHeaderInTile</td>
206 *    <td> Indicates that the packet headers are packed in the tiles' headers.
207 *    The default is false.
208 *    </td>
209 *    <td>No</td>
210 * </tr>
211 * <tr>
212 *    <td>packPacketHeaderInMain</td>
213 *    <td> Indicates that the packet headers are packed in the main header.
214 *    The default is false.
215 *    </td>
216 *    <td>No</td>
217 * </tr>
218 * <tr>
219 *    <td>packetPerTilePart</td>
220 *    <td> Specifies the maximum number of packets to be put into one tile-part.
221 *    Zero means putting all packets in the first tile-part of each tile.
222 *    </td>
223 *    <td>No</td>
224 * </tr>
225 * <tr>
226 *    <td>ROIs</td>
227 *    <td> Specifies ROIs shape and location.  The component index specifies
228 *    which components contain the ROI.  If this parameter is used, the
229 *    codestream is layer progressive by default unless it is overridden by
230 *    the <code>progressionType</code>.  A rectanglar or circular ROI can be
231 *    specified in the format: [&lt;component idx&gt;] R &lt;left&gt;
232 *    &lt;top&gt; &lt;width&gt; &lt;height&gt; or [&lt;component idx&gt;] C
233 *    &lt;center x&gt; &lt;center y&gt; &lt;radius&gt;. An arbitrary shape
234 *    can be assigned by [&lt;component idx&gt;] A &lt;PGM file&gt;
235 *    </td>
236 *    <td>Yes, component-specified</td>
237 * </tr>
238 * <tr>
239 *    <td>startLevelROI</td>
240 *    <td> This parameter defines the lowest resolution levels to belong to
241 *    the ROI.  By doing this, it is possible to avoid getting
242 *    information for the ROI at an early stage of transmission.
243 *    startLevelROI = 0 means the lowest resolution level belongs to
244 *    the ROI, 1 means the second lowest etc.  The default values, -1,
245 *    deactivates this parameter.
246 *    </td>
247 *    <td>No</td>
248 * </tr>
249 * <tr>
250 *    <td>alignROI</td>
251 *    <td> By specifying this parameter, the ROI mask will be limited to
252 *    covering only entire code-blocks.  The ROI coding can then be
253 *    performed without any actual scaling of the coefficients but by
254 *    instead scaling the distortion estimates.
255 *    </td>
256 *    <td>No</td>
257 * </tr>
258 * <tr>
259 *    <td>bypass</td>
260 *    <td> Uses the lazy coding mode with the entropy coder.  This will bypass
261 *    the MQ coder for some of the coding passes, where the distribution
262 *    is often close to uniform.  Since the MQ codeword will be terminated
263 *    at least once per lazy pass, it is important to use an efficient
264 *    termination algorithm, <code>methodForMQTermination</code>.
265 *    true enables, and false disables it.  The default value is false.
266 *    </td>
267 *    <td>Yes</td>
268 * </tr>
269 * <tr>
270 *    <td>resetMQ</td>
271 *    <td> If this is enabled the probability estimates of the MQ coder are
272 *    reset after each arithmetically coded (i.e. non-lazy) coding pass.
273 *    true enables, and false disables it.  The default value is false.
274 *    </td>
275 *    <td>Yes</td>
276 * </tr>
277 * <tr>
278 *    <td>terminateOnByte</td>
279 *    <td> If this is enabled the codeword (raw or MQ) is terminated on a byte
280 *    boundary after each coding pass. In this case it is important to use
281 *    an efficient termination algorithm, "methodForMQTermination".
282 *    true enables, and false disables it.  The default value is false.
283 *    </td>
284 *    <td>Yes</td>
285 * </tr>
286 * <tr>
287 *    <td>causalCXInfo</td>
288 *    <td> Uses vertically stripe causal context formation.  If this is
289 *    enabled the context formation process in one stripe is independant of
290 *    the next stripe (i.e. the one below it). true enables, and false
291 *    disables it.  The default value is false.
292 *    </td>
293 *    <td>Yes</td>
294 * </tr>
295 * <tr>
296 *    <td>codeSegSymbol</td>
297 *    <td> Inserts an error resilience segmentation symbol in the MQ codeword
298 *    at the end of each bit-plane (cleanup pass). Decoders can use this
299 *    information to detect and conceal errors. true enables, and false
300 *    disables it.  The default value is false.
301 *    </td>
302 *    <td>Yes</td>
303 * </tr>
304 * <tr>
305 *    <td>methodForMQTermination</td>
306 *    <td> Specifies the algorithm used to terminate the MQ codeword.  The
307 *    most efficient one is "near_opt", which delivers a codeword which
308 *    in almost all cases is the shortest possible.  The "easy" is a
309 *    simpler algorithm that delivers a codeword length that is close
310 *    to the previous one (in average 1 bit longer).  The "predict" is
311 *    almost the same as the "easy" but it leaves error resilient
312 *    information on the spare least significant bits (in average 3.5 bits),
313 *    which can be used by a decoder to detect errors.  The "full" algorithm
314 *    performs a full flush of the MQ coder and is highly inefficient.  It
315 *    is important to use a good termination policy since the MQ codeword
316 *    can be terminated quite often, specially if the "bypass" or
317 *    "terminateOnByte" parameters are enabled (in the normal case it would
318 *    be terminated once per code-block, while "terminateOnByte" is specified
319 *    it will be done almost 3 times per bit-plane in each code-block).
320 *    The default value is "near_opt".
321 *    </td>
322 *    <td>Yes</td>
323 * </tr>
324 * <tr>
325 *    <td>methodForMQLengthCalc</td>
326 *    <td> Specifies the algorithm to use in calculating the necessary MQ
327 *    length for each decoding pass.  The best one is "near_opt", which
328 *    performs a rather sophisticated calculation and provides the best
329 *    results.  The "lazy_good" and "lazy" are very simple algorithms
330 *    that provide rather conservative results. "lazy_good" performs
331 *    slightly better.  Please use the default unless the experiments
332 *    show the benefits of different length calculation algorithms.
333 *    The default value is "near_opt".
334 *    </td>
335 *    <td>Yes</td>
336 * </tr>
337 * <tr>
338 *    <td>precinctPartition</td>
339 *    <td> Specifies precinct partition dimensions for tiles/components.  They
340 *    are stored from those applied to the highest resolution to those
341 *    applied to the remaining resolutions in decreasing order.  If less
342 *    values than the number of decomposition levels are specified, then
343 *    the last two values are used for the remaining resolutions.
344 *    </td>
345 *    <td>Yes</td>
346 * </tr>
347 * <tr>
348 *    <td>layers</td>
349 *    <td> Explicitly specifies the codestream layer formation parameters.
350 *    The rate (double) parameter specifies the bitrate to which the first
351 *    layer should be optimized.  The layers (int) parameter, if present,
352 *    specifies the number of extra layers that should be added for
353 *    scalability.  These extra layers are not optimized.  Any extra rate
354 *    and layers parameters add more layers, in the same way.  An
355 *    additional layer is always added at the end, which is optimized
356 *    to the overall target bitrate of the bit stream. Any layers
357 *    (optimized or not) whose target bitrate is higher that the overall
358 *    target bitrate are silently ignored. The bitrates of the extra layers
359 *    that are added through the layers parameter are approximately
360 *    log-spaced between the other target bitrates.  If several (rate, layers)
361 *    constructs appear the rate parameters must appear in increasing order.
362 *    The rate allocation algorithm ensures that all coded layers have a
363 *    minimal reasonable size, if not these layers are silently ignored.
364 *    Default: 0.015 +20 2.0 +10.
365 *    </td>
366 *    <td>No</td>
367 * </tr>
368 * <tr>
369 *    <td>SOP</td>
370 *    <td>Specifies whether start of packet (SOP) markers should be used.
371 *    true enables, false disables it.  The default value is false.
372 *    </td>
373 *    <td>Yes</td>
374 * </tr>
375 * <tr>
376 *    <td>EPH</td>
377 *    <td>Specifies whether end of packet header (EPH) markers should be used.
378 *    true enables, false disables it.  The default value is false.
379 *    </td>
380 *    <td>Yes</td>
381 * </tr>
382 * </table>
383 */
384public class J2KImageWriteParamJava extends ImageWriteParam {
385    /**
386     * Indicates that the packet headers are packed in the tiles' headers.
387     */
388    private boolean packPacketHeaderInTile = false;
389
390    /**
391     * Indicates that the packet headers are packed in the main header.
392     */
393    private boolean packPacketHeaderInMain = false;
394
395    /**
396     * Specifies the maximum number of packets to be put into one tile-part.
397     * Zero means include all packets in first tile-part of each tile.
398     */
399    private int packetPerTilePart = 0;
400
401    /**
402     * The bitrate in bits-per-pixel for encoding.  Should be set when lossy
403     * compression scheme is used.  The default is
404     * <code>Double.MAX_VALUE</code>.
405     */
406    private double encodingRate = Double.MAX_VALUE;
407
408    /**
409     * Indicates using the loseless scheme or not.  It is equivalent to
410     * use reversible quantization and 5x3 integer wavelet filters.
411     */
412    private boolean lossless = true;
413
414    /** Specifies to utilize the component transformation with some tiles.
415     *  If the wavelet transform is reversible (w5x3 filter), the
416     *  Reversible Component Transformation (RCT) is applied. If not reversible
417     *  (w9x7 filter), the Irreversible Component Transformation (ICT)
418     *  is used.
419     */
420    private ForwCompTransfSpec componentTransformation = null;
421    private boolean enableCT = true;
422
423    /** Specifies which filters to use for the specified tile-components.
424     *  JPEG 2000 part I only supports w5x3 and w9x7 filters.
425     */
426    private AnWTFilterSpec filters = null;
427
428    /** Specifies the number of wavelet decomposition levels to apply to
429     *  the image.  If it is 0, no wavelet transform is performed, in which
430     *  case the original image data will be sent to the encoder and an
431     *  example is the binary data.  All components and all tiles have
432     *  the same number of decomposition levels. Default: 5.
433     */
434    private IntegerSpec decompositionLevel = null; // = 5;
435
436    /** The number of bits used for each tile-component in
437     *  the quantizer to avoid overflow.  It takes values in the range 0
438     *  through 7.  Default: 2.
439     */
440    private GuardBitsSpec guardBits = null;
441
442    /** This parameter specifies the base normalized quantization step
443     *  size for the tiles/components.  It is normalized to a dynamic range
444     *  of 1 in the image domain.  This parameter is ignored in reversible
445     *  coding.  Default: 0.0078125.
446     */
447    private QuantStepSizeSpec quantizationStep = null;
448
449    /** Specifies which quantization type to use for specified
450     *  tiles/components.  Not specified for lossless compression.  By
451     *  default , the quantization step size is "expounded".  Supported
452     *  quantization types specification are : "reversible" (no quantization),
453     *  "derived" (derived quantization step size) and "expounded".
454     */
455    private QuantTypeSpec quantizationType = null;
456
457    /** This parameter defines the lowest resolution levels to belong to
458     *  the ROI.  By doing this, it is possible to avoid only getting
459     *  information for the ROI at an early stage of transmission.
460     *  startLevelROI = 0 means the lowest resolution level belongs to
461     *  the ROI, 1 means the second lowest etc.  The default values, -1,
462     *  deactivates this parameter.
463     */
464    private int startLevelROI = -1;
465
466    /** By specifying this parameter, the ROI mask will be limited to
467     *  covering only entire code-blocks. The ROI coding can then be
468     *  performed without any actual scaling of the coefficients but
469     *  by instead scaling the distortion estimates.
470     */
471    private boolean alignROI = false;
472
473    /** Specifies ROIs shape and location. The component index specifies
474     *  which components contain the ROI.  If this parameter is used, the
475     *  codestream is layer progressive by default unless it is
476     *  overridden by the <code>progressionType</code>.
477     */
478    private MaxShiftSpec ROIs = null;
479
480    /** Specifies the maximum code-block size to use for tile-component.
481     *  The maximum width and height is 1024, however the image area
482     *  (i.e. width x height) must not exceed 4096. The minimum
483     *  width and height is 4.  Default: 64 64.
484     */
485    private CBlkSizeSpec codeBlockSize = null;
486
487    /** Uses the lazy coding mode with the entropy coder.  This will bypass
488     *  the MQ coder for some of the coding passes, where the distribution
489     *  is often close to uniform.  Since the MQ codeword will be terminated
490     *  at least once per lazy pass, it is important to use an efficient
491     *  termination algorithm, <code>methodForMQTermination</code>.
492     *  true enables, and false disables it.  Default: false.
493     */
494    private StringSpec bypass = null;
495
496    /** If this is enabled the probability estimates of the MQ coder are
497     *  reset after each arithmetically coded (i.e. non-lazy) coding pass.
498     *  true enables, and false disables it.  Default: false.
499     */
500    private StringSpec resetMQ = null;
501
502    /** If this is enabled the codeword (raw or MQ) is terminated on a byte
503     *  boundary after each coding pass. In this case it is important to
504     *  use an efficient termination algorithm, the "methodForMQTermination".
505     *  true enables, and false disables it.  Default: false.
506     */
507    private StringSpec terminateOnByte = null;
508
509    /** Uses vertically stripe causal context formation.  If this is
510     *  enabled the context formation process in one stripe is independant
511     *  of the next stripe (i.e. the one below it). true enables, and
512     *  false disables it.  Default: false.
513     */
514     private StringSpec causalCXInfo = null;
515
516    /** Inserts an error resilience segmentation symbol in the MQ codeword
517     *  at the end of each bit-plane (cleanup pass). Decoders can use this
518     *  information to detect and conceal errors. true enables,
519     *  and false disables it.  Default: false.
520     */
521     private StringSpec codeSegSymbol = null;
522
523    /** Specifies the algorithm used to terminate the MQ codeword.  The
524     *  most efficient one is "near_opt", which delivers a codeword which
525     *  in almost all cases is the shortest possible.  The "easy" is a
526     *  simpler algorithm that delivers a codeword length that is close
527     *  to the previous one (in average 1 bit longer).  The "predict" is
528     *  almost the same as the "easy" but it leaves error resilient
529     *  information on the spare least significant bits (in average
530     *  3.5 bits), which can be used by a decoder to detect errors.
531     *  The "full" algorithm performs a full flush of the MQ coder and
532     *  is highly inefficient.  It is important to use a good termination
533     *  policy since the MQ codeword can be terminated quite often,
534     *  specially if the "bypass" or "terminateOnByte" parameters are
535     *  enabled (in the normal case it would be terminated once per
536     *  code-block, while "terminateOnByte" is specified it will be
537     *  done almost 3 times per bit-plane in each code-block).
538     *  Default: near_opt.
539     */
540    private StringSpec methodForMQTermination = null;
541
542    /** Specifies the algorithm to use in calculating the necessary MQ
543     *  length for each decoding pass.  The best one is "near_opt", which
544     *  performs a rather sophisticated calculation and provides the best
545     *  results.  The "lazy_good" and "lazy" are very simple algorithms
546     *  that provide rather conservative results. "lazy_good" performs
547     *  slightly better.  Please use the default unless the experiments
548     *  show the benefits of different length calculation algorithms.
549     *  Default: near_opt.
550     */
551    private StringSpec methodForMQLengthCalc = null;
552
553    /** Specifies precinct partition dimensions for tiles/components.  They
554     *  are stored from those applied to the highest resolution to those
555     *  applied to the remaining resolutions in decreasing order.  If less
556     *  values than the number of decomposition levels are specified, then
557     *  the last two values are used for the remaining resolutions.
558     */
559    private PrecinctSizeSpec precinctPartition = null;
560
561    /** Specifies which type of progression should be used when generating
562     *  the codestream. The value "res" generates a resolution progressive
563     *  codestream with the number of layers specified by "layers" parameter.
564     *  The value "layer" generates a layer progressive codestream with
565     *  multiple layers.  In any case, the rate-allocation algorithm optimizes
566     *  for best quality in each layer.  The quality measure is mean squared
567     *  error (MSE) or a weighted version of it (WMSE).  If no progression
568     *  type is specified or imposed by other modules, the default value
569     *  is "layer".  It is also possible to describe progression order
570     *  changes.  In this case, "res_start" is the index (from 0) of the
571     *  first resolution level, "comp_start" is the index (from 0) of the
572     *  first component, "ly_end" is the index (from 0) of the first layer
573     *  not included, "res_end" is the index (from 0) of the first
574     *  resolution level not included, "comp_end" is index (from 0) of
575     *  the first component not included and "prog" is the progression type
576     *  to be used for the rest of the tile/image.  Several progression
577     *  order changes can be specified, one after the other.
578     */
579    private ProgressionSpec progressionType = null;
580
581    /**
582     * The specified (tile-component) progression.  Will be used to generate
583     * the progression type.
584     */
585    private String progressionName = null;
586
587    /** Explicitly specifies the codestream layer formation parameters.
588     *  The rate (double) parameter specifies the bitrate to which the first
589     *  layer should be optimized.  The layers (int) parameter, if present,
590     *  specifies the number of extra layers that should be added for
591     *  scalability.  These extra layers are not optimized.  Any extra rate
592     *  and layers parameters add more layers, in the same way.  An
593     *  additional layer is always added at the end, which is optimized
594     *  to the overall target bitrate of the bit stream. Any layers
595     *  (optimized or not) whose target bitrate is higher that the
596     *  overall target bitrate are silently ignored. The bitrates of
597     *  the extra layers that are added through the layers parameter
598     *  are approximately log-spaced between the other target bitrates.
599     *  If several (rate, layers) constructs appear the rate parameters
600     *  must appear in increasing order. The rate allocation algorithm
601     *  ensures that all coded layers have a minimal reasonable size,
602     *  if not these layers are silently ignored.  Default: 0.015 +20 2.0 +10.
603     */
604     private String layers = "0.015 +20 2.0 +10";
605
606    /** Specifies whether end of packet header (EPH) markers should be used.
607     *  true enables, false disables it.  Default: false.
608     */
609     private StringSpec EPH = null;
610
611    /** Specifies whether start of packet (SOP) markers should be used.
612     *  true enables, false disables it. Default: false.
613     */
614    private StringSpec SOP = null;
615
616    private int numTiles;
617    private int numComponents;
618
619    private RenderedImage imgsrc;
620    private Raster raster;
621
622    private int minX;
623    private int minY;
624
625    /** Constructor to set locales. */
626    public J2KImageWriteParamJava(RenderedImage imgsrc, Locale locale) {
627        super(locale);
628        setDefaults(imgsrc);
629    }
630
631    /** Constructor to set locales. */
632    public J2KImageWriteParamJava(IIOImage image,  ImageWriteParam param) {
633        super(param.getLocale());
634        if(image != null) {
635            if (image.hasRaster())
636                setDefaults(image.getRaster());
637            else
638                setDefaults(image.getRenderedImage());
639        }
640
641        setSourceRegion(param.getSourceRegion());
642        setSourceBands(param.getSourceBands());
643        try {
644            setTiling(param.getTileWidth(), param.getTileHeight(),
645                      param.getTileGridXOffset(), param.getTileGridYOffset());
646        } catch (IllegalStateException e) {
647            // tileing is not set do nothing.
648        }
649
650        setDestinationOffset(param.getDestinationOffset());
651        setSourceSubsampling(param.getSourceXSubsampling(),
652                             param.getSourceYSubsampling(),
653                             param.getSubsamplingXOffset(),
654                             param.getSubsamplingYOffset());
655        setDestinationType(param.getDestinationType());
656
657        J2KImageWriteParam j2kParam;
658        if(param instanceof J2KImageWriteParam) {
659            j2kParam = (J2KImageWriteParam)param;
660        } else {
661            j2kParam = new J2KImageWriteParam();
662        }
663
664        setDecompositionLevel(""+j2kParam.getNumDecompositionLevels());
665        setEncodingRate(j2kParam.getEncodingRate());
666        setLossless(j2kParam.getLossless());
667        setFilters(j2kParam.getFilter());
668        setEPH("" + j2kParam.getEPH());
669        setSOP("" + j2kParam.getSOP());
670        setProgressionName(j2kParam.getProgressionType());
671        int[] size = j2kParam.getCodeBlockSize();
672        setCodeBlockSize("" + size[0] +" " + size[1]);
673        enableCT = j2kParam.getComponentTransformation();
674        setComponentTransformation("" + enableCT);
675    }
676
677
678    /**
679     * Constructs a <code>J2KImageWriteParamJava</code> object with default
680     * values for all parameters.
681     */
682    public J2KImageWriteParamJava() {
683        super();
684        setSuperProperties();
685    }
686
687    /**
688     * Constructs a <code>J2KImageWriteParamJava</code> object with default
689     * values for all parameters.
690     */
691    public J2KImageWriteParamJava(RenderedImage imgsrc) {
692        super();
693        setDefaults(imgsrc);
694    }
695
696    /**
697     * Constructs a <code>J2KImageWriteParamJava</code> object with default
698     * values for all parameters.
699     */
700    public J2KImageWriteParamJava(Raster raster) {
701        super();
702        setDefaults(raster);
703    }
704
705    private void setSuperProperties() {
706        canOffsetTiles = true;
707        canWriteTiles = true;
708        canOffsetTiles = true;
709        canWriteProgressive = true;
710        tilingMode = MODE_EXPLICIT;
711    }
712
713    /** Set source */
714    private void setDefaults(Raster raster) {
715        // override the params in the super class
716        setSuperProperties();
717
718        if (raster != null) {
719            this.raster = raster;
720            tileGridXOffset = raster.getMinX();
721            tileGridYOffset = raster.getMinY();
722            tileWidth = raster.getWidth();
723            tileHeight = raster.getHeight();
724            tilingSet = true;
725
726            numTiles = 1;
727            numComponents = raster.getSampleModel().getNumBands();
728        }
729        setDefaults();
730    }
731
732    /** Set source */
733    private void setDefaults(RenderedImage imgsrc) {
734        // override the params in the super class
735        setSuperProperties();
736
737        tilingMode = MODE_EXPLICIT;
738
739        if (imgsrc != null) {
740            this.imgsrc = imgsrc;
741            tileGridXOffset = imgsrc.getTileGridXOffset();
742            tileGridYOffset = imgsrc.getTileGridYOffset();
743            tileWidth = imgsrc.getTileWidth();
744            tileHeight = imgsrc.getTileHeight();
745            tilingSet = true;
746
747            numTiles = imgsrc.getNumXTiles() * imgsrc.getNumYTiles();
748            numComponents = imgsrc.getSampleModel().getNumBands();
749        }
750        setDefaults();
751    }
752
753    private void setDefaults() {
754        setROIs(null);
755        setQuantizationType(null);
756        setQuantizationStep(null);
757        setGuardBits(null);
758        setFilters(null);
759        setDecompositionLevel(null);
760        setComponentTransformation(null);
761        setMethodForMQLengthCalc(null);
762        setMethodForMQTermination(null);
763        setCodeSegSymbol(null);
764        setCausalCXInfo(null);
765        setTerminateOnByte(null);
766        setResetMQ(null);
767        setBypass(null);
768        setCodeBlockSize(null);
769        setPrecinctPartition(null);
770        setSOP(null);
771        setEPH(null);
772    }
773
774    /** Sets <code>encodingRate</code> */
775    public void setEncodingRate(double rate) {
776        this.encodingRate = rate;
777    }
778
779    /** Gets <code>encodingRate</code> */
780    public double getEncodingRate() {
781        return encodingRate;
782    }
783
784    /** Sets <code>lossless</code> */
785    public void setLossless(boolean lossless) {
786        this.lossless = lossless;
787    }
788
789    /** Gets <code>encodingRate</code> */
790    public boolean getLossless() {
791        return lossless;
792    }
793    /** Sets <code>packetPerTilePart</code> */
794    public void setPacketPerTilePart(int packetPerTilePart) {
795        if (packetPerTilePart < 0)
796            throw new IllegalArgumentException(I18N.getString("J2KImageWriteParamJava0"));
797
798        this.packetPerTilePart = packetPerTilePart;
799        if (packetPerTilePart > 0) {
800            setSOP("true");
801            setEPH("true");
802        }
803    }
804
805    /** Gets <code>packetPerTilePart</code> */
806    public int getPacketPerTilePart() {
807        return packetPerTilePart;
808    }
809
810    /** Sets <code>packPacketHeaderInTile</code> */
811    public void setPackPacketHeaderInTile(boolean packPacketHeaderInTile) {
812        this.packPacketHeaderInTile = packPacketHeaderInTile;
813        if (packPacketHeaderInTile) {
814            setSOP("true");
815            setEPH("true");
816        }
817    }
818
819    /** Gets <code>packPacketHeaderInTile</code> */
820    public boolean getPackPacketHeaderInTile() {
821        return packPacketHeaderInTile;
822    }
823
824    /** Sets <code>packPacketHeaderInMain</code> */
825    public void setPackPacketHeaderInMain(boolean packPacketHeaderInMain) {
826        this.packPacketHeaderInMain = packPacketHeaderInMain;
827        if (packPacketHeaderInMain) {
828            setSOP("true");
829            setEPH("true");
830        }
831    }
832
833    /** Gets <code>packPacketHeaderInMain</code> */
834    public boolean getPackPacketHeaderInMain() {
835        return packPacketHeaderInMain;
836    }
837
838    /** Sets <code>alignROI</code> */
839    public void setAlignROI(boolean align) {
840        alignROI = align;
841    }
842
843    /** Gets <code>alignROI</code> */
844    public boolean getAlignROI() {
845        return alignROI;
846    }
847
848    /** Sets <code>ROIs</code> */
849    public void setROIs(String values) {
850        ROIs = new MaxShiftSpec(numTiles, numComponents, ModuleSpec.SPEC_TYPE_TILE_COMP, values);
851    }
852
853    /** Gets <code>ROIs</code> */
854    public MaxShiftSpec getROIs() {
855        return ROIs;
856    }
857
858    /** Sets <code>quantizationType</code> */
859    public void setQuantizationType(String values) {
860        quantizationType = new QuantTypeSpec(numTiles, numComponents,
861                ModuleSpec.SPEC_TYPE_TILE_COMP, this, values);
862    }
863
864    /** Gets <code>quantizationType</code> */
865    public QuantTypeSpec getQuantizationType() {
866        return quantizationType;
867    }
868
869    /** Sets <code>quantizationStep</code> */
870    public void setQuantizationStep(String values) {
871        quantizationStep = new QuantStepSizeSpec(numTiles,
872                                                 numComponents,
873                                                 ModuleSpec.SPEC_TYPE_TILE_COMP,
874                                                 this,
875                                                 values);
876    }
877
878    /** Gets <code>quantizationStep</code> */
879    public QuantStepSizeSpec getQuantizationStep() {
880        return quantizationStep;
881    }
882
883    /** Sets <code>guardBits</code> */
884    public void setGuardBits(String values) {
885        guardBits = new GuardBitsSpec(numTiles,
886                                      numComponents,
887                                      ModuleSpec.SPEC_TYPE_TILE_COMP,
888                                      this,
889                                      values);
890    }
891
892    /** Gets <code>guardBits</code> */
893    public GuardBitsSpec getGuardBits() {
894        return guardBits;
895    }
896
897    /** Sets <code>filters</code> */
898    // NOTE This also sets quantizationType and componentTransformation.
899    public void setFilters(String values) {
900        if (J2KImageWriteParam.FILTER_97.equals(values))
901            setQuantizationType ("expounded");
902        else
903            setQuantizationType("reversible");
904
905        filters = new AnWTFilterSpec(numTiles,
906                                     numComponents,
907                                     ModuleSpec.SPEC_TYPE_TILE_COMP,
908                                     (QuantTypeSpec)quantizationType,
909                                     this,
910                                     values);
911        setComponentTransformation(""+enableCT);
912    }
913
914    /** Gets <code>filters</code> */
915    public AnWTFilterSpec getFilters() {
916        return filters;
917    }
918
919    /** Sets <code>decompositionLevel</code> */
920    public void setDecompositionLevel(String values) {
921        decompositionLevel = new IntegerSpec(numTiles,
922                                             numComponents,
923                                             ModuleSpec.SPEC_TYPE_TILE_COMP,
924                                             this,
925                                             values,
926                                             "5");
927
928        // NOTE The precinctPartition depends upon decompositionLevel
929        // so it needs to be re-initialized. Note that the parameter of
930        // setPrecinctPartition() is not used in the current implementation.
931        setPrecinctPartition(null);
932    }
933
934    /** Gets <code>decompositionLevel</code> */
935    public IntegerSpec getDecompositionLevel() {
936        return decompositionLevel;
937    }
938
939    /** Sets <code>componentTransformation</code> */
940    // NOTE This requires filters having been set previously.
941    public void setComponentTransformation(String values) {
942        componentTransformation =
943            new ForwCompTransfSpec(numTiles,
944                                   numComponents,
945                                   ModuleSpec.SPEC_TYPE_TILE,
946                                   (AnWTFilterSpec)filters,
947                                   this,
948                                   values);
949    }
950
951    /** Gets <code>componentTransformation</code> */
952    public ForwCompTransfSpec getComponentTransformation() {
953        return componentTransformation;
954    }
955    /** Sets <code>methodForMQLengthCalc</code> */
956    public void setMethodForMQLengthCalc(String values) {
957        String[] strLcs = {"near_opt","lazy_good","lazy"};
958        methodForMQLengthCalc =
959            new StringSpec(numTiles,
960                           numComponents,
961                           ModuleSpec.SPEC_TYPE_TILE_COMP,
962                           "near_opt",
963                           strLcs,
964                           this,
965                           values);
966    }
967
968    /** Gets <code>methodForMQLengthCalc</code> */
969    public StringSpec getMethodForMQLengthCalc() {
970        return methodForMQLengthCalc;
971    }
972
973    /** Sets <code>methodForMQTermination</code> */
974    public void setMethodForMQTermination(String values) {
975        String[] strTerm = {"near_opt","easy","predict","full"};
976        methodForMQTermination =
977            new StringSpec(numTiles,
978                           numComponents,
979                           ModuleSpec.SPEC_TYPE_TILE_COMP,
980                           "near_opt",
981                           strTerm,
982                           this,
983                           values);
984    }
985
986    /** Gets <code>methodForMQTermination</code> */
987    public StringSpec getMethodForMQTermination() {
988        return methodForMQTermination;
989    }
990
991    /** Sets <code>codeSegSymbol</code> */
992    public void setCodeSegSymbol(String values) {
993        String[] strBoolean = {"true","false"};
994        codeSegSymbol =
995            new StringSpec(numTiles,
996                           numComponents,
997                           ModuleSpec.SPEC_TYPE_TILE_COMP,
998                           "false",
999                           strBoolean,
1000                           this,
1001                           values);
1002    }
1003
1004    /** Gets <code>codeSegSymbol</code> */
1005    public StringSpec getCodeSegSymbol() {
1006        return codeSegSymbol;
1007    }
1008
1009    /** Sets <code>causalCXInfo</code> */
1010    public void setCausalCXInfo(String values) {
1011        String[] strBoolean = {"true","false"};
1012        causalCXInfo = new StringSpec(numTiles,
1013                                      numComponents,
1014                                      ModuleSpec.SPEC_TYPE_TILE_COMP,
1015                                      "false",
1016                                      strBoolean,
1017                                      this,
1018                                      values);
1019    }
1020
1021    /** Gets <code>causalCXInfo</code> */
1022    public StringSpec getCausalCXInfo() {
1023        return causalCXInfo;
1024    }
1025
1026    /** Sets <code>terminateOnByte</code> */
1027    public void setTerminateOnByte(String values) {
1028        String[] strBoolean = {"true","false"};
1029        terminateOnByte = new StringSpec(numTiles,
1030                                         numComponents,
1031                                         ModuleSpec.SPEC_TYPE_TILE_COMP,
1032                                         "false",
1033                                         strBoolean,
1034                                         this,
1035                                         values);
1036    }
1037
1038    /** Gets <code>terminateOnByte</code> */
1039    public StringSpec getTerminateOnByte() {
1040        return terminateOnByte;
1041    }
1042
1043    /** Sets <code>resetMQ</code> */
1044    public void setResetMQ(String values) {
1045        String[] strBoolean = {"true","false"};
1046        resetMQ = new StringSpec(numTiles,
1047                                 numComponents,
1048                                 ModuleSpec.SPEC_TYPE_TILE_COMP,
1049                                 "false",
1050                                 strBoolean,
1051                                 this,
1052                                 values);
1053    }
1054
1055    /** Gets <code>resetMQ</code> */
1056    public StringSpec getResetMQ() {
1057        return resetMQ;
1058    }
1059
1060    /** Sets <code>bypass</code> */
1061    public void setBypass(String values) {
1062        String[] strBoolean = {"true","false"};
1063        bypass = new StringSpec(numTiles,
1064                                numComponents,
1065                                ModuleSpec.SPEC_TYPE_TILE_COMP,
1066                                "false",
1067                                strBoolean,
1068                                this,
1069                                values);
1070    }
1071
1072    /** Gets <code>bypass</code> */
1073    public StringSpec getBypass() {
1074        return bypass;
1075    }
1076
1077    /** Sets <code>codeBlockSize</code> */
1078    public void setCodeBlockSize(String values) {
1079        codeBlockSize = new CBlkSizeSpec(numTiles,
1080                                         numComponents,
1081                                         ModuleSpec.SPEC_TYPE_TILE_COMP,
1082                                         this,
1083                                         values);
1084    }
1085
1086    /** Gets <code>codeBlockSize</code> */
1087    public CBlkSizeSpec getCodeBlockSize() {
1088        return codeBlockSize;
1089    }
1090
1091    /** Sets <code>precinctPartition</code> */
1092    public void setPrecinctPartition(String values) {
1093        String[] strBoolean = {"true","false"};
1094        if (imgsrc != null)
1095            precinctPartition =
1096                new PrecinctSizeSpec(numTiles,
1097                                     numComponents,
1098                                     ModuleSpec.SPEC_TYPE_TILE_COMP,
1099                                     new RenderedImageSrc(imgsrc, this, null),
1100                                     decompositionLevel,
1101                                     this,
1102                                     values);
1103        else if (raster != null)
1104            precinctPartition =
1105                new PrecinctSizeSpec(numTiles,
1106                                     numComponents,
1107                                     ModuleSpec.SPEC_TYPE_TILE_COMP,
1108                                     new RenderedImageSrc(raster, this, null),
1109                                     decompositionLevel,
1110                                     this,
1111                                     values);
1112    }
1113
1114    /** Gets <code>precinctPartition</code> */
1115    public PrecinctSizeSpec getPrecinctPartition() {
1116        return precinctPartition;
1117    }
1118
1119    /** Sets <code>SOP</code> */
1120    public void setSOP(String values) {
1121            String[] strBoolean = {"true","false"};
1122            SOP = new StringSpec(numTiles,
1123                                 numComponents,
1124                                 ModuleSpec.SPEC_TYPE_TILE_COMP,
1125                                 "false",
1126                                 strBoolean,
1127                                 this,
1128                                 values);
1129    }
1130
1131    /** Gets <code>SOP</code> */
1132    public StringSpec getSOP() {
1133        return SOP;
1134    }
1135
1136    /** Sets <code>EPH</code> */
1137    public void setEPH(String values) {
1138        String[] strBoolean = {"true","false"};
1139        EPH = new StringSpec(numTiles,
1140                             numComponents,
1141                             ModuleSpec.SPEC_TYPE_TILE_COMP,
1142                             "false",
1143                             strBoolean,
1144                             this,
1145                             values);
1146    }
1147
1148    /** Gets <code>EPH</code> */
1149    public StringSpec getEPH() {
1150        return EPH;
1151    }
1152
1153    /** Sets <code>progressionName</code> */
1154    public void setProgressionName(String values) {
1155        progressionName = values;
1156    }
1157
1158    /** Gets <code>progressionType</code> */
1159    public String getProgressionName() {
1160        return progressionName;
1161    }
1162
1163    /** Sets <code>progressionType</code> */
1164    public void setProgressionType(LayersInfo lyrs, String values) {
1165        String[] strBoolean = {"true","false"};
1166        progressionType = new ProgressionSpec(numTiles,
1167                                              numComponents,
1168                                              lyrs.getTotNumLayers(),
1169                                              decompositionLevel,
1170                                              ModuleSpec.SPEC_TYPE_TILE_COMP,
1171                                              this,
1172                                              values);
1173    }
1174
1175    /** Gets <code>progressionType</code> */
1176    public ProgressionSpec getProgressionType() {
1177        return progressionType;
1178    }
1179
1180    /** Sets the <code>startLevelROI</code> */
1181    public void setStartLevelROI(int value) {
1182        startLevelROI = value;
1183    }
1184
1185    /** Gets <code>startLevel</code> */
1186    public int getStartLevelROI() {
1187        return startLevelROI;
1188    }
1189
1190    /** Sets the <code>layers</code> */
1191    public void setLayers(String value) {
1192        layers = value;
1193    }
1194
1195    /** Gets <code>layers</code> */
1196    public String getLayers() {
1197        return layers;
1198    }
1199
1200    /** Sets <code>minX</code> */
1201    public void setMinX(int minX) {
1202        this.minX = minX;
1203    }
1204
1205    /** Gets <code>minX</code> */
1206    public int getMinX() {
1207        return minX;
1208    }
1209
1210    /** Sets <code>minY</code> */
1211    public void setMinY(int minY) {
1212        this.minY = minY;
1213    }
1214
1215    /** Gets <code>minY</code> */
1216    public int getMinY() {
1217        return minY;
1218    }
1219
1220    /** Gets the number of tiles */
1221    public int getNumTiles() {
1222        Rectangle sourceRegion = getSourceRegion();
1223        if (sourceRegion == null) {
1224            if (imgsrc != null)
1225                sourceRegion = new Rectangle(imgsrc.getMinX(),
1226                                         imgsrc.getMinY(),
1227                                         imgsrc.getWidth(),
1228                                         imgsrc.getHeight());
1229            else  sourceRegion = raster.getBounds();
1230        } else {
1231            if (imgsrc != null)
1232                sourceRegion =
1233                    sourceRegion.intersection(new Rectangle(imgsrc.getMinX(),
1234                                         imgsrc.getMinY(),
1235                                         imgsrc.getWidth(),
1236                                         imgsrc.getHeight()));
1237            else  sourceRegion = sourceRegion.intersection(raster.getBounds());
1238        }
1239
1240        int scaleX = getSourceXSubsampling();
1241        int scaleY = getSourceYSubsampling();
1242        int xOffset = getSubsamplingXOffset();
1243        int yOffset = getSubsamplingYOffset();
1244
1245        int w = (sourceRegion.width - xOffset + scaleX - 1) / scaleX;
1246        int h = (sourceRegion.height - yOffset + scaleY - 1) / scaleY;
1247
1248        minX = (sourceRegion.x + xOffset) / scaleX;
1249        minY = (sourceRegion.y + yOffset) / scaleY;
1250
1251        numTiles = (int)((Math.floor((minX + w + tileWidth - 1.0) / tileWidth) -
1252                   Math.floor((double)minX/tileWidth) ) *
1253                   (Math.floor((minY + h + tileHeight - 1.0) / tileHeight) -
1254                   Math.floor((double)minY/tileHeight) ) );
1255        tileGridXOffset += (minX - tileGridXOffset) / tileWidth * tileWidth;
1256        tileGridYOffset += (minY - tileGridYOffset) / tileHeight * tileHeight;
1257
1258        return numTiles;
1259    }
1260
1261    /** Gets the number of components */
1262    public int getNumComponents() {
1263        return numComponents;
1264    }
1265
1266    /** Override the method setSourceBands in the super class.  This method
1267     *  should be called before any tile-specific parameter setting method
1268     *  to be called.
1269     */
1270    public void setSourceBands(int[] bands) {
1271        super.setSourceBands(bands);
1272        if (bands != null) {
1273            numComponents = bands.length;
1274            setDefaults();
1275        }
1276    }
1277
1278    /** Override the method setTiling in the super class.  This method
1279     *  should be called before any tile-specific parameter setting method
1280     *  to be called.
1281     */
1282    public void setTiling(int tw, int th, int xOff, int yOff) {
1283        super.setTiling(tw, th, xOff, yOff);
1284        getNumTiles();
1285        setDefaults();
1286    }
1287
1288    /** Override the method setSourceSubsampling in the super class.  This
1289     *  method should be called before any tile-specific parameter setting
1290     *  method to be called.
1291     */
1292    public void setSourceSubsampling(int sx, int sy, int xOff, int yOff) {
1293        super.setSourceSubsampling(sx, sy, xOff, yOff);
1294        getNumTiles();
1295        setDefaults();
1296    }
1297}