Source Code Cross Referenced for BufferedImage.java in  » 6.0-JDK-Core » AWT » java » awt » image » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » AWT » java.awt.image 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package java.awt.image;
0027
0028        import java.awt.Transparency;
0029        import java.awt.color.ColorSpace;
0030        import java.awt.Graphics2D;
0031        import java.awt.GraphicsConfiguration;
0032        import java.awt.GraphicsEnvironment;
0033        import java.awt.ImageCapabilities;
0034        import java.awt.geom.Rectangle2D;
0035        import java.awt.geom.Point2D;
0036        import java.awt.Point;
0037        import java.awt.Rectangle;
0038        import java.util.Hashtable;
0039        import java.util.Vector;
0040
0041        import sun.awt.image.BytePackedRaster;
0042        import sun.awt.image.ShortComponentRaster;
0043        import sun.awt.image.ByteComponentRaster;
0044        import sun.awt.image.IntegerComponentRaster;
0045        import sun.awt.image.OffScreenImageSource;
0046
0047        /**
0048         *
0049         * The <code>BufferedImage</code> subclass describes an {@link
0050         * java.awt.Image Image} with an accessible buffer of image data.
0051         * A <code>BufferedImage</code> is comprised of a {@link ColorModel} and a
0052         * {@link Raster} of image data.
0053         * The number and types of bands in the {@link SampleModel} of the
0054         * <code>Raster</code> must match the number and types required by the
0055         * <code>ColorModel</code> to represent its color and alpha components.
0056         * All <code>BufferedImage</code> objects have an upper left corner
0057         * coordinate of (0,&nbsp;0).  Any <code>Raster</code> used to construct a
0058         * <code>BufferedImage</code> must therefore have minX=0 and minY=0. 
0059         *
0060         * <p>
0061         * This class relies on the data fetching and setting methods
0062         * of <code>Raster</code>,
0063         * and on the color characterization methods of <code>ColorModel</code>.
0064         *
0065         * @see ColorModel
0066         * @see Raster
0067         * @see WritableRaster
0068         * @version 10 Feb 1997
0069         */
0070
0071        public class BufferedImage extends java.awt.Image implements 
0072                WritableRenderedImage, Transparency {
0073            int imageType = TYPE_CUSTOM;
0074            ColorModel colorModel;
0075            WritableRaster raster;
0076            OffScreenImageSource osis;
0077            Hashtable properties;
0078
0079            boolean isAlphaPremultiplied;// If true, alpha has been premultiplied in
0080            // color channels
0081
0082            /**
0083             * Image Type Constants
0084             */
0085
0086            /**
0087             * Image type is not recognized so it must be a customized
0088             * image.  This type is only used as a return value for the getType()
0089             * method.
0090             */
0091            public static final int TYPE_CUSTOM = 0;
0092
0093            /**
0094             * Represents an image with 8-bit RGB color components packed into
0095             * integer pixels.  The image has a {@link DirectColorModel} without
0096             * alpha.
0097             * When data with non-opaque alpha is stored
0098             * in an image of this type,
0099             * the color data must be adjusted to a non-premultiplied form
0100             * and the alpha discarded,
0101             * as described in the
0102             * {@link java.awt.AlphaComposite} documentation.
0103             */
0104            public static final int TYPE_INT_RGB = 1;
0105
0106            /**
0107             * Represents an image with 8-bit RGBA color components packed into
0108             * integer pixels.  The image has a <code>DirectColorModel</code> 
0109             * with alpha. The color data in this image is considered not to be
0110             * premultiplied with alpha.  When this type is used as the 
0111             * <code>imageType</code> argument to a <code>BufferedImage</code>
0112             * constructor, the created image is consistent with images
0113             * created in the JDK1.1 and earlier releases.
0114             */
0115            public static final int TYPE_INT_ARGB = 2;
0116
0117            /**
0118             * Represents an image with 8-bit RGBA color components packed into
0119             * integer pixels.  The image has a <code>DirectColorModel</code> 
0120             * with alpha.  The color data in this image is considered to be
0121             * premultiplied with alpha.
0122             */
0123            public static final int TYPE_INT_ARGB_PRE = 3;
0124
0125            /**
0126             * Represents an image with 8-bit RGB color components, corresponding 
0127             * to a Windows- or Solaris- style BGR color model, with the colors
0128             * Blue, Green, and Red packed into integer pixels.  There is no alpha.
0129             * The image has a {@link DirectColorModel}.
0130             * When data with non-opaque alpha is stored
0131             * in an image of this type,
0132             * the color data must be adjusted to a non-premultiplied form
0133             * and the alpha discarded,
0134             * as described in the
0135             * {@link java.awt.AlphaComposite} documentation.
0136             */
0137            public static final int TYPE_INT_BGR = 4;
0138
0139            /**
0140             * Represents an image with 8-bit RGB color components, corresponding 
0141             * to a Windows-style BGR color model) with the colors Blue, Green,
0142             * and Red stored in 3 bytes.  There is no alpha.  The image has a
0143             * <code>ComponentColorModel</code>.
0144             * When data with non-opaque alpha is stored
0145             * in an image of this type,
0146             * the color data must be adjusted to a non-premultiplied form
0147             * and the alpha discarded,
0148             * as described in the
0149             * {@link java.awt.AlphaComposite} documentation.
0150             */
0151            public static final int TYPE_3BYTE_BGR = 5;
0152
0153            /**
0154             * Represents an image with 8-bit RGBA color components with the colors
0155             * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha.  The
0156             * image has a <code>ComponentColorModel</code> with alpha.  The
0157             * color data in this image is considered not to be premultiplied with
0158             * alpha.  The byte data is interleaved in a single 
0159             * byte array in the order A, B, G, R
0160             * from lower to higher byte addresses within each pixel.
0161             */
0162            public static final int TYPE_4BYTE_ABGR = 6;
0163
0164            /**
0165             * Represents an image with 8-bit RGBA color components with the colors
0166             * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha.  The
0167             * image has a <code>ComponentColorModel</code> with alpha. The color
0168             * data in this image is considered to be premultiplied with alpha.
0169             * The byte data is interleaved in a single byte array in the order
0170             * A, B, G, R from lower to higher byte addresses within each pixel.
0171             */
0172            public static final int TYPE_4BYTE_ABGR_PRE = 7;
0173
0174            /**
0175             * Represents an image with 5-6-5 RGB color components (5-bits red,
0176             * 6-bits green, 5-bits blue) with no alpha.  This image has
0177             * a <code>DirectColorModel</code>.
0178             * When data with non-opaque alpha is stored
0179             * in an image of this type,
0180             * the color data must be adjusted to a non-premultiplied form
0181             * and the alpha discarded,
0182             * as described in the
0183             * {@link java.awt.AlphaComposite} documentation.
0184             */
0185            public static final int TYPE_USHORT_565_RGB = 8;
0186
0187            /**
0188             * Represents an image with 5-5-5 RGB color components (5-bits red,
0189             * 5-bits green, 5-bits blue) with no alpha.  This image has
0190             * a <code>DirectColorModel</code>.
0191             * When data with non-opaque alpha is stored
0192             * in an image of this type,
0193             * the color data must be adjusted to a non-premultiplied form
0194             * and the alpha discarded,
0195             * as described in the
0196             * {@link java.awt.AlphaComposite} documentation.
0197             */
0198            public static final int TYPE_USHORT_555_RGB = 9;
0199
0200            /**
0201             * Represents a unsigned byte grayscale image, non-indexed.  This
0202             * image has a <code>ComponentColorModel</code> with a CS_GRAY
0203             * {@link ColorSpace}.
0204             * When data with non-opaque alpha is stored
0205             * in an image of this type,
0206             * the color data must be adjusted to a non-premultiplied form
0207             * and the alpha discarded,
0208             * as described in the
0209             * {@link java.awt.AlphaComposite} documentation.
0210             */
0211            public static final int TYPE_BYTE_GRAY = 10;
0212
0213            /**
0214             * Represents an unsigned short grayscale image, non-indexed).  This
0215             * image has a <code>ComponentColorModel</code> with a CS_GRAY
0216             * <code>ColorSpace</code>.
0217             * When data with non-opaque alpha is stored
0218             * in an image of this type,
0219             * the color data must be adjusted to a non-premultiplied form
0220             * and the alpha discarded,
0221             * as described in the
0222             * {@link java.awt.AlphaComposite} documentation.
0223             */
0224            public static final int TYPE_USHORT_GRAY = 11;
0225
0226            /**
0227             * Represents an opaque byte-packed 1, 2, or 4 bit image.  The
0228             * image has an {@link IndexColorModel} without alpha.  When this
0229             * type is used as the <code>imageType</code> argument to the
0230             * <code>BufferedImage</code> constructor that takes an
0231             * <code>imageType</code> argument but no <code>ColorModel</code>
0232             * argument, a 1-bit image is created with an
0233             * <code>IndexColorModel</code> with two colors in the default
0234             * sRGB <code>ColorSpace</code>: {0,&nbsp;0,&nbsp;0} and
0235             * {255,&nbsp;255,&nbsp;255}.
0236             *
0237             * <p> Images with 2 or 4 bits per pixel may be constructed via
0238             * the <code>BufferedImage</code> constructor that takes a
0239             * <code>ColorModel</code> argument by supplying a
0240             * <code>ColorModel</code> with an appropriate map size.
0241             *
0242             * <p> Images with 8 bits per pixel should use the image types
0243             * <code>TYPE_BYTE_INDEXED</code> or <code>TYPE_BYTE_GRAY</code>
0244             * depending on their <code>ColorModel</code>.
0245
0246             * <p> When color data is stored in an image of this type,
0247             * the closest color in the colormap is determined 
0248             * by the <code>IndexColorModel</code> and the resulting index is stored.
0249             * Approximation and loss of alpha or color components
0250             * can result, depending on the colors in the 
0251             * <code>IndexColorModel</code> colormap.
0252             */
0253            public static final int TYPE_BYTE_BINARY = 12;
0254
0255            /**
0256             * Represents an indexed byte image.  When this type is used as the
0257             * <code>imageType</code> argument to the <code>BufferedImage</code>
0258             * constructor that takes an <code>imageType</code> argument
0259             * but no <code>ColorModel</code> argument, an 
0260             * <code>IndexColorModel</code> is created with
0261             * a 256-color 6/6/6 color cube palette with the rest of the colors
0262             * from 216-255 populated by grayscale values in the
0263             * default sRGB ColorSpace.
0264             *
0265             * <p> When color data is stored in an image of this type,
0266             * the closest color in the colormap is determined 
0267             * by the <code>IndexColorModel</code> and the resulting index is stored.
0268             * Approximation and loss of alpha or color components
0269             * can result, depending on the colors in the 
0270             * <code>IndexColorModel</code> colormap.
0271             */
0272            public static final int TYPE_BYTE_INDEXED = 13;
0273
0274            private static final int DCM_RED_MASK = 0x00ff0000;
0275            private static final int DCM_GREEN_MASK = 0x0000ff00;
0276            private static final int DCM_BLUE_MASK = 0x000000ff;
0277            private static final int DCM_ALPHA_MASK = 0xff000000;
0278            private static final int DCM_565_RED_MASK = 0xf800;
0279            private static final int DCM_565_GRN_MASK = 0x07E0;
0280            private static final int DCM_565_BLU_MASK = 0x001F;
0281            private static final int DCM_555_RED_MASK = 0x7C00;
0282            private static final int DCM_555_GRN_MASK = 0x03E0;
0283            private static final int DCM_555_BLU_MASK = 0x001F;
0284            private static final int DCM_BGR_RED_MASK = 0x0000ff;
0285            private static final int DCM_BGR_GRN_MASK = 0x00ff00;
0286            private static final int DCM_BGR_BLU_MASK = 0xff0000;
0287
0288            static private native void initIDs();
0289
0290            static {
0291                ColorModel.loadLibraries();
0292                initIDs();
0293            }
0294
0295            /**
0296             * Constructs a <code>BufferedImage</code> of one of the predefined
0297             * image types.  The <code>ColorSpace</code> for the image is the
0298             * default sRGB space.
0299             * @param width     width of the created image
0300             * @param height    height of the created image
0301             * @param imageType type of the created image
0302             * @see ColorSpace
0303             * @see #TYPE_INT_RGB
0304             * @see #TYPE_INT_ARGB
0305             * @see #TYPE_INT_ARGB_PRE
0306             * @see #TYPE_INT_BGR
0307             * @see #TYPE_3BYTE_BGR
0308             * @see #TYPE_4BYTE_ABGR
0309             * @see #TYPE_4BYTE_ABGR_PRE
0310             * @see #TYPE_BYTE_GRAY
0311             * @see #TYPE_USHORT_GRAY
0312             * @see #TYPE_BYTE_BINARY
0313             * @see #TYPE_BYTE_INDEXED
0314             * @see #TYPE_USHORT_565_RGB
0315             * @see #TYPE_USHORT_555_RGB
0316             */
0317            public BufferedImage(int width, int height, int imageType) {
0318                switch (imageType) {
0319                case TYPE_INT_RGB: {
0320                    colorModel = new DirectColorModel(24, 0x00ff0000, // Red
0321                            0x0000ff00, // Green
0322                            0x000000ff, // Blue
0323                            0x0 // Alpha
0324                    );
0325                    raster = colorModel.createCompatibleWritableRaster(width,
0326                            height);
0327                }
0328                    break;
0329
0330                case TYPE_INT_ARGB: {
0331                    colorModel = ColorModel.getRGBdefault();
0332
0333                    raster = colorModel.createCompatibleWritableRaster(width,
0334                            height);
0335                }
0336                    break;
0337
0338                case TYPE_INT_ARGB_PRE: {
0339                    colorModel = new DirectColorModel(ColorSpace
0340                            .getInstance(ColorSpace.CS_sRGB), 32, 0x00ff0000,// Red
0341                            0x0000ff00,// Green
0342                            0x000000ff,// Blue
0343                            0xff000000,// Alpha
0344                            true, // Alpha Premultiplied
0345                            DataBuffer.TYPE_INT);
0346
0347                    raster = colorModel.createCompatibleWritableRaster(width,
0348                            height);
0349                }
0350                    break;
0351
0352                case TYPE_INT_BGR: {
0353                    colorModel = new DirectColorModel(24, 0x000000ff, // Red
0354                            0x0000ff00, // Green
0355                            0x00ff0000 // Blue
0356                    );
0357                    raster = colorModel.createCompatibleWritableRaster(width,
0358                            height);
0359                }
0360                    break;
0361
0362                case TYPE_3BYTE_BGR: {
0363                    ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
0364                    int[] nBits = { 8, 8, 8 };
0365                    int[] bOffs = { 2, 1, 0 };
0366                    colorModel = new ComponentColorModel(cs, nBits, false,
0367                            false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
0368                    raster = Raster.createInterleavedRaster(
0369                            DataBuffer.TYPE_BYTE, width, height, width * 3, 3,
0370                            bOffs, null);
0371                }
0372                    break;
0373
0374                case TYPE_4BYTE_ABGR: {
0375                    ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
0376                    int[] nBits = { 8, 8, 8, 8 };
0377                    int[] bOffs = { 3, 2, 1, 0 };
0378                    colorModel = new ComponentColorModel(cs, nBits, true,
0379                            false, Transparency.TRANSLUCENT,
0380                            DataBuffer.TYPE_BYTE);
0381                    raster = Raster.createInterleavedRaster(
0382                            DataBuffer.TYPE_BYTE, width, height, width * 4, 4,
0383                            bOffs, null);
0384                }
0385                    break;
0386
0387                case TYPE_4BYTE_ABGR_PRE: {
0388                    ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
0389                    int[] nBits = { 8, 8, 8, 8 };
0390                    int[] bOffs = { 3, 2, 1, 0 };
0391                    colorModel = new ComponentColorModel(cs, nBits, true, true,
0392                            Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
0393                    raster = Raster.createInterleavedRaster(
0394                            DataBuffer.TYPE_BYTE, width, height, width * 4, 4,
0395                            bOffs, null);
0396                }
0397                    break;
0398
0399                case TYPE_BYTE_GRAY: {
0400                    ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
0401                    int[] nBits = { 8 };
0402                    colorModel = new ComponentColorModel(cs, nBits, false,
0403                            true, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
0404                    raster = colorModel.createCompatibleWritableRaster(width,
0405                            height);
0406                }
0407                    break;
0408
0409                case TYPE_USHORT_GRAY: {
0410                    ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
0411                    int[] nBits = { 16 };
0412                    colorModel = new ComponentColorModel(cs, nBits, false,
0413                            true, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
0414                    raster = colorModel.createCompatibleWritableRaster(width,
0415                            height);
0416                }
0417                    break;
0418
0419                case TYPE_BYTE_BINARY: {
0420                    byte[] arr = { (byte) 0, (byte) 0xff };
0421
0422                    colorModel = new IndexColorModel(1, 2, arr, arr, arr);
0423                    raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
0424                            width, height, 1, 1, null);
0425                }
0426                    break;
0427
0428                case TYPE_BYTE_INDEXED: {
0429                    // Create a 6x6x6 color cube
0430                    int[] cmap = new int[256];
0431                    int i = 0;
0432                    for (int r = 0; r < 256; r += 51) {
0433                        for (int g = 0; g < 256; g += 51) {
0434                            for (int b = 0; b < 256; b += 51) {
0435                                cmap[i++] = (r << 16) | (g << 8) | b;
0436                            }
0437                        }
0438                    }
0439                    // And populate the rest of the cmap with gray values
0440                    int grayIncr = 256 / (256 - i);
0441
0442                    // The gray ramp will be between 18 and 252
0443                    int gray = grayIncr * 3;
0444                    for (; i < 256; i++) {
0445                        cmap[i] = (gray << 16) | (gray << 8) | gray;
0446                        gray += grayIncr;
0447                    }
0448
0449                    colorModel = new IndexColorModel(8, 256, cmap, 0, false,
0450                            -1, DataBuffer.TYPE_BYTE);
0451                    raster = Raster.createInterleavedRaster(
0452                            DataBuffer.TYPE_BYTE, width, height, 1, null);
0453                }
0454                    break;
0455
0456                case TYPE_USHORT_565_RGB: {
0457                    colorModel = new DirectColorModel(16, DCM_565_RED_MASK,
0458                            DCM_565_GRN_MASK, DCM_565_BLU_MASK);
0459                    raster = colorModel.createCompatibleWritableRaster(width,
0460                            height);
0461                }
0462                    break;
0463
0464                case TYPE_USHORT_555_RGB: {
0465                    colorModel = new DirectColorModel(15, DCM_555_RED_MASK,
0466                            DCM_555_GRN_MASK, DCM_555_BLU_MASK);
0467                    raster = colorModel.createCompatibleWritableRaster(width,
0468                            height);
0469                }
0470                    break;
0471
0472                default:
0473                    throw new IllegalArgumentException("Unknown image type "
0474                            + imageType);
0475                }
0476
0477                this .imageType = imageType;
0478            }
0479
0480            /**
0481             * Constructs a <code>BufferedImage</code> of one of the predefined
0482             * image types:
0483             * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED.
0484             *
0485             * <p> If the image type is TYPE_BYTE_BINARY, the number of
0486             * entries in the color model is used to determine whether the
0487             * image should have 1, 2, or 4 bits per pixel.  If the color model
0488             * has 1 or 2 entries, the image will have 1 bit per pixel.  If it
0489             * has 3 or 4 entries, the image with have 2 bits per pixel.  If
0490             * it has between 5 and 16 entries, the image will have 4 bits per
0491             * pixel.  Otherwise, an IllegalArgumentException will be thrown.
0492             *
0493             * @param width     width of the created image
0494             * @param height    height of the created image
0495             * @param imageType type of the created image
0496             * @param cm        <code>IndexColorModel</code> of the created image
0497             * @throws IllegalArgumentException   if the imageType is not
0498             * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED or if the imageType is
0499             * TYPE_BYTE_BINARY and the color map has more than 16 entries.
0500             * @see #TYPE_BYTE_BINARY
0501             * @see #TYPE_BYTE_INDEXED
0502             */
0503            public BufferedImage(int width, int height, int imageType,
0504                    IndexColorModel cm) {
0505                if (cm.hasAlpha() && cm.isAlphaPremultiplied()) {
0506                    throw new IllegalArgumentException(
0507                            "This image types do not have "
0508                                    + "premultiplied alpha.");
0509                }
0510
0511                switch (imageType) {
0512                case TYPE_BYTE_BINARY:
0513                    int bits; // Will be set below
0514                    int mapSize = cm.getMapSize();
0515                    if (mapSize <= 2) {
0516                        bits = 1;
0517                    } else if (mapSize <= 4) {
0518                        bits = 2;
0519                    } else if (mapSize <= 16) {
0520                        bits = 4;
0521                    } else {
0522                        throw new IllegalArgumentException(
0523                                "Color map for TYPE_BYTE_BINARY "
0524                                        + "must have no more than 16 entries");
0525                    }
0526                    raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
0527                            width, height, 1, bits, null);
0528                    break;
0529
0530                case TYPE_BYTE_INDEXED:
0531                    raster = Raster.createInterleavedRaster(
0532                            DataBuffer.TYPE_BYTE, width, height, 1, null);
0533                    break;
0534                default:
0535                    throw new IllegalArgumentException("Invalid image type ("
0536                            + imageType + ").  Image type must"
0537                            + " be either TYPE_BYTE_BINARY or "
0538                            + " TYPE_BYTE_INDEXED");
0539                }
0540
0541                if (!cm.isCompatibleRaster(raster)) {
0542                    throw new IllegalArgumentException(
0543                            "Incompatible image type and IndexColorModel");
0544                }
0545
0546                colorModel = cm;
0547                this .imageType = imageType;
0548            }
0549
0550            /**
0551             * Constructs a new <code>BufferedImage</code> with a specified 
0552             * <code>ColorModel</code> and <code>Raster</code>.  If the number and
0553             * types of bands in the <code>SampleModel</code> of the 
0554             * <code>Raster</code> do not match the number and types required by
0555             * the <code>ColorModel</code> to represent its color and alpha
0556             * components, a {@link RasterFormatException} is thrown.  This
0557             * method can multiply or divide the color <code>Raster</code> data by
0558             * alpha to match the <code>alphaPremultiplied</code> state
0559             * in the <code>ColorModel</code>.  Properties for this 
0560             * <code>BufferedImage</code> can be established by passing
0561             * in a {@link Hashtable} of <code>String</code>/<code>Object</code> 
0562             * pairs.
0563             * @param cm <code>ColorModel</code> for the new image
0564             * @param raster     <code>Raster</code> for the image data
0565             * @param isRasterPremultiplied   if <code>true</code>, the data in
0566             *                  the raster has been premultiplied with alpha.
0567             * @param properties <code>Hashtable</code> of
0568             *                  <code>String</code>/<code>Object</code> pairs. 
0569             * @exception <code>RasterFormatException</code> if the number and
0570             * types of bands in the <code>SampleModel</code> of the
0571             * <code>Raster</code> do not match the number and types required by
0572             * the <code>ColorModel</code> to represent its color and alpha
0573             * components.
0574             * @exception <code>IllegalArgumentException</code> if 
0575             *		<code>raster</code> is incompatible with <code>cm</code>
0576             * @see ColorModel
0577             * @see Raster
0578             * @see WritableRaster
0579             */
0580
0581            /*
0582             *
0583             *  FOR NOW THE CODE WHICH DEFINES THE RASTER TYPE IS DUPLICATED BY DVF
0584             *  SEE THE METHOD DEFINERASTERTYPE @ RASTEROUTPUTMANAGER
0585             *
0586             */
0587            public BufferedImage(ColorModel cm, WritableRaster raster,
0588                    boolean isRasterPremultiplied, Hashtable<?, ?> properties) {
0589
0590                if (!cm.isCompatibleRaster(raster)) {
0591                    throw new IllegalArgumentException("Raster " + raster
0592                            + " is incompatible with ColorModel " + cm);
0593                }
0594
0595                if ((raster.minX != 0) || (raster.minY != 0)) {
0596                    throw new IllegalArgumentException("Raster " + raster
0597                            + " has minX or minY not equal to zero: "
0598                            + raster.minX + " " + raster.minY);
0599                }
0600
0601                colorModel = cm;
0602                this .raster = raster;
0603                this .properties = properties;
0604                int numBands = raster.getNumBands();
0605                boolean isAlphaPre = cm.isAlphaPremultiplied();
0606                ColorSpace cs;
0607
0608                // Force the raster data alpha state to match the premultiplied 
0609                // state in the color model
0610                coerceData(isRasterPremultiplied);
0611
0612                SampleModel sm = raster.getSampleModel();
0613                cs = cm.getColorSpace();
0614                int csType = cs.getType();
0615                if (csType != ColorSpace.TYPE_RGB) {
0616                    if (csType == ColorSpace.TYPE_GRAY
0617                            && cm instanceof  ComponentColorModel) {
0618                        // Check if this might be a child raster (fix for bug 4240596)
0619                        if (sm instanceof  ComponentSampleModel
0620                                && ((ComponentSampleModel) sm).getPixelStride() != numBands) {
0621                            imageType = TYPE_CUSTOM;
0622                        } else if (raster instanceof  ByteComponentRaster
0623                                && raster.getNumBands() == 1
0624                                && cm.getComponentSize(0) == 8
0625                                && ((ByteComponentRaster) raster)
0626                                        .getPixelStride() == 1) {
0627                            imageType = TYPE_BYTE_GRAY;
0628                        } else if (raster instanceof  ShortComponentRaster
0629                                && raster.getNumBands() == 1
0630                                && cm.getComponentSize(0) == 16
0631                                && ((ShortComponentRaster) raster)
0632                                        .getPixelStride() == 1) {
0633                            imageType = TYPE_USHORT_GRAY;
0634                        }
0635                    } else {
0636                        imageType = TYPE_CUSTOM;
0637                    }
0638                    return;
0639                }
0640
0641                if ((raster instanceof  IntegerComponentRaster)
0642                        && (numBands == 3 || numBands == 4)) {
0643                    IntegerComponentRaster iraster = (IntegerComponentRaster) raster;
0644                    // Check if the raster params and the color model
0645                    // are correct
0646                    int pixSize = cm.getPixelSize();
0647                    if (iraster.getPixelStride() == 1
0648                            && cm instanceof  DirectColorModel
0649                            && (pixSize == 32 || pixSize == 24)) {
0650                        // Now check on the DirectColorModel params
0651                        DirectColorModel dcm = (DirectColorModel) cm;
0652                        int rmask = dcm.getRedMask();
0653                        int gmask = dcm.getGreenMask();
0654                        int bmask = dcm.getBlueMask();
0655                        if (rmask == DCM_RED_MASK && gmask == DCM_GREEN_MASK
0656                                && bmask == DCM_BLUE_MASK) {
0657                            if (dcm.getAlphaMask() == DCM_ALPHA_MASK) {
0658                                imageType = (isAlphaPre ? TYPE_INT_ARGB_PRE
0659                                        : TYPE_INT_ARGB);
0660                            } else {
0661                                // No Alpha
0662                                if (!dcm.hasAlpha()) {
0663                                    imageType = TYPE_INT_RGB;
0664                                }
0665                            }
0666                        } // if (dcm.getRedMask() == DCM_RED_MASK &&
0667                        else if (rmask == DCM_BGR_RED_MASK
0668                                && gmask == DCM_BGR_GRN_MASK
0669                                && bmask == DCM_BGR_BLU_MASK) {
0670                            if (!dcm.hasAlpha()) {
0671                                imageType = TYPE_INT_BGR;
0672                            }
0673                        } // if (rmask == DCM_BGR_RED_MASK &&
0674                    } // if (iraster.getPixelStride() == 1 
0675                } // ((raster instanceof IntegerComponentRaster) &&
0676                else if ((cm instanceof  IndexColorModel) && (numBands == 1)
0677                        && (!cm.hasAlpha() || !isAlphaPre)) {
0678                    IndexColorModel icm = (IndexColorModel) cm;
0679                    int pixSize = icm.getPixelSize();
0680
0681                    if (raster instanceof  BytePackedRaster) {
0682                        imageType = TYPE_BYTE_BINARY;
0683                    } // if (raster instanceof BytePackedRaster)
0684                    else if (raster instanceof  ByteComponentRaster) {
0685                        ByteComponentRaster braster = (ByteComponentRaster) raster;
0686                        if (braster.getPixelStride() == 1 && pixSize <= 8) {
0687                            imageType = TYPE_BYTE_INDEXED;
0688                        }
0689                    }
0690                } // else if (cm instanceof IndexColorModel) && (numBands == 1))
0691                else if ((raster instanceof  ShortComponentRaster)
0692                        && (cm instanceof  DirectColorModel) && (numBands == 3)
0693                        && !cm.hasAlpha()) {
0694                    DirectColorModel dcm = (DirectColorModel) cm;
0695                    if (dcm.getRedMask() == DCM_565_RED_MASK) {
0696                        if (dcm.getGreenMask() == DCM_565_GRN_MASK
0697                                && dcm.getBlueMask() == DCM_565_BLU_MASK) {
0698                            imageType = TYPE_USHORT_565_RGB;
0699                        }
0700                    } else if (dcm.getRedMask() == DCM_555_RED_MASK) {
0701                        if (dcm.getGreenMask() == DCM_555_GRN_MASK
0702                                && dcm.getBlueMask() == DCM_555_BLU_MASK) {
0703                            imageType = TYPE_USHORT_555_RGB;
0704                        }
0705                    }
0706                } // else if ((cm instanceof IndexColorModel) && (numBands == 1))
0707                else if ((raster instanceof  ByteComponentRaster)
0708                        && (cm instanceof  ComponentColorModel)
0709                        && (raster.getSampleModel() instanceof  PixelInterleavedSampleModel)
0710                        && (numBands == 3 || numBands == 4)) {
0711                    ComponentColorModel ccm = (ComponentColorModel) cm;
0712                    PixelInterleavedSampleModel csm = (PixelInterleavedSampleModel) raster
0713                            .getSampleModel();
0714                    ByteComponentRaster braster = (ByteComponentRaster) raster;
0715                    int[] offs = csm.getBandOffsets();
0716                    if (ccm.getNumComponents() != numBands) {
0717                        throw new RasterFormatException(
0718                                "Number of components in " + "ColorModel ("
0719                                        + ccm.getNumComponents()
0720                                        + ") does not match # in "
0721                                        + " Raster (" + numBands + ")");
0722                    }
0723                    int[] nBits = ccm.getComponentSize();
0724                    boolean is8bit = true;
0725                    for (int i = 0; i < numBands; i++) {
0726                        if (nBits[i] != 8) {
0727                            is8bit = false;
0728                            break;
0729                        }
0730                    }
0731                    if (is8bit && offs[0] == numBands - 1
0732                            && offs[1] == numBands - 2
0733                            && offs[2] == numBands - 3) {
0734                        if (numBands == 3) {
0735                            imageType = TYPE_3BYTE_BGR;
0736                        } else if (offs[3] == 0) {
0737                            imageType = (isAlphaPre ? TYPE_4BYTE_ABGR_PRE
0738                                    : TYPE_4BYTE_ABGR);
0739                        }
0740                    }
0741                } // else if ((raster instanceof ByteComponentRaster) &&
0742            }
0743
0744            /**
0745             * Returns the image type.  If it is not one of the known types,
0746             * TYPE_CUSTOM is returned.
0747             * @return the image type of this <code>BufferedImage</code>.
0748             * @see #TYPE_INT_RGB
0749             * @see #TYPE_INT_ARGB
0750             * @see #TYPE_INT_ARGB_PRE
0751             * @see #TYPE_INT_BGR
0752             * @see #TYPE_3BYTE_BGR
0753             * @see #TYPE_4BYTE_ABGR
0754             * @see #TYPE_4BYTE_ABGR_PRE
0755             * @see #TYPE_BYTE_GRAY
0756             * @see #TYPE_BYTE_BINARY
0757             * @see #TYPE_BYTE_INDEXED
0758             * @see #TYPE_USHORT_GRAY
0759             * @see #TYPE_USHORT_565_RGB
0760             * @see #TYPE_USHORT_555_RGB
0761             * @see #TYPE_CUSTOM
0762             */
0763            public int getType() {
0764                return imageType;
0765            }
0766
0767            /**
0768             * Returns the <code>ColorModel</code>.
0769             * @return the <code>ColorModel</code> of this
0770             *  <code>BufferedImage</code>.
0771             */
0772            public ColorModel getColorModel() {
0773                return colorModel;
0774            }
0775
0776            /**
0777             * Returns the {@link WritableRaster}.
0778             * @return the <code>WriteableRaster</code> of this
0779             *  <code>BufferedImage</code>.
0780             */
0781            public WritableRaster getRaster() {
0782                return raster;
0783            }
0784
0785            /**
0786             * Returns a <code>WritableRaster</code> representing the alpha
0787             * channel for <code>BufferedImage</code> objects
0788             * with <code>ColorModel</code> objects that support a separate
0789             * spatial alpha channel, such as <code>ComponentColorModel</code> and
0790             * <code>DirectColorModel</code>.  Returns <code>null</code> if there
0791             * is no alpha channel associated with the <code>ColorModel</code> in
0792             * this image.  This method assumes that for all 
0793             * <code>ColorModel</code> objects other than 
0794             * <code>IndexColorModel</code>, if the <code>ColorModel</code> 
0795             * supports alpha, there is a separate alpha channel
0796             * which is stored as the last band of image data.
0797             * If the image uses an <code>IndexColorModel</code> that
0798             * has alpha in the lookup table, this method returns
0799             * <code>null</code> since there is no spatially discrete alpha
0800             * channel.  This method creates a new
0801             * <code>WritableRaster</code>, but shares the data array.
0802             * @return a <code>WritableRaster</code> or <code>null</code> if this
0803             *          <code>BufferedImage</code> has no alpha channel associated
0804             *          with its <code>ColorModel</code>.
0805             */
0806            public WritableRaster getAlphaRaster() {
0807                return colorModel.getAlphaRaster(raster);
0808            }
0809
0810            /**
0811             * Returns an integer pixel in the default RGB color model
0812             * (TYPE_INT_ARGB) and default sRGB colorspace.  Color
0813             * conversion takes place if this default model does not match
0814             * the image <code>ColorModel</code>.  There are only 8-bits of
0815             * precision for each color component in the returned data when using
0816             * this method.
0817             *
0818             * <p>
0819             *
0820             * An <code>ArrayOutOfBoundsException</code> may be thrown
0821             * if the coordinates are not in bounds.
0822             * However, explicit bounds checking is not guaranteed.
0823             *
0824             * @param x the X coordinate of the pixel from which to get
0825             *          the pixel in the default RGB color model and sRGB
0826             *          color space
0827             * @param y the Y coordinate of the pixel from which to get
0828             *          the pixel in the default RGB color model and sRGB
0829             *          color space
0830             * @return an integer pixel in the default RGB color model and
0831             *          default sRGB colorspace. 
0832             * @see #setRGB(int, int, int)
0833             * @see #setRGB(int, int, int, int, int[], int, int)
0834             */
0835            public int getRGB(int x, int y) {
0836                return colorModel.getRGB(raster.getDataElements(x, y, null));
0837            }
0838
0839            /**
0840             * Returns an array of integer pixels in the default RGB color model
0841             * (TYPE_INT_ARGB) and default sRGB color space,
0842             * from a portion of the image data.  Color conversion takes
0843             * place if the default model does not match the image 
0844             * <code>ColorModel</code>.  There are only 8-bits of precision for
0845             * each color component in the returned data when
0846             * using this method.  With a specified coordinate (x,&nbsp;y) in the
0847             * image, the ARGB pixel can be accessed in this way:
0848             * </p>
0849             *
0850             * <pre>
0851             *    pixel   = rgbArray[offset + (y-startY)*scansize + (x-startX)]; </pre>
0852             *
0853             * <p>
0854             *
0855             * An <code>ArrayOutOfBoundsException</code> may be thrown
0856             * if the region is not in bounds.
0857             * However, explicit bounds checking is not guaranteed.
0858             *
0859             * @param startX      the starting X coordinate
0860             * @param startY      the starting Y coordinate
0861             * @param w           width of region
0862             * @param h           height of region
0863             * @param rgbArray    if not <code>null</code>, the rgb pixels are 
0864             *          written here
0865             * @param offset      offset into the <code>rgbArray</code>
0866             * @param scansize    scanline stride for the <code>rgbArray</code>
0867             * @return            array of RGB pixels. 
0868             * @see #setRGB(int, int, int)
0869             * @see #setRGB(int, int, int, int, int[], int, int)
0870             */
0871            public int[] getRGB(int startX, int startY, int w, int h,
0872                    int[] rgbArray, int offset, int scansize) {
0873                int yoff = offset;
0874                int off;
0875                Object data;
0876                int nbands = raster.getNumBands();
0877                int dataType = raster.getDataBuffer().getDataType();
0878                switch (dataType) {
0879                case DataBuffer.TYPE_BYTE:
0880                    data = new byte[nbands];
0881                    break;
0882                case DataBuffer.TYPE_USHORT:
0883                    data = new short[nbands];
0884                    break;
0885                case DataBuffer.TYPE_INT:
0886                    data = new int[nbands];
0887                    break;
0888                case DataBuffer.TYPE_FLOAT:
0889                    data = new float[nbands];
0890                    break;
0891                case DataBuffer.TYPE_DOUBLE:
0892                    data = new double[nbands];
0893                    break;
0894                default:
0895                    throw new IllegalArgumentException(
0896                            "Unknown data buffer type: " + dataType);
0897                }
0898
0899                if (rgbArray == null) {
0900                    rgbArray = new int[offset + h * scansize];
0901                }
0902
0903                for (int y = startY; y < startY + h; y++, yoff += scansize) {
0904                    off = yoff;
0905                    for (int x = startX; x < startX + w; x++) {
0906                        rgbArray[off++] = colorModel.getRGB(raster
0907                                .getDataElements(x, y, data));
0908                    }
0909                }
0910
0911                return rgbArray;
0912            }
0913
0914            /**
0915             * Sets a pixel in this <code>BufferedImage</code> to the specified   
0916             * RGB value. The pixel is assumed to be in the default RGB color
0917             * model, TYPE_INT_ARGB, and default sRGB color space.  For images
0918             * with an <code>IndexColorModel</code>, the index with the nearest
0919             * color is chosen.
0920             *
0921             * <p>
0922             *
0923             * An <code>ArrayOutOfBoundsException</code> may be thrown
0924             * if the coordinates are not in bounds.
0925             * However, explicit bounds checking is not guaranteed.
0926             *
0927             * @param x the X coordinate of the pixel to set
0928             * @param y the Y coordinate of the pixel to set
0929             * @param rgb the RGB value 
0930             * @see #getRGB(int, int)
0931             * @see #getRGB(int, int, int, int, int[], int, int)
0932             */
0933            public synchronized void setRGB(int x, int y, int rgb) {
0934                raster.setDataElements(x, y, colorModel.getDataElements(rgb,
0935                        null));
0936            }
0937
0938            /**
0939             * Sets an array of integer pixels in the default RGB color model
0940             * (TYPE_INT_ARGB) and default sRGB color space,
0941             * into a portion of the image data.  Color conversion takes place
0942             * if the default model does not match the image 
0943             * <code>ColorModel</code>.  There are only 8-bits of precision for
0944             * each color component in the returned data when
0945             * using this method.  With a specified coordinate (x,&nbsp;y) in the   
0946             * this image, the ARGB pixel can be accessed in this way:
0947             * <pre>
0948             *    pixel   = rgbArray[offset + (y-startY)*scansize + (x-startX)];
0949             * </pre>
0950             * WARNING: No dithering takes place.
0951             *
0952             * <p>
0953             *
0954             * An <code>ArrayOutOfBoundsException</code> may be thrown
0955             * if the region is not in bounds.
0956             * However, explicit bounds checking is not guaranteed.
0957             *
0958             * @param startX      the starting X coordinate
0959             * @param startY      the starting Y coordinate
0960             * @param w           width of the region
0961             * @param h           height of the region
0962             * @param rgbArray    the rgb pixels
0963             * @param offset      offset into the <code>rgbArray</code>
0964             * @param scansize    scanline stride for the <code>rgbArray</code> 
0965             * @see #getRGB(int, int)
0966             * @see #getRGB(int, int, int, int, int[], int, int)
0967             */
0968            public void setRGB(int startX, int startY, int w, int h,
0969                    int[] rgbArray, int offset, int scansize) {
0970                int yoff = offset;
0971                int off;
0972                Object pixel = null;
0973
0974                for (int y = startY; y < startY + h; y++, yoff += scansize) {
0975                    off = yoff;
0976                    for (int x = startX; x < startX + w; x++) {
0977                        pixel = colorModel.getDataElements(rgbArray[off++],
0978                                pixel);
0979                        raster.setDataElements(x, y, pixel);
0980                    }
0981                }
0982            }
0983
0984            /**
0985             * Returns the width of the <code>BufferedImage</code>.
0986             * @return the width of this <code>BufferedImage</code>
0987             */
0988            public int getWidth() {
0989                return raster.getWidth();
0990            }
0991
0992            /**
0993             * Returns the height of the <code>BufferedImage</code>.
0994             * @return the height of this <code>BufferedImage</code>
0995             */
0996            public int getHeight() {
0997                return raster.getHeight();
0998            }
0999
1000            /**
1001             * Returns the width of the <code>BufferedImage</code>.  
1002             * @param observer ignored
1003             * @return the width of this <code>BufferedImage</code> 
1004             */
1005            public int getWidth(ImageObserver observer) {
1006                return raster.getWidth();
1007            }
1008
1009            /**
1010             * Returns the height of the <code>BufferedImage</code>.  
1011             * @param observer ignored
1012             * @return the height of this <code>BufferedImage</code> 
1013             */
1014            public int getHeight(ImageObserver observer) {
1015                return raster.getHeight();
1016            }
1017
1018            /**
1019             * Returns the object that produces the pixels for the image.  
1020             * @return the {@link ImageProducer} that is used to produce the
1021             * pixels for this image.
1022             * @see ImageProducer
1023             */
1024            public ImageProducer getSource() {
1025                if (osis == null) {
1026                    if (properties == null) {
1027                        properties = new Hashtable();
1028                    }
1029                    osis = new OffScreenImageSource(this , properties);
1030                }
1031                return osis;
1032            }
1033
1034            /**
1035             * Returns a property of the image by name.  Individual property names
1036             * are defined by the various image formats.  If a property is not
1037             * defined for a particular image, this method returns the
1038             * <code>UndefinedProperty</code> field.  If the properties
1039             * for this image are not yet known, then this method returns
1040             * <code>null</code> and the <code>ImageObserver</code> object is
1041             * notified later.  The property name "comment" should be used to
1042             * store an optional comment that can be presented to the user as a
1043             * description of the image, its source, or its author.
1044             * @param name the property name
1045             * @param observer the <code>ImageObserver</code> that receives
1046             *  notification regarding image information
1047             * @return an {@link Object} that is the property referred to by the
1048             *          specified <code>name</code> or <code>null</code> if the   
1049             *          properties of this image are not yet known. 
1050             * @throws <code>NullPointerException</code> if the property name is null.
1051             * @see ImageObserver
1052             * @see java.awt.Image#UndefinedProperty
1053             */
1054            public Object getProperty(String name, ImageObserver observer) {
1055                return getProperty(name);
1056            }
1057
1058            /**
1059             * Returns a property of the image by name.
1060             * @param name the property name
1061             * @return an <code>Object</code> that is the property referred to by
1062             *          the specified <code>name</code>. 
1063             * @throws <code>NullPointerException</code> if the property name is null.
1064             */
1065            public Object getProperty(String name) {
1066                if (name == null) {
1067                    throw new NullPointerException(
1068                            "null property name is not allowed");
1069                }
1070                if (properties == null) {
1071                    return java.awt.Image.UndefinedProperty;
1072                }
1073                Object o = properties.get(name);
1074                if (o == null) {
1075                    o = java.awt.Image.UndefinedProperty;
1076                }
1077                return o;
1078            }
1079
1080            /**
1081             * This method returns a {@link Graphics2D}, but is here
1082             * for backwards compatibility.  {@link #createGraphics() createGraphics} is more
1083             * convenient, since it is declared to return a 
1084             * <code>Graphics2D</code>.
1085             * @return a <code>Graphics2D</code>, which can be used to draw into
1086             *          this image.
1087             */
1088            public java.awt.Graphics getGraphics() {
1089                return createGraphics();
1090            }
1091
1092            /**
1093             * Creates a <code>Graphics2D</code>, which can be used to draw into
1094             * this <code>BufferedImage</code>.
1095             * @return a <code>Graphics2D</code>, used for drawing into this
1096             *          image. 
1097             */
1098            public Graphics2D createGraphics() {
1099                GraphicsEnvironment env = GraphicsEnvironment
1100                        .getLocalGraphicsEnvironment();
1101                return env.createGraphics(this );
1102            }
1103
1104            /**
1105             * Returns a subimage defined by a specified rectangular region.
1106             * The returned <code>BufferedImage</code> shares the same
1107             * data array as the original image.
1108             * @param x the X coordinate of the upper-left corner of the
1109             *          specified rectangular region
1110             * @param y the Y coordinate of the upper-left corner of the
1111             *          specified rectangular region
1112             * @param w the width of the specified rectangular region 
1113             * @param h the height of the specified rectangular region
1114             * @return a <code>BufferedImage</code> that is the subimage of this
1115             *          <code>BufferedImage</code>. 
1116             * @exception <code>RasterFormatException</code> if the specified
1117             * area is not contained within this <code>BufferedImage</code>.
1118             */
1119            public BufferedImage getSubimage(int x, int y, int w, int h) {
1120                return new BufferedImage(colorModel, raster
1121                        .createWritableChild(x, y, w, h, 0, 0, null),
1122                        colorModel.isAlphaPremultiplied(), properties);
1123            }
1124
1125            /**
1126             * Returns whether or not the alpha has been premultiplied.  It
1127             * returns <code>false</code> if there is no alpha.
1128             * @return <code>true</code> if the alpha has been premultiplied;   
1129             *          <code>false</code> otherwise. 
1130             */
1131            public boolean isAlphaPremultiplied() {
1132                return colorModel.isAlphaPremultiplied();
1133            }
1134
1135            /**
1136             * Forces the data to match the state specified in the
1137             * <code>isAlphaPremultiplied</code> variable.  It may multiply or
1138             * divide the color raster data by alpha, or do nothing if the data is
1139             * in the correct state.
1140             * @param isAlphaPremultiplied <code>true</code> if the alpha has been
1141             *          premultiplied; <code>false</code> otherwise. 
1142             */
1143            public void coerceData(boolean isAlphaPremultiplied) {
1144                if (colorModel.hasAlpha()
1145                        && colorModel.isAlphaPremultiplied() != isAlphaPremultiplied) {
1146                    // Make the color model do the conversion
1147                    colorModel = colorModel.coerceData(raster,
1148                            isAlphaPremultiplied);
1149                }
1150            }
1151
1152            /**
1153             * Returns a <code>String</code> representation of this
1154             * <code>BufferedImage</code> object and its values.   
1155             * @return a <code>String</code> representing this
1156             *          <code>BufferedImage</code>.
1157             */
1158            public String toString() {
1159                return new String("BufferedImage@"
1160                        + Integer.toHexString(hashCode()) + ": type = "
1161                        + imageType + " " + colorModel + " " + raster);
1162            }
1163
1164            /** 
1165             * Returns a {@link Vector} of {@link RenderedImage} objects that are
1166             * the immediate sources, not the sources of these immediate sources, 
1167             * of image data for this <code>BufferedImage</code>.  This
1168             * method returns <code>null</code> if the <code>BufferedImage</code> 
1169             * has no information about its immediate sources.  It returns an
1170             * empty <code>Vector</code> if the <code>BufferedImage</code> has no
1171             * immediate sources.
1172             * @return a <code>Vector</code> containing immediate sources of
1173             *          this <code>BufferedImage</code> object's image date, or
1174             *          <code>null</code> if this <code>BufferedImage</code> has
1175             *          no information about its immediate sources, or an empty
1176             *          <code>Vector</code> if this <code>BufferedImage</code>   
1177             *          has no immediate sources. 
1178             */
1179            public Vector<RenderedImage> getSources() {
1180                return null;
1181            }
1182
1183            /** 
1184             * Returns an array of names recognized by 
1185             * {@link #getProperty(String) getProperty(String)}
1186             * or <code>null</code>, if no property names are recognized.
1187             * @return a <code>String</code> array containing all of the property
1188             *          names that <code>getProperty(String)</code> recognizes;
1189             *		or <code>null</code> if no property names are recognized.
1190             */
1191            public String[] getPropertyNames() {
1192                return null;
1193            }
1194
1195            /** 
1196             * Returns the minimum x coordinate of this
1197             * <code>BufferedImage</code>.  This is always zero.
1198             * @return the minimum x coordinate of this
1199             *          <code>BufferedImage</code>.
1200             */
1201            public int getMinX() {
1202                return raster.getMinX();
1203            }
1204
1205            /** 
1206             * Returns the minimum y coordinate of this
1207             * <code>BufferedImage</code>.  This is always zero.
1208             * @return the minimum y coordinate of this
1209             *          <code>BufferedImage</code>.
1210             */
1211            public int getMinY() {
1212                return raster.getMinY();
1213            }
1214
1215            /** 
1216             * Returns the <code>SampleModel</code> associated with this
1217             * <code>BufferedImage</code>. 
1218             * @return the <code>SampleModel</code> of this
1219             *          <code>BufferedImage</code>.
1220             */
1221            public SampleModel getSampleModel() {
1222                return raster.getSampleModel();
1223            }
1224
1225            /**
1226             * Returns the number of tiles in the x direction.
1227             * This is always one.
1228             * @return the number of tiles in the x direction.
1229             */
1230            public int getNumXTiles() {
1231                return 1;
1232            }
1233
1234            /**
1235             * Returns the number of tiles in the y direction.
1236             * This is always one.
1237             * @return the number of tiles in the y direction.
1238             */
1239            public int getNumYTiles() {
1240                return 1;
1241            }
1242
1243            /**
1244             * Returns the minimum tile index in the x direction.
1245             * This is always zero.
1246             * @return the minimum tile index in the x direction.
1247             */
1248            public int getMinTileX() {
1249                return 0;
1250            }
1251
1252            /**
1253             * Returns the minimum tile index in the y direction.
1254             * This is always zero.
1255             * @return the mininum tile index in the y direction.
1256             */
1257            public int getMinTileY() {
1258                return 0;
1259            }
1260
1261            /**
1262             * Returns the tile width in pixels.
1263             * @return the tile width in pixels.
1264             */
1265            public int getTileWidth() {
1266                return raster.getWidth();
1267            }
1268
1269            /**
1270             * Returns the tile height in pixels.
1271             * @return the tile height in pixels.
1272             */
1273            public int getTileHeight() {
1274                return raster.getHeight();
1275            }
1276
1277            /**
1278             * Returns the x offset of the tile grid relative to the origin,
1279             * For example, the x coordinate of the location of tile 
1280             * (0,&nbsp;0).  This is always zero.
1281             * @return the x offset of the tile grid.
1282             */
1283            public int getTileGridXOffset() {
1284                return raster.getSampleModelTranslateX();
1285            }
1286
1287            /**
1288             * Returns the y offset of the tile grid relative to the origin,
1289             * For example, the y coordinate of the location of tile 
1290             * (0,&nbsp;0).  This is always zero.
1291             * @return the y offset of the tile grid.
1292             */
1293            public int getTileGridYOffset() {
1294                return raster.getSampleModelTranslateY();
1295            }
1296
1297            /** 
1298             * Returns tile (<code>tileX</code>,&nbsp;<code>tileY</code>).  Note
1299             * that <code>tileX</code> and <code>tileY</code> are indices
1300             * into the tile array, not pixel locations.  The <code>Raster</code> 
1301             * that is returned is live, which means that it is updated if the
1302             * image is changed.
1303             * @param tileX the x index of the requested tile in the tile array
1304             * @param tileY the y index of the requested tile in the tile array
1305             * @return a <code>Raster</code> that is the tile defined by the
1306             *          arguments <code>tileX</code> and <code>tileY</code>. 
1307             * @exception <code>ArrayIndexOutOfBoundsException</code> if both
1308             * 		<code>tileX</code> and <code>tileY</code> are not
1309             *		equal to 0
1310             */
1311            public Raster getTile(int tileX, int tileY) {
1312                if (tileX == 0 && tileY == 0) {
1313                    return raster;
1314                }
1315                throw new ArrayIndexOutOfBoundsException(
1316                        "BufferedImages only have" + " one tile with index 0,0");
1317            }
1318
1319            /** 
1320             * Returns the image as one large tile.  The <code>Raster</code> 
1321             * returned is a copy of the image data is not updated if the
1322             * image is changed.
1323             * @return a <code>Raster</code> that is a copy of the image data. 
1324             * @see #setData(Raster)
1325             */
1326            public Raster getData() {
1327
1328                // REMIND : this allocates a whole new tile if raster is a
1329                // subtile.  (It only copies in the requested area)
1330                // We should do something smarter.
1331                int width = raster.getWidth();
1332                int height = raster.getHeight();
1333                int startX = raster.getMinX();
1334                int startY = raster.getMinY();
1335                WritableRaster wr = Raster.createWritableRaster(raster
1336                        .getSampleModel(), new Point(raster
1337                        .getSampleModelTranslateX(), raster
1338                        .getSampleModelTranslateY()));
1339
1340                Object tdata = null;
1341
1342                for (int i = startY; i < startY + height; i++) {
1343                    tdata = raster.getDataElements(startX, i, width, 1, tdata);
1344                    wr.setDataElements(startX, i, width, 1, tdata);
1345                }
1346                return wr;
1347            }
1348
1349            /** 
1350             * Computes and returns an arbitrary region of the 
1351             * <code>BufferedImage</code>.  The <code>Raster</code> returned is a
1352             * copy of the image data and is not updated if the image is
1353             * changed.
1354             * @param rect the region of the <code>BufferedImage</code> to be
1355             * returned.
1356             * @return a <code>Raster</code> that is a copy of the image data of
1357             *          the specified region of the <code>BufferedImage</code> 
1358             * @see #setData(Raster)
1359             */
1360            public Raster getData(Rectangle rect) {
1361                SampleModel sm = raster.getSampleModel();
1362                SampleModel nsm = sm.createCompatibleSampleModel(rect.width,
1363                        rect.height);
1364                WritableRaster wr = Raster.createWritableRaster(nsm, rect
1365                        .getLocation());
1366                int width = rect.width;
1367                int height = rect.height;
1368                int startX = rect.x;
1369                int startY = rect.y;
1370
1371                Object tdata = null;
1372
1373                for (int i = startY; i < startY + height; i++) {
1374                    tdata = raster.getDataElements(startX, i, width, 1, tdata);
1375                    wr.setDataElements(startX, i, width, 1, tdata);
1376                }
1377                return wr;
1378            }
1379
1380            /** 
1381             * Computes an arbitrary rectangular region of the 
1382             * <code>BufferedImage</code> and copies it into a specified
1383             * <code>WritableRaster</code>.  The region to be computed is
1384             * determined from the bounds of the specified
1385             * <code>WritableRaster</code>.  The specified 
1386             * <code>WritableRaster</code> must have a
1387             * <code>SampleModel</code> that is compatible with this image.  If
1388             * <code>outRaster</code> is <code>null</code>,
1389             * an appropriate <code>WritableRaster</code> is created.
1390             * @param outRaster a <code>WritableRaster</code> to hold the returned
1391             *          part of the image, or <code>null</code>
1392             * @return a reference to the supplied or created
1393             *          <code>WritableRaster</code>. 
1394             */
1395            public WritableRaster copyData(WritableRaster outRaster) {
1396                if (outRaster == null) {
1397                    return (WritableRaster) getData();
1398                }
1399                int width = outRaster.getWidth();
1400                int height = outRaster.getHeight();
1401                int startX = outRaster.getMinX();
1402                int startY = outRaster.getMinY();
1403
1404                Object tdata = null;
1405
1406                for (int i = startY; i < startY + height; i++) {
1407                    tdata = raster.getDataElements(startX, i, width, 1, tdata);
1408                    outRaster.setDataElements(startX, i, width, 1, tdata);
1409                }
1410
1411                return outRaster;
1412            }
1413
1414            /**
1415             * Sets a rectangular region of the image to the contents of the
1416             * specified <code>Raster</code> <code>r</code>, which is
1417             * assumed to be in the same coordinate space as the
1418             * <code>BufferedImage</code>. The operation is clipped to the bounds
1419             * of the <code>BufferedImage</code>.
1420             * @param r the specified <code>Raster</code> 
1421             * @see #getData
1422             * @see #getData(Rectangle)
1423             */
1424            public void setData(Raster r) {
1425                int width = r.getWidth();
1426                int height = r.getHeight();
1427                int startX = r.getMinX();
1428                int startY = r.getMinY();
1429
1430                int[] tdata = null;
1431
1432                // Clip to the current Raster
1433                Rectangle rclip = new Rectangle(startX, startY, width, height);
1434                Rectangle bclip = new Rectangle(0, 0, raster.width,
1435                        raster.height);
1436                Rectangle intersect = rclip.intersection(bclip);
1437                if (intersect.isEmpty()) {
1438                    return;
1439                }
1440                width = intersect.width;
1441                height = intersect.height;
1442                startX = intersect.x;
1443                startY = intersect.y;
1444
1445                // remind use get/setDataElements for speed if Rasters are
1446                // compatible
1447                for (int i = startY; i < startY + height; i++) {
1448                    tdata = r.getPixels(startX, i, width, 1, tdata);
1449                    raster.setPixels(startX, i, width, 1, tdata);
1450                }
1451            }
1452
1453            /**
1454             * Adds a tile observer.  If the observer is already present,
1455             * it receives multiple notifications.
1456             * @param to the specified {@link TileObserver}
1457             */
1458            public void addTileObserver(TileObserver to) {
1459            }
1460
1461            /**
1462             * Removes a tile observer.  If the observer was not registered,
1463             * nothing happens.  If the observer was registered for multiple
1464             * notifications, it is now registered for one fewer notification.
1465             * @param to the specified <code>TileObserver</code>.
1466             */
1467            public void removeTileObserver(TileObserver to) {
1468            }
1469
1470            /**
1471             * Returns whether or not a tile is currently checked out for writing.
1472             * @param tileX the x index of the tile.
1473             * @param tileY the y index of the tile.
1474             * @return <code>true</code> if the tile specified by the specified
1475             *          indices is checked out for writing; <code>false</code>
1476             *          otherwise. 
1477             * @exception <code>ArrayIndexOutOfBoundsException</code> if both
1478             * 		<code>tileX</code> and <code>tileY</code> are not equal
1479             *		to 0
1480             */
1481            public boolean isTileWritable(int tileX, int tileY) {
1482                if (tileX == 0 && tileY == 0) {
1483                    return true;
1484                }
1485                throw new IllegalArgumentException("Only 1 tile in image");
1486            }
1487
1488            /**
1489             * Returns an array of {@link Point} objects indicating which tiles
1490             * are checked out for writing.  Returns <code>null</code> if none are
1491             * checked out.
1492             * @return a <code>Point</code> array that indicates the tiles that
1493             *          are checked out for writing, or <code>null</code> if no
1494             *          tiles are checked out for writing. 
1495             */
1496            public Point[] getWritableTileIndices() {
1497                Point[] p = new Point[1];
1498                p[0] = new Point(0, 0);
1499
1500                return p;
1501            }
1502
1503            /**
1504             * Returns whether or not any tile is checked out for writing.
1505             * Semantically equivalent to 
1506             * <pre>
1507             * (getWritableTileIndices() != null).
1508             * </pre>
1509             * @return <code>true</code> if any tile is checked out for writing;
1510             *          <code>false</code> otherwise. 
1511             */
1512            public boolean hasTileWriters() {
1513                return true;
1514            }
1515
1516            /**
1517             * Checks out a tile for writing.  All registered 
1518             * <code>TileObservers</code> are notified when a tile goes from having
1519             * no writers to having one writer.
1520             * @param tileX the x index of the tile
1521             * @param tileY the y index of the tile
1522             * @return a <code>WritableRaster</code> that is the tile, indicated by
1523             *            the specified indices, to be checked out for writing. 
1524             */
1525            public WritableRaster getWritableTile(int tileX, int tileY) {
1526                return raster;
1527            }
1528
1529            /**
1530             * Relinquishes permission to write to a tile.  If the caller 
1531             * continues to write to the tile, the results are undefined.
1532             * Calls to this method should only appear in matching pairs
1533             * with calls to {@link #getWritableTile(int, int) getWritableTile(int, int)}.  Any other leads
1534             * to undefined results.  All registered <code>TileObservers</code>
1535             * are notified when a tile goes from having one writer to having no
1536             * writers.
1537             * @param tileX the x index of the tile
1538             * @param tileY the y index of the tile
1539             */
1540            public void releaseWritableTile(int tileX, int tileY) {
1541            }
1542
1543            /**
1544             * Returns the transparency.  Returns either OPAQUE, BITMASK,
1545             * or TRANSLUCENT.
1546             * @return the transparency of this <code>BufferedImage</code>.
1547             * @see Transparency#OPAQUE
1548             * @see Transparency#BITMASK
1549             * @see Transparency#TRANSLUCENT
1550             * @since 1.5
1551             */
1552            public int getTransparency() {
1553                return colorModel.getTransparency();
1554            }
1555        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.