28 import java.awt.Graphics2D; 29 import java.awt.GraphicsEnvironment; 30 import java.awt.Point; 31 import java.awt.Rectangle; 32 import java.awt.Transparency; 33 import java.awt.color.ColorSpace; 34 import java.security.AccessController; 35 import java.security.PrivilegedAction; 36 import java.util.Hashtable; 37 import java.util.Set; 38 import java.util.Vector; 39 40 import sun.awt.image.ByteComponentRaster; 41 import sun.awt.image.BytePackedRaster; 42 import sun.awt.image.IntegerComponentRaster; 43 import sun.awt.image.OffScreenImageSource; 44 import sun.awt.image.ShortComponentRaster; 45 46 /** 47 * 48 * The <code>BufferedImage</code> subclass describes an {@link 49 * java.awt.Image Image} with an accessible buffer of image data. 50 * A <code>BufferedImage</code> is comprised of a {@link ColorModel} and a 51 * {@link Raster} of image data. 52 * The number and types of bands in the {@link SampleModel} of the 53 * <code>Raster</code> must match the number and types required by the 54 * <code>ColorModel</code> to represent its color and alpha components. 55 * All <code>BufferedImage</code> objects have an upper left corner 56 * coordinate of (0, 0). Any <code>Raster</code> used to construct a 57 * <code>BufferedImage</code> must therefore have minX=0 and minY=0. 58 * 59 * <p> 60 * This class relies on the data fetching and setting methods 61 * of <code>Raster</code>, 62 * and on the color characterization methods of <code>ColorModel</code>. 63 * 64 * @see ColorModel 65 * @see Raster 66 * @see WritableRaster 67 */ 68 public class BufferedImage extends java.awt.Image 69 implements WritableRenderedImage, Transparency 70 { 71 private int imageType = TYPE_CUSTOM; 72 private ColorModel colorModel; 73 private final WritableRaster raster; 74 private OffScreenImageSource osis; 75 private Hashtable<String, Object> properties; 76 77 /** 78 * Image Type Constants 79 */ 80 81 /** 82 * Image type is not recognized so it must be a customized 83 * image. This type is only used as a return value for the getType() 84 * method. 85 */ 86 public static final int TYPE_CUSTOM = 0; 87 88 /** 89 * Represents an image with 8-bit RGB color components packed into 90 * integer pixels. The image has a {@link DirectColorModel} without 91 * alpha. 92 * When data with non-opaque alpha is stored 93 * in an image of this type, 94 * the color data must be adjusted to a non-premultiplied form 95 * and the alpha discarded, 96 * as described in the 97 * {@link java.awt.AlphaComposite} documentation. 98 */ 99 public static final int TYPE_INT_RGB = 1; 100 101 /** 102 * Represents an image with 8-bit RGBA color components packed into 103 * integer pixels. The image has a <code>DirectColorModel</code> 104 * with alpha. The color data in this image is considered not to be 105 * premultiplied with alpha. When this type is used as the 106 * <code>imageType</code> argument to a <code>BufferedImage</code> 107 * constructor, the created image is consistent with images 108 * created in the JDK1.1 and earlier releases. 109 */ 110 public static final int TYPE_INT_ARGB = 2; 111 112 /** 113 * Represents an image with 8-bit RGBA color components packed into 114 * integer pixels. The image has a <code>DirectColorModel</code> 115 * with alpha. The color data in this image is considered to be 116 * premultiplied with alpha. 117 */ 118 public static final int TYPE_INT_ARGB_PRE = 3; 119 120 /** 121 * Represents an image with 8-bit RGB color components, corresponding 122 * to a Windows- or Solaris- style BGR color model, with the colors 123 * Blue, Green, and Red packed into integer pixels. There is no alpha. 124 * The image has a {@link DirectColorModel}. 125 * When data with non-opaque alpha is stored 126 * in an image of this type, 127 * the color data must be adjusted to a non-premultiplied form 128 * and the alpha discarded, 129 * as described in the 130 * {@link java.awt.AlphaComposite} documentation. 131 */ 132 public static final int TYPE_INT_BGR = 4; 133 134 /** 135 * Represents an image with 8-bit RGB color components, corresponding 136 * to a Windows-style BGR color model) with the colors Blue, Green, 137 * and Red stored in 3 bytes. There is no alpha. The image has a 138 * <code>ComponentColorModel</code>. 139 * When data with non-opaque alpha is stored 140 * in an image of this type, 141 * the color data must be adjusted to a non-premultiplied form 142 * and the alpha discarded, 143 * as described in the 144 * {@link java.awt.AlphaComposite} documentation. 145 */ 146 public static final int TYPE_3BYTE_BGR = 5; 147 148 /** 149 * Represents an image with 8-bit RGBA color components with the colors 150 * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha. The 151 * image has a <code>ComponentColorModel</code> with alpha. The 152 * color data in this image is considered not to be premultiplied with 153 * alpha. The byte data is interleaved in a single 154 * byte array in the order A, B, G, R 155 * from lower to higher byte addresses within each pixel. 156 */ 157 public static final int TYPE_4BYTE_ABGR = 6; 158 159 /** 160 * Represents an image with 8-bit RGBA color components with the colors 161 * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha. The 162 * image has a <code>ComponentColorModel</code> with alpha. The color 163 * data in this image is considered to be premultiplied with alpha. 164 * The byte data is interleaved in a single byte array in the order 165 * A, B, G, R from lower to higher byte addresses within each pixel. 166 */ 167 public static final int TYPE_4BYTE_ABGR_PRE = 7; 168 169 /** 170 * Represents an image with 5-6-5 RGB color components (5-bits red, 171 * 6-bits green, 5-bits blue) with no alpha. This image has 172 * a <code>DirectColorModel</code>. 173 * When data with non-opaque alpha is stored 174 * in an image of this type, 175 * the color data must be adjusted to a non-premultiplied form 176 * and the alpha discarded, 177 * as described in the 178 * {@link java.awt.AlphaComposite} documentation. 179 */ 180 public static final int TYPE_USHORT_565_RGB = 8; 181 182 /** 183 * Represents an image with 5-5-5 RGB color components (5-bits red, 184 * 5-bits green, 5-bits blue) with no alpha. This image has 185 * a <code>DirectColorModel</code>. 186 * When data with non-opaque alpha is stored 187 * in an image of this type, 188 * the color data must be adjusted to a non-premultiplied form 189 * and the alpha discarded, 190 * as described in the 191 * {@link java.awt.AlphaComposite} documentation. 192 */ 193 public static final int TYPE_USHORT_555_RGB = 9; 194 195 /** 196 * Represents a unsigned byte grayscale image, non-indexed. This 197 * image has a <code>ComponentColorModel</code> with a CS_GRAY 198 * {@link ColorSpace}. 199 * When data with non-opaque alpha is stored 200 * in an image of this type, 201 * the color data must be adjusted to a non-premultiplied form 202 * and the alpha discarded, 203 * as described in the 204 * {@link java.awt.AlphaComposite} documentation. 205 */ 206 public static final int TYPE_BYTE_GRAY = 10; 207 208 /** 209 * Represents an unsigned short grayscale image, non-indexed). This 210 * image has a <code>ComponentColorModel</code> with a CS_GRAY 211 * <code>ColorSpace</code>. 212 * When data with non-opaque alpha is stored 213 * in an image of this type, 214 * the color data must be adjusted to a non-premultiplied form 215 * and the alpha discarded, 216 * as described in the 217 * {@link java.awt.AlphaComposite} documentation. 218 */ 219 public static final int TYPE_USHORT_GRAY = 11; 220 221 /** 222 * Represents an opaque byte-packed 1, 2, or 4 bit image. The 223 * image has an {@link IndexColorModel} without alpha. When this 224 * type is used as the <code>imageType</code> argument to the 225 * <code>BufferedImage</code> constructor that takes an 226 * <code>imageType</code> argument but no <code>ColorModel</code> 227 * argument, a 1-bit image is created with an 228 * <code>IndexColorModel</code> with two colors in the default 229 * sRGB <code>ColorSpace</code>: {0, 0, 0} and 230 * {255, 255, 255}. 231 * 232 * <p> Images with 2 or 4 bits per pixel may be constructed via 233 * the <code>BufferedImage</code> constructor that takes a 234 * <code>ColorModel</code> argument by supplying a 235 * <code>ColorModel</code> with an appropriate map size. 236 * 237 * <p> Images with 8 bits per pixel should use the image types 238 * <code>TYPE_BYTE_INDEXED</code> or <code>TYPE_BYTE_GRAY</code> 239 * depending on their <code>ColorModel</code>. 240 241 * <p> When color data is stored in an image of this type, 242 * the closest color in the colormap is determined 243 * by the <code>IndexColorModel</code> and the resulting index is stored. 244 * Approximation and loss of alpha or color components 245 * can result, depending on the colors in the 246 * <code>IndexColorModel</code> colormap. 247 */ 248 public static final int TYPE_BYTE_BINARY = 12; 249 250 /** 251 * Represents an indexed byte image. When this type is used as the 252 * <code>imageType</code> argument to the <code>BufferedImage</code> 253 * constructor that takes an <code>imageType</code> argument 254 * but no <code>ColorModel</code> argument, an 255 * <code>IndexColorModel</code> is created with 256 * a 256-color 6/6/6 color cube palette with the rest of the colors 257 * from 216-255 populated by grayscale values in the 258 * default sRGB ColorSpace. 259 * 260 * <p> When color data is stored in an image of this type, 261 * the closest color in the colormap is determined 262 * by the <code>IndexColorModel</code> and the resulting index is stored. 263 * Approximation and loss of alpha or color components 264 * can result, depending on the colors in the 265 * <code>IndexColorModel</code> colormap. 266 */ 267 public static final int TYPE_BYTE_INDEXED = 13; 268 269 private static final int DCM_RED_MASK = 0x00ff0000; 270 private static final int DCM_GREEN_MASK = 0x0000ff00; 271 private static final int DCM_BLUE_MASK = 0x000000ff; 272 private static final int DCM_ALPHA_MASK = 0xff000000; 273 private static final int DCM_565_RED_MASK = 0xf800; 274 private static final int DCM_565_GRN_MASK = 0x07E0; 275 private static final int DCM_565_BLU_MASK = 0x001F; 276 private static final int DCM_555_RED_MASK = 0x7C00; 277 private static final int DCM_555_GRN_MASK = 0x03E0; 278 private static final int DCM_555_BLU_MASK = 0x001F; 279 private static final int DCM_BGR_RED_MASK = 0x0000ff; 280 private static final int DCM_BGR_GRN_MASK = 0x00ff00; 281 private static final int DCM_BGR_BLU_MASK = 0xff0000; 282 283 284 private static native void initIDs(); 285 static { 286 ColorModel.loadLibraries(); 287 initIDs(); 288 } 289 290 /** 291 * Constructs a <code>BufferedImage</code> of one of the predefined 292 * image types. The <code>ColorSpace</code> for the image is the 293 * default sRGB space. 294 * @param width width of the created image 295 * @param height height of the created image 296 * @param imageType type of the created image 297 * @see ColorSpace 298 * @see #TYPE_INT_RGB 299 * @see #TYPE_INT_ARGB 300 * @see #TYPE_INT_ARGB_PRE 301 * @see #TYPE_INT_BGR 302 * @see #TYPE_3BYTE_BGR 303 * @see #TYPE_4BYTE_ABGR 304 * @see #TYPE_4BYTE_ABGR_PRE 305 * @see #TYPE_BYTE_GRAY 306 * @see #TYPE_USHORT_GRAY 307 * @see #TYPE_BYTE_BINARY 308 * @see #TYPE_BYTE_INDEXED 309 * @see #TYPE_USHORT_565_RGB 310 * @see #TYPE_USHORT_555_RGB 311 */ 312 public BufferedImage(int width, 489 { 490 colorModel = new DirectColorModel(15, 491 DCM_555_RED_MASK, 492 DCM_555_GRN_MASK, 493 DCM_555_BLU_MASK 494 ); 495 raster = colorModel.createCompatibleWritableRaster(width, 496 height); 497 } 498 break; 499 500 default: 501 throw new IllegalArgumentException ("Unknown image type " + 502 imageType); 503 } 504 505 this.imageType = imageType; 506 } 507 508 /** 509 * Constructs a <code>BufferedImage</code> of one of the predefined 510 * image types: 511 * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED. 512 * 513 * <p> If the image type is TYPE_BYTE_BINARY, the number of 514 * entries in the color model is used to determine whether the 515 * image should have 1, 2, or 4 bits per pixel. If the color model 516 * has 1 or 2 entries, the image will have 1 bit per pixel. If it 517 * has 3 or 4 entries, the image with have 2 bits per pixel. If 518 * it has between 5 and 16 entries, the image will have 4 bits per 519 * pixel. Otherwise, an IllegalArgumentException will be thrown. 520 * 521 * @param width width of the created image 522 * @param height height of the created image 523 * @param imageType type of the created image 524 * @param cm <code>IndexColorModel</code> of the created image 525 * @throws IllegalArgumentException if the imageType is not 526 * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED or if the imageType is 527 * TYPE_BYTE_BINARY and the color map has more than 16 entries. 528 * @see #TYPE_BYTE_BINARY 529 * @see #TYPE_BYTE_INDEXED 530 */ 531 public BufferedImage (int width, 532 int height, 533 int imageType, 534 IndexColorModel cm) { 535 if (cm.hasAlpha() && cm.isAlphaPremultiplied()) { 536 throw new IllegalArgumentException("This image types do not have "+ 537 "premultiplied alpha."); 538 } 539 540 switch(imageType) { 541 case TYPE_BYTE_BINARY: 542 int bits; // Will be set below 543 int mapSize = cm.getMapSize(); 544 if (mapSize <= 2) { 559 case TYPE_BYTE_INDEXED: 560 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 561 width, height, 1, null); 562 break; 563 default: 564 throw new IllegalArgumentException("Invalid image type (" + 565 imageType+"). Image type must"+ 566 " be either TYPE_BYTE_BINARY or "+ 567 " TYPE_BYTE_INDEXED"); 568 } 569 570 if (!cm.isCompatibleRaster(raster)) { 571 throw new IllegalArgumentException("Incompatible image type and IndexColorModel"); 572 } 573 574 colorModel = cm; 575 this.imageType = imageType; 576 } 577 578 /** 579 * Constructs a new <code>BufferedImage</code> with a specified 580 * <code>ColorModel</code> and <code>Raster</code>. If the number and 581 * types of bands in the <code>SampleModel</code> of the 582 * <code>Raster</code> do not match the number and types required by 583 * the <code>ColorModel</code> to represent its color and alpha 584 * components, a {@link RasterFormatException} is thrown. This 585 * method can multiply or divide the color <code>Raster</code> data by 586 * alpha to match the <code>alphaPremultiplied</code> state 587 * in the <code>ColorModel</code>. Properties for this 588 * <code>BufferedImage</code> can be established by passing 589 * in a {@link Hashtable} of <code>String</code>/<code>Object</code> 590 * pairs. 591 * @param cm <code>ColorModel</code> for the new image 592 * @param raster <code>Raster</code> for the image data 593 * @param isRasterPremultiplied if <code>true</code>, the data in 594 * the raster has been premultiplied with alpha. 595 * @param properties <code>Hashtable</code> of 596 * <code>String</code>/<code>Object</code> pairs. 597 * @exception RasterFormatException if the number and 598 * types of bands in the <code>SampleModel</code> of the 599 * <code>Raster</code> do not match the number and types required by 600 * the <code>ColorModel</code> to represent its color and alpha 601 * components. 602 * @exception IllegalArgumentException if 603 * <code>raster</code> is incompatible with <code>cm</code> 604 * @see ColorModel 605 * @see Raster 606 * @see WritableRaster 607 */ 608 609 610 /* 611 * 612 * FOR NOW THE CODE WHICH DEFINES THE RASTER TYPE IS DUPLICATED BY DVF 613 * SEE THE METHOD DEFINERASTERTYPE @ RASTEROUTPUTMANAGER 614 * 615 */ 616 public BufferedImage (ColorModel cm, 617 WritableRaster raster, 618 boolean isRasterPremultiplied, 619 Hashtable<?,?> properties) { 620 621 if (!cm.isCompatibleRaster(raster)) { 622 throw new 623 IllegalArgumentException("Raster "+raster+ 807 808 final PrivilegedAction<Boolean> checkClassLoadersAction = 809 new PrivilegedAction<Boolean>() 810 { 811 812 @Override 813 public Boolean run() { 814 final ClassLoader std = System.class.getClassLoader(); 815 816 return (cmClass.getClassLoader() == std) && 817 (smClass.getClassLoader() == std) && 818 (wrClass.getClassLoader() == std); 819 } 820 }; 821 return AccessController.doPrivileged(checkClassLoadersAction); 822 } 823 824 /** 825 * Returns the image type. If it is not one of the known types, 826 * TYPE_CUSTOM is returned. 827 * @return the image type of this <code>BufferedImage</code>. 828 * @see #TYPE_INT_RGB 829 * @see #TYPE_INT_ARGB 830 * @see #TYPE_INT_ARGB_PRE 831 * @see #TYPE_INT_BGR 832 * @see #TYPE_3BYTE_BGR 833 * @see #TYPE_4BYTE_ABGR 834 * @see #TYPE_4BYTE_ABGR_PRE 835 * @see #TYPE_BYTE_GRAY 836 * @see #TYPE_BYTE_BINARY 837 * @see #TYPE_BYTE_INDEXED 838 * @see #TYPE_USHORT_GRAY 839 * @see #TYPE_USHORT_565_RGB 840 * @see #TYPE_USHORT_555_RGB 841 * @see #TYPE_CUSTOM 842 */ 843 public int getType() { 844 return imageType; 845 } 846 847 /** 848 * Returns the <code>ColorModel</code>. 849 * @return the <code>ColorModel</code> of this 850 * <code>BufferedImage</code>. 851 */ 852 public ColorModel getColorModel() { 853 return colorModel; 854 } 855 856 /** 857 * Returns the {@link WritableRaster}. 858 * @return the <code>WritableRaster</code> of this 859 * <code>BufferedImage</code>. 860 */ 861 public WritableRaster getRaster() { 862 return raster; 863 } 864 865 866 /** 867 * Returns a <code>WritableRaster</code> representing the alpha 868 * channel for <code>BufferedImage</code> objects 869 * with <code>ColorModel</code> objects that support a separate 870 * spatial alpha channel, such as <code>ComponentColorModel</code> and 871 * <code>DirectColorModel</code>. Returns <code>null</code> if there 872 * is no alpha channel associated with the <code>ColorModel</code> in 873 * this image. This method assumes that for all 874 * <code>ColorModel</code> objects other than 875 * <code>IndexColorModel</code>, if the <code>ColorModel</code> 876 * supports alpha, there is a separate alpha channel 877 * which is stored as the last band of image data. 878 * If the image uses an <code>IndexColorModel</code> that 879 * has alpha in the lookup table, this method returns 880 * <code>null</code> since there is no spatially discrete alpha 881 * channel. This method creates a new 882 * <code>WritableRaster</code>, but shares the data array. 883 * @return a <code>WritableRaster</code> or <code>null</code> if this 884 * <code>BufferedImage</code> has no alpha channel associated 885 * with its <code>ColorModel</code>. 886 */ 887 public WritableRaster getAlphaRaster() { 888 return colorModel.getAlphaRaster(raster); 889 } 890 891 /** 892 * Returns an integer pixel in the default RGB color model 893 * (TYPE_INT_ARGB) and default sRGB colorspace. Color 894 * conversion takes place if this default model does not match 895 * the image <code>ColorModel</code>. There are only 8-bits of 896 * precision for each color component in the returned data when using 897 * this method. 898 * 899 * <p> 900 * 901 * An <code>ArrayOutOfBoundsException</code> may be thrown 902 * if the coordinates are not in bounds. 903 * However, explicit bounds checking is not guaranteed. 904 * 905 * @param x the X coordinate of the pixel from which to get 906 * the pixel in the default RGB color model and sRGB 907 * color space 908 * @param y the Y coordinate of the pixel from which to get 909 * the pixel in the default RGB color model and sRGB 910 * color space 911 * @return an integer pixel in the default RGB color model and 912 * default sRGB colorspace. 913 * @see #setRGB(int, int, int) 914 * @see #setRGB(int, int, int, int, int[], int, int) 915 */ 916 public int getRGB(int x, int y) { 917 return colorModel.getRGB(raster.getDataElements(x, y, null)); 918 } 919 920 /** 921 * Returns an array of integer pixels in the default RGB color model 922 * (TYPE_INT_ARGB) and default sRGB color space, 923 * from a portion of the image data. Color conversion takes 924 * place if the default model does not match the image 925 * <code>ColorModel</code>. There are only 8-bits of precision for 926 * each color component in the returned data when 927 * using this method. With a specified coordinate (x, y) in the 928 * image, the ARGB pixel can be accessed in this way: 929 * 930 * <pre> 931 * pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)]; </pre> 932 * 933 * <p> 934 * 935 * An <code>ArrayOutOfBoundsException</code> may be thrown 936 * if the region is not in bounds. 937 * However, explicit bounds checking is not guaranteed. 938 * 939 * @param startX the starting X coordinate 940 * @param startY the starting Y coordinate 941 * @param w width of region 942 * @param h height of region 943 * @param rgbArray if not <code>null</code>, the rgb pixels are 944 * written here 945 * @param offset offset into the <code>rgbArray</code> 946 * @param scansize scanline stride for the <code>rgbArray</code> 947 * @return array of RGB pixels. 948 * @see #setRGB(int, int, int) 949 * @see #setRGB(int, int, int, int, int[], int, int) 950 */ 951 public int[] getRGB(int startX, int startY, int w, int h, 952 int[] rgbArray, int offset, int scansize) { 953 int yoff = offset; 954 int off; 955 Object data; 956 int nbands = raster.getNumBands(); 957 int dataType = raster.getDataBuffer().getDataType(); 958 switch (dataType) { 959 case DataBuffer.TYPE_BYTE: 960 data = new byte[nbands]; 961 break; 962 case DataBuffer.TYPE_USHORT: 963 data = new short[nbands]; 964 break; 965 case DataBuffer.TYPE_INT: 966 data = new int[nbands]; 977 } 978 979 if (rgbArray == null) { 980 rgbArray = new int[offset+h*scansize]; 981 } 982 983 for (int y = startY; y < startY+h; y++, yoff+=scansize) { 984 off = yoff; 985 for (int x = startX; x < startX+w; x++) { 986 rgbArray[off++] = colorModel.getRGB(raster.getDataElements(x, 987 y, 988 data)); 989 } 990 } 991 992 return rgbArray; 993 } 994 995 996 /** 997 * Sets a pixel in this <code>BufferedImage</code> to the specified 998 * RGB value. The pixel is assumed to be in the default RGB color 999 * model, TYPE_INT_ARGB, and default sRGB color space. For images 1000 * with an <code>IndexColorModel</code>, the index with the nearest 1001 * color is chosen. 1002 * 1003 * <p> 1004 * 1005 * An <code>ArrayOutOfBoundsException</code> may be thrown 1006 * if the coordinates are not in bounds. 1007 * However, explicit bounds checking is not guaranteed. 1008 * 1009 * @param x the X coordinate of the pixel to set 1010 * @param y the Y coordinate of the pixel to set 1011 * @param rgb the RGB value 1012 * @see #getRGB(int, int) 1013 * @see #getRGB(int, int, int, int, int[], int, int) 1014 */ 1015 public synchronized void setRGB(int x, int y, int rgb) { 1016 raster.setDataElements(x, y, colorModel.getDataElements(rgb, null)); 1017 } 1018 1019 /** 1020 * Sets an array of integer pixels in the default RGB color model 1021 * (TYPE_INT_ARGB) and default sRGB color space, 1022 * into a portion of the image data. Color conversion takes place 1023 * if the default model does not match the image 1024 * <code>ColorModel</code>. There are only 8-bits of precision for 1025 * each color component in the returned data when 1026 * using this method. With a specified coordinate (x, y) in the 1027 * this image, the ARGB pixel can be accessed in this way: 1028 * <pre> 1029 * pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)]; 1030 * </pre> 1031 * WARNING: No dithering takes place. 1032 * 1033 * <p> 1034 * 1035 * An <code>ArrayOutOfBoundsException</code> may be thrown 1036 * if the region is not in bounds. 1037 * However, explicit bounds checking is not guaranteed. 1038 * 1039 * @param startX the starting X coordinate 1040 * @param startY the starting Y coordinate 1041 * @param w width of the region 1042 * @param h height of the region 1043 * @param rgbArray the rgb pixels 1044 * @param offset offset into the <code>rgbArray</code> 1045 * @param scansize scanline stride for the <code>rgbArray</code> 1046 * @see #getRGB(int, int) 1047 * @see #getRGB(int, int, int, int, int[], int, int) 1048 */ 1049 public void setRGB(int startX, int startY, int w, int h, 1050 int[] rgbArray, int offset, int scansize) { 1051 int yoff = offset; 1052 int off; 1053 Object pixel = null; 1054 1055 for (int y = startY; y < startY+h; y++, yoff+=scansize) { 1056 off = yoff; 1057 for (int x = startX; x < startX+w; x++) { 1058 pixel = colorModel.getDataElements(rgbArray[off++], pixel); 1059 raster.setDataElements(x, y, pixel); 1060 } 1061 } 1062 } 1063 1064 1065 /** 1066 * Returns the width of the <code>BufferedImage</code>. 1067 * @return the width of this <code>BufferedImage</code> 1068 */ 1069 public int getWidth() { 1070 return raster.getWidth(); 1071 } 1072 1073 /** 1074 * Returns the height of the <code>BufferedImage</code>. 1075 * @return the height of this <code>BufferedImage</code> 1076 */ 1077 public int getHeight() { 1078 return raster.getHeight(); 1079 } 1080 1081 /** 1082 * Returns the width of the <code>BufferedImage</code>. 1083 * @param observer ignored 1084 * @return the width of this <code>BufferedImage</code> 1085 */ 1086 public int getWidth(ImageObserver observer) { 1087 return raster.getWidth(); 1088 } 1089 1090 /** 1091 * Returns the height of the <code>BufferedImage</code>. 1092 * @param observer ignored 1093 * @return the height of this <code>BufferedImage</code> 1094 */ 1095 public int getHeight(ImageObserver observer) { 1096 return raster.getHeight(); 1097 } 1098 1099 /** 1100 * Returns the object that produces the pixels for the image. 1101 * @return the {@link ImageProducer} that is used to produce the 1102 * pixels for this image. 1103 * @see ImageProducer 1104 */ 1105 public ImageProducer getSource() { 1106 if (osis == null) { 1107 if (properties == null) { 1108 properties = new Hashtable<>(); 1109 } 1110 osis = new OffScreenImageSource(this, properties); 1111 } 1112 return osis; 1113 } 1114 1115 1116 /** 1117 * Returns a property of the image by name. Individual property names 1118 * are defined by the various image formats. If a property is not 1119 * defined for a particular image, this method returns the 1120 * <code>UndefinedProperty</code> field. If the properties 1121 * for this image are not yet known, then this method returns 1122 * <code>null</code> and the <code>ImageObserver</code> object is 1123 * notified later. The property name "comment" should be used to 1124 * store an optional comment that can be presented to the user as a 1125 * description of the image, its source, or its author. 1126 * @param name the property name 1127 * @param observer the <code>ImageObserver</code> that receives 1128 * notification regarding image information 1129 * @return an {@link Object} that is the property referred to by the 1130 * specified <code>name</code> or <code>null</code> if the 1131 * properties of this image are not yet known. 1132 * @throws NullPointerException if the property name is null. 1133 * @see ImageObserver 1134 * @see java.awt.Image#UndefinedProperty 1135 */ 1136 public Object getProperty(String name, ImageObserver observer) { 1137 return getProperty(name); 1138 } 1139 1140 /** 1141 * Returns a property of the image by name. 1142 * @param name the property name 1143 * @return an <code>Object</code> that is the property referred to by 1144 * the specified <code>name</code>. 1145 * @throws NullPointerException if the property name is null. 1146 */ 1147 public Object getProperty(String name) { 1148 if (name == null) { 1149 throw new NullPointerException("null property name is not allowed"); 1150 } 1151 if (properties == null) { 1152 return java.awt.Image.UndefinedProperty; 1153 } 1154 Object o = properties.get(name); 1155 if (o == null) { 1156 o = java.awt.Image.UndefinedProperty; 1157 } 1158 return o; 1159 } 1160 1161 /** 1162 * This method returns a {@link Graphics2D}, but is here 1163 * for backwards compatibility. {@link #createGraphics() createGraphics} is more 1164 * convenient, since it is declared to return a 1165 * <code>Graphics2D</code>. 1166 * @return a <code>Graphics2D</code>, which can be used to draw into 1167 * this image. 1168 */ 1169 public java.awt.Graphics getGraphics() { 1170 return createGraphics(); 1171 } 1172 1173 /** 1174 * Creates a <code>Graphics2D</code>, which can be used to draw into 1175 * this <code>BufferedImage</code>. 1176 * @return a <code>Graphics2D</code>, used for drawing into this 1177 * image. 1178 */ 1179 public Graphics2D createGraphics() { 1180 GraphicsEnvironment env = 1181 GraphicsEnvironment.getLocalGraphicsEnvironment(); 1182 return env.createGraphics(this); 1183 } 1184 1185 /** 1186 * Returns a subimage defined by a specified rectangular region. 1187 * The returned <code>BufferedImage</code> shares the same 1188 * data array as the original image. 1189 * @param x the X coordinate of the upper-left corner of the 1190 * specified rectangular region 1191 * @param y the Y coordinate of the upper-left corner of the 1192 * specified rectangular region 1193 * @param w the width of the specified rectangular region 1194 * @param h the height of the specified rectangular region 1195 * @return a <code>BufferedImage</code> that is the subimage of this 1196 * <code>BufferedImage</code>. 1197 * @exception RasterFormatException if the specified 1198 * area is not contained within this <code>BufferedImage</code>. 1199 */ 1200 public BufferedImage getSubimage (int x, int y, int w, int h) { 1201 return new BufferedImage (colorModel, 1202 raster.createWritableChild(x, y, w, h, 1203 0, 0, null), 1204 colorModel.isAlphaPremultiplied(), 1205 properties); 1206 } 1207 1208 /** 1209 * Returns whether or not the alpha has been premultiplied. It 1210 * returns <code>false</code> if there is no alpha. 1211 * @return <code>true</code> if the alpha has been premultiplied; 1212 * <code>false</code> otherwise. 1213 */ 1214 public boolean isAlphaPremultiplied() { 1215 return colorModel.isAlphaPremultiplied(); 1216 } 1217 1218 /** 1219 * Forces the data to match the state specified in the 1220 * <code>isAlphaPremultiplied</code> variable. It may multiply or 1221 * divide the color raster data by alpha, or do nothing if the data is 1222 * in the correct state. 1223 * @param isAlphaPremultiplied <code>true</code> if the alpha has been 1224 * premultiplied; <code>false</code> otherwise. 1225 */ 1226 public void coerceData (boolean isAlphaPremultiplied) { 1227 if (colorModel.hasAlpha() && 1228 colorModel.isAlphaPremultiplied() != isAlphaPremultiplied) { 1229 // Make the color model do the conversion 1230 colorModel = colorModel.coerceData (raster, isAlphaPremultiplied); 1231 } 1232 } 1233 1234 /** 1235 * Returns a <code>String</code> representation of this 1236 * <code>BufferedImage</code> object and its values. 1237 * @return a <code>String</code> representing this 1238 * <code>BufferedImage</code>. 1239 */ 1240 public String toString() { 1241 return "BufferedImage@"+Integer.toHexString(hashCode()) 1242 +": type = "+imageType 1243 +" "+colorModel+" "+raster; 1244 } 1245 1246 /** 1247 * Returns a {@link Vector} of {@link RenderedImage} objects that are 1248 * the immediate sources, not the sources of these immediate sources, 1249 * of image data for this <code>BufferedImage</code>. This 1250 * method returns <code>null</code> if the <code>BufferedImage</code> 1251 * has no information about its immediate sources. It returns an 1252 * empty <code>Vector</code> if the <code>BufferedImage</code> has no 1253 * immediate sources. 1254 * @return a <code>Vector</code> containing immediate sources of 1255 * this <code>BufferedImage</code> object's image date, or 1256 * <code>null</code> if this <code>BufferedImage</code> has 1257 * no information about its immediate sources, or an empty 1258 * <code>Vector</code> if this <code>BufferedImage</code> 1259 * has no immediate sources. 1260 */ 1261 public Vector<RenderedImage> getSources() { 1262 return null; 1263 } 1264 1265 /** 1266 * Returns an array of names recognized by 1267 * {@link #getProperty(String) getProperty(String)} 1268 * or <code>null</code>, if no property names are recognized. 1269 * @return a <code>String</code> array containing all of the property 1270 * names that <code>getProperty(String)</code> recognizes; 1271 * or <code>null</code> if no property names are recognized. 1272 */ 1273 public String[] getPropertyNames() { 1274 if (properties == null || properties.isEmpty()) { 1275 return null; 1276 } 1277 final Set<String> keys = properties.keySet(); 1278 return keys.toArray(new String[keys.size()]); 1279 } 1280 1281 /** 1282 * Returns the minimum x coordinate of this 1283 * <code>BufferedImage</code>. This is always zero. 1284 * @return the minimum x coordinate of this 1285 * <code>BufferedImage</code>. 1286 */ 1287 public int getMinX() { 1288 return raster.getMinX(); 1289 } 1290 1291 /** 1292 * Returns the minimum y coordinate of this 1293 * <code>BufferedImage</code>. This is always zero. 1294 * @return the minimum y coordinate of this 1295 * <code>BufferedImage</code>. 1296 */ 1297 public int getMinY() { 1298 return raster.getMinY(); 1299 } 1300 1301 /** 1302 * Returns the <code>SampleModel</code> associated with this 1303 * <code>BufferedImage</code>. 1304 * @return the <code>SampleModel</code> of this 1305 * <code>BufferedImage</code>. 1306 */ 1307 public SampleModel getSampleModel() { 1308 return raster.getSampleModel(); 1309 } 1310 1311 /** 1312 * Returns the number of tiles in the x direction. 1313 * This is always one. 1314 * @return the number of tiles in the x direction. 1315 */ 1316 public int getNumXTiles() { 1317 return 1; 1318 } 1319 1320 /** 1321 * Returns the number of tiles in the y direction. 1322 * This is always one. 1323 * @return the number of tiles in the y direction. 1324 */ 1325 public int getNumYTiles() { 1364 * Returns the x offset of the tile grid relative to the origin, 1365 * For example, the x coordinate of the location of tile 1366 * (0, 0). This is always zero. 1367 * @return the x offset of the tile grid. 1368 */ 1369 public int getTileGridXOffset() { 1370 return raster.getSampleModelTranslateX(); 1371 } 1372 1373 /** 1374 * Returns the y offset of the tile grid relative to the origin, 1375 * For example, the y coordinate of the location of tile 1376 * (0, 0). This is always zero. 1377 * @return the y offset of the tile grid. 1378 */ 1379 public int getTileGridYOffset() { 1380 return raster.getSampleModelTranslateY(); 1381 } 1382 1383 /** 1384 * Returns tile (<code>tileX</code>, <code>tileY</code>). Note 1385 * that <code>tileX</code> and <code>tileY</code> are indices 1386 * into the tile array, not pixel locations. The <code>Raster</code> 1387 * that is returned is live, which means that it is updated if the 1388 * image is changed. 1389 * @param tileX the x index of the requested tile in the tile array 1390 * @param tileY the y index of the requested tile in the tile array 1391 * @return a <code>Raster</code> that is the tile defined by the 1392 * arguments <code>tileX</code> and <code>tileY</code>. 1393 * @exception ArrayIndexOutOfBoundsException if both 1394 * <code>tileX</code> and <code>tileY</code> are not 1395 * equal to 0 1396 */ 1397 public Raster getTile(int tileX, int tileY) { 1398 if (tileX == 0 && tileY == 0) { 1399 return raster; 1400 } 1401 throw new ArrayIndexOutOfBoundsException("BufferedImages only have"+ 1402 " one tile with index 0,0"); 1403 } 1404 1405 /** 1406 * Returns the image as one large tile. The <code>Raster</code> 1407 * returned is a copy of the image data is not updated if the 1408 * image is changed. 1409 * @return a <code>Raster</code> that is a copy of the image data. 1410 * @see #setData(Raster) 1411 */ 1412 public Raster getData() { 1413 1414 // REMIND : this allocates a whole new tile if raster is a 1415 // subtile. (It only copies in the requested area) 1416 // We should do something smarter. 1417 int width = raster.getWidth(); 1418 int height = raster.getHeight(); 1419 int startX = raster.getMinX(); 1420 int startY = raster.getMinY(); 1421 WritableRaster wr = 1422 Raster.createWritableRaster(raster.getSampleModel(), 1423 new Point(raster.getSampleModelTranslateX(), 1424 raster.getSampleModelTranslateY())); 1425 1426 Object tdata = null; 1427 1428 for (int i = startY; i < startY+height; i++) { 1429 tdata = raster.getDataElements(startX,i,width,1,tdata); 1430 wr.setDataElements(startX,i,width,1, tdata); 1431 } 1432 return wr; 1433 } 1434 1435 /** 1436 * Computes and returns an arbitrary region of the 1437 * <code>BufferedImage</code>. The <code>Raster</code> returned is a 1438 * copy of the image data and is not updated if the image is 1439 * changed. 1440 * @param rect the region of the <code>BufferedImage</code> to be 1441 * returned. 1442 * @return a <code>Raster</code> that is a copy of the image data of 1443 * the specified region of the <code>BufferedImage</code> 1444 * @see #setData(Raster) 1445 */ 1446 public Raster getData(Rectangle rect) { 1447 SampleModel sm = raster.getSampleModel(); 1448 SampleModel nsm = sm.createCompatibleSampleModel(rect.width, 1449 rect.height); 1450 WritableRaster wr = Raster.createWritableRaster(nsm, 1451 rect.getLocation()); 1452 int width = rect.width; 1453 int height = rect.height; 1454 int startX = rect.x; 1455 int startY = rect.y; 1456 1457 Object tdata = null; 1458 1459 for (int i = startY; i < startY+height; i++) { 1460 tdata = raster.getDataElements(startX,i,width,1,tdata); 1461 wr.setDataElements(startX,i,width,1, tdata); 1462 } 1463 return wr; 1464 } 1465 1466 /** 1467 * Computes an arbitrary rectangular region of the 1468 * <code>BufferedImage</code> and copies it into a specified 1469 * <code>WritableRaster</code>. The region to be computed is 1470 * determined from the bounds of the specified 1471 * <code>WritableRaster</code>. The specified 1472 * <code>WritableRaster</code> must have a 1473 * <code>SampleModel</code> that is compatible with this image. If 1474 * <code>outRaster</code> is <code>null</code>, 1475 * an appropriate <code>WritableRaster</code> is created. 1476 * @param outRaster a <code>WritableRaster</code> to hold the returned 1477 * part of the image, or <code>null</code> 1478 * @return a reference to the supplied or created 1479 * <code>WritableRaster</code>. 1480 */ 1481 public WritableRaster copyData(WritableRaster outRaster) { 1482 if (outRaster == null) { 1483 return (WritableRaster) getData(); 1484 } 1485 int width = outRaster.getWidth(); 1486 int height = outRaster.getHeight(); 1487 int startX = outRaster.getMinX(); 1488 int startY = outRaster.getMinY(); 1489 1490 Object tdata = null; 1491 1492 for (int i = startY; i < startY+height; i++) { 1493 tdata = raster.getDataElements(startX,i,width,1,tdata); 1494 outRaster.setDataElements(startX,i,width,1, tdata); 1495 } 1496 1497 return outRaster; 1498 } 1499 1500 /** 1501 * Sets a rectangular region of the image to the contents of the 1502 * specified <code>Raster</code> <code>r</code>, which is 1503 * assumed to be in the same coordinate space as the 1504 * <code>BufferedImage</code>. The operation is clipped to the bounds 1505 * of the <code>BufferedImage</code>. 1506 * @param r the specified <code>Raster</code> 1507 * @see #getData 1508 * @see #getData(Rectangle) 1509 */ 1510 public void setData(Raster r) { 1511 int width = r.getWidth(); 1512 int height = r.getHeight(); 1513 int startX = r.getMinX(); 1514 int startY = r.getMinY(); 1515 1516 int[] tdata = null; 1517 1518 // Clip to the current Raster 1519 Rectangle rclip = new Rectangle(startX, startY, width, height); 1520 Rectangle bclip = new Rectangle(0, 0, raster.width, raster.height); 1521 Rectangle intersect = rclip.intersection(bclip); 1522 if (intersect.isEmpty()) { 1523 return; 1524 } 1525 width = intersect.width; 1526 height = intersect.height; 1531 // compatible 1532 for (int i = startY; i < startY+height; i++) { 1533 tdata = r.getPixels(startX,i,width,1,tdata); 1534 raster.setPixels(startX,i,width,1, tdata); 1535 } 1536 } 1537 1538 1539 /** 1540 * Adds a tile observer. If the observer is already present, 1541 * it receives multiple notifications. 1542 * @param to the specified {@link TileObserver} 1543 */ 1544 public void addTileObserver (TileObserver to) { 1545 } 1546 1547 /** 1548 * Removes a tile observer. If the observer was not registered, 1549 * nothing happens. If the observer was registered for multiple 1550 * notifications, it is now registered for one fewer notification. 1551 * @param to the specified <code>TileObserver</code>. 1552 */ 1553 public void removeTileObserver (TileObserver to) { 1554 } 1555 1556 /** 1557 * Returns whether or not a tile is currently checked out for writing. 1558 * @param tileX the x index of the tile. 1559 * @param tileY the y index of the tile. 1560 * @return <code>true</code> if the tile specified by the specified 1561 * indices is checked out for writing; <code>false</code> 1562 * otherwise. 1563 * @exception ArrayIndexOutOfBoundsException if both 1564 * <code>tileX</code> and <code>tileY</code> are not equal 1565 * to 0 1566 */ 1567 public boolean isTileWritable (int tileX, int tileY) { 1568 if (tileX == 0 && tileY == 0) { 1569 return true; 1570 } 1571 throw new IllegalArgumentException("Only 1 tile in image"); 1572 } 1573 1574 /** 1575 * Returns an array of {@link Point} objects indicating which tiles 1576 * are checked out for writing. Returns <code>null</code> if none are 1577 * checked out. 1578 * @return a <code>Point</code> array that indicates the tiles that 1579 * are checked out for writing, or <code>null</code> if no 1580 * tiles are checked out for writing. 1581 */ 1582 public Point[] getWritableTileIndices() { 1583 Point[] p = new Point[1]; 1584 p[0] = new Point(0, 0); 1585 1586 return p; 1587 } 1588 1589 /** 1590 * Returns whether or not any tile is checked out for writing. 1591 * Semantically equivalent to 1592 * <pre> 1593 * (getWritableTileIndices() != null). 1594 * </pre> 1595 * @return <code>true</code> if any tile is checked out for writing; 1596 * <code>false</code> otherwise. 1597 */ 1598 public boolean hasTileWriters () { 1599 return true; 1600 } 1601 1602 /** 1603 * Checks out a tile for writing. All registered 1604 * <code>TileObservers</code> are notified when a tile goes from having 1605 * no writers to having one writer. 1606 * @param tileX the x index of the tile 1607 * @param tileY the y index of the tile 1608 * @return a <code>WritableRaster</code> that is the tile, indicated by 1609 * the specified indices, to be checked out for writing. 1610 */ 1611 public WritableRaster getWritableTile (int tileX, int tileY) { 1612 return raster; 1613 } 1614 1615 /** 1616 * Relinquishes permission to write to a tile. If the caller 1617 * continues to write to the tile, the results are undefined. 1618 * Calls to this method should only appear in matching pairs 1619 * with calls to {@link #getWritableTile(int, int) getWritableTile(int, int)}. Any other leads 1620 * to undefined results. All registered <code>TileObservers</code> 1621 * are notified when a tile goes from having one writer to having no 1622 * writers. 1623 * @param tileX the x index of the tile 1624 * @param tileY the y index of the tile 1625 */ 1626 public void releaseWritableTile (int tileX, int tileY) { 1627 } 1628 1629 /** 1630 * Returns the transparency. Returns either OPAQUE, BITMASK, 1631 * or TRANSLUCENT. 1632 * @return the transparency of this <code>BufferedImage</code>. 1633 * @see Transparency#OPAQUE 1634 * @see Transparency#BITMASK 1635 * @see Transparency#TRANSLUCENT 1636 * @since 1.5 1637 */ 1638 public int getTransparency() { 1639 return colorModel.getTransparency(); 1640 } 1641 } | 28 import java.awt.Graphics2D; 29 import java.awt.GraphicsEnvironment; 30 import java.awt.Point; 31 import java.awt.Rectangle; 32 import java.awt.Transparency; 33 import java.awt.color.ColorSpace; 34 import java.security.AccessController; 35 import java.security.PrivilegedAction; 36 import java.util.Hashtable; 37 import java.util.Set; 38 import java.util.Vector; 39 40 import sun.awt.image.ByteComponentRaster; 41 import sun.awt.image.BytePackedRaster; 42 import sun.awt.image.IntegerComponentRaster; 43 import sun.awt.image.OffScreenImageSource; 44 import sun.awt.image.ShortComponentRaster; 45 46 /** 47 * 48 * The {@code BufferedImage} subclass describes an {@link 49 * java.awt.Image Image} with an accessible buffer of image data. 50 * A {@code BufferedImage} is comprised of a {@link ColorModel} and a 51 * {@link Raster} of image data. 52 * The number and types of bands in the {@link SampleModel} of the 53 * {@code Raster} must match the number and types required by the 54 * {@code ColorModel} to represent its color and alpha components. 55 * All {@code BufferedImage} objects have an upper left corner 56 * coordinate of (0, 0). Any {@code Raster} used to construct a 57 * {@code BufferedImage} must therefore have minX=0 and minY=0. 58 * 59 * <p> 60 * This class relies on the data fetching and setting methods 61 * of {@code Raster}, 62 * and on the color characterization methods of {@code ColorModel}. 63 * 64 * @see ColorModel 65 * @see Raster 66 * @see WritableRaster 67 */ 68 public class BufferedImage extends java.awt.Image 69 implements WritableRenderedImage, Transparency 70 { 71 private int imageType = TYPE_CUSTOM; 72 private ColorModel colorModel; 73 private final WritableRaster raster; 74 private OffScreenImageSource osis; 75 private Hashtable<String, Object> properties; 76 77 /** 78 * Image Type Constants 79 */ 80 81 /** 82 * Image type is not recognized so it must be a customized 83 * image. This type is only used as a return value for the getType() 84 * method. 85 */ 86 public static final int TYPE_CUSTOM = 0; 87 88 /** 89 * Represents an image with 8-bit RGB color components packed into 90 * integer pixels. The image has a {@link DirectColorModel} without 91 * alpha. 92 * When data with non-opaque alpha is stored 93 * in an image of this type, 94 * the color data must be adjusted to a non-premultiplied form 95 * and the alpha discarded, 96 * as described in the 97 * {@link java.awt.AlphaComposite} documentation. 98 */ 99 public static final int TYPE_INT_RGB = 1; 100 101 /** 102 * Represents an image with 8-bit RGBA color components packed into 103 * integer pixels. The image has a {@code DirectColorModel} 104 * with alpha. The color data in this image is considered not to be 105 * premultiplied with alpha. When this type is used as the 106 * {@code imageType} argument to a {@code BufferedImage} 107 * constructor, the created image is consistent with images 108 * created in the JDK1.1 and earlier releases. 109 */ 110 public static final int TYPE_INT_ARGB = 2; 111 112 /** 113 * Represents an image with 8-bit RGBA color components packed into 114 * integer pixels. The image has a {@code DirectColorModel} 115 * with alpha. The color data in this image is considered to be 116 * premultiplied with alpha. 117 */ 118 public static final int TYPE_INT_ARGB_PRE = 3; 119 120 /** 121 * Represents an image with 8-bit RGB color components, corresponding 122 * to a Windows- or Solaris- style BGR color model, with the colors 123 * Blue, Green, and Red packed into integer pixels. There is no alpha. 124 * The image has a {@link DirectColorModel}. 125 * When data with non-opaque alpha is stored 126 * in an image of this type, 127 * the color data must be adjusted to a non-premultiplied form 128 * and the alpha discarded, 129 * as described in the 130 * {@link java.awt.AlphaComposite} documentation. 131 */ 132 public static final int TYPE_INT_BGR = 4; 133 134 /** 135 * Represents an image with 8-bit RGB color components, corresponding 136 * to a Windows-style BGR color model) with the colors Blue, Green, 137 * and Red stored in 3 bytes. There is no alpha. The image has a 138 * {@code ComponentColorModel}. 139 * When data with non-opaque alpha is stored 140 * in an image of this type, 141 * the color data must be adjusted to a non-premultiplied form 142 * and the alpha discarded, 143 * as described in the 144 * {@link java.awt.AlphaComposite} documentation. 145 */ 146 public static final int TYPE_3BYTE_BGR = 5; 147 148 /** 149 * Represents an image with 8-bit RGBA color components with the colors 150 * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha. The 151 * image has a {@code ComponentColorModel} with alpha. The 152 * color data in this image is considered not to be premultiplied with 153 * alpha. The byte data is interleaved in a single 154 * byte array in the order A, B, G, R 155 * from lower to higher byte addresses within each pixel. 156 */ 157 public static final int TYPE_4BYTE_ABGR = 6; 158 159 /** 160 * Represents an image with 8-bit RGBA color components with the colors 161 * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha. The 162 * image has a {@code ComponentColorModel} with alpha. The color 163 * data in this image is considered to be premultiplied with alpha. 164 * The byte data is interleaved in a single byte array in the order 165 * A, B, G, R from lower to higher byte addresses within each pixel. 166 */ 167 public static final int TYPE_4BYTE_ABGR_PRE = 7; 168 169 /** 170 * Represents an image with 5-6-5 RGB color components (5-bits red, 171 * 6-bits green, 5-bits blue) with no alpha. This image has 172 * a {@code DirectColorModel}. 173 * When data with non-opaque alpha is stored 174 * in an image of this type, 175 * the color data must be adjusted to a non-premultiplied form 176 * and the alpha discarded, 177 * as described in the 178 * {@link java.awt.AlphaComposite} documentation. 179 */ 180 public static final int TYPE_USHORT_565_RGB = 8; 181 182 /** 183 * Represents an image with 5-5-5 RGB color components (5-bits red, 184 * 5-bits green, 5-bits blue) with no alpha. This image has 185 * a {@code DirectColorModel}. 186 * When data with non-opaque alpha is stored 187 * in an image of this type, 188 * the color data must be adjusted to a non-premultiplied form 189 * and the alpha discarded, 190 * as described in the 191 * {@link java.awt.AlphaComposite} documentation. 192 */ 193 public static final int TYPE_USHORT_555_RGB = 9; 194 195 /** 196 * Represents a unsigned byte grayscale image, non-indexed. This 197 * image has a {@code ComponentColorModel} with a CS_GRAY 198 * {@link ColorSpace}. 199 * When data with non-opaque alpha is stored 200 * in an image of this type, 201 * the color data must be adjusted to a non-premultiplied form 202 * and the alpha discarded, 203 * as described in the 204 * {@link java.awt.AlphaComposite} documentation. 205 */ 206 public static final int TYPE_BYTE_GRAY = 10; 207 208 /** 209 * Represents an unsigned short grayscale image, non-indexed). This 210 * image has a {@code ComponentColorModel} with a CS_GRAY 211 * {@code ColorSpace}. 212 * When data with non-opaque alpha is stored 213 * in an image of this type, 214 * the color data must be adjusted to a non-premultiplied form 215 * and the alpha discarded, 216 * as described in the 217 * {@link java.awt.AlphaComposite} documentation. 218 */ 219 public static final int TYPE_USHORT_GRAY = 11; 220 221 /** 222 * Represents an opaque byte-packed 1, 2, or 4 bit image. The 223 * image has an {@link IndexColorModel} without alpha. When this 224 * type is used as the {@code imageType} argument to the 225 * {@code BufferedImage} constructor that takes an 226 * {@code imageType} argument but no {@code ColorModel} 227 * argument, a 1-bit image is created with an 228 * {@code IndexColorModel} with two colors in the default 229 * sRGB {@code ColorSpace}: {0, 0, 0} and 230 * {255, 255, 255}. 231 * 232 * <p> Images with 2 or 4 bits per pixel may be constructed via 233 * the {@code BufferedImage} constructor that takes a 234 * {@code ColorModel} argument by supplying a 235 * {@code ColorModel} with an appropriate map size. 236 * 237 * <p> Images with 8 bits per pixel should use the image types 238 * {@code TYPE_BYTE_INDEXED} or {@code TYPE_BYTE_GRAY} 239 * depending on their {@code ColorModel}. 240 241 * <p> When color data is stored in an image of this type, 242 * the closest color in the colormap is determined 243 * by the {@code IndexColorModel} and the resulting index is stored. 244 * Approximation and loss of alpha or color components 245 * can result, depending on the colors in the 246 * {@code IndexColorModel} colormap. 247 */ 248 public static final int TYPE_BYTE_BINARY = 12; 249 250 /** 251 * Represents an indexed byte image. When this type is used as the 252 * {@code imageType} argument to the {@code BufferedImage} 253 * constructor that takes an {@code imageType} argument 254 * but no {@code ColorModel} argument, an 255 * {@code IndexColorModel} is created with 256 * a 256-color 6/6/6 color cube palette with the rest of the colors 257 * from 216-255 populated by grayscale values in the 258 * default sRGB ColorSpace. 259 * 260 * <p> When color data is stored in an image of this type, 261 * the closest color in the colormap is determined 262 * by the {@code IndexColorModel} and the resulting index is stored. 263 * Approximation and loss of alpha or color components 264 * can result, depending on the colors in the 265 * {@code IndexColorModel} colormap. 266 */ 267 public static final int TYPE_BYTE_INDEXED = 13; 268 269 private static final int DCM_RED_MASK = 0x00ff0000; 270 private static final int DCM_GREEN_MASK = 0x0000ff00; 271 private static final int DCM_BLUE_MASK = 0x000000ff; 272 private static final int DCM_ALPHA_MASK = 0xff000000; 273 private static final int DCM_565_RED_MASK = 0xf800; 274 private static final int DCM_565_GRN_MASK = 0x07E0; 275 private static final int DCM_565_BLU_MASK = 0x001F; 276 private static final int DCM_555_RED_MASK = 0x7C00; 277 private static final int DCM_555_GRN_MASK = 0x03E0; 278 private static final int DCM_555_BLU_MASK = 0x001F; 279 private static final int DCM_BGR_RED_MASK = 0x0000ff; 280 private static final int DCM_BGR_GRN_MASK = 0x00ff00; 281 private static final int DCM_BGR_BLU_MASK = 0xff0000; 282 283 284 private static native void initIDs(); 285 static { 286 ColorModel.loadLibraries(); 287 initIDs(); 288 } 289 290 /** 291 * Constructs a {@code BufferedImage} of one of the predefined 292 * image types. The {@code ColorSpace} for the image is the 293 * default sRGB space. 294 * @param width width of the created image 295 * @param height height of the created image 296 * @param imageType type of the created image 297 * @see ColorSpace 298 * @see #TYPE_INT_RGB 299 * @see #TYPE_INT_ARGB 300 * @see #TYPE_INT_ARGB_PRE 301 * @see #TYPE_INT_BGR 302 * @see #TYPE_3BYTE_BGR 303 * @see #TYPE_4BYTE_ABGR 304 * @see #TYPE_4BYTE_ABGR_PRE 305 * @see #TYPE_BYTE_GRAY 306 * @see #TYPE_USHORT_GRAY 307 * @see #TYPE_BYTE_BINARY 308 * @see #TYPE_BYTE_INDEXED 309 * @see #TYPE_USHORT_565_RGB 310 * @see #TYPE_USHORT_555_RGB 311 */ 312 public BufferedImage(int width, 489 { 490 colorModel = new DirectColorModel(15, 491 DCM_555_RED_MASK, 492 DCM_555_GRN_MASK, 493 DCM_555_BLU_MASK 494 ); 495 raster = colorModel.createCompatibleWritableRaster(width, 496 height); 497 } 498 break; 499 500 default: 501 throw new IllegalArgumentException ("Unknown image type " + 502 imageType); 503 } 504 505 this.imageType = imageType; 506 } 507 508 /** 509 * Constructs a {@code BufferedImage} of one of the predefined 510 * image types: 511 * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED. 512 * 513 * <p> If the image type is TYPE_BYTE_BINARY, the number of 514 * entries in the color model is used to determine whether the 515 * image should have 1, 2, or 4 bits per pixel. If the color model 516 * has 1 or 2 entries, the image will have 1 bit per pixel. If it 517 * has 3 or 4 entries, the image with have 2 bits per pixel. If 518 * it has between 5 and 16 entries, the image will have 4 bits per 519 * pixel. Otherwise, an IllegalArgumentException will be thrown. 520 * 521 * @param width width of the created image 522 * @param height height of the created image 523 * @param imageType type of the created image 524 * @param cm {@code IndexColorModel} of the created image 525 * @throws IllegalArgumentException if the imageType is not 526 * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED or if the imageType is 527 * TYPE_BYTE_BINARY and the color map has more than 16 entries. 528 * @see #TYPE_BYTE_BINARY 529 * @see #TYPE_BYTE_INDEXED 530 */ 531 public BufferedImage (int width, 532 int height, 533 int imageType, 534 IndexColorModel cm) { 535 if (cm.hasAlpha() && cm.isAlphaPremultiplied()) { 536 throw new IllegalArgumentException("This image types do not have "+ 537 "premultiplied alpha."); 538 } 539 540 switch(imageType) { 541 case TYPE_BYTE_BINARY: 542 int bits; // Will be set below 543 int mapSize = cm.getMapSize(); 544 if (mapSize <= 2) { 559 case TYPE_BYTE_INDEXED: 560 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 561 width, height, 1, null); 562 break; 563 default: 564 throw new IllegalArgumentException("Invalid image type (" + 565 imageType+"). Image type must"+ 566 " be either TYPE_BYTE_BINARY or "+ 567 " TYPE_BYTE_INDEXED"); 568 } 569 570 if (!cm.isCompatibleRaster(raster)) { 571 throw new IllegalArgumentException("Incompatible image type and IndexColorModel"); 572 } 573 574 colorModel = cm; 575 this.imageType = imageType; 576 } 577 578 /** 579 * Constructs a new {@code BufferedImage} with a specified 580 * {@code ColorModel} and {@code Raster}. If the number and 581 * types of bands in the {@code SampleModel} of the 582 * {@code Raster} do not match the number and types required by 583 * the {@code ColorModel} to represent its color and alpha 584 * components, a {@link RasterFormatException} is thrown. This 585 * method can multiply or divide the color {@code Raster} data by 586 * alpha to match the {@code alphaPremultiplied} state 587 * in the {@code ColorModel}. Properties for this 588 * {@code BufferedImage} can be established by passing 589 * in a {@link Hashtable} of {@code String}/{@code Object} 590 * pairs. 591 * @param cm {@code ColorModel} for the new image 592 * @param raster {@code Raster} for the image data 593 * @param isRasterPremultiplied if {@code true}, the data in 594 * the raster has been premultiplied with alpha. 595 * @param properties {@code Hashtable} of 596 * {@code String}/{@code Object} pairs. 597 * @exception RasterFormatException if the number and 598 * types of bands in the {@code SampleModel} of the 599 * {@code Raster} do not match the number and types required by 600 * the {@code ColorModel} to represent its color and alpha 601 * components. 602 * @exception IllegalArgumentException if 603 * {@code raster} is incompatible with {@code cm} 604 * @see ColorModel 605 * @see Raster 606 * @see WritableRaster 607 */ 608 609 610 /* 611 * 612 * FOR NOW THE CODE WHICH DEFINES THE RASTER TYPE IS DUPLICATED BY DVF 613 * SEE THE METHOD DEFINERASTERTYPE @ RASTEROUTPUTMANAGER 614 * 615 */ 616 public BufferedImage (ColorModel cm, 617 WritableRaster raster, 618 boolean isRasterPremultiplied, 619 Hashtable<?,?> properties) { 620 621 if (!cm.isCompatibleRaster(raster)) { 622 throw new 623 IllegalArgumentException("Raster "+raster+ 807 808 final PrivilegedAction<Boolean> checkClassLoadersAction = 809 new PrivilegedAction<Boolean>() 810 { 811 812 @Override 813 public Boolean run() { 814 final ClassLoader std = System.class.getClassLoader(); 815 816 return (cmClass.getClassLoader() == std) && 817 (smClass.getClassLoader() == std) && 818 (wrClass.getClassLoader() == std); 819 } 820 }; 821 return AccessController.doPrivileged(checkClassLoadersAction); 822 } 823 824 /** 825 * Returns the image type. If it is not one of the known types, 826 * TYPE_CUSTOM is returned. 827 * @return the image type of this {@code BufferedImage}. 828 * @see #TYPE_INT_RGB 829 * @see #TYPE_INT_ARGB 830 * @see #TYPE_INT_ARGB_PRE 831 * @see #TYPE_INT_BGR 832 * @see #TYPE_3BYTE_BGR 833 * @see #TYPE_4BYTE_ABGR 834 * @see #TYPE_4BYTE_ABGR_PRE 835 * @see #TYPE_BYTE_GRAY 836 * @see #TYPE_BYTE_BINARY 837 * @see #TYPE_BYTE_INDEXED 838 * @see #TYPE_USHORT_GRAY 839 * @see #TYPE_USHORT_565_RGB 840 * @see #TYPE_USHORT_555_RGB 841 * @see #TYPE_CUSTOM 842 */ 843 public int getType() { 844 return imageType; 845 } 846 847 /** 848 * Returns the {@code ColorModel}. 849 * @return the {@code ColorModel} of this 850 * {@code BufferedImage}. 851 */ 852 public ColorModel getColorModel() { 853 return colorModel; 854 } 855 856 /** 857 * Returns the {@link WritableRaster}. 858 * @return the {@code WritableRaster} of this 859 * {@code BufferedImage}. 860 */ 861 public WritableRaster getRaster() { 862 return raster; 863 } 864 865 866 /** 867 * Returns a {@code WritableRaster} representing the alpha 868 * channel for {@code BufferedImage} objects 869 * with {@code ColorModel} objects that support a separate 870 * spatial alpha channel, such as {@code ComponentColorModel} and 871 * {@code DirectColorModel}. Returns {@code null} if there 872 * is no alpha channel associated with the {@code ColorModel} in 873 * this image. This method assumes that for all 874 * {@code ColorModel} objects other than 875 * {@code IndexColorModel}, if the {@code ColorModel} 876 * supports alpha, there is a separate alpha channel 877 * which is stored as the last band of image data. 878 * If the image uses an {@code IndexColorModel} that 879 * has alpha in the lookup table, this method returns 880 * {@code null} since there is no spatially discrete alpha 881 * channel. This method creates a new 882 * {@code WritableRaster}, but shares the data array. 883 * @return a {@code WritableRaster} or {@code null} if this 884 * {@code BufferedImage} has no alpha channel associated 885 * with its {@code ColorModel}. 886 */ 887 public WritableRaster getAlphaRaster() { 888 return colorModel.getAlphaRaster(raster); 889 } 890 891 /** 892 * Returns an integer pixel in the default RGB color model 893 * (TYPE_INT_ARGB) and default sRGB colorspace. Color 894 * conversion takes place if this default model does not match 895 * the image {@code ColorModel}. There are only 8-bits of 896 * precision for each color component in the returned data when using 897 * this method. 898 * 899 * <p> 900 * 901 * An {@code ArrayOutOfBoundsException} may be thrown 902 * if the coordinates are not in bounds. 903 * However, explicit bounds checking is not guaranteed. 904 * 905 * @param x the X coordinate of the pixel from which to get 906 * the pixel in the default RGB color model and sRGB 907 * color space 908 * @param y the Y coordinate of the pixel from which to get 909 * the pixel in the default RGB color model and sRGB 910 * color space 911 * @return an integer pixel in the default RGB color model and 912 * default sRGB colorspace. 913 * @see #setRGB(int, int, int) 914 * @see #setRGB(int, int, int, int, int[], int, int) 915 */ 916 public int getRGB(int x, int y) { 917 return colorModel.getRGB(raster.getDataElements(x, y, null)); 918 } 919 920 /** 921 * Returns an array of integer pixels in the default RGB color model 922 * (TYPE_INT_ARGB) and default sRGB color space, 923 * from a portion of the image data. Color conversion takes 924 * place if the default model does not match the image 925 * {@code ColorModel}. There are only 8-bits of precision for 926 * each color component in the returned data when 927 * using this method. With a specified coordinate (x, y) in the 928 * image, the ARGB pixel can be accessed in this way: 929 * 930 * <pre> 931 * pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)]; </pre> 932 * 933 * <p> 934 * 935 * An {@code ArrayOutOfBoundsException} may be thrown 936 * if the region is not in bounds. 937 * However, explicit bounds checking is not guaranteed. 938 * 939 * @param startX the starting X coordinate 940 * @param startY the starting Y coordinate 941 * @param w width of region 942 * @param h height of region 943 * @param rgbArray if not {@code null}, the rgb pixels are 944 * written here 945 * @param offset offset into the {@code rgbArray} 946 * @param scansize scanline stride for the {@code rgbArray} 947 * @return array of RGB pixels. 948 * @see #setRGB(int, int, int) 949 * @see #setRGB(int, int, int, int, int[], int, int) 950 */ 951 public int[] getRGB(int startX, int startY, int w, int h, 952 int[] rgbArray, int offset, int scansize) { 953 int yoff = offset; 954 int off; 955 Object data; 956 int nbands = raster.getNumBands(); 957 int dataType = raster.getDataBuffer().getDataType(); 958 switch (dataType) { 959 case DataBuffer.TYPE_BYTE: 960 data = new byte[nbands]; 961 break; 962 case DataBuffer.TYPE_USHORT: 963 data = new short[nbands]; 964 break; 965 case DataBuffer.TYPE_INT: 966 data = new int[nbands]; 977 } 978 979 if (rgbArray == null) { 980 rgbArray = new int[offset+h*scansize]; 981 } 982 983 for (int y = startY; y < startY+h; y++, yoff+=scansize) { 984 off = yoff; 985 for (int x = startX; x < startX+w; x++) { 986 rgbArray[off++] = colorModel.getRGB(raster.getDataElements(x, 987 y, 988 data)); 989 } 990 } 991 992 return rgbArray; 993 } 994 995 996 /** 997 * Sets a pixel in this {@code BufferedImage} to the specified 998 * RGB value. The pixel is assumed to be in the default RGB color 999 * model, TYPE_INT_ARGB, and default sRGB color space. For images 1000 * with an {@code IndexColorModel}, the index with the nearest 1001 * color is chosen. 1002 * 1003 * <p> 1004 * 1005 * An {@code ArrayOutOfBoundsException} may be thrown 1006 * if the coordinates are not in bounds. 1007 * However, explicit bounds checking is not guaranteed. 1008 * 1009 * @param x the X coordinate of the pixel to set 1010 * @param y the Y coordinate of the pixel to set 1011 * @param rgb the RGB value 1012 * @see #getRGB(int, int) 1013 * @see #getRGB(int, int, int, int, int[], int, int) 1014 */ 1015 public synchronized void setRGB(int x, int y, int rgb) { 1016 raster.setDataElements(x, y, colorModel.getDataElements(rgb, null)); 1017 } 1018 1019 /** 1020 * Sets an array of integer pixels in the default RGB color model 1021 * (TYPE_INT_ARGB) and default sRGB color space, 1022 * into a portion of the image data. Color conversion takes place 1023 * if the default model does not match the image 1024 * {@code ColorModel}. There are only 8-bits of precision for 1025 * each color component in the returned data when 1026 * using this method. With a specified coordinate (x, y) in the 1027 * this image, the ARGB pixel can be accessed in this way: 1028 * <pre> 1029 * pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)]; 1030 * </pre> 1031 * WARNING: No dithering takes place. 1032 * 1033 * <p> 1034 * 1035 * An {@code ArrayOutOfBoundsException} may be thrown 1036 * if the region is not in bounds. 1037 * However, explicit bounds checking is not guaranteed. 1038 * 1039 * @param startX the starting X coordinate 1040 * @param startY the starting Y coordinate 1041 * @param w width of the region 1042 * @param h height of the region 1043 * @param rgbArray the rgb pixels 1044 * @param offset offset into the {@code rgbArray} 1045 * @param scansize scanline stride for the {@code rgbArray} 1046 * @see #getRGB(int, int) 1047 * @see #getRGB(int, int, int, int, int[], int, int) 1048 */ 1049 public void setRGB(int startX, int startY, int w, int h, 1050 int[] rgbArray, int offset, int scansize) { 1051 int yoff = offset; 1052 int off; 1053 Object pixel = null; 1054 1055 for (int y = startY; y < startY+h; y++, yoff+=scansize) { 1056 off = yoff; 1057 for (int x = startX; x < startX+w; x++) { 1058 pixel = colorModel.getDataElements(rgbArray[off++], pixel); 1059 raster.setDataElements(x, y, pixel); 1060 } 1061 } 1062 } 1063 1064 1065 /** 1066 * Returns the width of the {@code BufferedImage}. 1067 * @return the width of this {@code BufferedImage} 1068 */ 1069 public int getWidth() { 1070 return raster.getWidth(); 1071 } 1072 1073 /** 1074 * Returns the height of the {@code BufferedImage}. 1075 * @return the height of this {@code BufferedImage} 1076 */ 1077 public int getHeight() { 1078 return raster.getHeight(); 1079 } 1080 1081 /** 1082 * Returns the width of the {@code BufferedImage}. 1083 * @param observer ignored 1084 * @return the width of this {@code BufferedImage} 1085 */ 1086 public int getWidth(ImageObserver observer) { 1087 return raster.getWidth(); 1088 } 1089 1090 /** 1091 * Returns the height of the {@code BufferedImage}. 1092 * @param observer ignored 1093 * @return the height of this {@code BufferedImage} 1094 */ 1095 public int getHeight(ImageObserver observer) { 1096 return raster.getHeight(); 1097 } 1098 1099 /** 1100 * Returns the object that produces the pixels for the image. 1101 * @return the {@link ImageProducer} that is used to produce the 1102 * pixels for this image. 1103 * @see ImageProducer 1104 */ 1105 public ImageProducer getSource() { 1106 if (osis == null) { 1107 if (properties == null) { 1108 properties = new Hashtable<>(); 1109 } 1110 osis = new OffScreenImageSource(this, properties); 1111 } 1112 return osis; 1113 } 1114 1115 1116 /** 1117 * Returns a property of the image by name. Individual property names 1118 * are defined by the various image formats. If a property is not 1119 * defined for a particular image, this method returns the 1120 * {@code UndefinedProperty} field. If the properties 1121 * for this image are not yet known, then this method returns 1122 * {@code null} and the {@code ImageObserver} object is 1123 * notified later. The property name "comment" should be used to 1124 * store an optional comment that can be presented to the user as a 1125 * description of the image, its source, or its author. 1126 * @param name the property name 1127 * @param observer the {@code ImageObserver} that receives 1128 * notification regarding image information 1129 * @return an {@link Object} that is the property referred to by the 1130 * specified {@code name} or {@code null} if the 1131 * properties of this image are not yet known. 1132 * @throws NullPointerException if the property name is null. 1133 * @see ImageObserver 1134 * @see java.awt.Image#UndefinedProperty 1135 */ 1136 public Object getProperty(String name, ImageObserver observer) { 1137 return getProperty(name); 1138 } 1139 1140 /** 1141 * Returns a property of the image by name. 1142 * @param name the property name 1143 * @return an {@code Object} that is the property referred to by 1144 * the specified {@code name}. 1145 * @throws NullPointerException if the property name is null. 1146 */ 1147 public Object getProperty(String name) { 1148 if (name == null) { 1149 throw new NullPointerException("null property name is not allowed"); 1150 } 1151 if (properties == null) { 1152 return java.awt.Image.UndefinedProperty; 1153 } 1154 Object o = properties.get(name); 1155 if (o == null) { 1156 o = java.awt.Image.UndefinedProperty; 1157 } 1158 return o; 1159 } 1160 1161 /** 1162 * This method returns a {@link Graphics2D}, but is here 1163 * for backwards compatibility. {@link #createGraphics() createGraphics} is more 1164 * convenient, since it is declared to return a 1165 * {@code Graphics2D}. 1166 * @return a {@code Graphics2D}, which can be used to draw into 1167 * this image. 1168 */ 1169 public java.awt.Graphics getGraphics() { 1170 return createGraphics(); 1171 } 1172 1173 /** 1174 * Creates a {@code Graphics2D}, which can be used to draw into 1175 * this {@code BufferedImage}. 1176 * @return a {@code Graphics2D}, used for drawing into this 1177 * image. 1178 */ 1179 public Graphics2D createGraphics() { 1180 GraphicsEnvironment env = 1181 GraphicsEnvironment.getLocalGraphicsEnvironment(); 1182 return env.createGraphics(this); 1183 } 1184 1185 /** 1186 * Returns a subimage defined by a specified rectangular region. 1187 * The returned {@code BufferedImage} shares the same 1188 * data array as the original image. 1189 * @param x the X coordinate of the upper-left corner of the 1190 * specified rectangular region 1191 * @param y the Y coordinate of the upper-left corner of the 1192 * specified rectangular region 1193 * @param w the width of the specified rectangular region 1194 * @param h the height of the specified rectangular region 1195 * @return a {@code BufferedImage} that is the subimage of this 1196 * {@code BufferedImage}. 1197 * @exception RasterFormatException if the specified 1198 * area is not contained within this {@code BufferedImage}. 1199 */ 1200 public BufferedImage getSubimage (int x, int y, int w, int h) { 1201 return new BufferedImage (colorModel, 1202 raster.createWritableChild(x, y, w, h, 1203 0, 0, null), 1204 colorModel.isAlphaPremultiplied(), 1205 properties); 1206 } 1207 1208 /** 1209 * Returns whether or not the alpha has been premultiplied. It 1210 * returns {@code false} if there is no alpha. 1211 * @return {@code true} if the alpha has been premultiplied; 1212 * {@code false} otherwise. 1213 */ 1214 public boolean isAlphaPremultiplied() { 1215 return colorModel.isAlphaPremultiplied(); 1216 } 1217 1218 /** 1219 * Forces the data to match the state specified in the 1220 * {@code isAlphaPremultiplied} variable. It may multiply or 1221 * divide the color raster data by alpha, or do nothing if the data is 1222 * in the correct state. 1223 * @param isAlphaPremultiplied {@code true} if the alpha has been 1224 * premultiplied; {@code false} otherwise. 1225 */ 1226 public void coerceData (boolean isAlphaPremultiplied) { 1227 if (colorModel.hasAlpha() && 1228 colorModel.isAlphaPremultiplied() != isAlphaPremultiplied) { 1229 // Make the color model do the conversion 1230 colorModel = colorModel.coerceData (raster, isAlphaPremultiplied); 1231 } 1232 } 1233 1234 /** 1235 * Returns a {@code String} representation of this 1236 * {@code BufferedImage} object and its values. 1237 * @return a {@code String} representing this 1238 * {@code BufferedImage}. 1239 */ 1240 public String toString() { 1241 return "BufferedImage@"+Integer.toHexString(hashCode()) 1242 +": type = "+imageType 1243 +" "+colorModel+" "+raster; 1244 } 1245 1246 /** 1247 * Returns a {@link Vector} of {@link RenderedImage} objects that are 1248 * the immediate sources, not the sources of these immediate sources, 1249 * of image data for this {@code BufferedImage}. This 1250 * method returns {@code null} if the {@code BufferedImage} 1251 * has no information about its immediate sources. It returns an 1252 * empty {@code Vector} if the {@code BufferedImage} has no 1253 * immediate sources. 1254 * @return a {@code Vector} containing immediate sources of 1255 * this {@code BufferedImage} object's image date, or 1256 * {@code null} if this {@code BufferedImage} has 1257 * no information about its immediate sources, or an empty 1258 * {@code Vector} if this {@code BufferedImage} 1259 * has no immediate sources. 1260 */ 1261 public Vector<RenderedImage> getSources() { 1262 return null; 1263 } 1264 1265 /** 1266 * Returns an array of names recognized by 1267 * {@link #getProperty(String) getProperty(String)} 1268 * or {@code null}, if no property names are recognized. 1269 * @return a {@code String} array containing all of the property 1270 * names that {@code getProperty(String)} recognizes; 1271 * or {@code null} if no property names are recognized. 1272 */ 1273 public String[] getPropertyNames() { 1274 if (properties == null || properties.isEmpty()) { 1275 return null; 1276 } 1277 final Set<String> keys = properties.keySet(); 1278 return keys.toArray(new String[keys.size()]); 1279 } 1280 1281 /** 1282 * Returns the minimum x coordinate of this 1283 * {@code BufferedImage}. This is always zero. 1284 * @return the minimum x coordinate of this 1285 * {@code BufferedImage}. 1286 */ 1287 public int getMinX() { 1288 return raster.getMinX(); 1289 } 1290 1291 /** 1292 * Returns the minimum y coordinate of this 1293 * {@code BufferedImage}. This is always zero. 1294 * @return the minimum y coordinate of this 1295 * {@code BufferedImage}. 1296 */ 1297 public int getMinY() { 1298 return raster.getMinY(); 1299 } 1300 1301 /** 1302 * Returns the {@code SampleModel} associated with this 1303 * {@code BufferedImage}. 1304 * @return the {@code SampleModel} of this 1305 * {@code BufferedImage}. 1306 */ 1307 public SampleModel getSampleModel() { 1308 return raster.getSampleModel(); 1309 } 1310 1311 /** 1312 * Returns the number of tiles in the x direction. 1313 * This is always one. 1314 * @return the number of tiles in the x direction. 1315 */ 1316 public int getNumXTiles() { 1317 return 1; 1318 } 1319 1320 /** 1321 * Returns the number of tiles in the y direction. 1322 * This is always one. 1323 * @return the number of tiles in the y direction. 1324 */ 1325 public int getNumYTiles() { 1364 * Returns the x offset of the tile grid relative to the origin, 1365 * For example, the x coordinate of the location of tile 1366 * (0, 0). This is always zero. 1367 * @return the x offset of the tile grid. 1368 */ 1369 public int getTileGridXOffset() { 1370 return raster.getSampleModelTranslateX(); 1371 } 1372 1373 /** 1374 * Returns the y offset of the tile grid relative to the origin, 1375 * For example, the y coordinate of the location of tile 1376 * (0, 0). This is always zero. 1377 * @return the y offset of the tile grid. 1378 */ 1379 public int getTileGridYOffset() { 1380 return raster.getSampleModelTranslateY(); 1381 } 1382 1383 /** 1384 * Returns tile ({@code tileX}, {@code tileY}). Note 1385 * that {@code tileX} and {@code tileY} are indices 1386 * into the tile array, not pixel locations. The {@code Raster} 1387 * that is returned is live, which means that it is updated if the 1388 * image is changed. 1389 * @param tileX the x index of the requested tile in the tile array 1390 * @param tileY the y index of the requested tile in the tile array 1391 * @return a {@code Raster} that is the tile defined by the 1392 * arguments {@code tileX} and {@code tileY}. 1393 * @exception ArrayIndexOutOfBoundsException if both 1394 * {@code tileX} and {@code tileY} are not 1395 * equal to 0 1396 */ 1397 public Raster getTile(int tileX, int tileY) { 1398 if (tileX == 0 && tileY == 0) { 1399 return raster; 1400 } 1401 throw new ArrayIndexOutOfBoundsException("BufferedImages only have"+ 1402 " one tile with index 0,0"); 1403 } 1404 1405 /** 1406 * Returns the image as one large tile. The {@code Raster} 1407 * returned is a copy of the image data is not updated if the 1408 * image is changed. 1409 * @return a {@code Raster} that is a copy of the image data. 1410 * @see #setData(Raster) 1411 */ 1412 public Raster getData() { 1413 1414 // REMIND : this allocates a whole new tile if raster is a 1415 // subtile. (It only copies in the requested area) 1416 // We should do something smarter. 1417 int width = raster.getWidth(); 1418 int height = raster.getHeight(); 1419 int startX = raster.getMinX(); 1420 int startY = raster.getMinY(); 1421 WritableRaster wr = 1422 Raster.createWritableRaster(raster.getSampleModel(), 1423 new Point(raster.getSampleModelTranslateX(), 1424 raster.getSampleModelTranslateY())); 1425 1426 Object tdata = null; 1427 1428 for (int i = startY; i < startY+height; i++) { 1429 tdata = raster.getDataElements(startX,i,width,1,tdata); 1430 wr.setDataElements(startX,i,width,1, tdata); 1431 } 1432 return wr; 1433 } 1434 1435 /** 1436 * Computes and returns an arbitrary region of the 1437 * {@code BufferedImage}. The {@code Raster} returned is a 1438 * copy of the image data and is not updated if the image is 1439 * changed. 1440 * @param rect the region of the {@code BufferedImage} to be 1441 * returned. 1442 * @return a {@code Raster} that is a copy of the image data of 1443 * the specified region of the {@code BufferedImage} 1444 * @see #setData(Raster) 1445 */ 1446 public Raster getData(Rectangle rect) { 1447 SampleModel sm = raster.getSampleModel(); 1448 SampleModel nsm = sm.createCompatibleSampleModel(rect.width, 1449 rect.height); 1450 WritableRaster wr = Raster.createWritableRaster(nsm, 1451 rect.getLocation()); 1452 int width = rect.width; 1453 int height = rect.height; 1454 int startX = rect.x; 1455 int startY = rect.y; 1456 1457 Object tdata = null; 1458 1459 for (int i = startY; i < startY+height; i++) { 1460 tdata = raster.getDataElements(startX,i,width,1,tdata); 1461 wr.setDataElements(startX,i,width,1, tdata); 1462 } 1463 return wr; 1464 } 1465 1466 /** 1467 * Computes an arbitrary rectangular region of the 1468 * {@code BufferedImage} and copies it into a specified 1469 * {@code WritableRaster}. The region to be computed is 1470 * determined from the bounds of the specified 1471 * {@code WritableRaster}. The specified 1472 * {@code WritableRaster} must have a 1473 * {@code SampleModel} that is compatible with this image. If 1474 * {@code outRaster} is {@code null}, 1475 * an appropriate {@code WritableRaster} is created. 1476 * @param outRaster a {@code WritableRaster} to hold the returned 1477 * part of the image, or {@code null} 1478 * @return a reference to the supplied or created 1479 * {@code WritableRaster}. 1480 */ 1481 public WritableRaster copyData(WritableRaster outRaster) { 1482 if (outRaster == null) { 1483 return (WritableRaster) getData(); 1484 } 1485 int width = outRaster.getWidth(); 1486 int height = outRaster.getHeight(); 1487 int startX = outRaster.getMinX(); 1488 int startY = outRaster.getMinY(); 1489 1490 Object tdata = null; 1491 1492 for (int i = startY; i < startY+height; i++) { 1493 tdata = raster.getDataElements(startX,i,width,1,tdata); 1494 outRaster.setDataElements(startX,i,width,1, tdata); 1495 } 1496 1497 return outRaster; 1498 } 1499 1500 /** 1501 * Sets a rectangular region of the image to the contents of the 1502 * specified {@code Raster r}, which is 1503 * assumed to be in the same coordinate space as the 1504 * {@code BufferedImage}. The operation is clipped to the bounds 1505 * of the {@code BufferedImage}. 1506 * @param r the specified {@code Raster} 1507 * @see #getData 1508 * @see #getData(Rectangle) 1509 */ 1510 public void setData(Raster r) { 1511 int width = r.getWidth(); 1512 int height = r.getHeight(); 1513 int startX = r.getMinX(); 1514 int startY = r.getMinY(); 1515 1516 int[] tdata = null; 1517 1518 // Clip to the current Raster 1519 Rectangle rclip = new Rectangle(startX, startY, width, height); 1520 Rectangle bclip = new Rectangle(0, 0, raster.width, raster.height); 1521 Rectangle intersect = rclip.intersection(bclip); 1522 if (intersect.isEmpty()) { 1523 return; 1524 } 1525 width = intersect.width; 1526 height = intersect.height; 1531 // compatible 1532 for (int i = startY; i < startY+height; i++) { 1533 tdata = r.getPixels(startX,i,width,1,tdata); 1534 raster.setPixels(startX,i,width,1, tdata); 1535 } 1536 } 1537 1538 1539 /** 1540 * Adds a tile observer. If the observer is already present, 1541 * it receives multiple notifications. 1542 * @param to the specified {@link TileObserver} 1543 */ 1544 public void addTileObserver (TileObserver to) { 1545 } 1546 1547 /** 1548 * Removes a tile observer. If the observer was not registered, 1549 * nothing happens. If the observer was registered for multiple 1550 * notifications, it is now registered for one fewer notification. 1551 * @param to the specified {@code TileObserver}. 1552 */ 1553 public void removeTileObserver (TileObserver to) { 1554 } 1555 1556 /** 1557 * Returns whether or not a tile is currently checked out for writing. 1558 * @param tileX the x index of the tile. 1559 * @param tileY the y index of the tile. 1560 * @return {@code true} if the tile specified by the specified 1561 * indices is checked out for writing; {@code false} 1562 * otherwise. 1563 * @exception ArrayIndexOutOfBoundsException if both 1564 * {@code tileX} and {@code tileY} are not equal 1565 * to 0 1566 */ 1567 public boolean isTileWritable (int tileX, int tileY) { 1568 if (tileX == 0 && tileY == 0) { 1569 return true; 1570 } 1571 throw new IllegalArgumentException("Only 1 tile in image"); 1572 } 1573 1574 /** 1575 * Returns an array of {@link Point} objects indicating which tiles 1576 * are checked out for writing. Returns {@code null} if none are 1577 * checked out. 1578 * @return a {@code Point} array that indicates the tiles that 1579 * are checked out for writing, or {@code null} if no 1580 * tiles are checked out for writing. 1581 */ 1582 public Point[] getWritableTileIndices() { 1583 Point[] p = new Point[1]; 1584 p[0] = new Point(0, 0); 1585 1586 return p; 1587 } 1588 1589 /** 1590 * Returns whether or not any tile is checked out for writing. 1591 * Semantically equivalent to 1592 * <pre> 1593 * (getWritableTileIndices() != null). 1594 * </pre> 1595 * @return {@code true} if any tile is checked out for writing; 1596 * {@code false} otherwise. 1597 */ 1598 public boolean hasTileWriters () { 1599 return true; 1600 } 1601 1602 /** 1603 * Checks out a tile for writing. All registered 1604 * {@code TileObservers} are notified when a tile goes from having 1605 * no writers to having one writer. 1606 * @param tileX the x index of the tile 1607 * @param tileY the y index of the tile 1608 * @return a {@code WritableRaster} that is the tile, indicated by 1609 * the specified indices, to be checked out for writing. 1610 */ 1611 public WritableRaster getWritableTile (int tileX, int tileY) { 1612 return raster; 1613 } 1614 1615 /** 1616 * Relinquishes permission to write to a tile. If the caller 1617 * continues to write to the tile, the results are undefined. 1618 * Calls to this method should only appear in matching pairs 1619 * with calls to {@link #getWritableTile(int, int) getWritableTile(int, int)}. Any other leads 1620 * to undefined results. All registered {@code TileObservers} 1621 * are notified when a tile goes from having one writer to having no 1622 * writers. 1623 * @param tileX the x index of the tile 1624 * @param tileY the y index of the tile 1625 */ 1626 public void releaseWritableTile (int tileX, int tileY) { 1627 } 1628 1629 /** 1630 * Returns the transparency. Returns either OPAQUE, BITMASK, 1631 * or TRANSLUCENT. 1632 * @return the transparency of this {@code BufferedImage}. 1633 * @see Transparency#OPAQUE 1634 * @see Transparency#BITMASK 1635 * @see Transparency#TRANSLUCENT 1636 * @since 1.5 1637 */ 1638 public int getTransparency() { 1639 return colorModel.getTransparency(); 1640 } 1641 } |