SimpleRenderedImage.java
上传用户:btjssb159
上传日期:2018-01-04
资源大小:241k
文件大小:20k
源码类别:

DNA

开发平台:

Java

  1. /*
  2.  * Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without 
  5.  * modification, are permitted provided that the following conditions are met:
  6.  * 
  7.  * -Redistributions of source code must retain the above copyright notice, this 
  8.  * list of conditions and the following disclaimer.
  9.  *
  10.  * -Redistribution in binary form must reproduct the above copyright notice,
  11.  * this list of conditions and the following disclaimer in the documentation
  12.  * and/or other materials provided with the distribution.
  13.  * 
  14.  * Neither the name of Sun Microsystems, Inc. or the names of contributors may
  15.  * be used to endorse or promote products derived from this software without
  16.  * specific prior written permission.
  17.  * 
  18.  * This software is provided "AS IS," without a warranty of any kind. ALL
  19.  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
  20.  * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
  21.  * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
  22.  * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
  23.  * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
  24.  * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
  25.  * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
  26.  * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
  27.  * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
  28.  * POSSIBILITY OF SUCH DAMAGES.
  29.  * 
  30.  * You acknowledge that Software is not designed,licensed or intended for use in 
  31.  * the design, construction, operation or maintenance of any nuclear facility.
  32.  */
  33. import java.awt.Point;
  34. import java.awt.Rectangle;
  35. import java.awt.image.Raster;
  36. import java.awt.image.WritableRaster;
  37. import java.awt.image.RenderedImage;
  38. import java.awt.image.ColorModel;
  39. import java.awt.image.SampleModel;
  40. import java.util.Enumeration;
  41. import java.util.Hashtable;
  42. import java.util.Iterator;
  43. import java.util.Vector;
  44. /**
  45.  * A simple class implemented the <code>RenderedImage</code>
  46.  * interface.  Only the <code>getTile()</code> method needs to be
  47.  * implemented by subclasses.  The instance variables must also be
  48.  * filled in properly.
  49.  *
  50.  * <p> Normally in JAI <code>PlanarImage</code> is used for this
  51.  * purpose, but in the interest of making
  52.  * <code>com.sun.media.jai.codec</code> and
  53.  * <code>com.sun.media.jai.codecimpl</code> be as modular as possible the
  54.  * use of <code>PlanarImage</code> has been avoided.
  55.  */
  56. public abstract class SimpleRenderedImage implements RenderedImage {
  57.     /** The X coordinate of the image's upper-left pixel. */
  58.     protected int minX;
  59.     
  60.     /** The Y coordinate of the image's upper-left pixel. */
  61.     protected int minY;
  62.     
  63.     /** The image's width in pixels. */
  64.     protected int width;
  65.     
  66.     /** The image's height in pixels. */
  67.     protected int height;
  68.     
  69.     /** The width of a tile. */
  70.     protected int tileWidth;
  71.     
  72.     /** The height of a tile. */
  73.     protected int tileHeight;
  74.     /** The X coordinate of the upper-left pixel of tile (0, 0). */
  75.     protected int tileGridXOffset = 0;
  76.     
  77.     /** The Y coordinate of the upper-left pixel of tile (0, 0). */
  78.     protected int tileGridYOffset = 0;
  79.     
  80.     /** The image's SampleModel. */
  81.     protected SampleModel sampleModel = null;
  82.     
  83.     /** The image's ColorModel. */
  84.     protected ColorModel colorModel = null;
  85.     
  86.     /** The image's sources, stored in a Vector. */
  87.     protected Vector sources = new Vector();
  88.     /** A Hashtable containing the image properties. */
  89.     protected Hashtable properties = new Hashtable();
  90.     public SimpleRenderedImage() {}
  91.     /** Returns the X coordinate of the leftmost column of the image. */
  92.     public int getMinX() {
  93.         return minX;
  94.     }
  95.     /**
  96.      * Returns the X coordinate of the column immediatetely to the
  97.      * right of the rightmost column of the image.  getMaxX() is
  98.      * implemented in terms of getMinX() and getWidth() and so does
  99.      * not need to be implemented by subclasses.
  100.      */
  101.     public final int getMaxX() {
  102.         return getMinX() + getWidth();
  103.     }
  104.     /** Returns the X coordinate of the uppermost row of the image. */
  105.     public int getMinY() {
  106.         return minY;
  107.     }
  108.     /**
  109.      * Returns the Y coordinate of the row immediately below the
  110.      * bottom row of the image.  getMaxY() is implemented in terms of
  111.      * getMinY() and getHeight() and so does not need to be
  112.      * implemented by subclasses.
  113.      */
  114.     public final int getMaxY() {
  115.         return getMinY() + getHeight();
  116.     }
  117.     /** Returns the width of the image. */
  118.     public int getWidth() {
  119.         return width;
  120.     }
  121.     /** Returns the height of the image. */
  122.     public int getHeight() {
  123.         return height;
  124.     }
  125.     
  126.     /** Returns a Rectangle indicating the image bounds. */
  127.     public Rectangle getBounds() {
  128.         return new Rectangle(getMinX(), getMinY(),
  129.                              getWidth(), getHeight());
  130.     }
  131.     
  132.     /** Returns the width of a tile. */
  133.     public int getTileWidth() {
  134.         return tileWidth;
  135.     }
  136.     /** Returns the height of a tile. */
  137.     public int getTileHeight() {
  138.         return tileHeight;
  139.     }
  140.     /** 
  141.      * Returns the X coordinate of the upper-left pixel of tile (0, 0).
  142.      */
  143.     public int getTileGridXOffset() {
  144.         return tileGridXOffset;
  145.     }
  146.     /** 
  147.      * Returns the Y coordinate of the upper-left pixel of tile (0, 0).
  148.      */
  149.     public int getTileGridYOffset() {
  150.         return tileGridYOffset;
  151.     }
  152.     /**
  153.      * Returns the horizontal index of the leftmost column of tiles.
  154.      * getMinTileX() is implemented in terms of getMinX()
  155.      * and so does not need to be implemented by subclasses.
  156.      */
  157.     public int getMinTileX() {
  158.         return XToTileX(getMinX());
  159.     }
  160.     /**
  161.      * Returns the horizontal index of the rightmost column of tiles.
  162.      * getMaxTileX() is implemented in terms of getMaxX()
  163.      * and so does not need to be implemented by subclasses.
  164.      */
  165.     public int getMaxTileX() {
  166.         return XToTileX(getMaxX() - 1);
  167.     }
  168.     /**
  169.      * Returns the number of tiles along the tile grid in the
  170.      * horizontal direction.  getNumXTiles() is implemented in terms
  171.      * of getMinTileX() and getMaxTileX() and so does not need to be
  172.      * implemented by subclasses.
  173.      */
  174.     public int getNumXTiles() {
  175.         return getMaxTileX() - getMinTileX() + 1;
  176.     }
  177.     
  178.     /**
  179.      * Returns the vertical index of the uppermost row of tiles.  getMinTileY()
  180.      * is implemented in terms of getMinY() and so does not need to be
  181.      * implemented by subclasses. 
  182.      */
  183.     public int getMinTileY() {
  184.         return YToTileY(getMinY());
  185.     }
  186.     /**
  187.      * Returns the vertical index of the bottom row of tiles.  getMaxTileY()
  188.      * is implemented in terms of getMaxY() and so does not need to
  189.      * be implemented by subclasses.
  190.      */
  191.     public int getMaxTileY() {
  192.         return YToTileY(getMaxY() - 1);
  193.     }
  194.     /**
  195.      * Returns the number of tiles along the tile grid in the vertical
  196.      * direction.  getNumYTiles() is implemented in terms
  197.      * of getMinTileY() and getMaxTileY() and so does not need to be
  198.      * implemented by subclasses.
  199.      */
  200.     public int getNumYTiles() {
  201.         return getMaxTileY() - getMinTileY() + 1;
  202.     }
  203.     /** Returns the SampleModel of the image. */
  204.     public SampleModel getSampleModel() {
  205.         return sampleModel;
  206.     }
  207.     /** Returns the ColorModel of the image. */
  208.     public ColorModel getColorModel() {
  209.         return colorModel;
  210.     }
  211.     /**
  212.      * Gets a property from the property set of this image.  If the
  213.      * property name is not recognized,
  214.      * <code>java.awt.Image.UndefinedProperty</code> will be returned.
  215.      *
  216.      * @param name the name of the property to get, as a
  217.      * <code>String</code>.  @return a reference to the property
  218.      * <code>Object</code>, or the value
  219.      * <code>java.awt.Image.UndefinedProperty.</code>
  220.      */
  221.     public Object getProperty(String name) {
  222.         name = name.toLowerCase();
  223.         Object value = properties.get(name);
  224.         return value != null ? value : java.awt.Image.UndefinedProperty;
  225.     }
  226.     
  227.     /**
  228.      * Returns a list of the properties recognized by this image.  If
  229.      * no properties are available, <code>null</code> will be
  230.      * returned.
  231.      *
  232.      * @return an array of <code>String</code>s representing valid
  233.      *         property names.
  234.      */
  235.     public String[] getPropertyNames() {
  236.         String[] names = null;
  237.         if(properties.size() > 0) {
  238.             names = new String[properties.size()];
  239.             int index = 0;
  240.             Enumeration e = properties.keys();
  241.             while (e.hasMoreElements()) {
  242.                 String name = (String)e.nextElement();
  243.                 names[index++] = name;
  244.             }
  245.         }
  246.         return names;
  247.     }
  248.     /**
  249.      * Returns an array of <code>String</code>s recognized as names by
  250.      * this property source that begin with the supplied prefix.  If
  251.      * no property names match, <code>null</code> will be returned.
  252.      * The comparison is done in a case-independent manner.
  253.      *
  254.      * <p> The default implementation calls
  255.      * <code>getPropertyNames()</code> and searches the list of names
  256.      * for matches.
  257.      *
  258.      * @return an array of <code>String</code>s giving the valid
  259.      * property names.
  260.      */
  261.     public String[] getPropertyNames(String prefix) {
  262.         String propertyNames[] = getPropertyNames();
  263.         if (propertyNames == null) {
  264.             return null;
  265.         }
  266.         prefix = prefix.toLowerCase();
  267.         Vector names = new Vector();
  268.         for (int i = 0; i < propertyNames.length; i++) {
  269.             if (propertyNames[i].startsWith(prefix)) {
  270.                 names.addElement(propertyNames[i]);
  271.             }
  272.         }
  273.         if (names.size() == 0) {
  274.             return null;
  275.         }
  276.         // Copy the strings from the Vector over to a String array.
  277.         String prefixNames[] = new String[names.size()];
  278.         int count = 0;
  279.         for (Iterator it = names.iterator(); it.hasNext(); ) {
  280.             prefixNames[count++] = (String)it.next();
  281.         }
  282.         return prefixNames;
  283.     }
  284.     // Utility methods.
  285.     /**
  286.      * Converts a pixel's X coordinate into a horizontal tile index
  287.      * relative to a given tile grid layout specified by its X offset
  288.      * and tile width.
  289.      */
  290.     public static int XToTileX(int x, int tileGridXOffset, int tileWidth) {
  291.         x -= tileGridXOffset;
  292.         if (x < 0) {
  293.             x += 1 - tileWidth; // Force round to -infinity
  294.         }
  295.         return x/tileWidth;
  296.     }
  297.     /**
  298.      * Converts a pixel's Y coordinate into a vertical tile index
  299.      * relative to a given tile grid layout specified by its Y offset
  300.      * and tile height.
  301.      */
  302.     public static int YToTileY(int y, int tileGridYOffset, int tileHeight) {
  303.         y -= tileGridYOffset;
  304.         if (y < 0) {
  305.             y += 1 - tileHeight; // Force round to -infinity
  306.         }
  307.         return y/tileHeight;
  308.     }
  309.     /**
  310.      * Converts a pixel's X coordinate into a horizontal tile index.
  311.      * This is a convenience method.  No attempt is made to detect
  312.      * out-of-range coordinates.
  313.      *
  314.      * @param x the X coordinate of a pixel.
  315.      * @return the X index of the tile containing the pixel.
  316.      */
  317.     public int XToTileX(int x) {
  318.         return XToTileX(x, getTileGridXOffset(), getTileWidth());
  319.     }
  320.     /**
  321.      * Converts a pixel's Y coordinate into a vertical tile index. 
  322.      * This is a convenience method.  No attempt is made to detect
  323.      * out-of-range coordinates.
  324.      *
  325.      * @param y the Y coordinate of a pixel.
  326.      * @return the Y index of the tile containing the pixel.
  327.      */
  328.     public int YToTileY(int y) {
  329.         return YToTileY(y, getTileGridYOffset(), getTileHeight());
  330.     }
  331.     /**
  332.      * Converts a horizontal tile index into the X coordinate of its
  333.      * upper left pixel relative to a given tile grid layout specified
  334.      * by its X offset and tile width.
  335.      */
  336.     public static int tileXToX(int tx, int tileGridXOffset, int tileWidth) {
  337.         return tx*tileWidth + tileGridXOffset;
  338.     }
  339.     /**
  340.      * Converts a vertical tile index into the Y coordinate of
  341.      * its upper left pixel relative to a given tile grid layout
  342.      * specified by its Y offset and tile height.
  343.      */
  344.     public static int tileYToY(int ty, int tileGridYOffset, int tileHeight) {
  345.         return ty*tileHeight + tileGridYOffset;
  346.     }
  347.     /**
  348.      * Converts a horizontal tile index into the X coordinate of its
  349.      * upper left pixel.  This is a convenience method.  No attempt is made
  350.      * to detect out-of-range indices.
  351.      *
  352.      * @param tx the horizontal index of a tile.
  353.      * @return the X coordinate of the tile's upper left pixel.
  354.      */
  355.     public int tileXToX(int tx) {
  356.         return tx*tileWidth + tileGridXOffset;
  357.     }
  358.     /**
  359.      * Converts a vertical tile index into the Y coordinate of its
  360.      * upper left pixel.  This is a convenience method.  No attempt is made
  361.      * to detect out-of-range indices.
  362.      *
  363.      * @param ty the vertical index of a tile.
  364.      * @return the Y coordinate of the tile's upper left pixel.
  365.      */
  366.     public int tileYToY(int ty) {
  367.         return ty*tileHeight + tileGridYOffset;
  368.     }
  369.     public Vector getSources() {
  370.         return null;
  371.     }
  372.     /**
  373.      * Returns the entire image in a single Raster.  For images with
  374.      * multiple tiles this will require making a copy.
  375.      *
  376.      * <p> The returned Raster is semantically a copy.  This means
  377.      * that updates to the source image will not be reflected in the
  378.      * returned Raster.  For non-writable (immutable) source images,
  379.      * the returned value may be a reference to the image's internal
  380.      * data.  The returned Raster should be considered non-writable;
  381.      * any attempt to alter its pixel data (such as by casting it to
  382.      * WritableRaster or obtaining and modifying its DataBuffer) may
  383.      * result in undefined behavior.  The copyData method should be
  384.      * used if the returned Raster is to be modified.
  385.      *
  386.      * @return a Raster containing a copy of this image's data.
  387.      */
  388.     public Raster getData() {
  389.         Rectangle rect = new Rectangle(getMinX(), getMinY(),
  390.                                        getWidth(), getHeight());
  391.         return getData(rect);
  392.     }
  393.     /**
  394.      * Returns an arbitrary rectangular region of the RenderedImage
  395.      * in a Raster.  The rectangle of interest will be clipped against
  396.      * the image bounds.
  397.      *
  398.      * <p> The returned Raster is semantically a copy.  This means
  399.      * that updates to the source image will not be reflected in the
  400.      * returned Raster.  For non-writable (immutable) source images,
  401.      * the returned value may be a reference to the image's internal
  402.      * data.  The returned Raster should be considered non-writable;
  403.      * any attempt to alter its pixel data (such as by casting it to
  404.      * WritableRaster or obtaining and modifying its DataBuffer) may
  405.      * result in undefined behavior.  The copyData method should be
  406.      * used if the returned Raster is to be modified.
  407.      *
  408.      * @param bounds the region of the RenderedImage to be returned.
  409.      */
  410.     public Raster getData(Rectangle bounds) {
  411.         int startX = XToTileX(bounds.x);
  412.         int startY = YToTileY(bounds.y);
  413.         int endX = XToTileX(bounds.x + bounds.width - 1);
  414.         int endY = YToTileY(bounds.y + bounds.height - 1);
  415.         Raster tile;
  416.         if ((startX == endX) && (startY == endY)) {
  417.             tile = getTile(startX, startY);
  418.             return tile.createChild(bounds.x, bounds.y,
  419.                                     bounds.width, bounds.height,
  420.                                     bounds.x, bounds.y, null);
  421.         } else {
  422.             // Create a WritableRaster of the desired size
  423.             SampleModel sm =
  424.                 sampleModel.createCompatibleSampleModel(bounds.width,
  425.                                                        bounds.height);
  426.             // Translate it
  427.             WritableRaster dest =
  428.                 RasterFactory.createWritableRaster(sm, bounds.getLocation());
  429.             for (int j = startY; j <= endY; j++) {
  430.                 for (int i = startX; i <= endX; i++) {
  431.                     tile = getTile(i, j);
  432.                     Rectangle tileRect = tile.getBounds();
  433.                     Rectangle intersectRect =
  434.                         bounds.intersection(tile.getBounds());
  435.                     Raster liveRaster = tile.createChild(intersectRect.x,
  436.                                                          intersectRect.y,
  437.                                                          intersectRect.width,
  438.                                                          intersectRect.height,
  439.                                                          intersectRect.x,
  440.                                                          intersectRect.y,
  441.                                                          null);
  442.                     dest.setDataElements(0, 0, liveRaster);
  443.                 }
  444.             }
  445.             return dest;
  446.         }
  447.     }
  448.     /**
  449.      * Copies an arbitrary rectangular region of the RenderedImage
  450.      * into a caller-supplied WritableRaster.  The region to be
  451.      * computed is determined by clipping the bounds of the supplied
  452.      * WritableRaster against the bounds of the image.  The supplied
  453.      * WritableRaster must have a SampleModel that is compatible with
  454.      * that of the image.
  455.      *
  456.      * <p> If the raster argument is null, the entire image will
  457.      * be copied into a newly-created WritableRaster with a SampleModel
  458.      * that is compatible with that of the image.
  459.      *
  460.      * @param dest a WritableRaster to hold the returned portion of
  461.      *        the image.
  462.      * @return a reference to the supplied WritableRaster, or to a 
  463.      *         new WritableRaster if the supplied one was null.
  464.      */
  465.     public WritableRaster copyData(WritableRaster dest) {
  466.         Rectangle bounds;
  467.         Raster tile;
  468.                     
  469.         if (dest == null) {
  470.             bounds = getBounds();
  471.             Point p = new Point(minX, minY);
  472.             /* A SampleModel to hold the entire image. */
  473.             SampleModel sm = sampleModel.createCompatibleSampleModel(
  474.                                          width, height);
  475.             dest = RasterFactory.createWritableRaster(sm, p);
  476.         } else {
  477.             bounds = dest.getBounds();
  478.         }
  479.         
  480.         int startX = XToTileX(bounds.x);
  481.         int startY = YToTileY(bounds.y);
  482.         int endX = XToTileX(bounds.x + bounds.width - 1);
  483.         int endY = YToTileY(bounds.y + bounds.height - 1);
  484.             
  485.         for (int j = startY; j <= endY; j++) {
  486.             for (int i = startX; i <= endX; i++) {
  487.                 tile = getTile(i, j);
  488.                 Rectangle tileRect = tile.getBounds();
  489.                 Rectangle intersectRect =
  490.                     bounds.intersection(tile.getBounds());
  491.                 Raster liveRaster = tile.createChild(intersectRect.x,
  492.                                                      intersectRect.y,
  493.                                                      intersectRect.width,
  494.                                                      intersectRect.height,
  495.                                                      intersectRect.x,
  496.                                                      intersectRect.y,
  497.                                                      null);
  498.                 /*
  499.                  * WritableRaster.setDataElements takes into account of
  500.                  * inRaster's minX and minY and add these to x and y. Since
  501.                  * liveRaster has the origin at the correct location, the
  502.                  * following call should not again give these coordinates in
  503.                  * places of x and y.
  504.                  */
  505.                 dest.setDataElements(0, 0, liveRaster);
  506.             }
  507.         }
  508.         return dest;
  509.     }
  510. }