Path: blob/master/src/java.desktop/share/classes/javax/imageio/ImageReadParam.java
41152 views
/*1* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.imageio;2627import java.awt.Dimension;28import java.awt.image.BufferedImage;2930/**31* A class describing how a stream is to be decoded. Instances of32* this class or its subclasses are used to supply prescriptive33* "how-to" information to instances of {@code ImageReader}.34*35* <p> An image encoded as part of a file or stream may be thought of36* extending out in multiple dimensions: the spatial dimensions of37* width and height, a number of bands, and a number of progressive38* decoding passes. This class allows a contiguous (hyper)rectangular39* subarea of the image in all of these dimensions to be selected for40* decoding. Additionally, the spatial dimensions may be subsampled41* discontinuously. Finally, color and format conversions may be42* specified by controlling the {@code ColorModel} and43* {@code SampleModel} of the destination image, either by44* providing a {@code BufferedImage} or by using an45* {@code ImageTypeSpecifier}.46*47* <p> An {@code ImageReadParam} object is used to specify how an48* image, or a set of images, will be converted on input from49* a stream in the context of the Java Image I/O framework. A plug-in for a50* specific image format will return instances of51* {@code ImageReadParam} from the52* {@code getDefaultReadParam} method of its53* {@code ImageReader} implementation.54*55* <p> The state maintained by an instance of56* {@code ImageReadParam} is independent of any particular image57* being decoded. When actual decoding takes place, the values set in58* the read param are combined with the actual properties of the image59* being decoded from the stream and the destination60* {@code BufferedImage} that will receive the decoded pixel61* data. For example, the source region set using62* {@code setSourceRegion} will first be intersected with the63* actual valid source area. The result will be translated by the64* value returned by {@code getDestinationOffset}, and the65* resulting rectangle intersected with the actual valid destination66* area to yield the destination area that will be written.67*68* <p> The parameters specified by an {@code ImageReadParam} are69* applied to an image as follows. First, if a rendering size has70* been set by {@code setSourceRenderSize}, the entire decoded71* image is rendered at the size given by72* {@code getSourceRenderSize}. Otherwise, the image has its73* natural size given by {@code ImageReader.getWidth} and74* {@code ImageReader.getHeight}.75*76* <p> Next, the image is clipped against the source region77* specified by {@code getSourceXOffset}, {@code getSourceYOffset},78* {@code getSourceWidth}, and {@code getSourceHeight}.79*80* <p> The resulting region is then subsampled according to the81* factors given in {@link IIOParam#setSourceSubsampling82* IIOParam.setSourceSubsampling}. The first pixel,83* the number of pixels per row, and the number of rows all depend84* on the subsampling settings.85* Call the minimum X and Y coordinates of the resulting rectangle86* ({@code minX}, {@code minY}), its width {@code w}87* and its height {@code h}.88*89* <p> This rectangle is offset by90* ({@code getDestinationOffset().x},91* {@code getDestinationOffset().y}) and clipped against the92* destination bounds. If no destination image has been set, the93* destination is defined to have a width of94* {@code getDestinationOffset().x} + {@code w}, and a95* height of {@code getDestinationOffset().y} + {@code h} so96* that all pixels of the source region may be written to the97* destination.98*99* <p> Pixels that land, after subsampling, within the destination100* image, and that are written in one of the progressive passes101* specified by {@code getSourceMinProgressivePass} and102* {@code getSourceNumProgressivePasses} are passed along to the103* next step.104*105* <p> Finally, the source samples of each pixel are mapped into106* destination bands according to the algorithm described in the107* comment for {@code setDestinationBands}.108*109* <p> Plug-in writers may extend the functionality of110* {@code ImageReadParam} by providing a subclass that implements111* additional, plug-in specific interfaces. It is up to the plug-in112* to document what interfaces are available and how they are to be113* used. Readers will silently ignore any extended features of an114* {@code ImageReadParam} subclass of which they are not aware.115* Also, they may ignore any optional features that they normally116* disable when creating their own {@code ImageReadParam}117* instances via {@code getDefaultReadParam}.118*119* <p> Note that unless a query method exists for a capability, it must120* be supported by all {@code ImageReader} implementations121* (<i>e.g.</i> source render size is optional, but subsampling must be122* supported).123*124*125* @see ImageReader126* @see ImageWriter127* @see ImageWriteParam128*/129public class ImageReadParam extends IIOParam {130131/**132* {@code true} if this {@code ImageReadParam} allows133* the source rendering dimensions to be set. By default, the134* value is {@code false}. Subclasses must set this value135* manually.136*137* <p> {@code ImageReader}s that do not support setting of138* the source render size should set this value to139* {@code false}.140*/141protected boolean canSetSourceRenderSize = false;142143/**144* The desired rendering width and height of the source, if145* {@code canSetSourceRenderSize} is {@code true}, or146* {@code null}.147*148* <p> {@code ImageReader}s that do not support setting of149* the source render size may ignore this value.150*/151protected Dimension sourceRenderSize = null;152153/**154* The current destination {@code BufferedImage}, or155* {@code null} if none has been set. By default, the value156* is {@code null}.157*/158protected BufferedImage destination = null;159160/**161* The set of destination bands to be used, as an array of162* {@code int}s. By default, the value is {@code null},163* indicating all destination bands should be written in order.164*/165protected int[] destinationBands = null;166167/**168* The minimum index of a progressive pass to read from the169* source. By default, the value is set to 0, which indicates170* that passes starting with the first available pass should be171* decoded.172*173* <p> Subclasses should ensure that this value is174* non-negative.175*/176protected int minProgressivePass = 0;177178/**179* The maximum number of progressive passes to read from the180* source. By default, the value is set to181* {@code Integer.MAX_VALUE}, which indicates that passes up182* to and including the last available pass should be decoded.183*184* <p> Subclasses should ensure that this value is positive.185* Additionally, if the value is not186* {@code Integer.MAX_VALUE}, then187* {@code minProgressivePass + numProgressivePasses - 1}188* should not exceed189* {@code Integer.MAX_VALUE}.190*/191protected int numProgressivePasses = Integer.MAX_VALUE;192193/**194* Constructs an {@code ImageReadParam}.195*/196public ImageReadParam() {}197198// Comment inherited199public void setDestinationType(ImageTypeSpecifier destinationType) {200super.setDestinationType(destinationType);201setDestination(null);202}203204/**205* Supplies a {@code BufferedImage} to be used as the206* destination for decoded pixel data. The currently set image207* will be written to by the {@code read},208* {@code readAll}, and {@code readRaster} methods, and209* a reference to it will be returned by those methods.210*211* <p> Pixel data from the aforementioned methods will be written212* starting at the offset specified by213* {@code getDestinationOffset}.214*215* <p> If {@code destination} is {@code null}, a216* newly-created {@code BufferedImage} will be returned by217* those methods.218*219* <p> At the time of reading, the image is checked to verify that220* its {@code ColorModel} and {@code SampleModel}221* correspond to one of the {@code ImageTypeSpecifier}s222* returned from the {@code ImageReader}'s223* {@code getImageTypes} method. If it does not, the reader224* will throw an {@code IIOException}.225*226* @param destination the BufferedImage to be written to, or227* {@code null}.228*229* @see #getDestination230*/231public void setDestination(BufferedImage destination) {232this.destination = destination;233}234235/**236* Returns the {@code BufferedImage} currently set by the237* {@code setDestination} method, or {@code null}238* if none is set.239*240* @return the BufferedImage to be written to.241*242* @see #setDestination243*/244public BufferedImage getDestination() {245return destination;246}247248/**249* Sets the indices of the destination bands where data250* will be placed. Duplicate indices are not allowed.251*252* <p> A {@code null} value indicates that all destination253* bands will be used.254*255* <p> Choosing a destination band subset will not affect the256* number of bands in the output image of a read if no destination257* image is specified; the created destination image will still258* have the same number of bands as if this method had never been259* called. If a different number of bands in the destination260* image is desired, an image must be supplied using the261* {@code ImageReadParam.setDestination} method.262*263* <p> At the time of reading or writing, an264* {@code IllegalArgumentException} will be thrown by the265* reader or writer if a value larger than the largest destination266* band index has been specified, or if the number of source bands267* and destination bands to be used differ. The268* {@code ImageReader.checkReadParamBandSettings} method may269* be used to automate this test.270*271* @param destinationBands an array of integer band indices to be272* used.273*274* @exception IllegalArgumentException if {@code destinationBands}275* contains a negative or duplicate value.276*277* @see #getDestinationBands278* @see #getSourceBands279* @see ImageReader#checkReadParamBandSettings280*/281public void setDestinationBands(int[] destinationBands) {282if (destinationBands == null) {283this.destinationBands = null;284} else {285int numBands = destinationBands.length;286for (int i = 0; i < numBands; i++) {287int band = destinationBands[i];288if (band < 0) {289throw new IllegalArgumentException("Band value < 0!");290}291for (int j = i + 1; j < numBands; j++) {292if (band == destinationBands[j]) {293throw new IllegalArgumentException("Duplicate band value!");294}295}296}297this.destinationBands = destinationBands.clone();298}299}300301/**302* Returns the set of band indices where data will be placed.303* If no value has been set, {@code null} is returned to304* indicate that all destination bands will be used.305*306* @return the indices of the destination bands to be used,307* or {@code null}.308*309* @see #setDestinationBands310*/311public int[] getDestinationBands() {312if (destinationBands == null) {313return null;314} else {315return destinationBands.clone();316}317}318319/**320* Returns {@code true} if this reader allows the source321* image to be rendered at an arbitrary size as part of the322* decoding process, by means of the323* {@code setSourceRenderSize} method. If this method324* returns {@code false}, calls to325* {@code setSourceRenderSize} will throw an326* {@code UnsupportedOperationException}.327*328* @return {@code true} if setting source rendering size is329* supported.330*331* @see #setSourceRenderSize332*/333public boolean canSetSourceRenderSize() {334return canSetSourceRenderSize;335}336337/**338* If the image is able to be rendered at an arbitrary size, sets339* the source width and height to the supplied values. Note that340* the values returned from the {@code getWidth} and341* {@code getHeight} methods on {@code ImageReader} are342* not affected by this method; they will continue to return the343* default size for the image. Similarly, if the image is also344* tiled the tile width and height are given in terms of the default345* size.346*347* <p> Typically, the width and height should be chosen such that348* the ratio of width to height closely approximates the aspect349* ratio of the image, as returned from350* {@code ImageReader.getAspectRatio}.351*352* <p> If this plug-in does not allow the rendering size to be353* set, an {@code UnsupportedOperationException} will be354* thrown.355*356* <p> To remove the render size setting, pass in a value of357* {@code null} for {@code size}.358*359* @param size a {@code Dimension} indicating the desired360* width and height.361*362* @exception IllegalArgumentException if either the width or the363* height is negative or 0.364* @exception UnsupportedOperationException if image resizing365* is not supported by this plug-in.366*367* @see #getSourceRenderSize368* @see ImageReader#getWidth369* @see ImageReader#getHeight370* @see ImageReader#getAspectRatio371*/372public void setSourceRenderSize(Dimension size)373throws UnsupportedOperationException {374if (!canSetSourceRenderSize()) {375throw new UnsupportedOperationException376("Can't set source render size!");377}378379if (size == null) {380this.sourceRenderSize = null;381} else {382if (size.width <= 0 || size.height <= 0) {383throw new IllegalArgumentException("width or height <= 0!");384}385this.sourceRenderSize = (Dimension)size.clone();386}387}388389/**390* Returns the width and height of the source image as it391* will be rendered during decoding, if they have been set via the392* {@code setSourceRenderSize} method. A393* {@code null} value indicates that no setting has been made.394*395* @return the rendered width and height of the source image396* as a {@code Dimension}.397*398* @see #setSourceRenderSize399*/400public Dimension getSourceRenderSize() {401return (sourceRenderSize == null) ?402null : (Dimension)sourceRenderSize.clone();403}404405/**406* Sets the range of progressive passes that will be decoded.407* Passes outside of this range will be ignored.408*409* <p> A progressive pass is a re-encoding of the entire image,410* generally at progressively higher effective resolutions, but411* requiring greater transmission bandwidth. The most common use412* of progressive encoding is found in the JPEG format, where413* successive passes include more detailed representations of the414* high-frequency image content.415*416* <p> The actual number of passes to be decoded is determined417* during decoding, based on the number of actual passes available418* in the stream. Thus if {@code minPass + numPasses - 1} is419* larger than the index of the last available passes, decoding420* will end with that pass.421*422* <p> A value of {@code numPasses} of423* {@code Integer.MAX_VALUE} indicates that all passes from424* {@code minPass} forward should be read. Otherwise, the425* index of the last pass (<i>i.e.</i>, {@code minPass + numPasses - 1})426* must not exceed {@code Integer.MAX_VALUE}.427*428* <p> There is no {@code unsetSourceProgressivePasses}429* method; the same effect may be obtained by calling430* {@code setSourceProgressivePasses(0, Integer.MAX_VALUE)}.431*432* @param minPass the index of the first pass to be decoded.433* @param numPasses the maximum number of passes to be decoded.434*435* @exception IllegalArgumentException if {@code minPass} is436* negative, {@code numPasses} is negative or 0, or437* {@code numPasses} is smaller than438* {@code Integer.MAX_VALUE} but439* {@code minPass + numPasses - 1} is greater than440* {@code INTEGER.MAX_VALUE}.441*442* @see #getSourceMinProgressivePass443* @see #getSourceMaxProgressivePass444*/445public void setSourceProgressivePasses(int minPass, int numPasses) {446if (minPass < 0) {447throw new IllegalArgumentException("minPass < 0!");448}449if (numPasses <= 0) {450throw new IllegalArgumentException("numPasses <= 0!");451}452if ((numPasses != Integer.MAX_VALUE) &&453(((minPass + numPasses - 1) & 0x80000000) != 0)) {454throw new IllegalArgumentException455("minPass + numPasses - 1 > INTEGER.MAX_VALUE!");456}457458this.minProgressivePass = minPass;459this.numProgressivePasses = numPasses;460}461462/**463* Returns the index of the first progressive pass that will be464* decoded. If no value has been set, 0 will be returned (which is465* the correct value).466*467* @return the index of the first pass that will be decoded.468*469* @see #setSourceProgressivePasses470* @see #getSourceNumProgressivePasses471*/472public int getSourceMinProgressivePass() {473return minProgressivePass;474}475476/**477* If {@code getSourceNumProgressivePasses} is equal to478* {@code Integer.MAX_VALUE}, returns479* {@code Integer.MAX_VALUE}. Otherwise, returns480* {@code getSourceMinProgressivePass() +481* getSourceNumProgressivePasses() - 1}.482*483* @return the index of the last pass to be read, or484* {@code Integer.MAX_VALUE}.485*/486public int getSourceMaxProgressivePass() {487if (numProgressivePasses == Integer.MAX_VALUE) {488return Integer.MAX_VALUE;489} else {490return minProgressivePass + numProgressivePasses - 1;491}492}493494/**495* Returns the number of the progressive passes that will be496* decoded. If no value has been set,497* {@code Integer.MAX_VALUE} will be returned (which is the498* correct value).499*500* @return the number of the passes that will be decoded.501*502* @see #setSourceProgressivePasses503* @see #getSourceMinProgressivePass504*/505public int getSourceNumProgressivePasses() {506return numProgressivePasses;507}508}509510511