@(#)Misc.txt 1.8 Proposal: Miscellaneous Core Modifications ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Brian Burkhalter Created: 12 May 2000 Revised: 12/18/00 CHANGES DURING COMMUNITY REVIEW ------------------------------- . ImageLayout: added equals() and hashCode() methods. . PixelAccessor: added management of bit offsets in packed data. . PlanarImage/RenderedOp: determine final changes to source accessor/mutators; clarify sink list management. . RenderableOp: Remove the protected variable "Rectangle2D boundingBox". . CollectionImage: . Deprecate CollectionImage.getProperty(String, Collection). . Add get(int index). . ROIShape.getAsImage(): should return a bilevel TiledImage instead of a TYPE_BYTE_GRAY BufferedImage. . Modify JAI createCollection() and createCollectionNS() "return" javadoc. . TiledImage: . Added PropertyChangeListener implementation. . Override getProperty[Names]() to use RenderedImage source as fallback. . OpImage: . Added getTileCacheMetric(). . Clarify getTile() javadoc. . PointOpImage: clarify constructor javadoc. . StatisticsOpImage: override computesUniqueTiles() to return "false". PROPOSAL -------- This proposal discusses miscellaneous fundamental changes to the JAI core. For elaboration of the classes and methods discussed in this proposal please refer to the respective HTML documentation. The HTML files for the following javax.media.jai classes should accompany this proposal: ColormapOpImage ColorSpaceJAI CRIFImpl GeometricOpImage Histogram IHSColorSpace OpImage PackedImageData PixelAccessor PlanarImage RasterAccessor TiledImage UnpackedImageData Note that there are also numerous minor modifications which were made as a result of the code review process. Items discussed in the various other proposals are in general not included here. 1. New Core Classes 1.1 CRIFImpl A utility class to simplify implemeting ContextualRenderedImageFactory classes. This was discussed in the approved "Non-image Data in Processing Chains" but is included here for completeness. 1.2 ColormapOpImage A class to be used to implement an operation which may conditionally be accelerated by transforming the colormap of the source image instead of its data. The method isColorMapOperation() is added to PointOpImage to support the use of this subclass. 1.3 GeometricOpImage An abstract base class for image operators that perform a geometric transformation of the source image. The core classes ScaleOpImage and WarpOpImage now extend this class. The former class hierarchy was OpImage > WarpOpImage > ScaleOpImage. 1.4 ColorSpace Classes Define a class to assist extenders with implementing mathematically defined color spaces and another to implement the oft requested IHS color space. 1.4.1 ColorSpaceJAI Adds some methods to the base ColorSpace class to enable color conversion of a raster of data at a time. This should permit efficient implementation of mathematically defined color spaces for which no ICC profile is available. The JAI "ColorConvert" operation would be modified to choose an optimal computation pathway based on the class of ColorSpace provided as well as on the image data type. 1.4.2 IHSColorSpace A representation of the IHS color space. 1.4 PixelAccessor A utility class that may be used to access the pixel data stored in a RenderedImage's Rasters, as well as performing pixel-to-color data translation based on the image's SampleModel and ColorModel. It also provides several static methods to determine information about the image data. This class uses two other new core classes: PackedImageData and UnpackedImageData which are used to store packed and unpacked data, respectively along with access information. 1.4.1 Community Review Change Add a parameter "coerceZeroOffset" to PixelAccessor.getPackedPixels(): * @param coerceZeroOffset If true the returned * PackedImageData will be forced to have a * bitOffset and offset of zero * and a lineStride of (rect.width+7)/8. * The coercedZeroOffset field of the returned * PackedImageData will be set to true. */ public PackedImageData getPackedPixels(Raster raster, Rectangle rect, boolean isDest, boolean coerceZeroOffset) {} Add a field "coercedZeroOffset" to PackedImageData: /** Whether the data have been coerced to have zero offsets. */ public final boolean coercedZeroOffset; Add "coercedZeroOffset" parameter to PackedImageData constructor: * @param coercedZeroOffset Whether the data have been coerced to * have zero offsets. */ public PackedImageData(Raster raster, Rectangle rect, byte[] data, int lineStride, int offset, int bitOffset, boolean convertToDest, boolean coercedZeroOffset) {} 2. Non-OpImage Core Class Modifications This section lists a variety of modifications of extant core classes excepting those in the OpImage hierarchy. They are discussed in the following section. 2.1 CollectionImage Classes 2.1.1 CollectionImage 2.1.1.1 Deprecate the method public CollectionImage.getProperty(String, Collection) {} 2.1.1.2 Add an element retrieval method: /** * Returns the element at the given index in imageCollection. * If imageCollection is a List then the call is * forwarded to imageCollection; otherwise an array is created * by applying toArray() to imageCollection and * the indicated element of that array is returned. Note that in the * latter case no guarantee as to element ordering beyond that stated in * the specification of Collection.toArray(). * * @param index The index of the desired element. * @throws IndexOutOfBoundsException if the index is out of range * (index < 0 || index ≥ * imageCollection.size()). */ public Object get(int index) {} 2.1.2 CollectionOp Deprecate a constructor: public CollectionOp(OperationRegistry registry, String opName, ParameterBlock args) {} 2.2 Histogram 2.2.1 Constructors Add a constructor which sets the same bin count and data range for all bands. public Histogram(int numBins, double lowValue, double highValue, int numBands) {} Add a constructor which expands arrays to a length of numBands if needed. /** * Constructor. * *

This constructor should be used when numBins, * lowValue, and/or highValues may be * different for each band of the image. The number of bands in the * image is provided explicitly. If any of the arrays provided * has a length which is less than the number of bands, the first * element in that array is used to fill out the array to a length * of numBands. * * * @param numBins The number of bins for each band of the image. * @param lowValue The lowest inclusive pixel value checked for * each band. * @param highValue The highest exclusive pixel value checked for * each band. * * @throws NullPointerException If numBins, * lowValue, or highValue is * null. * @throws IllegalArgumentException If any array length is 0. * @throws IllegalArgumentException If the number of bins for any band * is less than or equal to 0. * @throws IllegalArgumentException If the low-value of any band is * greater than or equal to its corresponding high-value. * @throws IllegalArgumentException If numBands is less * than or equal to 0. */ public Histogram(int[] numBins, double[] lowValue, double[] highValue, int numBands) {} 2.2.2 Totals Methods Add methods to retieve bin counts: public int[] getTotals() {} public int getSubTotal(int band, int minBin, int maxBin) {} 2.2.3 Derived Statistics Add methods to compute the mean, standard deviation, entropy, and arbitrary moments including central, absolute, and absolute central moments. 2.2.4 Smoothed Histogram Generation Add methods to derive a histogram using a rectangular, weighted rectangular, or Gaussian moving window. 2.2.5 Threshold Derivation Add methods to compute a band-by-band threshold by the iterative selection, maximum entropy, maximum between class to within class variance, minimum error, minimum fuzziness, mode, and P-tile algorithms. 2.3 JAI 2.3.1 Rendering Keys Add the following: /** * Key for TileScheduler object values. * The common RenderingHints by default contain a hint * corresponding to this key the value of which is equal to the value * returned by getTileScheduler(). The hint is * automatically set by setTileScheduler(). */ public static RenderingHints.Key KEY_TILE_SCHEDULER; /** * Key for enabling default ColorModel initialization * when a valid ColorModel may not be derived by * inheritance. The corresponding object must be a Boolean. * The common RenderingHints do not contain a default * hint corresponding to this key. */ public static RenderingHints.Key KEY_DEFAULT_COLOR_MODEL_ENABLED; /** * Key for specifying a method to be used as for default * ColorModel initialization. The corresponding object * must be a java.lang.reflect.Method which is static * and accepts a single SampleModel parameter and returns a * ColorModel or null. * The common RenderingHints do not contain a default * hint corresponding to this key. */ public static RenderingHints.Key KEY_DEFAULT_COLOR_MODEL_METHOD; 2.3.2 Default Tile Size Introduce the concept of a default tile size. Currently images by default inherit the tile dimensions of their first source image in an operation chain unless something else is specified in an ImageLayout passed via the RenderingHints. The proposal is to set a default tile size which would be used to set image tile size using the following algorithm: . Each dimension (tile width and tile height) is treated independently. . If a tile dimension is set via the ImageLayout hint, honor the hint. . If a tile dimension is set by default, i.e., inherited from the first source, then set the dimension to the default tile dimension if and only if A) the image would otherwise have no tile splits along that axis, and B) the image dimension is at least double the default tile dimension. 2.3.2.1 Accessor /** * Retrieves the clone of the default tile dimensions. * If null there are no default dimensions set. * * @return The default tile dimensions or null. */ public static final Dimension getDefaultTileSize() {} 2.3.2.2 Mutator /** * Sets the default tile dimensions to the clone of the provided parameter. * If null there are no default dimensions. * * @param tileDimensions The default tile dimensions or null. * * @throws IllegalArgumentException if * tileDimensions is non-null and * has non-positive width or height. */ public static final void setDefaultTileSize(Dimension tileDimensions) {} 2.3.3 getBuildVersion() A new method would be added as follows: /** * Returns JAI version information as a String */ public static final String getBuildVersion() {} 2.3.4 TileCache Factory Method Deprecate (tileCapacity no longer relevant): public static TileCache createTileCache(int tileCapacity, long memCapacity) {} A new method has been added which does not use the tileCapacity: /** * Constructs a TileCache with the given memory capacity * in bytes. Users may supply an instance of TileCache * to an operation by supplying a RenderingHint with a * JAI.KEY_TILE_CACHE key and the desired TileCache * instance as its value. Note that the absence of a tile cache * hint will result in the use of the TileCache * belonging to the defaultJAIinstance. To force an operation * not to perform caching, a TileCache instance with * a tile capacity of 0 may be used. * An exception will be thrown if memCapacity is negative. * Attempting to set either value larger than the JVM size may result in an * OutOfMemory exception. */ public static TileCache createTileCache(long memCapacity) {} 2.3.5 JAI.create() Convenience Methods Deprecate all static JAI.create() methods except: Method Usage ------ ----- create(String,ParameterBlock,RenderingHints) Principal method create(String,ParameterBlock) (null RenderingHints) create(String,Object) (awtimage,decoders) create(String,Object,Object) (stream,url,decoders) create(String,RenderedImage) (unary ops) create(String,RenderedImage,Object) (convolve,lookup) create(String,RenderedImage,Object,Object) (affine,rescale) create(String,RenderedImage,Object,Object,Object) (encode,fileload, filestore) create(String,RenderedImage,RenderedImage) ("binary" ops) 2.3.6 createCollection() and createCollectionNS() Correct specification of "return": * @return A Collection that represents the named * operation, or null if the specified operation * is in the "immediate" mode and the rendering of the * PlanarImage failed. 2.4 OperationDescriptorImpl Deprecate (superfluous due to a new constructor with one extra parameter): public OperationDescriptorImpl(String[][] resources, Class[] sourceClasses, Class[] renderableSourceClasses, Class[] paramClasses, String[] paramNames, Object[] paramDefaults) {} 2.5 ParameterBlockJAI Added public ParameterBlock add(Object obj) {} which merely throws an exception (prevents adding any parameters). Added public boolean getBooleanParameter(String paramName) {} to retrieve a boolean parameter from the parameter Vector. Added public int indexOfSource(String sourceName) {} to retrieve the index of the source with the given name (ancillary to the proposal "OperationDescriptor-related Modifications"). Added public ParameterBlock set(boolean b, String paramName) { to set the value of a parameter with a given name. Added public ParameterBlock setSource(Object source, String sourceName) { to set the value of the source with the given name (ancillary to the proposal "OperationDescriptor-related Modifications"). 2.6 PlanarImage 2.6.1 getDefaultColorModel() Add a factory method for ColorModel generation: public static ColorModel getDefaultColorModel(int dataType, int numBands) {} 2.6.2 Constructor Add a new constructor: public PlanarImage(ImageLayout layout, Vector sources, Map properties) {} 2.6.3 setImageLayout() Replace setImageParameters() methods with: protected void setImageLayout(ImageLayout layout) {} 2.6.4 getNumBands() Add a method to retrieve the number of bands: /** * Retrieve the number of image bands. Note that this may differ from the * number of components per pixel, e.g., if an IndexColorModel * is being used. This is equivalent to calling * getSampleModel().getNumBands(). */ public int getNumBands() {} 2.6.5 getTileIndices() Add a method to compute the indicies of all tiles which intersect a region: /** * Returns an array containing the indices of all tiles which overlap * the specified Rectangle. If the Rectangle * does not intersect the image bounds then null will be * returned. If an array is returned, it will be ordered in terms of * the row major ordering of its contained tile indices. If the * specified Rectangle is null, the tile * indicies for the entire image will be returned. * * @param region The Rectangle of interest. * @return An array of the indices of overlapping tiles or * null if region does not intersect * the image bounds. */ public Point[] getTileIndices(Rectangle region) {} 2.6.6 getTiles() Add a method to compute all tiles: /** * Computes and returns all tiles in the image. The tiles are returned * in a sequence corresponding to the row-major order of their respective * tile indices. The returned array may of course be ignored. */ Raster[] getTiles() {} 2.6.7 Source Accessor/Mutator Methods This section includes similar changes to be made in the RenderedOp subclass. Final changes to the source accessor/mutator methods for this release: PlanarImage: . deprecate: public PlanarImage getSource(int index) {} . remove: protected void addSource(PlanarImage source) {} protected void setSource(PlanarImage source, int index) {} protected boolean removeSource(PlanarImage source) {} . add: protected void addSource(Object source) {} protected void setSource(Object source, int index) {} protected boolean removeSource(Object source) {} public Object getSourceObject(int index) {} public PlanarImage getSourceImage(int index) {} RenderedOp: . deprecate: public PlanarImage getSource(int index) {} public void addSource(PlanarImage source) {} public void setSource(PlanarImage source, int index) {} public boolean removeSource(PlanarImage source) {} . add: public void addSource(Object source) {} public void setSource(Object source, int index) {} public boolean removeSource(Object source) {} These changes will be completed in the next JAI release wherein all deprecated methods will be removed and in PlanarImage public Object getSourceObject(int index) {} will be deprecated, public Object getSource(int index) {} will be added, and in RenderedOp public Object getSourceObject(int index) {} will be deprecated and public Object getSource(int index) {} will override the PlanarImage method. 2.6.8 Sink List Consistency Modify methods as needed to maintain consistency of the sink list. . setSource(): Remove image as sink of replaced PlanarImage. * [...] If a PlanarImage * source previously existed at this index, this image is removed from * its list of sinks. . setSources(): Remove image as sink of any PlanarImages in previous source list. * [...] This image is removed from the list of sinks of * any prior PlanarImages sources which are not * also elements of the supplied List. . removeSources(): Remove image as sink of any PlanarImages in source list. * [...] This image is removed from * the list of sinks of any prior PlanarImages sources. . Change access of addSink(Object), removeSink(Object) and removeSinks() from protected to public. 2.7 RasterAccessor Enhanced support for binary data handling. Bilevel Rasters, i.e., those with MultiPixelPackedSampleModels, are supported more efficiently. In the cases where the bilevel data are unpacked they are now transferred to bytes instead of integers which reduces memory consumption by a factor of four. Also, new methods are provided to handle the binary data directly: public boolean isBinary(); public void copyBinaryDataToRaster(); public byte[] getBinaryDataArray(); 2.8 TileCache Deprecate two methods (tile capacity no longer relevant): void setTileCapacity(int tileCapacity); int getTileCapacity(); 2.9 TiledImage 2.9.1 Constructors Added two constructors to create a TiledImage with the characteristics of an extant RenderedImage but possibly with different tile dimensions. public TiledImage(RenderedImage source) {} public TiledImage(RenderedImage source, int tileWidth, int tileHeight) {} Add another constructor to permit buffer re-use. If this is added then the constructor TiledImage(RenderedImage source) is unnecessary. /** * Constructs a TiledImage equivalent to a given * RenderedImage. Actual copying of the pixel data from * the RenderedImage will be deferred until the first time * they are requested from the TiledImage. The tiles of * the TiledImage may optionally share * DataBuffers with the tiles of the source image but it * should be realized in this case that data written into the * TiledImage will be visible in the source image. * * @param source The source RenderedImage. * @param areBuffersShared Whether the tile DataBuffers * of the source are re-used in the tiles of * this image. If false new * WritableRasters will be * created. */ public TiledImage(RenderedImage source, boolean areBuffersShared) {} 2.9.2 Sub-Image Methods Added two methods to retrieve a sub-image. public TiledImage getSubImage(int x, int y, int w, int h, int[] bandSelect, ColorModel cm) {} public TiledImage getSubImage(int[] bandSelect, ColorModel cm) { 2.9.3 Implement PropertyChangeListener Please refer to the proposal "Support for Editing Rendered Op Chains" for background information on the utility of this method. /** * Implementation of PropertyChangeListener. * *

When invoked with an event emitted by the source image specified * for this TiledImage and the event is either a * PropertyChangeEventJAI named "InvalidRegion" * (case-insensitive) or a RenderingChangeEvent, then * all tiles which overlap the intersection of the invalid region and the * region of interest specified for this image (if any) will * be cleared. If the event is a RenderingChangeEvent then * the invalid region will be obtained from the getInvalidRegion * method of the event object; if a PropertyChangeEventJAI * it will be obtained from the getNewValue() method. * In either case, a new PropertyChangeEventJAI will be * fired to all registered listeners of the property name * "InvalidRegion" and to all known sinks which are * PropertyChangeListeners. Its old and new values will * contain the previous and current invalid regions. This may be used to * determine which tiles must be re-requested. The * TiledImage itself will not re-request the data. */ public synchronized void propertyChange(PropertyChangeEvent evt) {} 2.9.4 Property Accessor Methods getProperty[Names](): Use the source RenderedImage, if any, as a fallback. 2.9.5 Deprecations Constructors (do not allow a ColorModel to be set): public TiledImage(Point origin, SampleModel sampleModel, int tileWidth, int tileHeight) {} public TiledImage(SampleModel sampleModel, int tileWidth, int tileHeight) {} Factory methods (do not allow a ColorModel to be set): public static TiledImage createInterleaved(int minX, int minY, int width, int height, int numBands, int dataType, int tileWidth, int tileHeight, int[] bandOffsets) {} public static TiledImage createBanded(int minX, int minY, int width, int height, int dataType, int tileWidth, int tileHeight, int[] bankIndices, int[] bandOffsets) {} Graphics method (redundant): public Graphics getGraphics() {} Sub-image extraction methods (do not allow a ColorModel to be set): public TiledImage getSubImage(int x, int y, int w, int h, int[] bandSelect) {} public TiledImage getSubImage(int[] bandSelect) {} 2.11 Warp Classes 2.11.1 WarpAffine Added public Rectangle mapSourceRect(Rectangle srcRect) {} The previous implementation returned null as it did not override the superclass method. 2.11.2 WarpGrid Removed overriding of public Rectangle mapDestRect(Rectangle destRect) { as the subclass added no functionality to the method in Warp. 2.11.3 WarpPerspective Added public Rectangle mapSourceRect(Rectangle srcRect) {} The previous implementation returned null as it did not override the superclass method. 2.11.4 WarpPolynomial Removed overriding of public Rectangle mapDestRect(Rectangle destRect) { as the subclass added no functionality to the method in Warp. 2.12 javax.media.jai.widget.* This package will be deprecated. The source code is already downloadable. 2.13 ImageLayout Make this class implement the equals() method. To be equal both ImageLayout objects would have to have the same validity mask and be equal according to strict comparison ("==") for all primitive fields; the SampleModel and ColorModel fields would use the equals() method. The hashCode() method will also be overridden according to the contract of java.lang.Object. 2.14 RenderableOp Remove the protected variable "Rectangle2D boundingBox". 2.15 ROIShape getAsImage(): should return a bilevel TiledImage instead of a TYPE_BYTE_GRAY BufferedImage. 3. OpImage Hierarchy 3.1 OpImage 3.1.2 Constructor All previous constructors are deleted and replaced with public OpImage(Vector sources, ImageLayout layout, Map configuration, boolean cobbleSources) {} No BorderExtender parameters are accepted unlike in the previous versions. 3.1.2 BorderExtenders Remove the instance variable "extenders" of type BorderExtender[]. BorderExtenders are not needed by all subclasses and so are pushed down to the top level classes in sub-hierarchies to which they are relevant. Within JAI this includes AreaOpImage and GeometricOpImage. 3.1.3 getExpandedNumBands() Deprecate: public static int getExpandedNumBands(SampleModel sampleModel, ColorModel colorModel) {} 3.1.4 getTileCacheMetric() Add a method: /** * Returns the tileCacheMetric instance variable by reference. */ public Object getTileCacheMetric() {} This was extant but had package scope. 3.1.5 getTile() Clarify getTile() documentation concerning method overrides: *

If a subclass overrides this method, then it needs to handle * tile caching and scheduling. It should also override * computeTile() which may be invoked directly by the * TileScheduler. 3.2 AreaOpImage Added methods /** * Retrieve the BorderExtender object associated with * this class instance. The object is returned by reference. * * @return The associated BorderExtender object * or null. */ public BorderExtender getBorderExtender() {} public boolean hasExtender() { Replace previous constructor with: public AreaOpImage(RenderedImage source, ImageLayout layout, Map configuration, boolean cobbleSources, BorderExtender extender, int leftPadding, int rightPadding, int topPadding, int bottomPadding) {} 3.3 ScaleOpImage Make this a subclass of GeometricOpImage. The mapDestRect() and mapSourceRect() methods are moved to the superclass and forwardMapRect() and backwardMapRect()] are implemented. A Warp object is no longer required. Replace previous constructor with: public ScaleOpImage(RenderedImage source, ImageLayout layout, Map configuration, boolean cobbleSources, BorderExtender extender, Interpolation interp, float scaleX, float scaleY, float transX, float transY) {} Deprecate padding accessors (information available from Interpolation object): public int get{Left,Right,Top,Bottom}Padding() {} 3.4 WarpOpImage Make this a subclass of GeometricOpImage. The mapDestRect() and mapSourceRect() methods are moved to the superclass and forwardMapRect() and backwardMapRect()] are implemented. Replace previous constructor with: public WarpOpImage(RenderedImage source, ImageLayout layout, Map configuration, boolean cobbleSources, BorderExtender extender, Interpolation interp, Warp warp) {} 3.5 PointOpImage 3.5.1 Constructor Replace previous generic constructor with: public PointOpImage(Vector sources, ImageLayout layout, Map configuration, boolean cobbleSources) {} Similar changes to be made to the convenience constructors which accept one, two, or three RenderedImages instead of a Vector of sources. Modify the generic constructor documentation to read: * Constructor. * *

There must be at least one valid source supplied via the * sources argument. However, there is no upper limit * on the number of sources this image may have. * *

The image's layout is encapsulated in the layout * argument. If the image bounds are supplied they must be contained * within the intersected source bounds which must be non-empty. * If the bounds are not supplied, they are calculated to be the * intersection of the bounds of all sources. * *

If no SampleModel is specified in the layout, a new * SampleModel will be created. This SampleModel * will have a number of bands equal to the minimum band count of all * sources and a depth which can accomodate the data of all sources. * The band count of sources which have an IndexColorModel * will be set to the number of components of the * IndexColorModel instead of to the number of bands of the * SampleModel. * *

In all cases, the layout is forwarded to the OpImage * constructor which sets the default layout values in the standard way. 3.5.2 isColormapOperation() Add a method to support accelerating colormap operations: /** * Indicates whether the operation is being effected directly on the * associated colormap. This method will in general return * true if the image is the destination of a unary, * shift-invariant operation with an IndexColorModel equal * to that of its unique source. * *

When this method returns true the * computeTile() method in this class will return either * a copy of the corresponding region of the first source image or, * if the operation is being performed in place, the corresponding * tile of the first source image. * *

The implementation in this class always returns false. */ protected boolean isColormapOperation() {} 3.6 NullOpImage 3.6.1 Constructor Replace previous constructor with: public NullOpImage(RenderedImage source, Map configuration, int computeType, ImageLayout layout) {} 3.6.2 ImageLayout/RenderingHints Formerly it was allowed to specify the tile grid layout, SampleModel, and ColorModel via the ImageLayout. This is not logical as the computeTile() method of this class simply returns the corresponding tile of the source image. This implies that the NullOpImage must have the same SampleModel and tile grid as its source. Consequently this class is modified to allow specifying only the ColorModel via the ImageLayout. Even this hint will be ignored if the ColorModel is not compatible with the image SampleModel. This should not affect anything except the output of the image decoders. 3.7 SourcelessOpImage Replace previous constructor with: public SourcelessOpImage(ImageLayout layout, Map configuration, SampleModel sampleModel, int minX, int minY, int width, int height) {} 3.8 UntiledOpImage Support multiple sources and conform to configuration variable specification. Add a constructor: public UntiledOpImage(Vector sources, ImageLayout layout, Map configuration) {} Change computeImage() specification to: protected abstract void computeImage(Raster[] sources, WritableRaster dest, Rectangle destRect) {} 3.9 StatisticsOpImage Override computesUniqueTiles() to return "false": /** * Returns false as computeTile() invocations * are forwarded to the RenderedImage source and are * therefore not unique objects in the global sense. */ public boolean computesUniqueTiles() {}