/** * Restores the <code>ImageReader</code> to its initial state. * * <p> The default implementation calls <code>setInput(null, * false)</code>, <code>setLocale(null)</code>, * <code>removeAllIIOReadUpdateListeners()</code>, * <code>removeAllIIOReadWarningListeners()</code>, * <code>removeAllIIOReadProgressListeners()</code>, and * <code>clearAbortRequest</code>. */ public void reset() { setInput(null, false, false); setLocale(null); removeAllIIOReadUpdateListeners(); removeAllIIOReadProgressListeners(); removeAllIIOReadWarningListeners(); clearAbortRequest(); } /** * Allows any resources held by this object to be released. The * result of calling any other method (other than * <code>finalize</code>) subsequent to a call to this method * is undefined. * * <p>It is important for applications to call this method when they * know they will no longer be using this <code>ImageReader</code>. * Otherwise, the reader may continue to hold on to resources * indefinitely. * * <p>The default implementation of this method in the superclass does * nothing. Subclass implementations should ensure that all resources, * especially native resources, are released. */ public void dispose() { } // Utility methods /** * A utility method that may be used by readers to compute the * region of the source image that should be read, taking into * account any source region and subsampling offset settings in * the supplied <code>ImageReadParam</code>. The actual * subsampling factors, destination size, and destination offset * are <em>not</em> taken into consideration, thus further * clipping must take place. The {@link #computeRegions * <code>computeRegions</code>} method performs all necessary * clipping. * * @param param the <code>ImageReadParam</code> being used, or * <code>null</code>. * @param srcWidth the width of the source image. * @param srcHeight the height of the source image. * * @return the source region as a <code>Rectangle</code>. */ protected static Rectangle getSourceRegion(ImageReadParam param, int srcWidth, int srcHeight) { Rectangle sourceRegion = new Rectangle(0, 0, srcWidth, srcHeight); if (param != null) { Rectangle region = param.getSourceRegion(); if (region != null) { sourceRegion = sourceRegion.intersection(region); } int subsampleXOffset = param.getSubsamplingXOffset(); int subsampleYOffset = param.getSubsamplingYOffset(); sourceRegion.x += subsampleXOffset; sourceRegion.y += subsampleYOffset; sourceRegion.width -= subsampleXOffset; sourceRegion.height -= subsampleYOffset; } return sourceRegion; } /** * Computes the source region of interest and the destination * region of interest, taking the width and height of the source * image, an optional destination image, and an optional * <code>ImageReadParam</code> into account. The source region * begins with the entire source image. Then that is clipped to * the source region specified in the <code>ImageReadParam</code>, * if one is specified. * * <p> If either of the destination offsets are negative, the * source region is clipped so that its top left will coincide * with the top left of the destination image, taking subsampling * into account. Then the result is clipped to the destination * image on the right and bottom, if one is specified, taking * subsampling and destination offsets into account. * * <p> Similarly, the destination region begins with the source * image, is translated to the destination offset given in the * <code>ImageReadParam</code> if there is one, and finally is * clipped to the destination image, if there is one. * * <p> If either the source or destination regions end up having a * width or height of 0, an <code>IllegalArgumentException</code> * is thrown. * * <p> The {@link #getSourceRegion <code>getSourceRegion</code>} * method may be used if only source clipping is desired. * * @param param an <code>ImageReadParam</code>, or <code>null</code>. * @param srcWidth the width of the source image. * @param srcHeight the height of the source image. * @param image a <code>BufferedImage</code> that will be the * destination image, or <code>null</code>. * @param srcRegion a <code>Rectangle</code> that will be filled with * the source region of interest. * @param destRegion a <code>Rectangle</code> that will be filled with * the destination region of interest. * @exception IllegalArgumentException if <code>srcRegion</code> * is <code>null</code>. * @exception IllegalArgumentException if <code>dstRegion</code> * is <code>null</code>. * @exception IllegalArgumentException if the resulting source or * destination region is empty. */ protected static void computeRegions(ImageReadParam param, int srcWidth, int srcHeight, BufferedImage image, Rectangle srcRegion, Rectangle destRegion) { if (srcRegion == null) { throw new IllegalArgumentException("srcRegion == null!"); } if (destRegion == null) { throw new IllegalArgumentException("destRegion == null!"); } // Start with the entire source image srcRegion.setBounds(0, 0, srcWidth, srcHeight); // Destination also starts with source image, as that is the // maximum extent if there is no subsampling destRegion.setBounds(0, 0, srcWidth, srcHeight); // Clip that to the param region, if there is one int periodX = 1; int periodY = 1; int gridX = 0; int gridY = 0; if (param != null) { Rectangle paramSrcRegion = param.getSourceRegion(); if (paramSrcRegion != null) { srcRegion.setBounds(srcRegion.intersection(paramSrcRegion)); } periodX = param.getSourceXSubsampling(); periodY = param.getSourceYSubsampling(); gridX = param.getSubsamplingXOffset(); gridY = param.getSubsamplingYOffset(); srcRegion.translate(gridX, gridY); srcRegion.width -= gridX; srcRegion.height -= gridY; destRegion.setLocation(param.getDestinationOffset()); } // Now clip any negative destination offsets, i.e. clip // to the top and left of the destination image if (destRegion.x < 0) { int delta = -destRegion.x*periodX; srcRegion.x += delta; srcRegion.width -= delta; destRegion.x = 0; } if (destRegion.y < 0) { int delta = -destRegion.y*periodY; srcRegion.y += delta; srcRegion.height -= delta; destRegion.y = 0; } // Now clip the destination Region to the subsampled width and height int subsampledWidth = (srcRegion.width + periodX - 1)/periodX; int subsampledHeight = (srcRegion.height + periodY - 1)/periodY; destRegion.width = subsampledWidth; destRegion.height = subsampledHeight; // Now clip that to right and bottom of the destination image, // if there is one, taking subsampling into account if (image != null) { Rectangle destImageRect = new Rectangle(0, 0, image.getWidth(), image.getHeight()); destRegion.setBounds(destRegion.intersection(destImageRect)); if (destRegion.isEmpty()) { throw new IllegalArgumentException ("Empty destination region!"); } int deltaX = destRegion.x + subsampledWidth - image.getWidth(); if (deltaX > 0) { srcRegion.width -= deltaX*periodX; } int deltaY = destRegion.y + subsampledHeight - image.getHeight(); if (deltaY > 0) { srcRegion.height -= deltaY*periodY; } } if (srcRegion.isEmpty() || destRegion.isEmpty()) { throw new IllegalArgumentException("Empty region!"); } } /** * A utility method that may be used by readers to test the * validity of the source and destination band settings of an * <code>ImageReadParam</code>. This method may be called as soon * as the reader knows both the number of bands of the source * image as it exists in the input stream, and the number of bands * of the destination image that being written. * * <p> The method retrieves the source and destination band * setting arrays from param using the <code>getSourceBands</code> * and <code>getDestinationBands</code>methods (or considers them * to be <code>null</code> if <code>param</code> is * <code>null</code>). If the source band setting array is * <code>null</code>, it is considered to be equal to the array * <code>{ 0, 1, ..., numSrcBands - 1 }</code>, and similarly for * the destination band setting array. * * <p> The method then tests that both arrays are equal in length, * and that neither array contains a value larger than the largest * available band index. * * <p> Any failure results in an * <code>IllegalArgumentException</code> being thrown; success * results in the method returning silently. * * @param param the <code>ImageReadParam</code> being used to read * the image. * @param numSrcBands the number of bands of the image as it exists * int the input source. * @param numDstBands the number of bands in the destination image * being written. * * @exception IllegalArgumentException if <code>param</code> * contains an invalid specification of a source and/or * destination band subset. */ protected static void checkReadParamBandSettings(ImageReadParam param, int numSrcBands, int numDstBands) { // A null param is equivalent to srcBands == dstBands == null. int[] srcBands = null; int[] dstBands = null; if (param != null) { srcBands = param.getSourceBands(); dstBands = param.getDestinationBands(); } int paramSrcBandLength = (srcBands == null) ? numSrcBands : srcBands.length; int paramDstBandLength = (dstBands == null) ? numDstBands : dstBands.length; if (paramSrcBandLength != paramDstBandLength) { throw new IllegalArgumentException("ImageReadParam num source & dest bands differ!"); } if (srcBands != null) { for (int i = 0; i < srcBands.length; i++) { if (srcBands[i] >= numSrcBands) { throw new IllegalArgumentException("ImageReadParam source bands contains a value >= the number of source bands!"); } } } if (dstBands != null) { for (int i = 0; i < dstBands.length; i++) { if (dstBands[i] >= numDstBands) { throw new IllegalArgumentException("ImageReadParam dest bands contains a value >= the number of dest bands!"); } } } } /** * Returns the <code>BufferedImage</code> to which decoded pixel * data should be written. The image is determined by inspecting * the supplied <code>ImageReadParam</code> if it is * non-<code>null</code>; if its <code>getDestination</code> * method returns a non-<code>null</code> value, that image is * simply returned. Otherwise, * <code>param.getDestinationType</code> method is called to * determine if a particular image type has been specified. If * so, the returned <code>ImageTypeSpecifier</code> is used after * checking that it is equal to one of those included in * <code>imageTypes</code>. * * <p> If <code>param</code> is <code>null</code> or the above * steps have not yielded an image or an * <code>ImageTypeSpecifier</code>, the first value obtained from * the <code>imageTypes</code> parameter is used. Typically, the * caller will set <code>imageTypes</code> to the value of * <code>getImageTypes(imageIndex)</code>. * * <p> Next, the dimensions of the image are determined by a call * to <code>computeRegions</code>. The actual width and height of * the image being decoded are passed in as the <code>width</code> * and <code>height</code> parameters. * * @param param an <code>ImageReadParam</code> to be used to get * the destination image or image type, or <code>null</code>. * @param imageTypes an <code>Iterator</code> of * <code>ImageTypeSpecifier</code>s indicating the legal image * types, with the default first. * @param width the true width of the image or tile begin decoded. * @param height the true width of the image or tile being decoded. * * @return the <code>BufferedImage</code> to which decoded pixel * data should be written. * * @exception IIOException if the <code>ImageTypeSpecifier</code> * specified by <code>param</code> does not match any of the legal * ones from <code>imageTypes</code>. * @exception IllegalArgumentException if <code>imageTypes</code> * is <code>null</code> or empty, or if an object not of type * <code>ImageTypeSpecifier</code> is retrieved from it. * @exception IllegalArgumentException if the resulting image would * have a width or height less than 1. * @exception IllegalArgumentException if the product of * <code>width</code> and <code>height</code> is greater than * <code>Integer.MAX_VALUE</code>. */ protected static BufferedImage getDestination(ImageReadParam param, Iterator<ImageTypeSpecifier> imageTypes, int width, int height) throws IIOException { if (imageTypes == null || !imageTypes.hasNext()) { throw new IllegalArgumentException("imageTypes null or empty!"); } if ((long)width*height > Integer.MAX_VALUE) { throw new IllegalArgumentException ("width*height > Integer.MAX_VALUE!"); } BufferedImage dest = null; ImageTypeSpecifier imageType = null; // If param is non-null, use it if (param != null) { // Try to get the image itself dest = param.getDestination(); if (dest != null) { return dest; } // No image, get the image type imageType = param.getDestinationType(); } // No info from param, use fallback image type if (imageType == null) { Object o = imageTypes.next(); if (!(o instanceof ImageTypeSpecifier)) { throw new IllegalArgumentException ("Non-ImageTypeSpecifier retrieved from imageTypes!"); } imageType = (ImageTypeSpecifier)o; } else { boolean foundIt = false; while (imageTypes.hasNext()) { ImageTypeSpecifier type = (ImageTypeSpecifier)imageTypes.next(); if (type.equals(imageType)) { foundIt = true; break; } } if (!foundIt) { throw new IIOException ("Destination type from ImageReadParam does not match!"); } } Rectangle srcRegion = new Rectangle(0,0,0,0); Rectangle destRegion = new Rectangle(0,0,0,0); computeRegions(param, width, height, null, srcRegion, destRegion); int destWidth = destRegion.x + destRegion.width; int destHeight = destRegion.y + destRegion.height; // Create a new image based on the type specifier return imageType.createBufferedImage(destWidth, destHeight); }}Lines 2501–2898 of 2898. Previous lines
/** * Restores the <code>ImageReader</code> to its initial state. * * <p> The default implementation calls <code>setInput(null, * false)</code>, <code>setLocale(null)</code>, * <code>removeAllIIOReadUpdateListeners()</code>, * <code>removeAllIIOReadWarningListeners()</code>, * <code>removeAllIIOReadProgressListeners()</code>, and * <code>clearAbortRequest</code>. */ public void reset() { setInput(null, false, false); setLocale(null); removeAllIIOReadUpdateListeners(); removeAllIIOReadProgressListeners(); removeAllIIOReadWarningListeners(); clearAbortRequest(); } /** * Allows any resources held by this object to be released. The * result of calling any other method (other than * <code>finalize</code>) subsequent to a call to this method * is undefined. * * <p>It is important for applications to call this method when they * know they will no longer be using this <code>ImageReader</code>. * Otherwise, the reader may continue to hold on to resources * indefinitely. * * <p>The default implementation of this method in the superclass does * nothing. Subclass implementations should ensure that all resources, * especially native resources, are released. */ public void dispose() { } // Utility methods /** * A utility method that may be used by readers to compute the * region of the source image that should be read, taking into * account any source region and subsampling offset settings in * the supplied <code>ImageReadParam</code>. The actual * subsampling factors, destination size, and destination offset * are <em>not</em> taken into consideration, thus further * clipping must take place. The {@link #computeRegions * <code>computeRegions</code>} method performs all necessary * clipping. * * @param param the <code>ImageReadParam</code> being used, or * <code>null</code>. * @param srcWidth the width of the source image. * @param srcHeight the height of the source image. * * @return the source region as a <code>Rectangle</code>. */ protected static Rectangle getSourceRegion(ImageReadParam param, int srcWidth, int srcHeight) { Rectangle sourceRegion = new Rectangle(0, 0, srcWidth, srcHeight); if (param != null) { Rectangle region = param.getSourceRegion(); if (region != null) { sourceRegion = sourceRegion.intersection(region); } int subsampleXOffset = param.getSubsamplingXOffset(); int subsampleYOffset = param.getSubsamplingYOffset(); sourceRegion.x += subsampleXOffset; sourceRegion.y += subsampleYOffset; sourceRegion.width -= subsampleXOffset; sourceRegion.height -= subsampleYOffset; } return sourceRegion; } /** * Computes the source region of interest and the destination * region of interest, taking the width and height of the source * image, an optional destination image, and an optional * <code>ImageReadParam</code> into account. The source region * begins with the entire source image. Then that is clipped to * the source region specified in the <code>ImageReadParam</code>, * if one is specified. * * <p> If either of the destination offsets are negative, the * source region is clipped so that its top left will coincide * with the top left of the destination image, taking subsampling * into account. Then the result is clipped to the destination * image on the right and bottom, if one is specified, taking * subsampling and destination offsets into account. * * <p> Similarly, the destination region begins with the source * image, is translated to the destination offset given in the * <code>ImageReadParam</code> if there is one, and finally is * clipped to the destination image, if there is one. * * <p> If either the source or destination regions end up having a * width or height of 0, an <code>IllegalArgumentException</code> * is thrown. * * <p> The {@link #getSourceRegion <code>getSourceRegion</code>} * method may be used if only source clipping is desired. * * @param param an <code>ImageReadParam</code>, or <code>null</code>. * @param srcWidth the width of the source image. * @param srcHeight the height of the source image. * @param image a <code>BufferedImage</code> that will be the * destination image, or <code>null</code>. * @param srcRegion a <code>Rectangle</code> that will be filled with * the source region of interest. * @param destRegion a <code>Rectangle</code> that will be filled with * the destination region of interest. * @exception IllegalArgumentException if <code>srcRegion</code> * is <code>null</code>. * @exception IllegalArgumentException if <code>dstRegion</code> * is <code>null</code>. * @exception IllegalArgumentException if the resulting source or * destination region is empty. */ protected static void computeRegions(ImageReadParam param, int srcWidth, int srcHeight, BufferedImage image, Rectangle srcRegion, Rectangle destRegion) { if (srcRegion == null) { throw new IllegalArgumentException("srcRegion == null!"); } if (destRegion == null) { throw new IllegalArgumentException("destRegion == null!"); } // Start with the entire source image srcRegion.setBounds(0, 0, srcWidth, srcHeight); // Destination also starts with source image, as that is the // maximum extent if there is no subsampling destRegion.setBounds(0, 0, srcWidth, srcHeight); // Clip that to the param region, if there is one int periodX = 1; int periodY = 1; int gridX = 0; int gridY = 0; if (param != null) { Rectangle paramSrcRegion = param.getSourceRegion(); if (paramSrcRegion != null) { srcRegion.setBounds(srcRegion.intersection(paramSrcRegion)); } periodX = param.getSourceXSubsampling(); periodY = param.getSourceYSubsampling(); gridX = param.getSubsamplingXOffset(); gridY = param.getSubsamplingYOffset(); srcRegion.translate(gridX, gridY); srcRegion.width -= gridX; srcRegion.height -= gridY; destRegion.setLocation(param.getDestinationOffset()); } // Now clip any negative destination offsets, i.e. clip // to the top and left of the destination image if (destRegion.x < 0) { int delta = -destRegion.x*periodX; srcRegion.x += delta; srcRegion.width -= delta; destRegion.x = 0; } if (destRegion.y < 0) { int delta = -destRegion.y*periodY; srcRegion.y += delta; srcRegion.height -= delta; destRegion.y = 0; } // Now clip the destination Region to the subsampled width and height int subsampledWidth = (srcRegion.width + periodX - 1)/periodX; int subsampledHeight = (srcRegion.height + periodY - 1)/periodY; destRegion.width = subsampledWidth; destRegion.height = subsampledHeight; // Now clip that to right and bottom of the destination image, // if there is one, taking subsampling into account if (image != null) { Rectangle destImageRect = new Rectangle(0, 0, image.getWidth(), image.getHeight()); destRegion.setBounds(destRegion.intersection(destImageRect)); if (destRegion.isEmpty()) { throw new IllegalArgumentException ("Empty destination region!"); } int deltaX = destRegion.x + subsampledWidth - image.getWidth(); if (deltaX > 0) { srcRegion.width -= deltaX*periodX; } int deltaY = destRegion.y + subsampledHeight - image.getHeight(); if (deltaY > 0) { srcRegion.height -= deltaY*periodY; } } if (srcRegion.isEmpty() || destRegion.isEmpty()) { throw new IllegalArgumentException("Empty region!"); } } /** * A utility method that may be used by readers to test the * validity of the source and destination band settings of an * <code>ImageReadParam</code>. This method may be called as soon * as the reader knows both the number of bands of the source * image as it exists in the input stream, and the number of bands * of the destination image that being written. * * <p> The method retrieves the source and destination band * setting arrays from param using the <code>getSourceBands</code> * and <code>getDestinationBands</code>methods (or considers them * to be <code>null</code> if <code>param</code> is * <code>null</code>). If the source band setting array is * <code>null</code>, it is considered to be equal to the array * <code>{ 0, 1, ..., numSrcBands - 1 }</code>, and similarly for * the destination band setting array. * * <p> The method then tests that both arrays are equal in length, * and that neither array contains a value larger than the largest * available band index. * * <p> Any failure results in an * <code>IllegalArgumentException</code> being thrown; success * results in the method returning silently. * * @param param the <code>ImageReadParam</code> being used to read * the image. * @param numSrcBands the number of bands of the image as it exists * int the input source. * @param numDstBands the number of bands in the destination image * being written. * * @exception IllegalArgumentException if <code>param</code> * contains an invalid specification of a source and/or * destination band subset. */ protected static void checkReadParamBandSettings(ImageReadParam param, int numSrcBands, int numDstBands) { // A null param is equivalent to srcBands == dstBands == null. int[] srcBands = null; int[] dstBands = null; if (param != null) { srcBands = param.getSourceBands(); dstBands = param.getDestinationBands(); } int paramSrcBandLength = (srcBands == null) ? numSrcBands : srcBands.length; int paramDstBandLength = (dstBands == null) ? numDstBands : dstBands.length; if (paramSrcBandLength != paramDstBandLength) { throw new IllegalArgumentException("ImageReadParam num source & dest bands differ!"); } if (srcBands != null) { for (int i = 0; i < srcBands.length; i++) { if (srcBands[i] >= numSrcBands) { throw new IllegalArgumentException("ImageReadParam source bands contains a value >= the number of source bands!"); } } } if (dstBands != null) { for (int i = 0; i < dstBands.length; i++) { if (dstBands[i] >= numDstBands) { throw new IllegalArgumentException("ImageReadParam dest bands contains a value >= the number of dest bands!"); } } } } /** * Returns the <code>BufferedImage</code> to which decoded pixel * data should be written. The image is determined by inspecting * the supplied <code>ImageReadParam</code> if it is * non-<code>null</code>; if its <code>getDestination</code> * method returns a non-<code>null</code> value, that image is * simply returned. Otherwise, * <code>param.getDestinationType</code> method is called to * determine if a particular image type has been specified. If * so, the returned <code>ImageTypeSpecifier</code> is used after * checking that it is equal to one of those included in * <code>imageTypes</code>. * * <p> If <code>param</code> is <code>null</code> or the above * steps have not yielded an image or an * <code>ImageTypeSpecifier</code>, the first value obtained from * the <code>imageTypes</code> parameter is used. Typically, the * caller will set <code>imageTypes</code> to the value of * <code>getImageTypes(imageIndex)</code>. * * <p> Next, the dimensions of the image are determined by a call * to <code>computeRegions</code>. The actual width and height of * the image being decoded are passed in as the <code>width</code> * and <code>height</code> parameters. * * @param param an <code>ImageReadParam</code> to be used to get * the destination image or image type, or <code>null</code>. * @param imageTypes an <code>Iterator</code> of * <code>ImageTypeSpecifier</code>s indicating the legal image * types, with the default first. * @param width the true width of the image or tile begin decoded. * @param height the true width of the image or tile being decoded. * * @return the <code>BufferedImage</code> to which decoded pixel * data should be written. * * @exception IIOException if the <code>ImageTypeSpecifier</code> * specified by <code>param</code> does not match any of the legal * ones from <code>imageTypes</code>. * @exception IllegalArgumentException if <code>imageTypes</code> * is <code>null</code> or empty, or if an object not of type * <code>ImageTypeSpecifier</code> is retrieved from it. * @exception IllegalArgumentException if the resulting image would * have a width or height less than 1. * @exception IllegalArgumentException if the product of * <code>width</code> and <code>height</code> is greater than * <code>Integer.MAX_VALUE</code>. */ protected static BufferedImage getDestination(ImageReadParam param, Iterator<ImageTypeSpecifier> imageTypes, int width, int height) throws IIOException { if (imageTypes == null || !imageTypes.hasNext()) { throw new IllegalArgumentException("imageTypes null or empty!"); } if ((long)width*height > Integer.MAX_VALUE) { throw new IllegalArgumentException ("width*height > Integer.MAX_VALUE!"); } BufferedImage dest = null; ImageTypeSpecifier imageType = null; // If param is non-null, use it if (param != null) { // Try to get the image itself dest = param.getDestination(); if (dest != null) { return dest; } // No image, get the image type imageType = param.getDestinationType(); } // No info from param, use fallback image type if (imageType == null) { Object o = imageTypes.next(); if (!(o instanceof ImageTypeSpecifier)) { throw new IllegalArgumentException ("Non-ImageTypeSpecifier retrieved from imageTypes!"); } imageType = (ImageTypeSpecifier)o; } else { boolean foundIt = false; while (imageTypes.hasNext()) { ImageTypeSpecifier type = (ImageTypeSpecifier)imageTypes.next(); if (type.equals(imageType)) { foundIt = true; break; } } if (!foundIt) { throw new IIOException ("Destination type from ImageReadParam does not match!"); } } Rectangle srcRegion = new Rectangle(0,0,0,0); Rectangle destRegion = new Rectangle(0,0,0,0); computeRegions(param, width, height, null, srcRegion, destRegion); int destWidth = destRegion.x + destRegion.width; int destHeight = destRegion.y + destRegion.height; // Create a new image based on the type specifier return imageType.createBufferedImage(destWidth, destHeight); } }