Home | History | Annotate | Download | only in imageio
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 /**
     18  * @author Rustem V. Rafikov
     19  * @version $Revision: 1.3 $
     20  */
     21 
     22 package javax.imageio;
     23 
     24 import java.util.Locale;
     25 import java.awt.*;
     26 
     27 /**
     28  * The ImageWriteParam class provides information to an ImageWriter about how an
     29  * image is to be encoded.
     30  *
     31  * @since Android 1.0
     32  */
     33 public class ImageWriteParam extends IIOParam {
     34 
     35     /**
     36      * The Constant MODE_DISABLED indicates that stream is not tiled,
     37      * progressive, or compressed.
     38      */
     39     public static final int MODE_DISABLED = 0;
     40 
     41     /**
     42      * The Constant MODE_DEFAULT indicates that the stream will be tiled,
     43      * progressive, or compressed according to the plug-in's default.
     44      */
     45     public static final int MODE_DEFAULT = 1;
     46 
     47     /**
     48      * The Constant MODE_EXPLICIT indicates that the stream will be tiled,
     49      * progressive, or compressed according to current settings which are
     50      * defined by set methods.
     51      */
     52     public static final int MODE_EXPLICIT = 2;
     53 
     54     /**
     55      * The Constant MODE_COPY_FROM_METADATA indicates that the stream will be
     56      * tiled, progressive, or compressed according to stream or image metadata.
     57      */
     58     public static final int MODE_COPY_FROM_METADATA = 3;
     59 
     60     /**
     61      * Whether the ImageWriter can write tiles.
     62      */
     63     protected boolean canWriteTiles = false;
     64 
     65     /**
     66      * The tiling mode.
     67      */
     68     protected int tilingMode = MODE_COPY_FROM_METADATA;
     69 
     70     /**
     71      * The preferred tile sizes.
     72      */
     73     protected Dimension[] preferredTileSizes = null;
     74 
     75     /**
     76      * The tiling set.
     77      */
     78     protected boolean tilingSet = false;
     79 
     80     /**
     81      * The tile width.
     82      */
     83     protected int tileWidth = 0;
     84 
     85     /**
     86      * The tile height.
     87      */
     88     protected int tileHeight = 0;
     89 
     90     /**
     91      * Whether the ImageWriter can offset tiles.
     92      */
     93     protected boolean canOffsetTiles = false;
     94 
     95     /**
     96      * The tile grid x offset.
     97      */
     98     protected int tileGridXOffset = 0;
     99 
    100     /**
    101      * The tile grid y offset.
    102      */
    103     protected int tileGridYOffset = 0;
    104 
    105     /**
    106      * Whether the ImageWriter can write in progressive mode.
    107      */
    108     protected boolean canWriteProgressive = false;
    109 
    110     /**
    111      * The progressive mode.
    112      */
    113     protected int progressiveMode = MODE_COPY_FROM_METADATA;
    114 
    115     /**
    116      * Whether the ImageWriter can write in compressed mode.
    117      */
    118     protected boolean canWriteCompressed = false;
    119 
    120     /**
    121      * The compression mode.
    122      */
    123     protected int compressionMode = MODE_COPY_FROM_METADATA;
    124 
    125     /**
    126      * The compression types.
    127      */
    128     protected String[] compressionTypes = null;
    129 
    130     /**
    131      * The compression type.
    132      */
    133     protected String compressionType = null;
    134 
    135     /**
    136      * The compression quality.
    137      */
    138     protected float compressionQuality = 1.0f;
    139 
    140     /**
    141      * The locale.
    142      */
    143     protected Locale locale = null;
    144 
    145     /**
    146      * Instantiates a new ImageWriteParam.
    147      */
    148     protected ImageWriteParam() {
    149     }
    150 
    151     /**
    152      * Instantiates a new ImageWriteParam with the specified Locale.
    153      *
    154      * @param locale
    155      *            the Locale.
    156      */
    157     public ImageWriteParam(Locale locale) {
    158         this.locale = locale;
    159 
    160     }
    161 
    162     /**
    163      * Gets the mode for writing the stream in a progressive sequence.
    164      *
    165      * @return the current progressive mode.
    166      */
    167     public int getProgressiveMode() {
    168         if (canWriteProgressive()) {
    169             return progressiveMode;
    170         }
    171         throw new UnsupportedOperationException("progressive mode is not supported");
    172     }
    173 
    174     /**
    175      * Returns true if images can be written using increasing quality passes by
    176      * progressive.
    177      *
    178      * @return true if images can be written using increasing quality passes by
    179      *         progressive, false otherwise.
    180      */
    181     public boolean canWriteProgressive() {
    182         return canWriteProgressive;
    183     }
    184 
    185     /**
    186      * Sets the progressive mode which defines whether the stream contains a
    187      * progressive sequence of increasing quality during writing. The
    188      * progressive mode should be one of the following values: MODE_DISABLED,
    189      * MODE_DEFAULT, or MODE_COPY_FROM_METADATA.
    190      *
    191      * @param mode
    192      *            the new progressive mode.
    193      */
    194     public void setProgressiveMode(int mode) {
    195         if (canWriteProgressive()) {
    196             if (mode < MODE_DISABLED || mode > MODE_COPY_FROM_METADATA || mode == MODE_EXPLICIT) {
    197                 throw new IllegalArgumentException("mode is not supported");
    198             }
    199             this.progressiveMode = mode;
    200         }
    201         throw new UnsupportedOperationException("progressive mode is not supported");
    202     }
    203 
    204     /**
    205      * Returns true if the writer can use tiles with non zero grid offsets while
    206      * writing.
    207      *
    208      * @return true, if the writer can use tiles with non zero grid offsets
    209      *         while writing, false otherwise.
    210      */
    211     public boolean canOffsetTiles() {
    212         return canOffsetTiles;
    213     }
    214 
    215     /**
    216      * Returns true if this writer can write images with compression.
    217      *
    218      * @return true, if this writer can write images with compression, false
    219      *         otherwise.
    220      */
    221     public boolean canWriteCompressed() {
    222         return canWriteCompressed;
    223     }
    224 
    225     /**
    226      * Returns true if the writer can write tiles.
    227      *
    228      * @return true, if the writer can write tiles, false otherwise.
    229      */
    230     public boolean canWriteTiles() {
    231         return canWriteTiles;
    232     }
    233 
    234     /**
    235      * Check write compressed.
    236      */
    237     private final void checkWriteCompressed() {
    238         if (!canWriteCompressed()) {
    239             throw new UnsupportedOperationException("Compression not supported.");
    240         }
    241     }
    242 
    243     /**
    244      * Check compression mode.
    245      */
    246     private final void checkCompressionMode() {
    247         if (getCompressionMode() != MODE_EXPLICIT) {
    248             throw new IllegalStateException("Compression mode not MODE_EXPLICIT!");
    249         }
    250     }
    251 
    252     /**
    253      * Check compression type.
    254      */
    255     private final void checkCompressionType() {
    256         if (getCompressionTypes() != null && getCompressionType() == null) {
    257             throw new IllegalStateException("No compression type set!");
    258         }
    259     }
    260 
    261     /**
    262      * Gets the compression mode.
    263      *
    264      * @return the compression mode if it's supported.
    265      */
    266     public int getCompressionMode() {
    267         checkWriteCompressed();
    268         return compressionMode;
    269     }
    270 
    271     /**
    272      * Gets the an array of supported compression types.
    273      *
    274      * @return the an array of supported compression types.
    275      */
    276     public String[] getCompressionTypes() {
    277         checkWriteCompressed();
    278         if (compressionTypes != null) {
    279             return compressionTypes.clone();
    280         }
    281         return null;
    282     }
    283 
    284     /**
    285      * Gets the current compression type, or returns null.
    286      *
    287      * @return the current compression type, or returns null if it is not set.
    288      */
    289     public String getCompressionType() {
    290         checkWriteCompressed();
    291         checkCompressionMode();
    292         return compressionType;
    293     }
    294 
    295     /**
    296      * Gets a bit rate which represents an estimate of the number of bits of
    297      * output data for each bit of input image data with the specified quality.
    298      *
    299      * @param quality
    300      *            the quality.
    301      * @return an estimate of the bit rate, or -1.0F if there is no estimate.
    302      */
    303     public float getBitRate(float quality) {
    304         checkWriteCompressed();
    305         checkCompressionMode();
    306         checkCompressionType();
    307         if (quality < 0 || quality > 1) {
    308             throw new IllegalArgumentException("Quality out-of-bounds!");
    309         }
    310         return -1.0f;
    311     }
    312 
    313     /**
    314      * Gets the compression quality.
    315      *
    316      * @return the compression quality.
    317      */
    318     public float getCompressionQuality() {
    319         checkWriteCompressed();
    320         checkCompressionMode();
    321         checkCompressionType();
    322         return compressionQuality;
    323     }
    324 
    325     /**
    326      * Gets the array of compression quality descriptions.
    327      *
    328      * @return the string array of compression quality descriptions.
    329      */
    330     public String[] getCompressionQualityDescriptions() {
    331         checkWriteCompressed();
    332         checkCompressionMode();
    333         checkCompressionType();
    334         return null;
    335     }
    336 
    337     /**
    338      * Gets an array of floats which describes compression quality levels.
    339      *
    340      * @return the array of compression quality values.
    341      */
    342     public float[] getCompressionQualityValues() {
    343         checkWriteCompressed();
    344         checkCompressionMode();
    345         checkCompressionType();
    346         return null;
    347     }
    348 
    349     /**
    350      * Gets the locale of this ImageWriteParam.
    351      *
    352      * @return the locale of this ImageWriteParam.
    353      */
    354     public Locale getLocale() {
    355         return locale;
    356     }
    357 
    358     /**
    359      * Gets the current compression type using the current Locale.
    360      *
    361      * @return the current compression type using the current Locale.
    362      */
    363     public String getLocalizedCompressionTypeName() {
    364         checkWriteCompressed();
    365         checkCompressionMode();
    366 
    367         String compressionType = getCompressionType();
    368         if (compressionType == null) {
    369             throw new IllegalStateException("No compression type set!");
    370         }
    371         return compressionType;
    372 
    373     }
    374 
    375     /**
    376      * Check tiling.
    377      */
    378     private final void checkTiling() {
    379         if (!canWriteTiles()) {
    380             throw new UnsupportedOperationException("Tiling not supported!");
    381         }
    382     }
    383 
    384     /**
    385      * Check tiling mode.
    386      */
    387     private final void checkTilingMode() {
    388         if (getTilingMode() != MODE_EXPLICIT) {
    389             throw new IllegalStateException("Tiling mode not MODE_EXPLICIT!");
    390         }
    391     }
    392 
    393     /**
    394      * Check tiling params.
    395      */
    396     private final void checkTilingParams() {
    397         if (!tilingSet) {
    398             throw new IllegalStateException("Tiling parameters not set!");
    399         }
    400     }
    401 
    402     /**
    403      * Gets the tiling mode if tiling is supported.
    404      *
    405      * @return the tiling mode if tiling is supported.
    406      */
    407     public int getTilingMode() {
    408         checkTiling();
    409         return tilingMode;
    410     }
    411 
    412     /**
    413      * Gets an array of Dimensions giving the sizes of the tiles as they are
    414      * encoded in the output file or stream.
    415      *
    416      * @return the preferred tile sizes.
    417      */
    418     public Dimension[] getPreferredTileSizes() {
    419         checkTiling();
    420         if (preferredTileSizes == null) {
    421             return null;
    422         }
    423 
    424         Dimension[] retval = new Dimension[preferredTileSizes.length];
    425         for (int i = 0; i < preferredTileSizes.length; i++) {
    426             retval[i] = new Dimension(retval[i]);
    427         }
    428         return retval;
    429     }
    430 
    431     /**
    432      * Gets the tile grid X offset for encoding.
    433      *
    434      * @return the tile grid X offset for encoding.
    435      */
    436     public int getTileGridXOffset() {
    437         checkTiling();
    438         checkTilingMode();
    439         checkTilingParams();
    440         return tileGridXOffset;
    441     }
    442 
    443     /**
    444      * Gets the tile grid Y offset for encoding.
    445      *
    446      * @return the tile grid Y offset for encoding.
    447      */
    448     public int getTileGridYOffset() {
    449         checkTiling();
    450         checkTilingMode();
    451         checkTilingParams();
    452         return tileGridYOffset;
    453     }
    454 
    455     /**
    456      * Gets the tile height in an image as it is written to the output stream.
    457      *
    458      * @return the tile height in an image as it is written to the output
    459      *         stream.
    460      */
    461     public int getTileHeight() {
    462         checkTiling();
    463         checkTilingMode();
    464         checkTilingParams();
    465         return tileHeight;
    466     }
    467 
    468     /**
    469      * Gets the tile width in an image as it is written to the output stream.
    470      *
    471      * @return the tile width in an image as it is written to the output stream.
    472      */
    473     public int getTileWidth() {
    474         checkTiling();
    475         checkTilingMode();
    476         checkTilingParams();
    477         return tileWidth;
    478     }
    479 
    480     /**
    481      * Checks if the current compression type has lossless compression or not.
    482      *
    483      * @return true, if the current compression type has lossless compression,
    484      *         false otherwise.
    485      */
    486     public boolean isCompressionLossless() {
    487         checkWriteCompressed();
    488         checkCompressionMode();
    489         checkCompressionType();
    490         return true;
    491     }
    492 
    493     /**
    494      * Removes current compression type.
    495      */
    496     public void unsetCompression() {
    497         checkWriteCompressed();
    498         checkCompressionMode();
    499         compressionType = null;
    500         compressionQuality = 1;
    501     }
    502 
    503     /**
    504      * Sets the compression mode to the specified value. The specified mode can
    505      * be one of the predefined constants: MODE_DEFAULT, MODE_DISABLED,
    506      * MODE_EXPLICIT, or MODE_COPY_FROM_METADATA.
    507      *
    508      * @param mode
    509      *            the new compression mode to be set.
    510      */
    511     public void setCompressionMode(int mode) {
    512         checkWriteCompressed();
    513         switch (mode) {
    514             case MODE_EXPLICIT: {
    515                 compressionMode = mode;
    516                 unsetCompression();
    517                 break;
    518             }
    519             case MODE_COPY_FROM_METADATA:
    520             case MODE_DISABLED:
    521             case MODE_DEFAULT: {
    522                 compressionMode = mode;
    523                 break;
    524             }
    525             default: {
    526                 throw new IllegalArgumentException("Illegal value for mode!");
    527             }
    528         }
    529     }
    530 
    531     /**
    532      * Sets the compression quality. The value should be between 0 and 1.
    533      *
    534      * @param quality
    535      *            the new compression quality, float value between 0 and 1.
    536      */
    537     public void setCompressionQuality(float quality) {
    538         checkWriteCompressed();
    539         checkCompressionMode();
    540         checkCompressionType();
    541         if (quality < 0 || quality > 1) {
    542             throw new IllegalArgumentException("Quality out-of-bounds!");
    543         }
    544         compressionQuality = quality;
    545     }
    546 
    547     /**
    548      * Sets the compression type. The specified string should be one of the
    549      * values returned by getCompressionTypes method.
    550      *
    551      * @param compressionType
    552      *            the new compression type.
    553      */
    554     public void setCompressionType(String compressionType) {
    555         checkWriteCompressed();
    556         checkCompressionMode();
    557 
    558         if (compressionType == null) { // Don't check anything
    559             this.compressionType = null;
    560         } else {
    561             String[] compressionTypes = getCompressionTypes();
    562             if (compressionTypes == null) {
    563                 throw new UnsupportedOperationException("No settable compression types");
    564             }
    565 
    566             for (int i = 0; i < compressionTypes.length; i++) {
    567                 if (compressionTypes[i].equals(compressionType)) {
    568                     this.compressionType = compressionType;
    569                     return;
    570                 }
    571             }
    572 
    573             // Compression type is not in the list.
    574             throw new IllegalArgumentException("Unknown compression type!");
    575         }
    576     }
    577 
    578     /**
    579      * Sets the instruction that tiling should be performed for the image in the
    580      * output stream with the specified parameters.
    581      *
    582      * @param tileWidth
    583      *            the tile's width.
    584      * @param tileHeight
    585      *            the tile's height.
    586      * @param tileGridXOffset
    587      *            the tile grid's x offset.
    588      * @param tileGridYOffset
    589      *            the tile grid's y offset.
    590      */
    591     public void setTiling(int tileWidth, int tileHeight, int tileGridXOffset, int tileGridYOffset) {
    592         checkTiling();
    593         checkTilingMode();
    594 
    595         if (!canOffsetTiles() && (tileGridXOffset != 0 || tileGridYOffset != 0)) {
    596             throw new UnsupportedOperationException("Can't offset tiles!");
    597         }
    598 
    599         if (tileWidth <= 0 || tileHeight <= 0) {
    600             throw new IllegalArgumentException("tile dimensions are non-positive!");
    601         }
    602 
    603         Dimension preferredTileSizes[] = getPreferredTileSizes();
    604         if (preferredTileSizes != null) {
    605             for (int i = 0; i < preferredTileSizes.length; i += 2) {
    606                 Dimension minSize = preferredTileSizes[i];
    607                 Dimension maxSize = preferredTileSizes[i + 1];
    608                 if (tileWidth < minSize.width || tileWidth > maxSize.width
    609                         || tileHeight < minSize.height || tileHeight > maxSize.height) {
    610                     throw new IllegalArgumentException("Illegal tile size!");
    611                 }
    612             }
    613         }
    614 
    615         tilingSet = true;
    616         this.tileWidth = tileWidth;
    617         this.tileHeight = tileHeight;
    618         this.tileGridXOffset = tileGridXOffset;
    619         this.tileGridYOffset = tileGridYOffset;
    620     }
    621 
    622     /**
    623      * Clears all tiling settings.
    624      */
    625     public void unsetTiling() {
    626         checkTiling();
    627         checkTilingMode();
    628 
    629         tilingSet = false;
    630         tileWidth = 0;
    631         tileHeight = 0;
    632         tileGridXOffset = 0;
    633         tileGridYOffset = 0;
    634     }
    635 
    636     /**
    637      * Sets the tiling mode. The specified mode should be one of the following
    638      * values: MODE_DISABLED, MODE_DEFAULT, MODE_EXPLICIT, or
    639      * MODE_COPY_FROM_METADATA.
    640      *
    641      * @param mode
    642      *            the new tiling mode.
    643      */
    644     public void setTilingMode(int mode) {
    645         checkTiling();
    646 
    647         switch (mode) {
    648             case MODE_EXPLICIT: {
    649                 tilingMode = mode;
    650                 unsetTiling();
    651                 break;
    652             }
    653             case MODE_COPY_FROM_METADATA:
    654             case MODE_DISABLED:
    655             case MODE_DEFAULT: {
    656                 tilingMode = mode;
    657                 break;
    658             }
    659             default: {
    660                 throw new IllegalArgumentException("Illegal value for mode!");
    661             }
    662         }
    663     }
    664 }
    665