001/*
002 * $RCSfile: J2KImageWriteParam.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.github.jaiimageio.jpeg2000;
046
047import java.util.Locale;
048
049import javax.imageio.ImageWriteParam;
050
051/**
052 * A subclass of <code>ImageWriteParam</code> for writing images in
053 * the JPEG 2000 format.
054 *
055 * <p>JPEG 2000 plugin supports to losslessly or lossy compress gray-scale,
056 * RGB, and RGBA images with byte, unsigned short or short data type.  It also
057 * supports losslessly compress bilevel, and 8-bit color indexed images.  The
058 * result data is in the of JP2 format -- JPEG 2000 Part 1 or baseline format.
059 *
060 * <p>The parameters for encoding JPEG 2000 are listed in the following table:
061 *
062 * <p><table border=1>
063 * <caption><b>JPEG 2000 Plugin Decoding Parameters</b></caption>
064 * <tr><th>Parameter Name</th> <th>Description</th></tr>
065 * <tr>
066 *    <td>numDecompositionLevels</td>
067 *    <td> The number of decomposition levels to generate. This value must
068 *         be in the range
069 *         <code>0&nbsp;&le;&nbsp;numDecompositionLevels&nbsp;&le;&nbsp;32
070 *         </code>. The default value is <code>5</code>. Note that the number
071 *         of resolution levels is
072 *         <code>numDecompositionLevels&nbsp;+&nbsp;1</code>.
073 *         The number of decomposition levels is constant across
074 *         all components and all tiles.
075 *    </td>
076 * </tr>
077 * <tr>
078 *    <td>encodingRate</td>
079 *    <td> The bitrate in bits-per-pixel for encoding.  Should be set when
080 *    lossy compression scheme is used.  With the default value
081 *    <code>Double.MAX_VALUE</code>, a lossless compression will be done.
082 *    </td>
083 * </tr>
084 * <tr>
085 *    <td>lossless</td>
086 *    <td> Indicates using the lossless scheme or not.  It is equivalent to
087 *    use reversible quantization and 5x3 integer wavelet filters.  The
088 *    default is <code>true</code>.
089 *    </td>
090 * </tr>
091 * <tr>
092 *    <td>componentTransformation</td>
093 *    <td> Specifies to utilize the component transformation on some tiles.
094 *    If the wavelet transform is reversible (w5x3 filter), the Reversible
095 *    Component Transformation (RCT) is applied. If not reversible
096 *    (w9x7 filter), the Irreversible Component Transformation (ICT) is used.
097 *    </td>
098 * </tr>
099 * <tr>
100 *    <td>filters</td>
101 *    <td> Specifies which wavelet filters to use for the specified
102 *    tile-components.  JPEG 2000 part I only supports w5x3 and w9x7 filters.
103 *    </td>
104 * </tr>
105 * <tr>
106 *    <td>codeBlockSize</td>
107 *    <td> Specifies the maximum code-block size to use for tile-component.
108 *    The maximum width and height is 1024, however the block size
109 *    (i.e. width x height) must not exceed 4096.  The minimum width and
110 *    height is 4.  The default values are (64, 64).
111 *    </td>
112 * </tr>
113 * <tr>
114 *    <td>progressionType</td>
115 *    <td> Specifies which type of progression should be used when generating
116 *    the codestream.
117 *    <p> The format is ont of the progression types defined below:
118 *
119 *    <p> res : Resolution-Layer-Component-Position
120 *    <p> layer: Layer-Resolution-Component-Position
121 *    <p> res-pos: Resolution-Position-Component-Layer
122 *    <p> pos-comp: Position-Component-Resolution-Layer
123 *    <p> comp-pos: Component-Position-Resolution-Layer
124 *    </td>
125 * </tr>
126 * <tr>
127 *    <td>SOP</td>
128 *    <td>Specifies whether start of packet (SOP) markers should be used.
129 *    true enables, false disables it.  The default value is false.
130 *    </td>
131 * </tr>
132 * <tr>
133 *    <td>EPH</td>
134 *    <td>Specifies whether end of packet header (EPH) markers should be used.
135 *    true enables, false disables it.  The default value is false.
136 *    </td>
137 * </tr>
138 * <tr>
139 *    <td>writeCodeStreamOnly</td>
140 *    <td>Specifies whether write only the jpeg2000 code stream, i.e, no any
141 *    box is written.  The default value is false.
142 *    </td>
143 * </tr> 
144 * </table>
145 */
146public class J2KImageWriteParam extends ImageWriteParam {
147    /** The filter for lossy compression. */
148    public static final String FILTER_97 = "w9x7";
149
150    /** The filter for lossless compression. */
151    public static final String FILTER_53 = "w5x3";
152
153    /**
154     * The number of decomposition levels.
155     */
156    private int numDecompositionLevels = 5;
157
158    /**
159     * The bitrate in bits-per-pixel for encoding.  Should be set when lossy
160     * compression scheme is used.  The default is
161     * <code>Double.MAX_VALUE</code>.
162     */
163    private double encodingRate = Double.MAX_VALUE;
164
165    /**
166     * Indicates using the lossless scheme or not.  It is equivalent to
167     * use reversible quantization and 5x3 integer wavelet filters.
168     */
169    private boolean lossless = true;
170
171    /** Specifies to utilize the component transformation with some tiles.
172     *  If the wavelet transform is reversible (w5x3 filter), the
173     *  Reversible Component Transformation (RCT) is applied. If not reversible
174     *  (w9x7 filter), the Irreversible Component Transformation (ICT)
175     *  is used.
176     */
177    private boolean componentTransformation = true;
178
179    /** Specifies which filters to use for the specified tile-components.
180     *  JPEG 2000 part I only supports w5x3 and w9x7 filters.
181     */
182    private String filter = FILTER_53;
183
184    /** Specifies the maximum code-block size to use for tile-component.
185     *  The maximum width and height is 1024, however the image area
186     *  (i.e. width x height) must not exceed 4096. The minimum
187     *  width and height is 4.  Default: 64 64.
188     */
189    private int[] codeBlockSize = new int[]{64, 64};
190
191    /** See above.
192     */
193    private String progressionType = "layer";
194
195    /** Specifies whether end of packet header (EPH) markers should be used.
196     *  true enables, false disables it.  Default: false.
197     */
198     private boolean EPH = false;
199
200    /** Specifies whether start of packet (SOP) markers should be used.
201     *  true enables, false disables it. Default: false.
202     */
203    private boolean SOP = false;
204
205    /** Specifies whether write only the jpeg2000 code stream, i.e, no any
206     *  box is written.  The default value is false.
207     */
208    private boolean writeCodeStreamOnly = false;
209
210    /**
211     * Constructor which sets the <code>Locale</code>.
212     *
213     * @param locale a <code>Locale</code> to be used to localize
214     * compression type names and quality descriptions, or
215     * <code>null</code>.
216     */
217    public J2KImageWriteParam(Locale locale) {
218        super(locale);
219        setDefaults();
220    }
221
222    /**
223     * Constructs a <code>J2KImageWriteParam</code> object with default
224     * values for all parameters.
225     */
226    public J2KImageWriteParam() {
227        super();
228        setDefaults();
229    }
230
231    /** Set source */
232    private void setDefaults() {
233        // override the params in the super class
234        canOffsetTiles = true;
235        canWriteTiles = true;
236        canOffsetTiles = true;
237        compressionTypes = new String[] {"JPEG2000"};
238        canWriteCompressed = true;
239        tilingMode = MODE_EXPLICIT;
240    }
241
242    /**
243     * Sets <code>numDecompositionLevels</code>.
244     *
245     * @param numDecompositionLevels the number of decomposition levels.
246     * @throws IllegalArgumentException if <code>numDecompositionLevels</code>
247     * is negative or greater than 32.
248     * @see #getNumDecompositionLevels
249     */
250    public void setNumDecompositionLevels(int numDecompositionLevels) {
251        if(numDecompositionLevels < 0 || numDecompositionLevels > 32) {
252            throw new IllegalArgumentException
253                ("numDecompositionLevels < 0 || numDecompositionLevels > 32");
254        }
255        this.numDecompositionLevels = numDecompositionLevels;
256    }
257
258    /**
259     * Gets <code>numDecompositionLevels</code>.
260     *
261     * @return the number of decomposition levels.
262     * @see #setNumDecompositionLevels
263     */
264    public int getNumDecompositionLevels() {
265        return numDecompositionLevels;
266    }
267
268    /**
269     * Sets <code>encodingRate</code>.
270     *
271     * @param rate the encoding rate in bits-per-pixel.
272     * @see #getEncodingRate()
273     */
274    public void setEncodingRate(double rate) {
275        this.encodingRate = rate;
276        if (encodingRate != Double.MAX_VALUE) {
277            lossless = false;
278            filter = FILTER_97;
279        } else {
280            lossless = true;
281            filter = FILTER_53;
282        }
283    }
284
285    /**
286     * Gets <code>encodingRate</code>.
287     *
288     * @return the encoding rate in bits-per-pixel.
289     * @see #setEncodingRate(double)
290     */
291    public double getEncodingRate() {
292        return encodingRate;
293    }
294
295    /**
296     * Sets <code>lossless</code>.
297     *
298     * @param lossless whether the compression scheme is lossless.
299     * @see #getLossless()
300     */
301    public void setLossless(boolean lossless) {
302        this.lossless = lossless;
303    }
304
305    /**
306     * Gets <code>lossless</code>.
307     *
308     * @return whether the compression scheme is lossless.
309     * @see #setLossless(boolean)
310     */
311    public boolean getLossless() {
312        return lossless;
313    }
314
315    /**
316     * Sets <code>filter</code>.
317     *
318     * @param value which wavelet filters to use for the specified
319     * tile-components.
320     * @see #getFilter()
321     */
322    public void setFilter(String value) {
323        filter = value;
324    }
325
326    /**
327     * Gets <code>filters</code>.
328     *
329     * @return which wavelet filters to use for the specified
330     * tile-components.
331     * @see #setFilter(String)
332     */
333    public String getFilter() {
334        return filter;
335    }
336
337    /**
338     * Sets <code>componentTransformation</code>.
339     *
340     * @param value whether to utilize the component transformation.
341     * @see #getComponentTransformation()
342     */
343    public void setComponentTransformation(boolean value) {
344        componentTransformation = value;
345    }
346
347    /**
348     * Gets <code>componentTransformation</code>.
349     *
350     * @return whether to utilize the component transformation.
351     * @see #setComponentTransformation(boolean)
352     */
353    public boolean getComponentTransformation() {
354        return componentTransformation;
355    }
356
357    /**
358     * Sets <code>codeBlockSize</code>.
359     *
360     * @param value the maximum code-block size to use per tile-component.
361     * @see #getCodeBlockSize()
362     */
363    public void setCodeBlockSize(int[] value) {
364        codeBlockSize = value;
365    }
366
367    /**
368     * Gets <code>codeBlockSize</code>.
369     *
370     * @return the maximum code-block size to use per tile-component.
371     * @see #setCodeBlockSize(int[])
372     */
373    public int[] getCodeBlockSize() {
374        return codeBlockSize;
375    }
376
377    /**
378     * Sets <code>SOP</code>.
379     *
380     * @param value whether start of packet (SOP) markers should be used.
381     * @see #getSOP()
382     */
383    public void setSOP(boolean value) {
384        SOP = value;
385    }
386
387    /**
388     * Gets <code>SOP</code>.
389     *
390     * @return whether start of packet (SOP) markers should be used.
391     * @see #setSOP(boolean)
392     */
393    public boolean getSOP() {
394        return SOP;
395    }
396
397    /**
398     * Sets <code>EPH</code>.
399     *
400     * @param value whether end of packet header (EPH) markers should be used.
401     * @see #getEPH()
402     */
403    public void setEPH(boolean value) {
404        EPH = value;
405    }
406
407    /**
408     * Gets <code>EPH</code>.
409     *
410     * @return whether end of packet header (EPH) markers should be used.
411     * @see #setEPH(boolean)
412     */
413    public boolean getEPH() {
414        return EPH;
415    }
416
417    /**
418     * Sets <code>progressionType</code>.
419     *
420     * @param value which type of progression should be used when generating
421     * the codestream.
422     * @see #getProgressionType()
423     */
424    public void setProgressionType(String value) {
425        progressionType = value;
426    }
427
428    /**
429     * Gets <code>progressionType</code>.
430     *
431     * @return which type of progression should be used when generating
432     * the codestream.
433     * @see #setProgressionType(String)
434     */
435    public String getProgressionType() {
436        return progressionType;
437    }
438
439    /** Sets <code>writeCodeStreamOnly</code>.
440     *
441     * @param value Whether the jpeg2000 code stream only or the jp2 format
442     *         will be written into the output.
443     * @see #getWriteCodeStreamOnly()
444     */
445    public void setWriteCodeStreamOnly(boolean value) {
446        writeCodeStreamOnly = value;
447    }
448
449    /** Gets <code>writeCodeStreamOnly</code>.
450     *
451     * @return whether the jpeg2000 code stream only or the jp2 format
452     *         will be written into the output.
453     * @see #setWriteCodeStreamOnly(boolean)
454     */
455    public boolean  getWriteCodeStreamOnly() {
456        return writeCodeStreamOnly;
457    }
458}