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 one 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        canWriteProgressive= true;
240        tilingMode = MODE_EXPLICIT;
241    }
242
243    /**
244     * Sets <code>numDecompositionLevels</code>.
245     *
246     * @param numDecompositionLevels the number of decomposition levels.
247     * @throws IllegalArgumentException if <code>numDecompositionLevels</code>
248     * is negative or greater than 32.
249     * @see #getNumDecompositionLevels
250     */
251    public void setNumDecompositionLevels(int numDecompositionLevels) {
252        if(numDecompositionLevels < 0 || numDecompositionLevels > 32) {
253            throw new IllegalArgumentException
254                ("numDecompositionLevels < 0 || numDecompositionLevels > 32");
255        }
256        this.numDecompositionLevels = numDecompositionLevels;
257    }
258
259    /**
260     * Gets <code>numDecompositionLevels</code>.
261     *
262     * @return the number of decomposition levels.
263     * @see #setNumDecompositionLevels
264     */
265    public int getNumDecompositionLevels() {
266        return numDecompositionLevels;
267    }
268
269    /**
270     * Sets <code>encodingRate</code>.
271     *
272     * @param rate the encoding rate in bits-per-pixel.
273     * @see #getEncodingRate()
274     */
275    public void setEncodingRate(double rate) {
276        this.encodingRate = rate;
277        if (encodingRate != Double.MAX_VALUE) {
278            lossless = false;
279            filter = FILTER_97;
280        } else {
281            lossless = true;
282            filter = FILTER_53;
283        }
284    }
285
286    /**
287     * Gets <code>encodingRate</code>.
288     *
289     * @return the encoding rate in bits-per-pixel.
290     * @see #setEncodingRate(double)
291     */
292    public double getEncodingRate() {
293        return encodingRate;
294    }
295
296    /**
297     * Sets <code>lossless</code>.
298     *
299     * @param lossless whether the compression scheme is lossless.
300     * @see #getLossless()
301     */
302    public void setLossless(boolean lossless) {
303        this.lossless = lossless;
304    }
305
306    /**
307     * Gets <code>lossless</code>.
308     *
309     * @return whether the compression scheme is lossless.
310     * @see #setLossless(boolean)
311     */
312    public boolean getLossless() {
313        return lossless;
314    }
315
316    /**
317     * Sets <code>filter</code>.
318     *
319     * @param value which wavelet filters to use for the specified
320     * tile-components.
321     * @see #getFilter()
322     */
323    public void setFilter(String value) {
324        filter = value;
325    }
326
327    /**
328     * Gets <code>filters</code>.
329     *
330     * @return which wavelet filters to use for the specified
331     * tile-components.
332     * @see #setFilter(String)
333     */
334    public String getFilter() {
335        return filter;
336    }
337
338    /**
339     * Sets <code>componentTransformation</code>.
340     *
341     * @param value whether to utilize the component transformation.
342     * @see #getComponentTransformation()
343     */
344    public void setComponentTransformation(boolean value) {
345        componentTransformation = value;
346    }
347
348    /**
349     * Gets <code>componentTransformation</code>.
350     *
351     * @return whether to utilize the component transformation.
352     * @see #setComponentTransformation(boolean)
353     */
354    public boolean getComponentTransformation() {
355        return componentTransformation;
356    }
357
358    /**
359     * Sets <code>codeBlockSize</code>.
360     *
361     * @param value the maximum code-block size to use per tile-component.
362     * @see #getCodeBlockSize()
363     */
364    public void setCodeBlockSize(int[] value) {
365        codeBlockSize = value;
366    }
367
368    /**
369     * Gets <code>codeBlockSize</code>.
370     *
371     * @return the maximum code-block size to use per tile-component.
372     * @see #setCodeBlockSize(int[])
373     */
374    public int[] getCodeBlockSize() {
375        return codeBlockSize;
376    }
377
378    /**
379     * Sets <code>SOP</code>.
380     *
381     * @param value whether start of packet (SOP) markers should be used.
382     * @see #getSOP()
383     */
384    public void setSOP(boolean value) {
385        SOP = value;
386    }
387
388    /**
389     * Gets <code>SOP</code>.
390     *
391     * @return whether start of packet (SOP) markers should be used.
392     * @see #setSOP(boolean)
393     */
394    public boolean getSOP() {
395        return SOP;
396    }
397
398    /**
399     * Sets <code>EPH</code>.
400     *
401     * @param value whether end of packet header (EPH) markers should be used.
402     * @see #getEPH()
403     */
404    public void setEPH(boolean value) {
405        EPH = value;
406    }
407
408    /**
409     * Gets <code>EPH</code>.
410     *
411     * @return whether end of packet header (EPH) markers should be used.
412     * @see #setEPH(boolean)
413     */
414    public boolean getEPH() {
415        return EPH;
416    }
417
418    /**
419     * Sets <code>progressionType</code>.
420     *
421     * @param value which type of progression should be used when generating
422     * the codestream.
423     * @see #getProgressionType()
424     */
425    public void setProgressionType(String value) {
426        progressionType = value;
427    }
428
429    /**
430     * Gets <code>progressionType</code>.
431     *
432     * @return which type of progression should be used when generating
433     * the codestream.
434     * @see #setProgressionType(String)
435     */
436    public String getProgressionType() {
437        return progressionType;
438    }
439
440    /** Sets <code>writeCodeStreamOnly</code>.
441     *
442     * @param value Whether the jpeg2000 code stream only or the jp2 format
443     *         will be written into the output.
444     * @see #getWriteCodeStreamOnly()
445     */
446    public void setWriteCodeStreamOnly(boolean value) {
447        writeCodeStreamOnly = value;
448    }
449
450    /** Gets <code>writeCodeStreamOnly</code>.
451     *
452     * @return whether the jpeg2000 code stream only or the jp2 format
453     *         will be written into the output.
454     * @see #setWriteCodeStreamOnly(boolean)
455     */
456    public boolean  getWriteCodeStreamOnly() {
457        return writeCodeStreamOnly;
458    }
459}