1 /*
   2  * Copyright (c) 1997, 2013, 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 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 = 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      *
 931      * <pre>
 932      *    pixel   = rgbArray[offset + (y-startY)*scansize + (x-startX)]; </pre>
 933      *
 934      * <p>
 935      *
 936      * An <code>ArrayOutOfBoundsException</code> may be thrown
 937      * if the region is not in bounds.
 938      * However, explicit bounds checking is not guaranteed.
 939      *
 940      * @param startX      the starting X coordinate
 941      * @param startY      the starting Y coordinate
 942      * @param w           width of region
 943      * @param h           height of region
 944      * @param rgbArray    if not <code>null</code>, the rgb pixels are
 945      *          written here
 946      * @param offset      offset into the <code>rgbArray</code>
 947      * @param scansize    scanline stride for the <code>rgbArray</code>
 948      * @return            array of RGB pixels.
 949      * @see #setRGB(int, int, int)
 950      * @see #setRGB(int, int, int, int, int[], int, int)
 951      */
 952     public int[] getRGB(int startX, int startY, int w, int h,
 953                         int[] rgbArray, int offset, int scansize) {
 954         int yoff  = offset;
 955         int off;
 956         Object data;
 957         int nbands = raster.getNumBands();
 958         int dataType = raster.getDataBuffer().getDataType();
 959         switch (dataType) {
 960         case DataBuffer.TYPE_BYTE:
 961             data = new byte[nbands];
 962             break;
 963         case DataBuffer.TYPE_USHORT:
 964             data = new short[nbands];
 965             break;
 966         case DataBuffer.TYPE_INT:
 967             data = new int[nbands];
 968             break;
 969         case DataBuffer.TYPE_FLOAT:
 970             data = new float[nbands];
 971             break;
 972         case DataBuffer.TYPE_DOUBLE:
 973             data = new double[nbands];
 974             break;
 975         default:
 976             throw new IllegalArgumentException("Unknown data buffer type: "+
 977                                                dataType);
 978         }
 979 
 980         if (rgbArray == null) {
 981             rgbArray = new int[offset+h*scansize];
 982         }
 983 
 984         for (int y = startY; y < startY+h; y++, yoff+=scansize) {
 985             off = yoff;
 986             for (int x = startX; x < startX+w; x++) {
 987                 rgbArray[off++] = colorModel.getRGB(raster.getDataElements(x,
 988                                                                         y,
 989                                                                         data));
 990             }
 991         }
 992 
 993         return rgbArray;
 994     }
 995 
 996 
 997     /**
 998      * Sets a pixel in this <code>BufferedImage</code> to the specified
 999      * RGB value. The pixel is assumed to be in the default RGB color
1000      * model, TYPE_INT_ARGB, and default sRGB color space.  For images
1001      * with an <code>IndexColorModel</code>, the index with the nearest
1002      * color is chosen.
1003      *
1004      * <p>
1005      *
1006      * An <code>ArrayOutOfBoundsException</code> may be thrown
1007      * if the coordinates are not in bounds.
1008      * However, explicit bounds checking is not guaranteed.
1009      *
1010      * @param x the X coordinate of the pixel to set
1011      * @param y the Y coordinate of the pixel to set
1012      * @param rgb the RGB value
1013      * @see #getRGB(int, int)
1014      * @see #getRGB(int, int, int, int, int[], int, int)
1015      */
1016     public synchronized void setRGB(int x, int y, int rgb) {
1017         raster.setDataElements(x, y, colorModel.getDataElements(rgb, null));
1018     }
1019 
1020     /**
1021      * Sets an array of integer pixels in the default RGB color model
1022      * (TYPE_INT_ARGB) and default sRGB color space,
1023      * into a portion of the image data.  Color conversion takes place
1024      * if the default model does not match the image
1025      * <code>ColorModel</code>.  There are only 8-bits of precision for
1026      * each color component in the returned data when
1027      * using this method.  With a specified coordinate (x,&nbsp;y) in the
1028      * this image, the ARGB pixel can be accessed in this way:
1029      * <pre>
1030      *    pixel   = rgbArray[offset + (y-startY)*scansize + (x-startX)];
1031      * </pre>
1032      * WARNING: No dithering takes place.
1033      *
1034      * <p>
1035      *
1036      * An <code>ArrayOutOfBoundsException</code> may be thrown
1037      * if the region is not in bounds.
1038      * However, explicit bounds checking is not guaranteed.
1039      *
1040      * @param startX      the starting X coordinate
1041      * @param startY      the starting Y coordinate
1042      * @param w           width of the region
1043      * @param h           height of the region
1044      * @param rgbArray    the rgb pixels
1045      * @param offset      offset into the <code>rgbArray</code>
1046      * @param scansize    scanline stride for the <code>rgbArray</code>
1047      * @see #getRGB(int, int)
1048      * @see #getRGB(int, int, int, int, int[], int, int)
1049      */
1050     public void setRGB(int startX, int startY, int w, int h,
1051                         int[] rgbArray, int offset, int scansize) {
1052         int yoff  = offset;
1053         int off;
1054         Object pixel = null;
1055 
1056         for (int y = startY; y < startY+h; y++, yoff+=scansize) {
1057             off = yoff;
1058             for (int x = startX; x < startX+w; x++) {
1059                 pixel = colorModel.getDataElements(rgbArray[off++], pixel);
1060                 raster.setDataElements(x, y, pixel);
1061             }
1062         }
1063     }
1064 
1065 
1066     /**
1067      * Returns the width of the <code>BufferedImage</code>.
1068      * @return the width of this <code>BufferedImage</code>
1069      */
1070     public int getWidth() {
1071         return raster.getWidth();
1072     }
1073 
1074     /**
1075      * Returns the height of the <code>BufferedImage</code>.
1076      * @return the height of this <code>BufferedImage</code>
1077      */
1078     public int getHeight() {
1079         return raster.getHeight();
1080     }
1081 
1082     /**
1083      * Returns the width of the <code>BufferedImage</code>.
1084      * @param observer ignored
1085      * @return the width of this <code>BufferedImage</code>
1086      */
1087     public int getWidth(ImageObserver observer) {
1088         return raster.getWidth();
1089     }
1090 
1091     /**
1092      * Returns the height of the <code>BufferedImage</code>.
1093      * @param observer ignored
1094      * @return the height of this <code>BufferedImage</code>
1095      */
1096     public int getHeight(ImageObserver observer) {
1097         return raster.getHeight();
1098     }
1099 
1100     /**
1101      * Returns the object that produces the pixels for the image.
1102      * @return the {@link ImageProducer} that is used to produce the
1103      * pixels for this image.
1104      * @see ImageProducer
1105      */
1106     public ImageProducer getSource() {
1107         if (osis == null) {
1108             if (properties == null) {
1109                 properties = new Hashtable();
1110             }
1111             osis = new OffScreenImageSource(this, properties);
1112         }
1113         return osis;
1114     }
1115 
1116 
1117     /**
1118      * Returns a property of the image by name.  Individual property names
1119      * are defined by the various image formats.  If a property is not
1120      * defined for a particular image, this method returns the
1121      * <code>UndefinedProperty</code> field.  If the properties
1122      * for this image are not yet known, then this method returns
1123      * <code>null</code> and the <code>ImageObserver</code> object is
1124      * notified later.  The property name "comment" should be used to
1125      * store an optional comment that can be presented to the user as a
1126      * description of the image, its source, or its author.
1127      * @param name the property name
1128      * @param observer the <code>ImageObserver</code> that receives
1129      *  notification regarding image information
1130      * @return an {@link Object} that is the property referred to by the
1131      *          specified <code>name</code> or <code>null</code> if the
1132      *          properties of this image are not yet known.
1133      * @throws NullPointerException if the property name is null.
1134      * @see ImageObserver
1135      * @see java.awt.Image#UndefinedProperty
1136      */
1137     public Object getProperty(String name, ImageObserver observer) {
1138         return getProperty(name);
1139     }
1140 
1141     /**
1142      * Returns a property of the image by name.
1143      * @param name the property name
1144      * @return an <code>Object</code> that is the property referred to by
1145      *          the specified <code>name</code>.
1146      * @throws NullPointerException if the property name is null.
1147      */
1148     public Object getProperty(String name) {
1149         if (name == null) {
1150             throw new NullPointerException("null property name is not allowed");
1151         }
1152         if (properties == null) {
1153             return java.awt.Image.UndefinedProperty;
1154         }
1155         Object o = properties.get(name);
1156         if (o == null) {
1157             o = java.awt.Image.UndefinedProperty;
1158         }
1159         return o;
1160     }
1161 
1162     /**
1163      * This method returns a {@link Graphics2D}, but is here
1164      * for backwards compatibility.  {@link #createGraphics() createGraphics} is more
1165      * convenient, since it is declared to return a
1166      * <code>Graphics2D</code>.
1167      * @return a <code>Graphics2D</code>, which can be used to draw into
1168      *          this image.
1169      */
1170     public java.awt.Graphics getGraphics() {
1171         return createGraphics();
1172     }
1173 
1174     /**
1175      * Creates a <code>Graphics2D</code>, which can be used to draw into
1176      * this <code>BufferedImage</code>.
1177      * @return a <code>Graphics2D</code>, used for drawing into this
1178      *          image.
1179      */
1180     public Graphics2D createGraphics() {
1181         GraphicsEnvironment env =
1182             GraphicsEnvironment.getLocalGraphicsEnvironment();
1183         return env.createGraphics(this);
1184     }
1185 
1186     /**
1187      * Returns a subimage defined by a specified rectangular region.
1188      * The returned <code>BufferedImage</code> shares the same
1189      * data array as the original image.
1190      * @param x the X coordinate of the upper-left corner of the
1191      *          specified rectangular region
1192      * @param y the Y coordinate of the upper-left corner of the
1193      *          specified rectangular region
1194      * @param w the width of the specified rectangular region
1195      * @param h the height of the specified rectangular region
1196      * @return a <code>BufferedImage</code> that is the subimage of this
1197      *          <code>BufferedImage</code>.
1198      * @exception RasterFormatException if the specified
1199      * area is not contained within this <code>BufferedImage</code>.
1200      */
1201     public BufferedImage getSubimage (int x, int y, int w, int h) {
1202         return new BufferedImage (colorModel,
1203                                   raster.createWritableChild(x, y, w, h,
1204                                                              0, 0, null),
1205                                   colorModel.isAlphaPremultiplied(),
1206                                   properties);
1207     }
1208 
1209     /**
1210      * Returns whether or not the alpha has been premultiplied.  It
1211      * returns <code>false</code> if there is no alpha.
1212      * @return <code>true</code> if the alpha has been premultiplied;
1213      *          <code>false</code> otherwise.
1214      */
1215     public boolean isAlphaPremultiplied() {
1216         return colorModel.isAlphaPremultiplied();
1217     }
1218 
1219     /**
1220      * Forces the data to match the state specified in the
1221      * <code>isAlphaPremultiplied</code> variable.  It may multiply or
1222      * divide the color raster data by alpha, or do nothing if the data is
1223      * in the correct state.
1224      * @param isAlphaPremultiplied <code>true</code> if the alpha has been
1225      *          premultiplied; <code>false</code> otherwise.
1226      */
1227     public void coerceData (boolean isAlphaPremultiplied) {
1228         if (colorModel.hasAlpha() &&
1229             colorModel.isAlphaPremultiplied() != isAlphaPremultiplied) {
1230             // Make the color model do the conversion
1231             colorModel = colorModel.coerceData (raster, isAlphaPremultiplied);
1232         }
1233     }
1234 
1235     /**
1236      * Returns a <code>String</code> representation of this
1237      * <code>BufferedImage</code> object and its values.
1238      * @return a <code>String</code> representing this
1239      *          <code>BufferedImage</code>.
1240      */
1241     public String toString() {
1242         return "BufferedImage@"+Integer.toHexString(hashCode())
1243             +": type = "+imageType
1244             +" "+colorModel+" "+raster;
1245     }
1246 
1247     /**
1248      * Returns a {@link Vector} of {@link RenderedImage} objects that are
1249      * the immediate sources, not the sources of these immediate sources,
1250      * of image data for this <code>BufferedImage</code>.  This
1251      * method returns <code>null</code> if the <code>BufferedImage</code>
1252      * has no information about its immediate sources.  It returns an
1253      * empty <code>Vector</code> if the <code>BufferedImage</code> has no
1254      * immediate sources.
1255      * @return a <code>Vector</code> containing immediate sources of
1256      *          this <code>BufferedImage</code> object's image date, or
1257      *          <code>null</code> if this <code>BufferedImage</code> has
1258      *          no information about its immediate sources, or an empty
1259      *          <code>Vector</code> if this <code>BufferedImage</code>
1260      *          has no immediate sources.
1261      */
1262     public Vector<RenderedImage> getSources() {
1263         return null;
1264     }
1265 
1266     /**
1267      * Returns an array of names recognized by
1268      * {@link #getProperty(String) getProperty(String)}
1269      * or <code>null</code>, if no property names are recognized.
1270      * @return a <code>String</code> array containing all of the property
1271      *          names that <code>getProperty(String)</code> recognizes;
1272      *          or <code>null</code> if no property names are recognized.
1273      */
1274     public String[] getPropertyNames() {
1275          return null;
1276     }
1277 
1278     /**
1279      * Returns the minimum x coordinate of this
1280      * <code>BufferedImage</code>.  This is always zero.
1281      * @return the minimum x coordinate of this
1282      *          <code>BufferedImage</code>.
1283      */
1284     public int getMinX() {
1285         return raster.getMinX();
1286     }
1287 
1288     /**
1289      * Returns the minimum y coordinate of this
1290      * <code>BufferedImage</code>.  This is always zero.
1291      * @return the minimum y coordinate of this
1292      *          <code>BufferedImage</code>.
1293      */
1294     public int getMinY() {
1295         return raster.getMinY();
1296     }
1297 
1298     /**
1299      * Returns the <code>SampleModel</code> associated with this
1300      * <code>BufferedImage</code>.
1301      * @return the <code>SampleModel</code> of this
1302      *          <code>BufferedImage</code>.
1303      */
1304     public SampleModel getSampleModel() {
1305         return raster.getSampleModel();
1306     }
1307 
1308     /**
1309      * Returns the number of tiles in the x direction.
1310      * This is always one.
1311      * @return the number of tiles in the x direction.
1312      */
1313     public int getNumXTiles() {
1314         return 1;
1315     }
1316 
1317     /**
1318      * Returns the number of tiles in the y direction.
1319      * This is always one.
1320      * @return the number of tiles in the y direction.
1321      */
1322     public int getNumYTiles() {
1323         return 1;
1324     }
1325 
1326     /**
1327      * Returns the minimum tile index in the x direction.
1328      * This is always zero.
1329      * @return the minimum tile index in the x direction.
1330      */
1331     public int getMinTileX() {
1332         return 0;
1333     }
1334 
1335     /**
1336      * Returns the minimum tile index in the y direction.
1337      * This is always zero.
1338      * @return the minimum tile index in the y direction.
1339      */
1340     public int getMinTileY() {
1341         return 0;
1342     }
1343 
1344     /**
1345      * Returns the tile width in pixels.
1346      * @return the tile width in pixels.
1347      */
1348     public int getTileWidth() {
1349        return raster.getWidth();
1350     }
1351 
1352     /**
1353      * Returns the tile height in pixels.
1354      * @return the tile height in pixels.
1355      */
1356     public int getTileHeight() {
1357        return raster.getHeight();
1358     }
1359 
1360     /**
1361      * Returns the x offset of the tile grid relative to the origin,
1362      * For example, the x coordinate of the location of tile
1363      * (0,&nbsp;0).  This is always zero.
1364      * @return the x offset of the tile grid.
1365      */
1366     public int getTileGridXOffset() {
1367         return raster.getSampleModelTranslateX();
1368     }
1369 
1370     /**
1371      * Returns the y offset of the tile grid relative to the origin,
1372      * For example, the y coordinate of the location of tile
1373      * (0,&nbsp;0).  This is always zero.
1374      * @return the y offset of the tile grid.
1375      */
1376     public int getTileGridYOffset() {
1377         return raster.getSampleModelTranslateY();
1378     }
1379 
1380     /**
1381      * Returns tile (<code>tileX</code>,&nbsp;<code>tileY</code>).  Note
1382      * that <code>tileX</code> and <code>tileY</code> are indices
1383      * into the tile array, not pixel locations.  The <code>Raster</code>
1384      * that is returned is live, which means that it is updated if the
1385      * image is changed.
1386      * @param tileX the x index of the requested tile in the tile array
1387      * @param tileY the y index of the requested tile in the tile array
1388      * @return a <code>Raster</code> that is the tile defined by the
1389      *          arguments <code>tileX</code> and <code>tileY</code>.
1390      * @exception ArrayIndexOutOfBoundsException if both
1391      *          <code>tileX</code> and <code>tileY</code> are not
1392      *          equal to 0
1393      */
1394     public Raster getTile(int tileX, int tileY) {
1395         if (tileX == 0 && tileY == 0) {
1396             return raster;
1397         }
1398         throw new ArrayIndexOutOfBoundsException("BufferedImages only have"+
1399              " one tile with index 0,0");
1400     }
1401 
1402     /**
1403      * Returns the image as one large tile.  The <code>Raster</code>
1404      * returned is a copy of the image data is not updated if the
1405      * image is changed.
1406      * @return a <code>Raster</code> that is a copy of the image data.
1407      * @see #setData(Raster)
1408      */
1409     public Raster getData() {
1410 
1411         // REMIND : this allocates a whole new tile if raster is a
1412         // subtile.  (It only copies in the requested area)
1413         // We should do something smarter.
1414         int width = raster.getWidth();
1415         int height = raster.getHeight();
1416         int startX = raster.getMinX();
1417         int startY = raster.getMinY();
1418         WritableRaster wr =
1419            Raster.createWritableRaster(raster.getSampleModel(),
1420                          new Point(raster.getSampleModelTranslateX(),
1421                                    raster.getSampleModelTranslateY()));
1422 
1423         Object tdata = null;
1424 
1425         for (int i = startY; i < startY+height; i++)  {
1426             tdata = raster.getDataElements(startX,i,width,1,tdata);
1427             wr.setDataElements(startX,i,width,1, tdata);
1428         }
1429         return wr;
1430     }
1431 
1432     /**
1433      * Computes and returns an arbitrary region of the
1434      * <code>BufferedImage</code>.  The <code>Raster</code> returned is a
1435      * copy of the image data and is not updated if the image is
1436      * changed.
1437      * @param rect the region of the <code>BufferedImage</code> to be
1438      * returned.
1439      * @return a <code>Raster</code> that is a copy of the image data of
1440      *          the specified region of the <code>BufferedImage</code>
1441      * @see #setData(Raster)
1442      */
1443     public Raster getData(Rectangle rect) {
1444         SampleModel sm = raster.getSampleModel();
1445         SampleModel nsm = sm.createCompatibleSampleModel(rect.width,
1446                                                          rect.height);
1447         WritableRaster wr = Raster.createWritableRaster(nsm,
1448                                                   rect.getLocation());
1449         int width = rect.width;
1450         int height = rect.height;
1451         int startX = rect.x;
1452         int startY = rect.y;
1453 
1454         Object tdata = null;
1455 
1456         for (int i = startY; i < startY+height; i++)  {
1457             tdata = raster.getDataElements(startX,i,width,1,tdata);
1458             wr.setDataElements(startX,i,width,1, tdata);
1459         }
1460         return wr;
1461     }
1462 
1463     /**
1464      * Computes an arbitrary rectangular region of the
1465      * <code>BufferedImage</code> and copies it into a specified
1466      * <code>WritableRaster</code>.  The region to be computed is
1467      * determined from the bounds of the specified
1468      * <code>WritableRaster</code>.  The specified
1469      * <code>WritableRaster</code> must have a
1470      * <code>SampleModel</code> that is compatible with this image.  If
1471      * <code>outRaster</code> is <code>null</code>,
1472      * an appropriate <code>WritableRaster</code> is created.
1473      * @param outRaster a <code>WritableRaster</code> to hold the returned
1474      *          part of the image, or <code>null</code>
1475      * @return a reference to the supplied or created
1476      *          <code>WritableRaster</code>.
1477      */
1478     public WritableRaster copyData(WritableRaster outRaster) {
1479         if (outRaster == null) {
1480             return (WritableRaster) getData();
1481         }
1482         int width = outRaster.getWidth();
1483         int height = outRaster.getHeight();
1484         int startX = outRaster.getMinX();
1485         int startY = outRaster.getMinY();
1486 
1487         Object tdata = null;
1488 
1489         for (int i = startY; i < startY+height; i++)  {
1490             tdata = raster.getDataElements(startX,i,width,1,tdata);
1491             outRaster.setDataElements(startX,i,width,1, tdata);
1492         }
1493 
1494         return outRaster;
1495     }
1496 
1497   /**
1498      * Sets a rectangular region of the image to the contents of the
1499      * specified <code>Raster</code> <code>r</code>, which is
1500      * assumed to be in the same coordinate space as the
1501      * <code>BufferedImage</code>. The operation is clipped to the bounds
1502      * of the <code>BufferedImage</code>.
1503      * @param r the specified <code>Raster</code>
1504      * @see #getData
1505      * @see #getData(Rectangle)
1506     */
1507     public void setData(Raster r) {
1508         int width = r.getWidth();
1509         int height = r.getHeight();
1510         int startX = r.getMinX();
1511         int startY = r.getMinY();
1512 
1513         int[] tdata = null;
1514 
1515         // Clip to the current Raster
1516         Rectangle rclip = new Rectangle(startX, startY, width, height);
1517         Rectangle bclip = new Rectangle(0, 0, raster.width, raster.height);
1518         Rectangle intersect = rclip.intersection(bclip);
1519         if (intersect.isEmpty()) {
1520             return;
1521         }
1522         width = intersect.width;
1523         height = intersect.height;
1524         startX = intersect.x;
1525         startY = intersect.y;
1526 
1527         // remind use get/setDataElements for speed if Rasters are
1528         // compatible
1529         for (int i = startY; i < startY+height; i++)  {
1530             tdata = r.getPixels(startX,i,width,1,tdata);
1531             raster.setPixels(startX,i,width,1, tdata);
1532         }
1533     }
1534 
1535 
1536   /**
1537    * Adds a tile observer.  If the observer is already present,
1538    * it receives multiple notifications.
1539    * @param to the specified {@link TileObserver}
1540    */
1541     public void addTileObserver (TileObserver to) {
1542     }
1543 
1544   /**
1545    * Removes a tile observer.  If the observer was not registered,
1546    * nothing happens.  If the observer was registered for multiple
1547    * notifications, it is now registered for one fewer notification.
1548    * @param to the specified <code>TileObserver</code>.
1549    */
1550     public void removeTileObserver (TileObserver to) {
1551     }
1552 
1553     /**
1554      * Returns whether or not a tile is currently checked out for writing.
1555      * @param tileX the x index of the tile.
1556      * @param tileY the y index of the tile.
1557      * @return <code>true</code> if the tile specified by the specified
1558      *          indices is checked out for writing; <code>false</code>
1559      *          otherwise.
1560      * @exception ArrayIndexOutOfBoundsException if both
1561      *          <code>tileX</code> and <code>tileY</code> are not equal
1562      *          to 0
1563      */
1564     public boolean isTileWritable (int tileX, int tileY) {
1565         if (tileX == 0 && tileY == 0) {
1566             return true;
1567         }
1568         throw new IllegalArgumentException("Only 1 tile in image");
1569     }
1570 
1571     /**
1572      * Returns an array of {@link Point} objects indicating which tiles
1573      * are checked out for writing.  Returns <code>null</code> if none are
1574      * checked out.
1575      * @return a <code>Point</code> array that indicates the tiles that
1576      *          are checked out for writing, or <code>null</code> if no
1577      *          tiles are checked out for writing.
1578      */
1579     public Point[] getWritableTileIndices() {
1580         Point[] p = new Point[1];
1581         p[0] = new Point(0, 0);
1582 
1583         return p;
1584     }
1585 
1586     /**
1587      * Returns whether or not any tile is checked out for writing.
1588      * Semantically equivalent to
1589      * <pre>
1590      * (getWritableTileIndices() != null).
1591      * </pre>
1592      * @return <code>true</code> if any tile is checked out for writing;
1593      *          <code>false</code> otherwise.
1594      */
1595     public boolean hasTileWriters () {
1596         return true;
1597     }
1598 
1599   /**
1600    * Checks out a tile for writing.  All registered
1601    * <code>TileObservers</code> are notified when a tile goes from having
1602    * no writers to having one writer.
1603    * @param tileX the x index of the tile
1604    * @param tileY the y index of the tile
1605    * @return a <code>WritableRaster</code> that is the tile, indicated by
1606    *            the specified indices, to be checked out for writing.
1607    */
1608     public WritableRaster getWritableTile (int tileX, int tileY) {
1609         return raster;
1610     }
1611 
1612   /**
1613    * Relinquishes permission to write to a tile.  If the caller
1614    * continues to write to the tile, the results are undefined.
1615    * Calls to this method should only appear in matching pairs
1616    * with calls to {@link #getWritableTile(int, int) getWritableTile(int, int)}.  Any other leads
1617    * to undefined results.  All registered <code>TileObservers</code>
1618    * are notified when a tile goes from having one writer to having no
1619    * writers.
1620    * @param tileX the x index of the tile
1621    * @param tileY the y index of the tile
1622    */
1623     public void releaseWritableTile (int tileX, int tileY) {
1624     }
1625 
1626     /**
1627      * Returns the transparency.  Returns either OPAQUE, BITMASK,
1628      * or TRANSLUCENT.
1629      * @return the transparency of this <code>BufferedImage</code>.
1630      * @see Transparency#OPAQUE
1631      * @see Transparency#BITMASK
1632      * @see Transparency#TRANSLUCENT
1633      * @since 1.5
1634      */
1635     public int getTransparency() {
1636         return colorModel.getTransparency();
1637     }
1638 }