1 /*
   2  * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.awt.image;
  27 
  28 import java.awt.Transparency;
  29 import java.awt.color.ColorSpace;
  30 import java.awt.Graphics2D;
  31 import java.awt.GraphicsConfiguration;
  32 import java.awt.GraphicsEnvironment;
  33 import java.awt.ImageCapabilities;
  34 import java.awt.geom.Rectangle2D;
  35 import java.awt.geom.Point2D;
  36 import java.awt.Point;
  37 import java.awt.Rectangle;
  38 import java.security.AccessController;
  39 import java.security.PrivilegedAction;
  40 import java.util.Hashtable;
  41 import java.util.Vector;
  42 
  43 import sun.awt.image.BytePackedRaster;
  44 import sun.awt.image.ShortComponentRaster;
  45 import sun.awt.image.ByteComponentRaster;
  46 import sun.awt.image.IntegerComponentRaster;
  47 import sun.awt.image.OffScreenImageSource;
  48 
  49 /**
  50  *
  51  * The <code>BufferedImage</code> subclass describes an {@link
  52  * java.awt.Image Image} with an accessible buffer of image data.
  53  * A <code>BufferedImage</code> is comprised of a {@link ColorModel} and a
  54  * {@link Raster} of image data.
  55  * The number and types of bands in the {@link SampleModel} of the
  56  * <code>Raster</code> must match the number and types required by the
  57  * <code>ColorModel</code> to represent its color and alpha components.
  58  * All <code>BufferedImage</code> objects have an upper left corner
  59  * coordinate of (0,&nbsp;0).  Any <code>Raster</code> used to construct a
  60  * <code>BufferedImage</code> must therefore have minX=0 and minY=0.
  61  *
  62  * <p>
  63  * This class relies on the data fetching and setting methods
  64  * of <code>Raster</code>,
  65  * and on the color characterization methods of <code>ColorModel</code>.
  66  *
  67  * @see ColorModel
  68  * @see Raster
  69  * @see WritableRaster
  70  */
  71 
  72 public class BufferedImage extends java.awt.Image
  73                            implements WritableRenderedImage, Transparency
  74 {
  75     int        imageType = TYPE_CUSTOM;
  76     ColorModel colorModel;
  77     WritableRaster raster;
  78     OffScreenImageSource osis;
  79     Hashtable<Object, Object> properties;
  80 
  81     boolean    isAlphaPremultiplied;// If true, alpha has been premultiplied in
  82     // color channels
  83 
  84     /**
  85      * Image Type Constants
  86      */
  87 
  88     /**
  89      * Image type is not recognized so it must be a customized
  90      * image.  This type is only used as a return value for the getType()
  91      * method.
  92      */
  93     public static final int TYPE_CUSTOM = 0;
  94 
  95     /**
  96      * Represents an image with 8-bit RGB color components packed into
  97      * integer pixels.  The image has a {@link DirectColorModel} without
  98      * alpha.
  99      * When data with non-opaque alpha is stored
 100      * in an image of this type,
 101      * the color data must be adjusted to a non-premultiplied form
 102      * and the alpha discarded,
 103      * as described in the
 104      * {@link java.awt.AlphaComposite} documentation.
 105      */
 106     public static final int TYPE_INT_RGB = 1;
 107 
 108     /**
 109      * Represents an image with 8-bit RGBA color components packed into
 110      * integer pixels.  The image has a <code>DirectColorModel</code>
 111      * with alpha. The color data in this image is considered not to be
 112      * premultiplied with alpha.  When this type is used as the
 113      * <code>imageType</code> argument to a <code>BufferedImage</code>
 114      * constructor, the created image is consistent with images
 115      * created in the JDK1.1 and earlier releases.
 116      */
 117     public static final int TYPE_INT_ARGB = 2;
 118 
 119     /**
 120      * Represents an image with 8-bit RGBA color components packed into
 121      * integer pixels.  The image has a <code>DirectColorModel</code>
 122      * with alpha.  The color data in this image is considered to be
 123      * premultiplied with alpha.
 124      */
 125     public static final int TYPE_INT_ARGB_PRE = 3;
 126 
 127     /**
 128      * Represents an image with 8-bit RGB color components, corresponding
 129      * to a Windows- or Solaris- style BGR color model, with the colors
 130      * Blue, Green, and Red packed into integer pixels.  There is no alpha.
 131      * The image has a {@link DirectColorModel}.
 132      * When data with non-opaque alpha is stored
 133      * in an image of this type,
 134      * the color data must be adjusted to a non-premultiplied form
 135      * and the alpha discarded,
 136      * as described in the
 137      * {@link java.awt.AlphaComposite} documentation.
 138      */
 139     public static final int TYPE_INT_BGR = 4;
 140 
 141     /**
 142      * Represents an image with 8-bit RGB color components, corresponding
 143      * to a Windows-style BGR color model) with the colors Blue, Green,
 144      * and Red stored in 3 bytes.  There is no alpha.  The image has a
 145      * <code>ComponentColorModel</code>.
 146      * When data with non-opaque alpha is stored
 147      * in an image of this type,
 148      * the color data must be adjusted to a non-premultiplied form
 149      * and the alpha discarded,
 150      * as described in the
 151      * {@link java.awt.AlphaComposite} documentation.
 152      */
 153     public static final int TYPE_3BYTE_BGR = 5;
 154 
 155     /**
 156      * Represents an image with 8-bit RGBA color components with the colors
 157      * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha.  The
 158      * image has a <code>ComponentColorModel</code> with alpha.  The
 159      * color data in this image is considered not to be premultiplied with
 160      * alpha.  The byte data is interleaved in a single
 161      * byte array in the order A, B, G, R
 162      * from lower to higher byte addresses within each pixel.
 163      */
 164     public static final int TYPE_4BYTE_ABGR = 6;
 165 
 166     /**
 167      * Represents an image with 8-bit RGBA color components with the colors
 168      * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha.  The
 169      * image has a <code>ComponentColorModel</code> with alpha. The color
 170      * data in this image is considered to be premultiplied with alpha.
 171      * The byte data is interleaved in a single byte array in the order
 172      * A, B, G, R from lower to higher byte addresses within each pixel.
 173      */
 174     public static final int TYPE_4BYTE_ABGR_PRE = 7;
 175 
 176     /**
 177      * Represents an image with 5-6-5 RGB color components (5-bits red,
 178      * 6-bits green, 5-bits blue) with no alpha.  This image has
 179      * a <code>DirectColorModel</code>.
 180      * When data with non-opaque alpha is stored
 181      * in an image of this type,
 182      * the color data must be adjusted to a non-premultiplied form
 183      * and the alpha discarded,
 184      * as described in the
 185      * {@link java.awt.AlphaComposite} documentation.
 186      */
 187     public static final int TYPE_USHORT_565_RGB = 8;
 188 
 189     /**
 190      * Represents an image with 5-5-5 RGB color components (5-bits red,
 191      * 5-bits green, 5-bits blue) with no alpha.  This image has
 192      * a <code>DirectColorModel</code>.
 193      * When data with non-opaque alpha is stored
 194      * in an image of this type,
 195      * the color data must be adjusted to a non-premultiplied form
 196      * and the alpha discarded,
 197      * as described in the
 198      * {@link java.awt.AlphaComposite} documentation.
 199      */
 200     public static final int TYPE_USHORT_555_RGB = 9;
 201 
 202     /**
 203      * Represents a unsigned byte grayscale image, non-indexed.  This
 204      * image has a <code>ComponentColorModel</code> with a CS_GRAY
 205      * {@link ColorSpace}.
 206      * When data with non-opaque alpha is stored
 207      * in an image of this type,
 208      * the color data must be adjusted to a non-premultiplied form
 209      * and the alpha discarded,
 210      * as described in the
 211      * {@link java.awt.AlphaComposite} documentation.
 212      */
 213     public static final int TYPE_BYTE_GRAY = 10;
 214 
 215     /**
 216      * Represents an unsigned short grayscale image, non-indexed).  This
 217      * image has a <code>ComponentColorModel</code> with a CS_GRAY
 218      * <code>ColorSpace</code>.
 219      * When data with non-opaque alpha is stored
 220      * in an image of this type,
 221      * the color data must be adjusted to a non-premultiplied form
 222      * and the alpha discarded,
 223      * as described in the
 224      * {@link java.awt.AlphaComposite} documentation.
 225      */
 226     public static final int TYPE_USHORT_GRAY = 11;
 227 
 228     /**
 229      * Represents an opaque byte-packed 1, 2, or 4 bit image.  The
 230      * image has an {@link IndexColorModel} without alpha.  When this
 231      * type is used as the <code>imageType</code> argument to the
 232      * <code>BufferedImage</code> constructor that takes an
 233      * <code>imageType</code> argument but no <code>ColorModel</code>
 234      * argument, a 1-bit image is created with an
 235      * <code>IndexColorModel</code> with two colors in the default
 236      * sRGB <code>ColorSpace</code>: {0,&nbsp;0,&nbsp;0} and
 237      * {255,&nbsp;255,&nbsp;255}.
 238      *
 239      * <p> Images with 2 or 4 bits per pixel may be constructed via
 240      * the <code>BufferedImage</code> constructor that takes a
 241      * <code>ColorModel</code> argument by supplying a
 242      * <code>ColorModel</code> with an appropriate map size.
 243      *
 244      * <p> Images with 8 bits per pixel should use the image types
 245      * <code>TYPE_BYTE_INDEXED</code> or <code>TYPE_BYTE_GRAY</code>
 246      * depending on their <code>ColorModel</code>.
 247 
 248      * <p> When color data is stored in an image of this type,
 249      * the closest color in the colormap is determined
 250      * by the <code>IndexColorModel</code> and the resulting index is stored.
 251      * Approximation and loss of alpha or color components
 252      * can result, depending on the colors in the
 253      * <code>IndexColorModel</code> colormap.
 254      */
 255     public static final int TYPE_BYTE_BINARY = 12;
 256 
 257     /**
 258      * Represents an indexed byte image.  When this type is used as the
 259      * <code>imageType</code> argument to the <code>BufferedImage</code>
 260      * constructor that takes an <code>imageType</code> argument
 261      * but no <code>ColorModel</code> argument, an
 262      * <code>IndexColorModel</code> is created with
 263      * a 256-color 6/6/6 color cube palette with the rest of the colors
 264      * from 216-255 populated by grayscale values in the
 265      * default sRGB ColorSpace.
 266      *
 267      * <p> When color data is stored in an image of this type,
 268      * the closest color in the colormap is determined
 269      * by the <code>IndexColorModel</code> and the resulting index is stored.
 270      * Approximation and loss of alpha or color components
 271      * can result, depending on the colors in the
 272      * <code>IndexColorModel</code> colormap.
 273      */
 274     public static final int TYPE_BYTE_INDEXED = 13;
 275 
 276     private static final int DCM_RED_MASK   = 0x00ff0000;
 277     private static final int DCM_GREEN_MASK = 0x0000ff00;
 278     private static final int DCM_BLUE_MASK  = 0x000000ff;
 279     private static final int DCM_ALPHA_MASK = 0xff000000;
 280     private static final int DCM_565_RED_MASK = 0xf800;
 281     private static final int DCM_565_GRN_MASK = 0x07E0;
 282     private static final int DCM_565_BLU_MASK = 0x001F;
 283     private static final int DCM_555_RED_MASK = 0x7C00;
 284     private static final int DCM_555_GRN_MASK = 0x03E0;
 285     private static final int DCM_555_BLU_MASK = 0x001F;
 286     private static final int DCM_BGR_RED_MASK = 0x0000ff;
 287     private static final int DCM_BGR_GRN_MASK = 0x00ff00;
 288     private static final int DCM_BGR_BLU_MASK = 0xff0000;
 289 
 290 
 291     static private native void initIDs();
 292     static {
 293         ColorModel.loadLibraries();
 294         initIDs();
 295     }
 296 
 297     /**
 298      * Constructs a <code>BufferedImage</code> of one of the predefined
 299      * image types.  The <code>ColorSpace</code> for the image is the
 300      * default sRGB space.
 301      * @param width     width of the created image
 302      * @param height    height of the created image
 303      * @param imageType type of the created image
 304      * @see ColorSpace
 305      * @see #TYPE_INT_RGB
 306      * @see #TYPE_INT_ARGB
 307      * @see #TYPE_INT_ARGB_PRE
 308      * @see #TYPE_INT_BGR
 309      * @see #TYPE_3BYTE_BGR
 310      * @see #TYPE_4BYTE_ABGR
 311      * @see #TYPE_4BYTE_ABGR_PRE
 312      * @see #TYPE_BYTE_GRAY
 313      * @see #TYPE_USHORT_GRAY
 314      * @see #TYPE_BYTE_BINARY
 315      * @see #TYPE_BYTE_INDEXED
 316      * @see #TYPE_USHORT_565_RGB
 317      * @see #TYPE_USHORT_555_RGB
 318      */
 319     public BufferedImage(int width,
 320                          int height,
 321                          int imageType) {
 322         switch (imageType) {
 323         case TYPE_INT_RGB:
 324             {
 325                 colorModel = new DirectColorModel(24,
 326                                                   0x00ff0000,   // Red
 327                                                   0x0000ff00,   // Green
 328                                                   0x000000ff,   // Blue
 329                                                   0x0           // Alpha
 330                                                   );
 331                   raster = colorModel.createCompatibleWritableRaster(width,
 332                                                                       height);
 333             }
 334         break;
 335 
 336         case TYPE_INT_ARGB:
 337             {
 338                 colorModel = ColorModel.getRGBdefault();
 339 
 340                 raster = colorModel.createCompatibleWritableRaster(width,
 341                                                                    height);
 342             }
 343         break;
 344 
 345         case TYPE_INT_ARGB_PRE:
 346             {
 347                 colorModel = new
 348                     DirectColorModel(
 349                                      ColorSpace.getInstance(ColorSpace.CS_sRGB),
 350                                      32,
 351                                      0x00ff0000,// Red
 352                                      0x0000ff00,// Green
 353                                      0x000000ff,// Blue
 354                                      0xff000000,// Alpha
 355                                      true,       // Alpha Premultiplied
 356                                      DataBuffer.TYPE_INT
 357                                      );
 358 
 359                   raster = colorModel.createCompatibleWritableRaster(width,
 360                                                                       height);
 361             }
 362         break;
 363 
 364         case TYPE_INT_BGR:
 365             {
 366                 colorModel = new DirectColorModel(24,
 367                                                   0x000000ff,   // Red
 368                                                   0x0000ff00,   // Green
 369                                                   0x00ff0000    // Blue
 370                                                   );
 371                   raster = colorModel.createCompatibleWritableRaster(width,
 372                                                                       height);
 373             }
 374         break;
 375 
 376         case TYPE_3BYTE_BGR:
 377             {
 378                 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
 379                 int[] nBits = {8, 8, 8};
 380                 int[] bOffs = {2, 1, 0};
 381                 colorModel = new ComponentColorModel(cs, nBits, false, false,
 382                                                      Transparency.OPAQUE,
 383                                                      DataBuffer.TYPE_BYTE);
 384                 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
 385                                                         width, height,
 386                                                         width*3, 3,
 387                                                         bOffs, null);
 388             }
 389         break;
 390 
 391         case TYPE_4BYTE_ABGR:
 392             {
 393                 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
 394                 int[] nBits = {8, 8, 8, 8};
 395                 int[] bOffs = {3, 2, 1, 0};
 396                 colorModel = new ComponentColorModel(cs, nBits, true, false,
 397                                                      Transparency.TRANSLUCENT,
 398                                                      DataBuffer.TYPE_BYTE);
 399                 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
 400                                                         width, height,
 401                                                         width*4, 4,
 402                                                         bOffs, null);
 403             }
 404         break;
 405 
 406         case TYPE_4BYTE_ABGR_PRE:
 407             {
 408                 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
 409                 int[] nBits = {8, 8, 8, 8};
 410                 int[] bOffs = {3, 2, 1, 0};
 411                 colorModel = new ComponentColorModel(cs, nBits, true, true,
 412                                                      Transparency.TRANSLUCENT,
 413                                                      DataBuffer.TYPE_BYTE);
 414                 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
 415                                                         width, height,
 416                                                         width*4, 4,
 417                                                         bOffs, null);
 418             }
 419         break;
 420 
 421         case TYPE_BYTE_GRAY:
 422             {
 423                 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
 424                 int[] nBits = {8};
 425                 colorModel = new ComponentColorModel(cs, nBits, false, true,
 426                                                      Transparency.OPAQUE,
 427                                                      DataBuffer.TYPE_BYTE);
 428                 raster = colorModel.createCompatibleWritableRaster(width,
 429                                                                    height);
 430             }
 431         break;
 432 
 433         case TYPE_USHORT_GRAY:
 434             {
 435                 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
 436                 int[] nBits = {16};
 437                 colorModel = new ComponentColorModel(cs, nBits, false, true,
 438                                                      Transparency.OPAQUE,
 439                                                      DataBuffer.TYPE_USHORT);
 440                 raster = colorModel.createCompatibleWritableRaster(width,
 441                                                                    height);
 442             }
 443         break;
 444 
 445         case TYPE_BYTE_BINARY:
 446             {
 447                 byte[] arr = {(byte)0, (byte)0xff};
 448 
 449                 colorModel = new IndexColorModel(1, 2, arr, arr, arr);
 450                 raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
 451                                                    width, height, 1, 1, null);
 452             }
 453         break;
 454 
 455         case TYPE_BYTE_INDEXED:
 456             {
 457                 // Create a 6x6x6 color cube
 458                 int[] cmap = new int[256];
 459                 int i=0;
 460                 for (int r=0; r < 256; r += 51) {
 461                     for (int g=0; g < 256; g += 51) {
 462                         for (int b=0; b < 256; b += 51) {
 463                             cmap[i++] = (r<<16)|(g<<8)|b;
 464                         }
 465                     }
 466                 }
 467                 // And populate the rest of the cmap with gray values
 468                 int grayIncr = 256/(256-i);
 469 
 470                 // The gray ramp will be between 18 and 252
 471                 int gray = grayIncr*3;
 472                 for (; i < 256; i++) {
 473                     cmap[i] = (gray<<16)|(gray<<8)|gray;
 474                     gray += grayIncr;
 475                 }
 476 
 477                 colorModel = new IndexColorModel(8, 256, cmap, 0, false, -1,
 478                                                  DataBuffer.TYPE_BYTE);
 479                 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
 480                                                       width, height, 1, null);
 481             }
 482         break;
 483 
 484         case TYPE_USHORT_565_RGB:
 485             {
 486                 colorModel = new DirectColorModel(16,
 487                                                   DCM_565_RED_MASK,
 488                                                   DCM_565_GRN_MASK,
 489                                                   DCM_565_BLU_MASK
 490                                                   );
 491                 raster = colorModel.createCompatibleWritableRaster(width,
 492                                                                    height);
 493             }
 494             break;
 495 
 496         case TYPE_USHORT_555_RGB:
 497             {
 498                 colorModel = new DirectColorModel(15,
 499                                                   DCM_555_RED_MASK,
 500                                                   DCM_555_GRN_MASK,
 501                                                   DCM_555_BLU_MASK
 502                                                   );
 503                 raster = colorModel.createCompatibleWritableRaster(width,
 504                                                                    height);
 505             }
 506             break;
 507 
 508         default:
 509             throw new IllegalArgumentException ("Unknown image type " +
 510                                                 imageType);
 511         }
 512 
 513         this.imageType = imageType;
 514     }
 515 
 516     /**
 517      * Constructs a <code>BufferedImage</code> of one of the predefined
 518      * image types:
 519      * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED.
 520      *
 521      * <p> If the image type is TYPE_BYTE_BINARY, the number of
 522      * entries in the color model is used to determine whether the
 523      * image should have 1, 2, or 4 bits per pixel.  If the color model
 524      * has 1 or 2 entries, the image will have 1 bit per pixel.  If it
 525      * has 3 or 4 entries, the image with have 2 bits per pixel.  If
 526      * it has between 5 and 16 entries, the image will have 4 bits per
 527      * pixel.  Otherwise, an IllegalArgumentException will be thrown.
 528      *
 529      * @param width     width of the created image
 530      * @param height    height of the created image
 531      * @param imageType type of the created image
 532      * @param cm        <code>IndexColorModel</code> of the created image
 533      * @throws IllegalArgumentException   if the imageType is not
 534      * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED or if the imageType is
 535      * TYPE_BYTE_BINARY and the color map has more than 16 entries.
 536      * @see #TYPE_BYTE_BINARY
 537      * @see #TYPE_BYTE_INDEXED
 538      */
 539     public BufferedImage (int width,
 540                           int height,
 541                           int imageType,
 542                           IndexColorModel cm) {
 543         if (cm.hasAlpha() && cm.isAlphaPremultiplied()) {
 544             throw new IllegalArgumentException("This image types do not have "+
 545                                                "premultiplied alpha.");
 546         }
 547 
 548         switch(imageType) {
 549         case TYPE_BYTE_BINARY:
 550             int bits; // Will be set below
 551             int mapSize = cm.getMapSize();
 552             if (mapSize <= 2) {
 553                 bits = 1;
 554             } else if (mapSize <= 4) {
 555                 bits = 2;
 556             } else if (mapSize <= 16) {
 557                 bits = 4;
 558             } else {
 559                 throw new IllegalArgumentException
 560                     ("Color map for TYPE_BYTE_BINARY " +
 561                      "must have no more than 16 entries");
 562             }
 563             raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
 564                                                 width, height, 1, bits, null);
 565             break;
 566 
 567         case TYPE_BYTE_INDEXED:
 568             raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
 569                                                     width, height, 1, null);
 570             break;
 571         default:
 572             throw new IllegalArgumentException("Invalid image type (" +
 573                                                imageType+").  Image type must"+
 574                                                " be either TYPE_BYTE_BINARY or "+
 575                                                " TYPE_BYTE_INDEXED");
 576         }
 577 
 578         if (!cm.isCompatibleRaster(raster)) {
 579             throw new IllegalArgumentException("Incompatible image type and IndexColorModel");
 580         }
 581 
 582         colorModel = cm;
 583         this.imageType = imageType;
 584     }
 585 
 586     /**
 587      * Constructs a new <code>BufferedImage</code> with a specified
 588      * <code>ColorModel</code> and <code>Raster</code>.  If the number and
 589      * types of bands in the <code>SampleModel</code> of the
 590      * <code>Raster</code> do not match the number and types required by
 591      * the <code>ColorModel</code> to represent its color and alpha
 592      * components, a {@link RasterFormatException} is thrown.  This
 593      * method can multiply or divide the color <code>Raster</code> data by
 594      * alpha to match the <code>alphaPremultiplied</code> state
 595      * in the <code>ColorModel</code>.  Properties for this
 596      * <code>BufferedImage</code> can be established by passing
 597      * in a {@link Hashtable} of <code>String</code>/<code>Object</code>
 598      * pairs.
 599      * @param cm <code>ColorModel</code> for the new image
 600      * @param raster     <code>Raster</code> for the image data
 601      * @param isRasterPremultiplied   if <code>true</code>, the data in
 602      *                  the raster has been premultiplied with alpha.
 603      * @param properties <code>Hashtable</code> of
 604      *                  <code>String</code>/<code>Object</code> pairs.
 605      * @exception RasterFormatException if the number and
 606      * types of bands in the <code>SampleModel</code> of the
 607      * <code>Raster</code> do not match the number and types required by
 608      * the <code>ColorModel</code> to represent its color and alpha
 609      * components.
 610      * @exception IllegalArgumentException if
 611      *          <code>raster</code> is incompatible with <code>cm</code>
 612      * @see ColorModel
 613      * @see Raster
 614      * @see WritableRaster
 615      */
 616 
 617 
 618 /*
 619  *
 620  *  FOR NOW THE CODE WHICH DEFINES THE RASTER TYPE IS DUPLICATED BY DVF
 621  *  SEE THE METHOD DEFINERASTERTYPE @ RASTEROUTPUTMANAGER
 622  *
 623  */
 624     public BufferedImage (ColorModel cm,
 625                           WritableRaster raster,
 626                           boolean isRasterPremultiplied,
 627                           Hashtable<?,?> properties) {
 628 
 629         if (!cm.isCompatibleRaster(raster)) {
 630             throw new
 631                 IllegalArgumentException("Raster "+raster+
 632                                          " is incompatible with ColorModel "+
 633                                          cm);
 634         }
 635 
 636         if ((raster.minX != 0) || (raster.minY != 0)) {
 637             throw new
 638                 IllegalArgumentException("Raster "+raster+
 639                                          " has minX or minY not equal to zero: "
 640                                          + raster.minX + " " + raster.minY);
 641         }
 642 
 643         colorModel = cm;
 644         this.raster  = raster;
 645         this.properties = (Hashtable<Object,Object>)properties;
 646         int numBands = raster.getNumBands();
 647         boolean isAlphaPre = cm.isAlphaPremultiplied();
 648         final boolean isStandard = isStandard(cm, raster);
 649         ColorSpace cs;
 650 
 651         // Force the raster data alpha state to match the premultiplied
 652         // state in the color model
 653         coerceData(isRasterPremultiplied);
 654 
 655         SampleModel sm = raster.getSampleModel();
 656         cs = cm.getColorSpace();
 657         int csType = cs.getType();
 658         if (csType != ColorSpace.TYPE_RGB) {
 659             if (csType == ColorSpace.TYPE_GRAY &&
 660                 isStandard &&
 661                 cm instanceof ComponentColorModel) {
 662                 // Check if this might be a child raster (fix for bug 4240596)
 663                 if (sm instanceof ComponentSampleModel &&
 664                     ((ComponentSampleModel)sm).getPixelStride() != numBands) {
 665                     imageType = TYPE_CUSTOM;
 666                 } else if (raster instanceof ByteComponentRaster &&
 667                        raster.getNumBands() == 1 &&
 668                        cm.getComponentSize(0) == 8 &&
 669                        ((ByteComponentRaster)raster).getPixelStride() == 1) {
 670                     imageType = TYPE_BYTE_GRAY;
 671                 } else if (raster instanceof ShortComponentRaster &&
 672                        raster.getNumBands() == 1 &&
 673                        cm.getComponentSize(0) == 16 &&
 674                        ((ShortComponentRaster)raster).getPixelStride() == 1) {
 675                     imageType = TYPE_USHORT_GRAY;
 676                 }
 677             } else {
 678                 imageType = TYPE_CUSTOM;
 679             }
 680             return;
 681         }
 682 
 683         if ((raster instanceof IntegerComponentRaster) &&
 684             (numBands == 3 || numBands == 4)) {
 685             IntegerComponentRaster iraster =
 686                 (IntegerComponentRaster) raster;
 687             // Check if the raster params and the color model
 688             // are correct
 689             int pixSize = cm.getPixelSize();
 690             if (iraster.getPixelStride() == 1 &&
 691                 isStandard &&
 692                 cm instanceof DirectColorModel  &&
 693                 (pixSize == 32 || pixSize == 24))
 694             {
 695                 // Now check on the DirectColorModel params
 696                 DirectColorModel dcm = (DirectColorModel) cm;
 697                 int rmask = dcm.getRedMask();
 698                 int gmask = dcm.getGreenMask();
 699                 int bmask = dcm.getBlueMask();
 700                 if (rmask == DCM_RED_MASK && gmask == DCM_GREEN_MASK &&
 701                     bmask == DCM_BLUE_MASK)
 702                 {
 703                     if (dcm.getAlphaMask() == DCM_ALPHA_MASK) {
 704                         imageType = (isAlphaPre
 705                                      ? TYPE_INT_ARGB_PRE
 706                                      : TYPE_INT_ARGB);
 707                     }
 708                     else {
 709                         // No Alpha
 710                         if (!dcm.hasAlpha()) {
 711                             imageType = TYPE_INT_RGB;
 712                         }
 713                     }
 714                 }   // if (dcm.getRedMask() == DCM_RED_MASK &&
 715                 else if (rmask == DCM_BGR_RED_MASK && gmask == DCM_BGR_GRN_MASK
 716                          && bmask == DCM_BGR_BLU_MASK) {
 717                     if (!dcm.hasAlpha()) {
 718                         imageType = TYPE_INT_BGR;
 719                     }
 720                 }  // if (rmask == DCM_BGR_RED_MASK &&
 721             }   // if (iraster.getPixelStride() == 1
 722         }   // ((raster instanceof IntegerComponentRaster) &&
 723         else if ((cm instanceof IndexColorModel) && (numBands == 1) &&
 724                  isStandard &&
 725                  (!cm.hasAlpha() || !isAlphaPre))
 726         {
 727             IndexColorModel icm = (IndexColorModel) cm;
 728             int pixSize = icm.getPixelSize();
 729 
 730             if (raster instanceof BytePackedRaster) {
 731                 imageType = TYPE_BYTE_BINARY;
 732             }   // if (raster instanceof BytePackedRaster)
 733             else if (raster instanceof ByteComponentRaster) {
 734                 ByteComponentRaster braster = (ByteComponentRaster) raster;
 735                 if (braster.getPixelStride() == 1 && pixSize <= 8) {
 736                     imageType = TYPE_BYTE_INDEXED;
 737                 }
 738             }
 739         }   // else if (cm instanceof IndexColorModel) && (numBands == 1))
 740         else if ((raster instanceof ShortComponentRaster)
 741                  && (cm instanceof DirectColorModel)
 742                  && isStandard
 743                  && (numBands == 3)
 744                  && !cm.hasAlpha())
 745         {
 746             DirectColorModel dcm = (DirectColorModel) cm;
 747             if (dcm.getRedMask() == DCM_565_RED_MASK) {
 748                 if (dcm.getGreenMask() == DCM_565_GRN_MASK &&
 749                     dcm.getBlueMask()  == DCM_565_BLU_MASK) {
 750                     imageType = TYPE_USHORT_565_RGB;
 751                 }
 752             }
 753             else if (dcm.getRedMask() == DCM_555_RED_MASK) {
 754                 if (dcm.getGreenMask() == DCM_555_GRN_MASK &&
 755                     dcm.getBlueMask() == DCM_555_BLU_MASK) {
 756                     imageType = TYPE_USHORT_555_RGB;
 757                 }
 758             }
 759         }   // else if ((cm instanceof IndexColorModel) && (numBands == 1))
 760         else if ((raster instanceof ByteComponentRaster)
 761                  && (cm instanceof ComponentColorModel)
 762                  && isStandard
 763                  && (raster.getSampleModel() instanceof PixelInterleavedSampleModel)
 764                  && (numBands == 3 || numBands == 4))
 765         {
 766             ComponentColorModel ccm = (ComponentColorModel) cm;
 767             PixelInterleavedSampleModel csm =
 768                 (PixelInterleavedSampleModel)raster.getSampleModel();
 769             ByteComponentRaster braster = (ByteComponentRaster) raster;
 770             int[] offs = csm.getBandOffsets();
 771             if (ccm.getNumComponents() != numBands) {
 772                 throw new RasterFormatException("Number of components in "+
 773                                                 "ColorModel ("+
 774                                                 ccm.getNumComponents()+
 775                                                 ") does not match # in "+
 776                                                 " Raster ("+numBands+")");
 777             }
 778             int[] nBits = ccm.getComponentSize();
 779             boolean is8bit = true;
 780             for (int i=0; i < numBands; i++) {
 781                 if (nBits[i] != 8) {
 782                     is8bit = false;
 783                     break;
 784                 }
 785             }
 786             if (is8bit &&
 787                 braster.getPixelStride() == numBands &&
 788                 offs[0] == numBands-1 &&
 789                 offs[1] == numBands-2 &&
 790                 offs[2] == numBands-3)
 791             {
 792                 if (numBands == 3 && !ccm.hasAlpha()) {
 793                     imageType = TYPE_3BYTE_BGR;
 794                 }
 795                 else if (offs[3] == 0 && ccm.hasAlpha()) {
 796                     imageType = (isAlphaPre
 797                                  ? TYPE_4BYTE_ABGR_PRE
 798                                  : TYPE_4BYTE_ABGR);
 799                 }
 800             }
 801         }   // else if ((raster instanceof ByteComponentRaster) &&
 802     }
 803 
 804     private static boolean isStandard(ColorModel cm, WritableRaster wr) {
 805         final Class<? extends ColorModel> cmClass = cm.getClass();
 806         final Class<? extends WritableRaster> wrClass = wr.getClass();
 807         final Class<? extends SampleModel> smClass = wr.getSampleModel().getClass();
 808 
 809         final PrivilegedAction<Boolean> checkClassLoadersAction =
 810                 new PrivilegedAction<Boolean>()
 811         {
 812 
 813             @Override
 814             public Boolean run() {
 815                 final ClassLoader std = System.class.getClassLoader();
 816 
 817                 return (cmClass.getClassLoader() == std) &&
 818                         (smClass.getClassLoader() == std) &&
 819                         (wrClass.getClassLoader() == std);
 820             }
 821         };
 822         return AccessController.doPrivileged(checkClassLoadersAction);
 823     }
 824 
 825     /**
 826      * Returns the image type.  If it is not one of the known types,
 827      * TYPE_CUSTOM is returned.
 828      * @return the image type of this <code>BufferedImage</code>.
 829      * @see #TYPE_INT_RGB
 830      * @see #TYPE_INT_ARGB
 831      * @see #TYPE_INT_ARGB_PRE
 832      * @see #TYPE_INT_BGR
 833      * @see #TYPE_3BYTE_BGR
 834      * @see #TYPE_4BYTE_ABGR
 835      * @see #TYPE_4BYTE_ABGR_PRE
 836      * @see #TYPE_BYTE_GRAY
 837      * @see #TYPE_BYTE_BINARY
 838      * @see #TYPE_BYTE_INDEXED
 839      * @see #TYPE_USHORT_GRAY
 840      * @see #TYPE_USHORT_565_RGB
 841      * @see #TYPE_USHORT_555_RGB
 842      * @see #TYPE_CUSTOM
 843      */
 844     public int getType() {
 845         return imageType;
 846     }
 847 
 848     /**
 849      * Returns the <code>ColorModel</code>.
 850      * @return the <code>ColorModel</code> of this
 851      *  <code>BufferedImage</code>.
 852      */
 853     public ColorModel getColorModel() {
 854         return colorModel;
 855     }
 856 
 857     /**
 858      * Returns the {@link WritableRaster}.
 859      * @return the <code>WriteableRaster</code> of this
 860      *  <code>BufferedImage</code>.
 861      */
 862     public WritableRaster getRaster() {
 863         return raster;
 864     }
 865 
 866 
 867     /**
 868      * Returns a <code>WritableRaster</code> representing the alpha
 869      * channel for <code>BufferedImage</code> objects
 870      * with <code>ColorModel</code> objects that support a separate
 871      * spatial alpha channel, such as <code>ComponentColorModel</code> and
 872      * <code>DirectColorModel</code>.  Returns <code>null</code> if there
 873      * is no alpha channel associated with the <code>ColorModel</code> in
 874      * this image.  This method assumes that for all
 875      * <code>ColorModel</code> objects other than
 876      * <code>IndexColorModel</code>, if the <code>ColorModel</code>
 877      * supports alpha, there is a separate alpha channel
 878      * which is stored as the last band of image data.
 879      * If the image uses an <code>IndexColorModel</code> that
 880      * has alpha in the lookup table, this method returns
 881      * <code>null</code> since there is no spatially discrete alpha
 882      * channel.  This method creates a new
 883      * <code>WritableRaster</code>, but shares the data array.
 884      * @return a <code>WritableRaster</code> or <code>null</code> if this
 885      *          <code>BufferedImage</code> has no alpha channel associated
 886      *          with its <code>ColorModel</code>.
 887      */
 888     public WritableRaster getAlphaRaster() {
 889         return colorModel.getAlphaRaster(raster);
 890     }
 891 
 892     /**
 893      * Returns an integer pixel in the default RGB color model
 894      * (TYPE_INT_ARGB) and default sRGB colorspace.  Color
 895      * conversion takes place if this default model does not match
 896      * the image <code>ColorModel</code>.  There are only 8-bits of
 897      * precision for each color component in the returned data when using
 898      * this method.
 899      *
 900      * <p>
 901      *
 902      * An <code>ArrayOutOfBoundsException</code> may be thrown
 903      * if the coordinates are not in bounds.
 904      * However, explicit bounds checking is not guaranteed.
 905      *
 906      * @param x the X coordinate of the pixel from which to get
 907      *          the pixel in the default RGB color model and sRGB
 908      *          color space
 909      * @param y the Y coordinate of the pixel from which to get
 910      *          the pixel in the default RGB color model and sRGB
 911      *          color space
 912      * @return an integer pixel in the default RGB color model and
 913      *          default sRGB colorspace.
 914      * @see #setRGB(int, int, int)
 915      * @see #setRGB(int, int, int, int, int[], int, int)
 916      */
 917     public int getRGB(int x, int y) {
 918         return colorModel.getRGB(raster.getDataElements(x, y, null));
 919     }
 920 
 921     /**
 922      * Returns an array of integer pixels in the default RGB color model
 923      * (TYPE_INT_ARGB) and default sRGB color space,
 924      * from a portion of the image data.  Color conversion takes
 925      * place if the default model does not match the image
 926      * <code>ColorModel</code>.  There are only 8-bits of precision for
 927      * each color component in the returned data when
 928      * using this method.  With a specified coordinate (x,&nbsp;y) in the
 929      * image, the ARGB pixel can be accessed in this way:
 930      * <p>
 931      *
 932      * <pre>
 933      *    pixel   = rgbArray[offset + (y-startY)*scansize + (x-startX)]; </pre>
 934      *
 935      * <p>
 936      *
 937      * An <code>ArrayOutOfBoundsException</code> may be thrown
 938      * if the region is not in bounds.
 939      * However, explicit bounds checking is not guaranteed.
 940      *
 941      * @param startX      the starting X coordinate
 942      * @param startY      the starting Y coordinate
 943      * @param w           width of region
 944      * @param h           height of region
 945      * @param rgbArray    if not <code>null</code>, the rgb pixels are
 946      *          written here
 947      * @param offset      offset into the <code>rgbArray</code>
 948      * @param scansize    scanline stride for the <code>rgbArray</code>
 949      * @return            array of RGB pixels.
 950      * @see #setRGB(int, int, int)
 951      * @see #setRGB(int, int, int, int, int[], int, int)
 952      */
 953     public int[] getRGB(int startX, int startY, int w, int h,
 954                         int[] rgbArray, int offset, int scansize) {
 955         int yoff  = offset;
 956         int off;
 957         Object data;
 958         int nbands = raster.getNumBands();
 959         int dataType = raster.getDataBuffer().getDataType();
 960         switch (dataType) {
 961         case DataBuffer.TYPE_BYTE:
 962             data = new byte[nbands];
 963             break;
 964         case DataBuffer.TYPE_USHORT:
 965             data = new short[nbands];
 966             break;
 967         case DataBuffer.TYPE_INT:
 968             data = new int[nbands];
 969             break;
 970         case DataBuffer.TYPE_FLOAT:
 971             data = new float[nbands];
 972             break;
 973         case DataBuffer.TYPE_DOUBLE:
 974             data = new double[nbands];
 975             break;
 976         default:
 977             throw new IllegalArgumentException("Unknown data buffer type: "+
 978                                                dataType);
 979         }
 980 
 981         if (rgbArray == null) {
 982             rgbArray = new int[offset+h*scansize];
 983         }
 984 
 985         for (int y = startY; y < startY+h; y++, yoff+=scansize) {
 986             off = yoff;
 987             for (int x = startX; x < startX+w; x++) {
 988                 rgbArray[off++] = colorModel.getRGB(raster.getDataElements(x,
 989                                                                         y,
 990                                                                         data));
 991             }
 992         }
 993 
 994         return rgbArray;
 995     }
 996 
 997 
 998     /**
 999      * Sets a pixel in this <code>BufferedImage</code> to the specified
1000      * RGB value. The pixel is assumed to be in the default RGB color
1001      * model, TYPE_INT_ARGB, and default sRGB color space.  For images
1002      * with an <code>IndexColorModel</code>, the index with the nearest
1003      * color is chosen.
1004      *
1005      * <p>
1006      *
1007      * An <code>ArrayOutOfBoundsException</code> may be thrown
1008      * if the coordinates are not in bounds.
1009      * However, explicit bounds checking is not guaranteed.
1010      *
1011      * @param x the X coordinate of the pixel to set
1012      * @param y the Y coordinate of the pixel to set
1013      * @param rgb the RGB value
1014      * @see #getRGB(int, int)
1015      * @see #getRGB(int, int, int, int, int[], int, int)
1016      */
1017     public synchronized void setRGB(int x, int y, int rgb) {
1018         raster.setDataElements(x, y, colorModel.getDataElements(rgb, null));
1019     }
1020 
1021     /**
1022      * Sets an array of integer pixels in the default RGB color model
1023      * (TYPE_INT_ARGB) and default sRGB color space,
1024      * into a portion of the image data.  Color conversion takes place
1025      * if the default model does not match the image
1026      * <code>ColorModel</code>.  There are only 8-bits of precision for
1027      * each color component in the returned data when
1028      * using this method.  With a specified coordinate (x,&nbsp;y) in the
1029      * this image, the ARGB pixel can be accessed in this way:
1030      * <pre>
1031      *    pixel   = rgbArray[offset + (y-startY)*scansize + (x-startX)];
1032      * </pre>
1033      * WARNING: No dithering takes place.
1034      *
1035      * <p>
1036      *
1037      * An <code>ArrayOutOfBoundsException</code> may be thrown
1038      * if the region is not in bounds.
1039      * However, explicit bounds checking is not guaranteed.
1040      *
1041      * @param startX      the starting X coordinate
1042      * @param startY      the starting Y coordinate
1043      * @param w           width of the region
1044      * @param h           height of the region
1045      * @param rgbArray    the rgb pixels
1046      * @param offset      offset into the <code>rgbArray</code>
1047      * @param scansize    scanline stride for the <code>rgbArray</code>
1048      * @see #getRGB(int, int)
1049      * @see #getRGB(int, int, int, int, int[], int, int)
1050      */
1051     public void setRGB(int startX, int startY, int w, int h,
1052                         int[] rgbArray, int offset, int scansize) {
1053         int yoff  = offset;
1054         int off;
1055         Object pixel = null;
1056 
1057         for (int y = startY; y < startY+h; y++, yoff+=scansize) {
1058             off = yoff;
1059             for (int x = startX; x < startX+w; x++) {
1060                 pixel = colorModel.getDataElements(rgbArray[off++], pixel);
1061                 raster.setDataElements(x, y, pixel);
1062             }
1063         }
1064     }
1065 
1066 
1067     /**
1068      * Returns the width of the <code>BufferedImage</code>.
1069      * @return the width of this <code>BufferedImage</code>
1070      */
1071     public int getWidth() {
1072         return raster.getWidth();
1073     }
1074 
1075     /**
1076      * Returns the height of the <code>BufferedImage</code>.
1077      * @return the height of this <code>BufferedImage</code>
1078      */
1079     public int getHeight() {
1080         return raster.getHeight();
1081     }
1082 
1083     /**
1084      * Returns the width of the <code>BufferedImage</code>.
1085      * @param observer ignored
1086      * @return the width of this <code>BufferedImage</code>
1087      */
1088     public int getWidth(ImageObserver observer) {
1089         return raster.getWidth();
1090     }
1091 
1092     /**
1093      * Returns the height of the <code>BufferedImage</code>.
1094      * @param observer ignored
1095      * @return the height of this <code>BufferedImage</code>
1096      */
1097     public int getHeight(ImageObserver observer) {
1098         return raster.getHeight();
1099     }
1100 
1101     /**
1102      * Returns the object that produces the pixels for the image.
1103      * @return the {@link ImageProducer} that is used to produce the
1104      * pixels for this image.
1105      * @see ImageProducer
1106      */
1107     public ImageProducer getSource() {
1108         if (osis == null) {
1109             if (properties == null) {
1110                 properties = new Hashtable<>();
1111             }
1112             osis = new OffScreenImageSource(this, properties);
1113         }
1114         return osis;
1115     }
1116 
1117 
1118     /**
1119      * Returns a property of the image by name.  Individual property names
1120      * are defined by the various image formats.  If a property is not
1121      * defined for a particular image, this method returns the
1122      * <code>UndefinedProperty</code> field.  If the properties
1123      * for this image are not yet known, then this method returns
1124      * <code>null</code> and the <code>ImageObserver</code> object is
1125      * notified later.  The property name "comment" should be used to
1126      * store an optional comment that can be presented to the user as a
1127      * description of the image, its source, or its author.
1128      * @param name the property name
1129      * @param observer the <code>ImageObserver</code> that receives
1130      *  notification regarding image information
1131      * @return an {@link Object} that is the property referred to by the
1132      *          specified <code>name</code> or <code>null</code> if the
1133      *          properties of this image are not yet known.
1134      * @throws NullPointerException if the property name is null.
1135      * @see ImageObserver
1136      * @see java.awt.Image#UndefinedProperty
1137      */
1138     public Object getProperty(String name, ImageObserver observer) {
1139         return getProperty(name);
1140     }
1141 
1142     /**
1143      * Returns a property of the image by name.
1144      * @param name the property name
1145      * @return an <code>Object</code> that is the property referred to by
1146      *          the specified <code>name</code>.
1147      * @throws NullPointerException if the property name is null.
1148      */
1149     public Object getProperty(String name) {
1150         if (name == null) {
1151             throw new NullPointerException("null property name is not allowed");
1152         }
1153         if (properties == null) {
1154             return java.awt.Image.UndefinedProperty;
1155         }
1156         Object o = properties.get(name);
1157         if (o == null) {
1158             o = java.awt.Image.UndefinedProperty;
1159         }
1160         return o;
1161     }
1162 
1163     /**
1164      * This method returns a {@link Graphics2D}, but is here
1165      * for backwards compatibility.  {@link #createGraphics() createGraphics} is more
1166      * convenient, since it is declared to return a
1167      * <code>Graphics2D</code>.
1168      * @return a <code>Graphics2D</code>, which can be used to draw into
1169      *          this image.
1170      */
1171     public java.awt.Graphics getGraphics() {
1172         return createGraphics();
1173     }
1174 
1175     /**
1176      * Creates a <code>Graphics2D</code>, which can be used to draw into
1177      * this <code>BufferedImage</code>.
1178      * @return a <code>Graphics2D</code>, used for drawing into this
1179      *          image.
1180      */
1181     public Graphics2D createGraphics() {
1182         GraphicsEnvironment env =
1183             GraphicsEnvironment.getLocalGraphicsEnvironment();
1184         return env.createGraphics(this);
1185     }
1186 
1187     /**
1188      * Returns a subimage defined by a specified rectangular region.
1189      * The returned <code>BufferedImage</code> shares the same
1190      * data array as the original image.
1191      * @param x the X coordinate of the upper-left corner of the
1192      *          specified rectangular region
1193      * @param y the Y coordinate of the upper-left corner of the
1194      *          specified rectangular region
1195      * @param w the width of the specified rectangular region
1196      * @param h the height of the specified rectangular region
1197      * @return a <code>BufferedImage</code> that is the subimage of this
1198      *          <code>BufferedImage</code>.
1199      * @exception RasterFormatException if the specified
1200      * area is not contained within this <code>BufferedImage</code>.
1201      */
1202     public BufferedImage getSubimage (int x, int y, int w, int h) {
1203         return new BufferedImage (colorModel,
1204                                   raster.createWritableChild(x, y, w, h,
1205                                                              0, 0, null),
1206                                   colorModel.isAlphaPremultiplied(),
1207                                   properties);
1208     }
1209 
1210     /**
1211      * Returns whether or not the alpha has been premultiplied.  It
1212      * returns <code>false</code> if there is no alpha.
1213      * @return <code>true</code> if the alpha has been premultiplied;
1214      *          <code>false</code> otherwise.
1215      */
1216     public boolean isAlphaPremultiplied() {
1217         return colorModel.isAlphaPremultiplied();
1218     }
1219 
1220     /**
1221      * Forces the data to match the state specified in the
1222      * <code>isAlphaPremultiplied</code> variable.  It may multiply or
1223      * divide the color raster data by alpha, or do nothing if the data is
1224      * in the correct state.
1225      * @param isAlphaPremultiplied <code>true</code> if the alpha has been
1226      *          premultiplied; <code>false</code> otherwise.
1227      */
1228     public void coerceData (boolean isAlphaPremultiplied) {
1229         if (colorModel.hasAlpha() &&
1230             colorModel.isAlphaPremultiplied() != isAlphaPremultiplied) {
1231             // Make the color model do the conversion
1232             colorModel = colorModel.coerceData (raster, isAlphaPremultiplied);
1233         }
1234     }
1235 
1236     /**
1237      * Returns a <code>String</code> representation of this
1238      * <code>BufferedImage</code> object and its values.
1239      * @return a <code>String</code> representing this
1240      *          <code>BufferedImage</code>.
1241      */
1242     public String toString() {
1243         return "BufferedImage@"+Integer.toHexString(hashCode())
1244             +": type = "+imageType
1245             +" "+colorModel+" "+raster;
1246     }
1247 
1248     /**
1249      * Returns a {@link Vector} of {@link RenderedImage} objects that are
1250      * the immediate sources, not the sources of these immediate sources,
1251      * of image data for this <code>BufferedImage</code>.  This
1252      * method returns <code>null</code> if the <code>BufferedImage</code>
1253      * has no information about its immediate sources.  It returns an
1254      * empty <code>Vector</code> if the <code>BufferedImage</code> has no
1255      * immediate sources.
1256      * @return a <code>Vector</code> containing immediate sources of
1257      *          this <code>BufferedImage</code> object's image date, or
1258      *          <code>null</code> if this <code>BufferedImage</code> has
1259      *          no information about its immediate sources, or an empty
1260      *          <code>Vector</code> if this <code>BufferedImage</code>
1261      *          has no immediate sources.
1262      */
1263     public Vector<RenderedImage> getSources() {
1264         return null;
1265     }
1266 
1267     /**
1268      * Returns an array of names recognized by
1269      * {@link #getProperty(String) getProperty(String)}
1270      * or <code>null</code>, if no property names are recognized.
1271      * @return a <code>String</code> array containing all of the property
1272      *          names that <code>getProperty(String)</code> recognizes;
1273      *          or <code>null</code> if no property names are recognized.
1274      */
1275     public String[] getPropertyNames() {
1276          return null;
1277     }
1278 
1279     /**
1280      * Returns the minimum x coordinate of this
1281      * <code>BufferedImage</code>.  This is always zero.
1282      * @return the minimum x coordinate of this
1283      *          <code>BufferedImage</code>.
1284      */
1285     public int getMinX() {
1286         return raster.getMinX();
1287     }
1288 
1289     /**
1290      * Returns the minimum y coordinate of this
1291      * <code>BufferedImage</code>.  This is always zero.
1292      * @return the minimum y coordinate of this
1293      *          <code>BufferedImage</code>.
1294      */
1295     public int getMinY() {
1296         return raster.getMinY();
1297     }
1298 
1299     /**
1300      * Returns the <code>SampleModel</code> associated with this
1301      * <code>BufferedImage</code>.
1302      * @return the <code>SampleModel</code> of this
1303      *          <code>BufferedImage</code>.
1304      */
1305     public SampleModel getSampleModel() {
1306         return raster.getSampleModel();
1307     }
1308 
1309     /**
1310      * Returns the number of tiles in the x direction.
1311      * This is always one.
1312      * @return the number of tiles in the x direction.
1313      */
1314     public int getNumXTiles() {
1315         return 1;
1316     }
1317 
1318     /**
1319      * Returns the number of tiles in the y direction.
1320      * This is always one.
1321      * @return the number of tiles in the y direction.
1322      */
1323     public int getNumYTiles() {
1324         return 1;
1325     }
1326 
1327     /**
1328      * Returns the minimum tile index in the x direction.
1329      * This is always zero.
1330      * @return the minimum tile index in the x direction.
1331      */
1332     public int getMinTileX() {
1333         return 0;
1334     }
1335 
1336     /**
1337      * Returns the minimum tile index in the y direction.
1338      * This is always zero.
1339      * @return the mininum tile index in the y direction.
1340      */
1341     public int getMinTileY() {
1342         return 0;
1343     }
1344 
1345     /**
1346      * Returns the tile width in pixels.
1347      * @return the tile width in pixels.
1348      */
1349     public int getTileWidth() {
1350        return raster.getWidth();
1351     }
1352 
1353     /**
1354      * Returns the tile height in pixels.
1355      * @return the tile height in pixels.
1356      */
1357     public int getTileHeight() {
1358        return raster.getHeight();
1359     }
1360 
1361     /**
1362      * Returns the x offset of the tile grid relative to the origin,
1363      * For example, the x coordinate of the location of tile
1364      * (0,&nbsp;0).  This is always zero.
1365      * @return the x offset of the tile grid.
1366      */
1367     public int getTileGridXOffset() {
1368         return raster.getSampleModelTranslateX();
1369     }
1370 
1371     /**
1372      * Returns the y offset of the tile grid relative to the origin,
1373      * For example, the y coordinate of the location of tile
1374      * (0,&nbsp;0).  This is always zero.
1375      * @return the y offset of the tile grid.
1376      */
1377     public int getTileGridYOffset() {
1378         return raster.getSampleModelTranslateY();
1379     }
1380 
1381     /**
1382      * Returns tile (<code>tileX</code>,&nbsp;<code>tileY</code>).  Note
1383      * that <code>tileX</code> and <code>tileY</code> are indices
1384      * into the tile array, not pixel locations.  The <code>Raster</code>
1385      * that is returned is live, which means that it is updated if the
1386      * image is changed.
1387      * @param tileX the x index of the requested tile in the tile array
1388      * @param tileY the y index of the requested tile in the tile array
1389      * @return a <code>Raster</code> that is the tile defined by the
1390      *          arguments <code>tileX</code> and <code>tileY</code>.
1391      * @exception ArrayIndexOutOfBoundsException if both
1392      *          <code>tileX</code> and <code>tileY</code> are not
1393      *          equal to 0
1394      */
1395     public Raster getTile(int tileX, int tileY) {
1396         if (tileX == 0 && tileY == 0) {
1397             return raster;
1398         }
1399         throw new ArrayIndexOutOfBoundsException("BufferedImages only have"+
1400              " one tile with index 0,0");
1401     }
1402 
1403     /**
1404      * Returns the image as one large tile.  The <code>Raster</code>
1405      * returned is a copy of the image data is not updated if the
1406      * image is changed.
1407      * @return a <code>Raster</code> that is a copy of the image data.
1408      * @see #setData(Raster)
1409      */
1410     public Raster getData() {
1411 
1412         // REMIND : this allocates a whole new tile if raster is a
1413         // subtile.  (It only copies in the requested area)
1414         // We should do something smarter.
1415         int width = raster.getWidth();
1416         int height = raster.getHeight();
1417         int startX = raster.getMinX();
1418         int startY = raster.getMinY();
1419         WritableRaster wr =
1420            Raster.createWritableRaster(raster.getSampleModel(),
1421                          new Point(raster.getSampleModelTranslateX(),
1422                                    raster.getSampleModelTranslateY()));
1423 
1424         Object tdata = null;
1425 
1426         for (int i = startY; i < startY+height; i++)  {
1427             tdata = raster.getDataElements(startX,i,width,1,tdata);
1428             wr.setDataElements(startX,i,width,1, tdata);
1429         }
1430         return wr;
1431     }
1432 
1433     /**
1434      * Computes and returns an arbitrary region of the
1435      * <code>BufferedImage</code>.  The <code>Raster</code> returned is a
1436      * copy of the image data and is not updated if the image is
1437      * changed.
1438      * @param rect the region of the <code>BufferedImage</code> to be
1439      * returned.
1440      * @return a <code>Raster</code> that is a copy of the image data of
1441      *          the specified region of the <code>BufferedImage</code>
1442      * @see #setData(Raster)
1443      */
1444     public Raster getData(Rectangle rect) {
1445         SampleModel sm = raster.getSampleModel();
1446         SampleModel nsm = sm.createCompatibleSampleModel(rect.width,
1447                                                          rect.height);
1448         WritableRaster wr = Raster.createWritableRaster(nsm,
1449                                                   rect.getLocation());
1450         int width = rect.width;
1451         int height = rect.height;
1452         int startX = rect.x;
1453         int startY = rect.y;
1454 
1455         Object tdata = null;
1456 
1457         for (int i = startY; i < startY+height; i++)  {
1458             tdata = raster.getDataElements(startX,i,width,1,tdata);
1459             wr.setDataElements(startX,i,width,1, tdata);
1460         }
1461         return wr;
1462     }
1463 
1464     /**
1465      * Computes an arbitrary rectangular region of the
1466      * <code>BufferedImage</code> and copies it into a specified
1467      * <code>WritableRaster</code>.  The region to be computed is
1468      * determined from the bounds of the specified
1469      * <code>WritableRaster</code>.  The specified
1470      * <code>WritableRaster</code> must have a
1471      * <code>SampleModel</code> that is compatible with this image.  If
1472      * <code>outRaster</code> is <code>null</code>,
1473      * an appropriate <code>WritableRaster</code> is created.
1474      * @param outRaster a <code>WritableRaster</code> to hold the returned
1475      *          part of the image, or <code>null</code>
1476      * @return a reference to the supplied or created
1477      *          <code>WritableRaster</code>.
1478      */
1479     public WritableRaster copyData(WritableRaster outRaster) {
1480         if (outRaster == null) {
1481             return (WritableRaster) getData();
1482         }
1483         int width = outRaster.getWidth();
1484         int height = outRaster.getHeight();
1485         int startX = outRaster.getMinX();
1486         int startY = outRaster.getMinY();
1487 
1488         Object tdata = null;
1489 
1490         for (int i = startY; i < startY+height; i++)  {
1491             tdata = raster.getDataElements(startX,i,width,1,tdata);
1492             outRaster.setDataElements(startX,i,width,1, tdata);
1493         }
1494 
1495         return outRaster;
1496     }
1497 
1498   /**
1499      * Sets a rectangular region of the image to the contents of the
1500      * specified <code>Raster</code> <code>r</code>, which is
1501      * assumed to be in the same coordinate space as the
1502      * <code>BufferedImage</code>. The operation is clipped to the bounds
1503      * of the <code>BufferedImage</code>.
1504      * @param r the specified <code>Raster</code>
1505      * @see #getData
1506      * @see #getData(Rectangle)
1507     */
1508     public void setData(Raster r) {
1509         int width = r.getWidth();
1510         int height = r.getHeight();
1511         int startX = r.getMinX();
1512         int startY = r.getMinY();
1513 
1514         int[] tdata = null;
1515 
1516         // Clip to the current Raster
1517         Rectangle rclip = new Rectangle(startX, startY, width, height);
1518         Rectangle bclip = new Rectangle(0, 0, raster.width, raster.height);
1519         Rectangle intersect = rclip.intersection(bclip);
1520         if (intersect.isEmpty()) {
1521             return;
1522         }
1523         width = intersect.width;
1524         height = intersect.height;
1525         startX = intersect.x;
1526         startY = intersect.y;
1527 
1528         // remind use get/setDataElements for speed if Rasters are
1529         // compatible
1530         for (int i = startY; i < startY+height; i++)  {
1531             tdata = r.getPixels(startX,i,width,1,tdata);
1532             raster.setPixels(startX,i,width,1, tdata);
1533         }
1534     }
1535 
1536 
1537   /**
1538    * Adds a tile observer.  If the observer is already present,
1539    * it receives multiple notifications.
1540    * @param to the specified {@link TileObserver}
1541    */
1542     public void addTileObserver (TileObserver to) {
1543     }
1544 
1545   /**
1546    * Removes a tile observer.  If the observer was not registered,
1547    * nothing happens.  If the observer was registered for multiple
1548    * notifications, it is now registered for one fewer notification.
1549    * @param to the specified <code>TileObserver</code>.
1550    */
1551     public void removeTileObserver (TileObserver to) {
1552     }
1553 
1554     /**
1555      * Returns whether or not a tile is currently checked out for writing.
1556      * @param tileX the x index of the tile.
1557      * @param tileY the y index of the tile.
1558      * @return <code>true</code> if the tile specified by the specified
1559      *          indices is checked out for writing; <code>false</code>
1560      *          otherwise.
1561      * @exception ArrayIndexOutOfBoundsException if both
1562      *          <code>tileX</code> and <code>tileY</code> are not equal
1563      *          to 0
1564      */
1565     public boolean isTileWritable (int tileX, int tileY) {
1566         if (tileX == 0 && tileY == 0) {
1567             return true;
1568         }
1569         throw new IllegalArgumentException("Only 1 tile in image");
1570     }
1571 
1572     /**
1573      * Returns an array of {@link Point} objects indicating which tiles
1574      * are checked out for writing.  Returns <code>null</code> if none are
1575      * checked out.
1576      * @return a <code>Point</code> array that indicates the tiles that
1577      *          are checked out for writing, or <code>null</code> if no
1578      *          tiles are checked out for writing.
1579      */
1580     public Point[] getWritableTileIndices() {
1581         Point[] p = new Point[1];
1582         p[0] = new Point(0, 0);
1583 
1584         return p;
1585     }
1586 
1587     /**
1588      * Returns whether or not any tile is checked out for writing.
1589      * Semantically equivalent to
1590      * <pre>
1591      * (getWritableTileIndices() != null).
1592      * </pre>
1593      * @return <code>true</code> if any tile is checked out for writing;
1594      *          <code>false</code> otherwise.
1595      */
1596     public boolean hasTileWriters () {
1597         return true;
1598     }
1599 
1600   /**
1601    * Checks out a tile for writing.  All registered
1602    * <code>TileObservers</code> are notified when a tile goes from having
1603    * no writers to having one writer.
1604    * @param tileX the x index of the tile
1605    * @param tileY the y index of the tile
1606    * @return a <code>WritableRaster</code> that is the tile, indicated by
1607    *            the specified indices, to be checked out for writing.
1608    */
1609     public WritableRaster getWritableTile (int tileX, int tileY) {
1610         return raster;
1611     }
1612 
1613   /**
1614    * Relinquishes permission to write to a tile.  If the caller
1615    * continues to write to the tile, the results are undefined.
1616    * Calls to this method should only appear in matching pairs
1617    * with calls to {@link #getWritableTile(int, int) getWritableTile(int, int)}.  Any other leads
1618    * to undefined results.  All registered <code>TileObservers</code>
1619    * are notified when a tile goes from having one writer to having no
1620    * writers.
1621    * @param tileX the x index of the tile
1622    * @param tileY the y index of the tile
1623    */
1624     public void releaseWritableTile (int tileX, int tileY) {
1625     }
1626 
1627     /**
1628      * Returns the transparency.  Returns either OPAQUE, BITMASK,
1629      * or TRANSLUCENT.
1630      * @return the transparency of this <code>BufferedImage</code>.
1631      * @see Transparency#OPAQUE
1632      * @see Transparency#BITMASK
1633      * @see Transparency#TRANSLUCENT
1634      * @since 1.5
1635      */
1636     public int getTransparency() {
1637         return colorModel.getTransparency();
1638     }
1639 }