KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > image > BufferedImage


1 /*
2  * @(#)BufferedImage.java 1.101 04/07/16
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.awt.image;
9
10 import java.awt.Transparency JavaDoc;
11 import java.awt.color.ColorSpace JavaDoc;
12 import java.awt.Graphics2D JavaDoc;
13 import java.awt.GraphicsConfiguration JavaDoc;
14 import java.awt.GraphicsEnvironment JavaDoc;
15 import java.awt.ImageCapabilities JavaDoc;
16 import java.awt.geom.Rectangle2D JavaDoc;
17 import java.awt.geom.Point2D JavaDoc;
18 import java.awt.Point JavaDoc;
19 import java.awt.Rectangle JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import java.util.Vector JavaDoc;
22
23 import sun.awt.image.BytePackedRaster;
24 import sun.awt.image.ShortComponentRaster;
25 import sun.awt.image.ByteComponentRaster;
26 import sun.awt.image.IntegerComponentRaster;
27 import sun.awt.image.OffScreenImageSource;
28
29 /**
30  *
31  * The <code>BufferedImage</code> subclass describes an {@link
32  * java.awt.Image Image} with an accessible buffer of image data.
33  * A <code>BufferedImage</code> is comprised of a {@link ColorModel} and a
34  * {@link Raster} of image data.
35  * The number and types of bands in the {@link SampleModel} of the
36  * <code>Raster</code> must match the number and types required by the
37  * <code>ColorModel</code> to represent its color and alpha components.
38  * All <code>BufferedImage</code> objects have an upper left corner
39  * coordinate of (0,&nbsp;0). Any <code>Raster</code> used to construct a
40  * <code>BufferedImage</code> must therefore have minX=0 and minY=0.
41  *
42  * <p>
43  * This class relies on the data fetching and setting methods
44  * of <code>Raster</code>,
45  * and on the color characterization methods of <code>ColorModel</code>.
46  *
47  * @see ColorModel
48  * @see Raster
49  * @see WritableRaster
50  * @version 10 Feb 1997
51  */

52
53 public class BufferedImage extends java.awt.Image JavaDoc
54                            implements WritableRenderedImage JavaDoc, Transparency JavaDoc
55 {
56     int imageType = TYPE_CUSTOM;
57     ColorModel JavaDoc colorModel;
58     WritableRaster JavaDoc raster;
59     OffScreenImageSource osis;
60     Hashtable JavaDoc properties;
61
62     boolean isAlphaPremultiplied;// If true, alpha has been premultiplied in
63
// color channels
64

65     sun.awt.image.SurfaceManager surfaceManager;
66
67     /**
68      * Image Type Constants
69      */

70
71     /**
72      * Image type is not recognized so it must be a customized
73      * image. This type is only used as a return value for the getType()
74      * method.
75      */

76     public static final int TYPE_CUSTOM = 0;
77
78     /**
79      * Represents an image with 8-bit RGB color components packed into
80      * integer pixels. The image has a {@link DirectColorModel} without
81      * alpha.
82      * When data with non-opaque alpha is stored
83      * in an image of this type,
84      * the color data must be adjusted to a non-premultiplied form
85      * and the alpha discarded,
86      * as described in the
87      * {@link java.awt.AlphaComposite} documentation.
88      */

89     public static final int TYPE_INT_RGB = 1;
90
91     /**
92      * Represents an image with 8-bit RGBA color components packed into
93      * integer pixels. The image has a <code>DirectColorModel</code>
94      * with alpha. The color data in this image is considered not to be
95      * premultiplied with alpha. When this type is used as the
96      * <code>imageType</code> argument to a <code>BufferedImage</code>
97      * constructor, the created image is consistent with images
98      * created in the JDK1.1 and earlier releases.
99      */

100     public static final int TYPE_INT_ARGB = 2;
101
102     /**
103      * Represents an image with 8-bit RGBA color components packed into
104      * integer pixels. The image has a <code>DirectColorModel</code>
105      * with alpha. The color data in this image is considered to be
106      * premultiplied with alpha.
107      */

108     public static final int TYPE_INT_ARGB_PRE = 3;
109
110     /**
111      * Represents an image with 8-bit RGB color components, corresponding
112      * to a Windows- or Solaris- style BGR color model, with the colors
113      * Blue, Green, and Red packed into integer pixels. There is no alpha.
114      * The image has a {@link DirectColorModel}.
115      * When data with non-opaque alpha is stored
116      * in an image of this type,
117      * the color data must be adjusted to a non-premultiplied form
118      * and the alpha discarded,
119      * as described in the
120      * {@link java.awt.AlphaComposite} documentation.
121      */

122     public static final int TYPE_INT_BGR = 4;
123
124     /**
125      * Represents an image with 8-bit RGB color components, corresponding
126      * to a Windows-style BGR color model) with the colors Blue, Green,
127      * and Red stored in 3 bytes. There is no alpha. The image has a
128      * <code>ComponentColorModel</code>.
129      * When data with non-opaque alpha is stored
130      * in an image of this type,
131      * the color data must be adjusted to a non-premultiplied form
132      * and the alpha discarded,
133      * as described in the
134      * {@link java.awt.AlphaComposite} documentation.
135      */

136     public static final int TYPE_3BYTE_BGR = 5;
137
138     /**
139      * Represents an image with 8-bit RGBA color components with the colors
140      * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha. The
141      * image has a <code>ComponentColorModel</code> with alpha. The
142      * color data in this image is considered not to be premultiplied with
143      * alpha. The byte data is interleaved in a single
144      * byte array in the order A, B, G, R
145      * from lower to higher byte addresses within each pixel.
146      */

147     public static final int TYPE_4BYTE_ABGR = 6;
148
149     /**
150      * Represents an image with 8-bit RGBA color components with the colors
151      * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha. The
152      * image has a <code>ComponentColorModel</code> with alpha. The color
153      * data in this image is considered to be premultiplied with alpha.
154      * The byte data is interleaved in a single byte array in the order
155      * A, B, G, R from lower to higher byte addresses within each pixel.
156      */

157     public static final int TYPE_4BYTE_ABGR_PRE = 7;
158
159     /**
160      * Represents an image with 5-6-5 RGB color components (5-bits red,
161      * 6-bits green, 5-bits blue) with no alpha. This image has
162      * a <code>DirectColorModel</code>.
163      * When data with non-opaque alpha is stored
164      * in an image of this type,
165      * the color data must be adjusted to a non-premultiplied form
166      * and the alpha discarded,
167      * as described in the
168      * {@link java.awt.AlphaComposite} documentation.
169      */

170     public static final int TYPE_USHORT_565_RGB = 8;
171     
172     /**
173      * Represents an image with 5-5-5 RGB color components (5-bits red,
174      * 5-bits green, 5-bits blue) with no alpha. This image has
175      * a <code>DirectColorModel</code>.
176      * When data with non-opaque alpha is stored
177      * in an image of this type,
178      * the color data must be adjusted to a non-premultiplied form
179      * and the alpha discarded,
180      * as described in the
181      * {@link java.awt.AlphaComposite} documentation.
182      */

183     public static final int TYPE_USHORT_555_RGB = 9;
184
185     /**
186      * Represents a unsigned byte grayscale image, non-indexed. This
187      * image has a <code>ComponentColorModel</code> with a CS_GRAY
188      * {@link ColorSpace}.
189      * When data with non-opaque alpha is stored
190      * in an image of this type,
191      * the color data must be adjusted to a non-premultiplied form
192      * and the alpha discarded,
193      * as described in the
194      * {@link java.awt.AlphaComposite} documentation.
195      */

196     public static final int TYPE_BYTE_GRAY = 10;
197     
198     /**
199      * Represents an unsigned short grayscale image, non-indexed). This
200      * image has a <code>ComponentColorModel</code> with a CS_GRAY
201      * <code>ColorSpace</code>.
202      * When data with non-opaque alpha is stored
203      * in an image of this type,
204      * the color data must be adjusted to a non-premultiplied form
205      * and the alpha discarded,
206      * as described in the
207      * {@link java.awt.AlphaComposite} documentation.
208      */

209     public static final int TYPE_USHORT_GRAY = 11;
210     
211     /**
212      * Represents an opaque byte-packed 1, 2, or 4 bit image. The
213      * image has an {@link IndexColorModel} without alpha. When this
214      * type is used as the <code>imageType</code> argument to the
215      * <code>BufferedImage</code> constructor that takes an
216      * <code>imageType</code> argument but no <code>ColorModel</code>
217      * argument, a 1-bit image is created with an
218      * <code>IndexColorModel</code> with two colors in the default
219      * sRGB <code>ColorSpace</code>: {0,&nbsp;0,&nbsp;0} and
220      * {255,&nbsp;255,&nbsp;255}.
221      *
222      * <p> Images with 2 or 4 bits per pixel may be constructed via
223      * the <code>BufferedImage</code> constructor that takes a
224      * <code>ColorModel</code> argument by supplying a
225      * <code>ColorModel</code> with an appropriate map size.
226      *
227      * <p> Images with 8 bits per pixel should use the image types
228      * <code>TYPE_BYTE_INDEXED</code> or <code>TYPE_BYTE_GRAY</code>
229      * depending on their <code>ColorModel</code>.
230
231      * <p> When color data is stored in an image of this type,
232      * the closest color in the colormap is determined
233      * by the <code>IndexColorModel</code> and the resulting index is stored.
234      * Approximation and loss of alpha or color components
235      * can result, depending on the colors in the
236      * <code>IndexColorModel</code> colormap.
237      */

238     public static final int TYPE_BYTE_BINARY = 12;
239
240     /**
241      * Represents an indexed byte image. When this type is used as the
242      * <code>imageType</code> argument to the <code>BufferedImage</code>
243      * constructor that takes an <code>imageType</code> argument
244      * but no <code>ColorModel</code> argument, an
245      * <code>IndexColorModel</code> is created with
246      * a 256-color 6/6/6 color cube palette with the rest of the colors
247      * from 216-255 populated by grayscale values in the
248      * default sRGB ColorSpace.
249      *
250      * <p> When color data is stored in an image of this type,
251      * the closest color in the colormap is determined
252      * by the <code>IndexColorModel</code> and the resulting index is stored.
253      * Approximation and loss of alpha or color components
254      * can result, depending on the colors in the
255      * <code>IndexColorModel</code> colormap.
256      */

257     public static final int TYPE_BYTE_INDEXED = 13;
258     
259     private static final int DCM_RED_MASK = 0x00ff0000;
260     private static final int DCM_GREEN_MASK = 0x0000ff00;
261     private static final int DCM_BLUE_MASK = 0x000000ff;
262     private static final int DCM_ALPHA_MASK = 0xff000000;
263     private static final int DCM_565_RED_MASK = 0xf800;
264     private static final int DCM_565_GRN_MASK = 0x07E0;
265     private static final int DCM_565_BLU_MASK = 0x001F;
266     private static final int DCM_555_RED_MASK = 0x7C00;
267     private static final int DCM_555_GRN_MASK = 0x03E0;
268     private static final int DCM_555_BLU_MASK = 0x001F;
269     private static final int DCM_BGR_RED_MASK = 0x0000ff;
270     private static final int DCM_BGR_GRN_MASK = 0x00ff00;
271     private static final int DCM_BGR_BLU_MASK = 0xff0000;
272
273     
274     static private native void initIDs();
275     static {
276         ColorModel.loadLibraries();
277         initIDs();
278     }
279
280     /**
281      * Constructs a <code>BufferedImage</code> of one of the predefined
282      * image types. The <code>ColorSpace</code> for the image is the
283      * default sRGB space.
284      * @param width width of the created image
285      * @param height height of the created image
286      * @param imageType type of the created image
287      * @see ColorSpace
288      * @see #TYPE_INT_RGB
289      * @see #TYPE_INT_ARGB
290      * @see #TYPE_INT_ARGB_PRE
291      * @see #TYPE_INT_BGR
292      * @see #TYPE_3BYTE_BGR
293      * @see #TYPE_4BYTE_ABGR
294      * @see #TYPE_4BYTE_ABGR_PRE
295      * @see #TYPE_BYTE_GRAY
296      * @see #TYPE_USHORT_GRAY
297      * @see #TYPE_BYTE_BINARY
298      * @see #TYPE_BYTE_INDEXED
299      * @see #TYPE_USHORT_565_RGB
300      * @see #TYPE_USHORT_555_RGB
301      */

302     public BufferedImage(int width,
303                          int height,
304                          int imageType) {
305         switch (imageType) {
306         case TYPE_INT_RGB:
307             {
308                 colorModel = new DirectColorModel JavaDoc(24,
309                                                   0x00ff0000, // Red
310
0x0000ff00, // Green
311
0x000000ff, // Blue
312
0x0 // Alpha
313
);
314                   raster = colorModel.createCompatibleWritableRaster(width,
315                                                                       height);
316             }
317         break;
318             
319         case TYPE_INT_ARGB:
320             {
321                 colorModel = ColorModel.getRGBdefault();
322                 
323                 raster = colorModel.createCompatibleWritableRaster(width,
324                                                                    height);
325             }
326         break;
327
328         case TYPE_INT_ARGB_PRE:
329             {
330                 colorModel = new
331                     DirectColorModel JavaDoc(
332                                      ColorSpace.getInstance(ColorSpace.CS_sRGB),
333                                      32,
334                                      0x00ff0000,// Red
335
0x0000ff00,// Green
336
0x000000ff,// Blue
337
0xff000000,// Alpha
338
true, // Alpha Premultiplied
339
DataBuffer.TYPE_INT
340                                      );
341
342                   raster = colorModel.createCompatibleWritableRaster(width,
343                                                                       height);
344             }
345         break;
346
347         case TYPE_INT_BGR:
348             {
349                 colorModel = new DirectColorModel JavaDoc(24,
350                                                   0x000000ff, // Red
351
0x0000ff00, // Green
352
0x00ff0000 // Blue
353
);
354                   raster = colorModel.createCompatibleWritableRaster(width,
355                                                                       height);
356             }
357         break;
358
359         case TYPE_3BYTE_BGR:
360             {
361                 ColorSpace JavaDoc cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
362                 int[] nBits = {8, 8, 8};
363                 int[] bOffs = {2, 1, 0};
364                 colorModel = new ComponentColorModel JavaDoc(cs, nBits, false, false,
365                                                      Transparency.OPAQUE,
366                                                      DataBuffer.TYPE_BYTE);
367                 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
368                                                         width, height,
369                                                         width*3, 3,
370                                                         bOffs, null);
371             }
372         break;
373             
374         case TYPE_4BYTE_ABGR:
375             {
376                 ColorSpace JavaDoc cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
377                 int[] nBits = {8, 8, 8, 8};
378                 int[] bOffs = {3, 2, 1, 0};
379                 colorModel = new ComponentColorModel JavaDoc(cs, nBits, true, false,
380                                                      Transparency.TRANSLUCENT,
381                                                      DataBuffer.TYPE_BYTE);
382                 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
383                                                         width, height,
384                                                         width*4, 4,
385                                                         bOffs, null);
386             }
387         break;
388
389         case TYPE_4BYTE_ABGR_PRE:
390             {
391                 ColorSpace JavaDoc cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
392                 int[] nBits = {8, 8, 8, 8};
393                 int[] bOffs = {3, 2, 1, 0};
394                 colorModel = new ComponentColorModel JavaDoc(cs, nBits, true, true,
395                                                      Transparency.TRANSLUCENT,
396                                                      DataBuffer.TYPE_BYTE);
397                 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
398                                                         width, height,
399                                                         width*4, 4,
400                                                         bOffs, null);
401             }
402         break;
403
404         case TYPE_BYTE_GRAY:
405             {
406                 ColorSpace JavaDoc cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
407                 int[] nBits = {8};
408                 colorModel = new ComponentColorModel JavaDoc(cs, nBits, false, true,
409                                                      Transparency.OPAQUE,
410                                                      DataBuffer.TYPE_BYTE);
411                 raster = colorModel.createCompatibleWritableRaster(width,
412                                                                    height);
413             }
414         break;
415                 
416         case TYPE_USHORT_GRAY:
417             {
418                 ColorSpace JavaDoc cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
419                 int[] nBits = {16};
420                 colorModel = new ComponentColorModel JavaDoc(cs, nBits, false, true,
421                                                      Transparency.OPAQUE,
422                                                      DataBuffer.TYPE_USHORT);
423                 raster = colorModel.createCompatibleWritableRaster(width,
424                                                                    height);
425             }
426         break;
427                 
428         case TYPE_BYTE_BINARY:
429             {
430                 byte[] arr = {(byte)0, (byte)0xff};
431                 
432                 colorModel = new IndexColorModel JavaDoc(1, 2, arr, arr, arr);
433                 raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
434                                                    width, height, 1, 1, null);
435             }
436         break;
437         
438         case TYPE_BYTE_INDEXED:
439             {
440                 // Create a 6x6x6 color cube
441
int[] cmap = new int[256];
442                 int i=0;
443                 for (int r=0; r < 256; r += 51) {
444                     for (int g=0; g < 256; g += 51) {
445                         for (int b=0; b < 256; b += 51) {
446                             cmap[i++] = (r<<16)|(g<<8)|b;
447                         }
448                     }
449                 }
450                 // And populate the rest of the cmap with gray values
451
int grayIncr = 256/(256-i);
452                 
453                 // The gray ramp will be between 18 and 252
454
int gray = grayIncr*3;
455                 for (; i < 256; i++) {
456                     cmap[i] = (gray<<16)|(gray<<8)|gray;
457                     gray += grayIncr;
458                 }
459
460                 colorModel = new IndexColorModel JavaDoc(8, 256, cmap, 0, false, -1,
461                                                  DataBuffer.TYPE_BYTE);
462                 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
463                                                       width, height, 1, null);
464             }
465         break;
466
467         case TYPE_USHORT_565_RGB:
468             {
469                 colorModel = new DirectColorModel JavaDoc(16,
470                                                   DCM_565_RED_MASK,
471                                                   DCM_565_GRN_MASK,
472                                                   DCM_565_BLU_MASK
473                                                   );
474                 raster = colorModel.createCompatibleWritableRaster(width,
475                                                                    height);
476             }
477             break;
478
479         case TYPE_USHORT_555_RGB:
480             {
481                 colorModel = new DirectColorModel JavaDoc(15,
482                                                   DCM_555_RED_MASK,
483                                                   DCM_555_GRN_MASK,
484                                                   DCM_555_BLU_MASK
485                                                   );
486                 raster = colorModel.createCompatibleWritableRaster(width,
487                                                                    height);
488             }
489             break;
490
491         default:
492             throw new IllegalArgumentException JavaDoc ("Unknown image type " +
493                                                 imageType);
494         }
495
496         this.imageType = imageType;
497     }
498
499     /**
500      * Constructs a <code>BufferedImage</code> of one of the predefined
501      * image types:
502      * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED.
503      *
504      * <p> If the image type is TYPE_BYTE_BINARY, the number of
505      * entries in the color model is used to determine whether the
506      * image should have 1, 2, or 4 bits per pixel. If the color model
507      * has 1 or 2 entries, the image will have 1 bit per pixel. If it
508      * has 3 or 4 entries, the image with have 2 bits per pixel. If
509      * it has between 5 and 16 entries, the image will have 4 bits per
510      * pixel. Otherwise, an IllegalArgumentException will be thrown.
511      *
512      * @param width width of the created image
513      * @param height height of the created image
514      * @param imageType type of the created image
515      * @param cm <code>IndexColorModel</code> of the created image
516      * @throws IllegalArgumentException if the imageType is not
517      * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED or if the imageType is
518      * TYPE_BYTE_BINARY and the color map has more than 16 entries.
519      * @see #TYPE_BYTE_BINARY
520      * @see #TYPE_BYTE_INDEXED
521      */

522     public BufferedImage (int width,
523                           int height,
524                           int imageType,
525                           IndexColorModel JavaDoc cm) {
526         if (cm.hasAlpha() && cm.isAlphaPremultiplied()) {
527             throw new IllegalArgumentException JavaDoc("This image types do not have "+
528                                                "premultiplied alpha.");
529         }
530
531         switch(imageType) {
532         case TYPE_BYTE_BINARY:
533             int bits; // Will be set below
534
int mapSize = cm.getMapSize();
535             if (mapSize <= 2) {
536                 bits = 1;
537             } else if (mapSize <= 4) {
538                 bits = 2;
539             } else if (mapSize <= 16) {
540                 bits = 4;
541             } else {
542                 throw new IllegalArgumentException JavaDoc
543                     ("Color map for TYPE_BYTE_BINARY " +
544                      "must have no more than 16 entries");
545             }
546             raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
547                                                 width, height, 1, bits, null);
548             break;
549             
550         case TYPE_BYTE_INDEXED:
551             raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
552                                                     width, height, 1, null);
553             break;
554         default:
555             throw new IllegalArgumentException JavaDoc("Invalid image type (" +
556                                                imageType+"). Image type must"+
557                                                " be either TYPE_BYTE_BINARY or "+
558                                                " TYPE_BYTE_INDEXED");
559         }
560
561         if (!cm.isCompatibleRaster(raster)) {
562             throw new IllegalArgumentException JavaDoc("Incompatible image type and IndexColorModel");
563         }
564
565         colorModel = cm;
566         this.imageType = imageType;
567     }
568
569     /**
570      * Constructs a new <code>BufferedImage</code> with a specified
571      * <code>ColorModel</code> and <code>Raster</code>. If the number and
572      * types of bands in the <code>SampleModel</code> of the
573      * <code>Raster</code> do not match the number and types required by
574      * the <code>ColorModel</code> to represent its color and alpha
575      * components, a {@link RasterFormatException} is thrown. This
576      * method can multiply or divide the color <code>Raster</code> data by
577      * alpha to match the <code>alphaPremultiplied</code> state
578      * in the <code>ColorModel</code>. Properties for this
579      * <code>BufferedImage</code> can be established by passing
580      * in a {@link Hashtable} of <code>String</code>/<code>Object</code>
581      * pairs.
582      * @param cm <code>ColorModel</code> for the new image
583      * @param raster <code>Raster</code> for the image data
584      * @param isRasterPremultiplied if <code>true</code>, the data in
585      * the raster has been premultiplied with alpha.
586      * @param properties <code>Hashtable</code> of
587      * <code>String</code>/<code>Object</code> pairs.
588      * @exception <code>RasterFormatException</code> if the number and
589      * types of bands in the <code>SampleModel</code> of the
590      * <code>Raster</code> do not match the number and types required by
591      * the <code>ColorModel</code> to represent its color and alpha
592      * components.
593      * @exception <code>IllegalArgumentException</code> if
594      * <code>raster</code> is incompatible with <code>cm</code>
595      * @see ColorModel
596      * @see Raster
597      * @see WritableRaster
598      */

599
600
601 /*
602  *
603  * FOR NOW THE CODE WHICH DEFINES THE RASTER TYPE IS DUPLICATED BY DVF
604  * SEE THE METHOD DEFINERASTERTYPE @ RASTEROUTPUTMANAGER
605  *
606  */

607     public BufferedImage (ColorModel JavaDoc cm,
608                           WritableRaster JavaDoc raster,
609                           boolean isRasterPremultiplied,
610                           Hashtable JavaDoc<?,?> properties) {
611
612         if (!cm.isCompatibleRaster(raster)) {
613             throw new
614                 IllegalArgumentException JavaDoc("Raster "+raster+
615                                          " is incompatible with ColorModel "+
616                                          cm);
617         }
618
619     if ((raster.minX != 0) || (raster.minY != 0)) {
620             throw new
621                 IllegalArgumentException JavaDoc("Raster "+raster+
622                                          " has minX or minY not equal to zero: "
623                                          + raster.minX + " " + raster.minY);
624     }
625
626         colorModel = cm;
627         this.raster = raster;
628         this.properties = properties;
629         int numBands = raster.getNumBands();
630         boolean isAlphaPre = cm.isAlphaPremultiplied();
631         ColorSpace JavaDoc cs;
632         
633         // Force the raster data alpha state to match the premultiplied
634
// state in the color model
635
coerceData(isRasterPremultiplied);
636
637         SampleModel JavaDoc sm = raster.getSampleModel();
638         cs = cm.getColorSpace();
639         int csType = cs.getType();
640         if (csType != ColorSpace.TYPE_RGB) {
641             if (csType == ColorSpace.TYPE_GRAY
642                 && cm instanceof ComponentColorModel JavaDoc) {
643                 // Check if this might be a child raster (fix for bug 4240596)
644
if (sm instanceof ComponentSampleModel JavaDoc &&
645                     ((ComponentSampleModel JavaDoc)sm).getPixelStride() != numBands) {
646                     imageType = TYPE_CUSTOM;
647                 } else if (raster instanceof ByteComponentRaster &&
648                        raster.getNumBands() == 1 &&
649                        cm.getComponentSize(0) == 8 &&
650                        ((ByteComponentRaster)raster).getPixelStride() == 1) {
651                     imageType = TYPE_BYTE_GRAY;
652                 } else if (raster instanceof ShortComponentRaster &&
653                        raster.getNumBands() == 1 &&
654                        cm.getComponentSize(0) == 16 &&
655                        ((ShortComponentRaster)raster).getPixelStride() == 1) {
656                     imageType = TYPE_USHORT_GRAY;
657                 }
658             } else {
659                 imageType = TYPE_CUSTOM;
660             }
661             return;
662         }
663
664         if ((raster instanceof IntegerComponentRaster) &&
665             (numBands == 3 || numBands == 4)) {
666             IntegerComponentRaster iraster =
667                 (IntegerComponentRaster) raster;
668             // Check if the raster params and the color model
669
// are correct
670
int pixSize = cm.getPixelSize();
671             if (iraster.getPixelStride() == 1 &&
672                 cm instanceof DirectColorModel JavaDoc &&
673                 (pixSize == 32 || pixSize == 24))
674             {
675                 // Now check on the DirectColorModel params
676
DirectColorModel JavaDoc dcm = (DirectColorModel JavaDoc) cm;
677                 int rmask = dcm.getRedMask();
678                 int gmask = dcm.getGreenMask();
679                 int bmask = dcm.getBlueMask();
680                 if (rmask == DCM_RED_MASK && gmask == DCM_GREEN_MASK &&
681                     bmask == DCM_BLUE_MASK)
682                 {
683                     if (dcm.getAlphaMask() == DCM_ALPHA_MASK) {
684                         imageType = (isAlphaPre
685                                      ? TYPE_INT_ARGB_PRE
686                                      : TYPE_INT_ARGB);
687                     }
688                     else {
689                         // No Alpha
690
if (!dcm.hasAlpha()) {
691                             imageType = TYPE_INT_RGB;
692                         }
693                     }
694                 } // if (dcm.getRedMask() == DCM_RED_MASK &&
695
else if (rmask == DCM_BGR_RED_MASK && gmask == DCM_BGR_GRN_MASK
696                          && bmask == DCM_BGR_BLU_MASK) {
697                     if (!dcm.hasAlpha()) {
698                         imageType = TYPE_INT_BGR;
699                     }
700                 } // if (rmask == DCM_BGR_RED_MASK &&
701
} // if (iraster.getPixelStride() == 1
702
} // ((raster instanceof IntegerComponentRaster) &&
703
else if ((cm instanceof IndexColorModel JavaDoc) && (numBands == 1) &&
704                  (!cm.hasAlpha() || !isAlphaPre))
705         {
706             IndexColorModel JavaDoc icm = (IndexColorModel JavaDoc) cm;
707             int pixSize = icm.getPixelSize();
708
709             if (raster instanceof BytePackedRaster) {
710                 imageType = TYPE_BYTE_BINARY;
711             } // if (raster instanceof BytePackedRaster)
712
else if (raster instanceof ByteComponentRaster) {
713                 ByteComponentRaster braster = (ByteComponentRaster) raster;
714                 if (braster.getPixelStride() == 1 && pixSize <= 8) {
715                     imageType = TYPE_BYTE_INDEXED;
716                 }
717             }
718         } // else if (cm instanceof IndexColorModel) && (numBands == 1))
719
else if ((raster instanceof ShortComponentRaster)
720                  && (cm instanceof DirectColorModel JavaDoc)
721                  && (numBands == 3)
722                  && !cm.hasAlpha())
723         {
724             DirectColorModel JavaDoc dcm = (DirectColorModel JavaDoc) cm;
725             if (dcm.getRedMask() == DCM_565_RED_MASK) {
726                 if (dcm.getGreenMask() == DCM_565_GRN_MASK &&
727                     dcm.getBlueMask() == DCM_565_BLU_MASK) {
728                     imageType = TYPE_USHORT_565_RGB;
729                 }
730             }
731             else if (dcm.getRedMask() == DCM_555_RED_MASK) {
732                 if (dcm.getGreenMask() == DCM_555_GRN_MASK &&
733                     dcm.getBlueMask() == DCM_555_BLU_MASK) {
734                     imageType = TYPE_USHORT_555_RGB;
735                 }
736             }
737         } // else if ((cm instanceof IndexColorModel) && (numBands == 1))
738
else if ((raster instanceof ByteComponentRaster)
739                  && (cm instanceof ComponentColorModel JavaDoc)
740                  && (raster.getSampleModel() instanceof PixelInterleavedSampleModel JavaDoc)
741                  && (numBands == 3 || numBands == 4))
742         {
743             ComponentColorModel JavaDoc ccm = (ComponentColorModel JavaDoc) cm;
744             PixelInterleavedSampleModel JavaDoc csm =
745                 (PixelInterleavedSampleModel JavaDoc)raster.getSampleModel();
746             ByteComponentRaster braster = (ByteComponentRaster) raster;
747             int[] offs = csm.getBandOffsets();
748             if (ccm.getNumComponents() != numBands) {
749                 throw new RasterFormatException JavaDoc("Number of components in "+
750                                                 "ColorModel ("+
751                                                 ccm.getNumComponents()+
752                                                 ") does not match # in "+
753                                                 " Raster ("+numBands+")");
754             }
755             int[] nBits = ccm.getComponentSize();
756             boolean is8bit = true;
757             for (int i=0; i < numBands; i++) {
758                 if (nBits[i] != 8) {
759                     is8bit = false;
760                     break;
761                 }
762             }
763             if (is8bit &&
764                 offs[0] == numBands-1 &&
765                 offs[1] == numBands-2 &&
766                 offs[2] == numBands-3)
767             {
768                 if (numBands == 3) {
769                     imageType = TYPE_3BYTE_BGR;
770                 }
771                 else if (offs[3] == 0) {
772                     imageType = (isAlphaPre
773                                  ? TYPE_4BYTE_ABGR_PRE
774                                  : TYPE_4BYTE_ABGR);
775                 }
776             }
777         } // else if ((raster instanceof ByteComponentRaster) &&
778
}
779
780     /**
781      * Returns the image type. If it is not one of the known types,
782      * TYPE_CUSTOM is returned.
783      * @return the image type of this <code>BufferedImage</code>.
784      * @see #TYPE_INT_RGB
785      * @see #TYPE_INT_ARGB
786      * @see #TYPE_INT_ARGB_PRE
787      * @see #TYPE_INT_BGR
788      * @see #TYPE_3BYTE_BGR
789      * @see #TYPE_4BYTE_ABGR
790      * @see #TYPE_4BYTE_ABGR_PRE
791      * @see #TYPE_BYTE_GRAY
792      * @see #TYPE_BYTE_BINARY
793      * @see #TYPE_BYTE_INDEXED
794      * @see #TYPE_USHORT_GRAY
795      * @see #TYPE_USHORT_565_RGB
796      * @see #TYPE_USHORT_555_RGB
797      * @see #TYPE_CUSTOM
798      */

799     public int getType() {
800         return imageType;
801     }
802     
803     /**
804      * Returns the <code>ColorModel</code>.
805      * @return the <code>ColorModel</code> of this
806      * <code>BufferedImage</code>.
807      */

808     public ColorModel JavaDoc getColorModel() {
809         return colorModel;
810     }
811
812     /**
813      * Returns the {@link WritableRaster}.
814      * @return the <code>WriteableRaster</code> of this
815      * <code>BufferedImage</code>.
816      */

817     public WritableRaster JavaDoc getRaster() {
818     return raster;
819     }
820     
821     
822     /**
823      * Returns a <code>WritableRaster</code> representing the alpha
824      * channel for <code>BufferedImage</code> objects
825      * with <code>ColorModel</code> objects that support a separate
826      * spatial alpha channel, such as <code>ComponentColorModel</code> and
827      * <code>DirectColorModel</code>. Returns <code>null</code> if there
828      * is no alpha channel associated with the <code>ColorModel</code> in
829      * this image. This method assumes that for all
830      * <code>ColorModel</code> objects other than
831      * <code>IndexColorModel</code>, if the <code>ColorModel</code>
832      * supports alpha, there is a separate alpha channel
833      * which is stored as the last band of image data.
834      * If the image uses an <code>IndexColorModel</code> that
835      * has alpha in the lookup table, this method returns
836      * <code>null</code> since there is no spatially discrete alpha
837      * channel. This method creates a new
838      * <code>WritableRaster</code>, but shares the data array.
839      * @return a <code>WritableRaster</code> or <code>null</code> if this
840      * <code>BufferedImage</code> has no alpha channel associated
841      * with its <code>ColorModel</code>.
842      */

843     public WritableRaster JavaDoc getAlphaRaster() {
844         return colorModel.getAlphaRaster(raster);
845     }
846
847     /**
848      * Returns an integer pixel in the default RGB color model
849      * (TYPE_INT_ARGB) and default sRGB colorspace. Color
850      * conversion takes place if this default model does not match
851      * the image <code>ColorModel</code>. There are only 8-bits of
852      * precision for each color component in the returned data when using
853      * this method.
854      *
855      * <p>
856      *
857      * An <code>ArrayOutOfBoundsException</code> may be thrown
858      * if the coordinates are not in bounds.
859      * However, explicit bounds checking is not guaranteed.
860      *
861      * @param x,&nbsp;y the coordinates of the pixel from which to get
862      * the pixel in the default RGB color model and sRGB
863      * color space
864      * @return an integer pixel in the default RGB color model and
865      * default sRGB colorspace.
866      * @see #setRGB(int, int, int)
867      * @see #setRGB(int, int, int, int, int[], int, int)
868      */

869     public int getRGB(int x, int y) {
870         return colorModel.getRGB(raster.getDataElements(x, y, null));
871     }
872
873     /**
874      * Returns an array of integer pixels in the default RGB color model
875      * (TYPE_INT_ARGB) and default sRGB color space,
876      * from a portion of the image data. Color conversion takes
877      * place if the default model does not match the image
878      * <code>ColorModel</code>. There are only 8-bits of precision for
879      * each color component in the returned data when
880      * using this method. With a specified coordinate (x,&nbsp;y) in the
881      * image, the ARGB pixel can be accessed in this way:
882      * </p>
883      *
884      * <pre>
885      * pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)]; </pre>
886      *
887      * <p>
888      *
889      * An <code>ArrayOutOfBoundsException</code> may be thrown
890      * if the region is not in bounds.
891      * However, explicit bounds checking is not guaranteed.
892      *
893      * @param startX,&nbsp;startY the starting coordinates
894      * @param w width of region
895      * @param h height of region
896      * @param rgbArray if not <code>null</code>, the rgb pixels are
897      * written here
898      * @param offset offset into the <code>rgbArray</code>
899      * @param scansize scanline stride for the <code>rgbArray</code>
900      * @return array of RGB pixels.
901      * @see #setRGB(int, int, int)
902      * @see #setRGB(int, int, int, int, int[], int, int)
903      */

904     public int[] getRGB(int startX, int startY, int w, int h,
905                         int[] rgbArray, int offset, int scansize) {
906         int yoff = offset;
907         int off;
908         Object JavaDoc data;
909         int nbands = raster.getNumBands();
910         int dataType = raster.getDataBuffer().getDataType();
911         switch (dataType) {
912         case DataBuffer.TYPE_BYTE:
913             data = new byte[nbands];
914             break;
915         case DataBuffer.TYPE_USHORT:
916             data = new short[nbands];
917             break;
918         case DataBuffer.TYPE_INT:
919             data = new int[nbands];
920             break;
921         case DataBuffer.TYPE_FLOAT:
922             data = new float[nbands];
923             break;
924         case DataBuffer.TYPE_DOUBLE:
925             data = new double[nbands];
926             break;
927         default:
928             throw new IllegalArgumentException JavaDoc("Unknown data buffer type: "+
929                                                dataType);
930         }
931
932         if (rgbArray == null) {
933             rgbArray = new int[offset+h*scansize];
934         }
935
936         for (int y = startY; y < startY+h; y++, yoff+=scansize) {
937             off = yoff;
938             for (int x = startX; x < startX+w; x++) {
939                 rgbArray[off++] = colorModel.getRGB(raster.getDataElements(x,
940                                     y,
941                                     data));
942             }
943         }
944
945         return rgbArray;
946     }
947
948     
949     /**
950      * Sets a pixel in this <code>BufferedImage</code> to the specified
951      * RGB value. The pixel is assumed to be in the default RGB color
952      * model, TYPE_INT_ARGB, and default sRGB color space. For images
953      * with an <code>IndexColorModel</code>, the index with the nearest
954      * color is chosen.
955      *
956      * <p>
957      *
958      * An <code>ArrayOutOfBoundsException</code> may be thrown
959      * if the coordinates are not in bounds.
960      * However, explicit bounds checking is not guaranteed.
961      *
962      * @param x,&nbsp;y the coordinates of the pixel to set
963      * @param rgb the RGB value
964      * @see #getRGB(int, int)
965      * @see #getRGB(int, int, int, int, int[], int, int)
966      */

967     public synchronized void setRGB(int x, int y, int rgb) {
968         raster.setDataElements(x, y, colorModel.getDataElements(rgb, null));
969     }
970
971     /**
972      * Sets an array of integer pixels in the default RGB color model
973      * (TYPE_INT_ARGB) and default sRGB color space,
974      * into a portion of the image data. Color conversion takes place
975      * if the default model does not match the image
976      * <code>ColorModel</code>. There are only 8-bits of precision for
977      * each color component in the returned data when
978      * using this method. With a specified coordinate (x,&nbsp;y) in the
979      * this image, the ARGB pixel can be accessed in this way:
980      * <pre>
981      * pixel = rgbArray[offset + (y-startY)*scansize + (x-startX)];
982      * </pre>
983      * WARNING: No dithering takes place.
984      *
985      * <p>
986      *
987      * An <code>ArrayOutOfBoundsException</code> may be thrown
988      * if the region is not in bounds.
989      * However, explicit bounds checking is not guaranteed.
990      *
991      * @param startX,&nbsp;startY the starting coordinates
992      * @param w width of the region
993      * @param h height of the region
994      * @param rgbArray the rgb pixels
995      * @param offset offset into the <code>rgbArray</code>
996      * @param scansize scanline stride for the <code>rgbArray</code>
997      * @see #getRGB(int, int)
998      * @see #getRGB(int, int, int, int, int[], int, int)
999      */

1000    public void setRGB(int startX, int startY, int w, int h,
1001                        int[] rgbArray, int offset, int scansize) {
1002        int yoff = offset;
1003        int off;
1004        Object JavaDoc pixel = null;
1005
1006        for (int y = startY; y < startY+h; y++, yoff+=scansize) {
1007            off = yoff;
1008            for (int x = startX; x < startX+w; x++) {
1009                pixel = colorModel.getDataElements(rgbArray[off++], pixel);
1010                raster.setDataElements(x, y, pixel);
1011            }
1012        }
1013    }
1014
1015    
1016    /**
1017     * Returns the width of the <code>BufferedImage</code>.
1018     * @return the width of this <code>BufferedImage</code>
1019     */

1020    public int getWidth() {
1021        return raster.getWidth();
1022    }
1023
1024    /**
1025     * Returns the height of the <code>BufferedImage</code>.
1026     * @return the height of this <code>BufferedImage</code>
1027     */

1028    public int getHeight() {
1029        return raster.getHeight();
1030    }
1031
1032    /**
1033     * Returns the width of the <code>BufferedImage</code>.
1034     * @param observer ignored
1035     * @return the width of this <code>BufferedImage</code>
1036     */

1037    public int getWidth(ImageObserver JavaDoc observer) {
1038        return raster.getWidth();
1039    }
1040
1041    /**
1042     * Returns the height of the <code>BufferedImage</code>.
1043     * @param observer ignored
1044     * @return the height of this <code>BufferedImage</code>
1045     */

1046    public int getHeight(ImageObserver JavaDoc observer) {
1047        return raster.getHeight();
1048    }
1049
1050    /**
1051     * Returns the object that produces the pixels for the image.
1052     * @return the {@link ImageProducer} that is used to produce the
1053     * pixels for this image.
1054     * @see ImageProducer
1055     */

1056    public ImageProducer JavaDoc getSource() {
1057        if (osis == null) {
1058        if (properties == null) {
1059        properties = new Hashtable JavaDoc();
1060        }
1061            osis = new OffScreenImageSource(this, properties);
1062        }
1063        return osis;
1064    }
1065
1066
1067    /**
1068     * Returns a property of the image by name. Individual property names
1069     * are defined by the various image formats. If a property is not
1070     * defined for a particular image, this method returns the
1071     * <code>UndefinedProperty</code> field. If the properties
1072     * for this image are not yet known, then this method returns
1073     * <code>null</code> and the <code>ImageObserver</code> object is
1074     * notified later. The property name "comment" should be used to
1075     * store an optional comment that can be presented to the user as a
1076     * description of the image, its source, or its author.
1077     * @param name the property name
1078     * @param observer the <code>ImageObserver</code> that receives
1079     * notification regarding image information
1080     * @return an {@link Object} that is the property referred to by the
1081     * specified <code>name</code> or <code>null</code> if the
1082     * properties of this image are not yet known.
1083     * @throws <code>NullPointerException<code> if the property name is null.
1084     * @see ImageObserver
1085     * @see java.awt.Image#UndefinedProperty
1086     */

1087    public Object JavaDoc getProperty(String JavaDoc name, ImageObserver JavaDoc observer) {
1088        return getProperty(name);
1089    }
1090
1091    /**
1092     * Returns a property of the image by name.
1093     * @param name the property name
1094     * @return an <code>Object</code> that is the property referred to by
1095     * the specified <code>name</code>.
1096     * @throws <code>NullPointerException<code> if the property name is null.
1097     */

1098    public Object JavaDoc getProperty(String JavaDoc name) {
1099    if (name == null) {
1100        throw new NullPointerException JavaDoc("null property name is not allowed");
1101    }
1102    if (properties == null) {
1103            properties = new Hashtable JavaDoc();
1104    }
1105    Object JavaDoc o = properties.get(name);
1106    if (o == null) {
1107        o = java.awt.Image.UndefinedProperty;
1108    }
1109    return o;
1110    }
1111
1112    /**
1113     * Flushes all resources being used to cache optimization information.
1114     * The underlying pixel data is unaffected.
1115     */

1116    public void flush() {
1117        if (surfaceManager != null) {
1118            surfaceManager.flush();
1119        }
1120    }
1121
1122    /**
1123     * This method returns a {@link Graphics2D}, but is here
1124     * for backwards compatibility. {@link #createGraphics() createGraphics} is more
1125     * convenient, since it is declared to return a
1126     * <code>Graphics2D</code>.
1127     * @return a <code>Graphics2D</code>, which can be used to draw into
1128     * this image.
1129     */

1130    public java.awt.Graphics JavaDoc getGraphics() {
1131    return createGraphics();
1132    }
1133
1134    /**
1135     * Creates a <code>Graphics2D</code>, which can be used to draw into
1136     * this <code>BufferedImage</code>.
1137     * @return a <code>Graphics2D</code>, used for drawing into this
1138     * image.
1139     */

1140    public Graphics2D JavaDoc createGraphics() {
1141    GraphicsEnvironment JavaDoc env =
1142        GraphicsEnvironment.getLocalGraphicsEnvironment();
1143    return env.createGraphics(this);
1144    }
1145
1146    /**
1147     * Returns a subimage defined by a specified rectangular region.
1148     * The returned <code>BufferedImage</code> shares the same
1149     * data array as the original image.
1150     * @param x,&nbsp;y the coordinates of the upper-left corner of the
1151     * specified rectangular region
1152     * @param w the width of the specified rectangular region
1153     * @param h the height of the specified rectangular region
1154     * @return a <code>BufferedImage</code> that is the subimage of this
1155     * <code>BufferedImage</code>.
1156     * @exception <code>RasterFormatException</code> if the specified
1157     * area is not contained within this <code>BufferedImage</code>.
1158     */

1159    public BufferedImage JavaDoc getSubimage (int x, int y, int w, int h) {
1160        return new BufferedImage JavaDoc (colorModel,
1161                                  raster.createWritableChild(x, y, w, h,
1162                                                             0, 0, null),
1163                                  colorModel.isAlphaPremultiplied(),
1164                                  properties);
1165    }
1166
1167    /**
1168     * Returns whether or not the alpha has been premultiplied. It
1169     * returns <code>false</code> if there is no alpha.
1170     * @return <code>true</code> if the alpha has been premultiplied;
1171     * <code>false</code> otherwise.
1172     */

1173    public boolean isAlphaPremultiplied() {
1174        return colorModel.isAlphaPremultiplied();
1175    }
1176
1177    /**
1178     * Forces the data to match the state specified in the
1179     * <code>isAlphaPremultiplied</code> variable. It may multiply or
1180     * divide the color raster data by alpha, or do nothing if the data is
1181     * in the correct state.
1182     * @param isAlphaPremultiplied <code>true</code> if the alpha has been
1183     * premultiplied; <code>false</code> otherwise.
1184     */

1185    public void coerceData (boolean isAlphaPremultiplied) {
1186        if (colorModel.hasAlpha() &&
1187            colorModel.isAlphaPremultiplied() != isAlphaPremultiplied) {
1188            // Make the color model do the conversion
1189
colorModel = colorModel.coerceData (raster, isAlphaPremultiplied);
1190        }
1191    }
1192
1193    /**
1194     * Returns a <code>String</code> representation of this
1195     * <code>BufferedImage</code> object and its values.
1196     * @return a <code>String</code> representing this
1197     * <code>BufferedImage</code>.
1198     */

1199    public String JavaDoc toString() {
1200        return new String JavaDoc("BufferedImage@"+Integer.toHexString(hashCode())
1201                          +": type = "+imageType
1202                          +" "+colorModel+" "+raster);
1203    }
1204
1205    /**
1206     * Returns a {@link Vector} of {@link RenderedImage} objects that are
1207     * the immediate sources, not the sources of these immediate sources,
1208     * of image data for this <code>BufferedImage</code>. This
1209     * method returns <code>null</code> if the <code>BufferedImage</code>
1210     * has no information about its immediate sources. It returns an
1211     * empty <code>Vector</code> if the <code>BufferedImage</code> has no
1212     * immediate sources.
1213     * @return a <code>Vector</code> containing immediate sources of
1214     * this <code>BufferedImage</code> object's image date, or
1215     * <code>null</code> if this <code>BufferedImage</code> has
1216     * no information about its immediate sources, or an empty
1217     * <code>Vector</code> if this <code>BufferedImage</code>
1218     * has no immediate sources.
1219     */

1220    public Vector JavaDoc<RenderedImage JavaDoc> getSources() {
1221        return null;
1222    }
1223
1224    /**
1225     * Returns an array of names recognized by
1226     * {@link #getProperty(String) getProperty(String)}
1227     * or <code>null</code>, if no property names are recognized.
1228     * @return a <code>String</code> array containing all of the property
1229     * names that <code>getProperty(String)</code> recognizes;
1230     * or <code>null</code> if no property names are recognized.
1231     */

1232    public String JavaDoc[] getPropertyNames() {
1233         return null;
1234    }
1235
1236    /**
1237     * Returns the minimum x coordinate of this
1238     * <code>BufferedImage</code>. This is always zero.
1239     * @return the minimum x coordinate of this
1240     * <code>BufferedImage</code>.
1241     */

1242    public int getMinX() {
1243        return raster.getMinX();
1244    }
1245
1246    /**
1247     * Returns the minimum y coordinate of this
1248     * <code>BufferedImage</code>. This is always zero.
1249     * @return the minimum y coordinate of this
1250     * <code>BufferedImage</code>.
1251     */

1252    public int getMinY() {
1253        return raster.getMinY();
1254    }
1255
1256    /**
1257     * Returns the <code>SampleModel</code> associated with this
1258     * <code>BufferedImage</code>.
1259     * @return the <code>SampleModel</code> of this
1260     * <code>BufferedImage</code>.
1261     */

1262    public SampleModel JavaDoc getSampleModel() {
1263        return raster.getSampleModel();
1264    }
1265
1266    /**
1267     * Returns the number of tiles in the x direction.
1268     * This is always one.
1269     * @return the number of tiles in the x direction.
1270     */

1271    public int getNumXTiles() {
1272        return 1;
1273    }
1274
1275    /**
1276     * Returns the number of tiles in the y direction.
1277     * This is always one.
1278     * @return the number of tiles in the y direction.
1279     */

1280    public int getNumYTiles() {
1281        return 1;
1282    }
1283
1284    /**
1285     * Returns the minimum tile index in the x direction.
1286     * This is always zero.
1287     * @return the minimum tile index in the x direction.
1288     */

1289    public int getMinTileX() {
1290        return 0;
1291    }
1292
1293    /**
1294     * Returns the minimum tile index in the y direction.
1295     * This is always zero.
1296     * @return the mininum tile index in the y direction.
1297     */

1298    public int getMinTileY() {
1299        return 0;
1300    }
1301
1302    /**
1303     * Returns the tile width in pixels.
1304     * @return the tile width in pixels.
1305     */

1306    public int getTileWidth() {
1307       return raster.getWidth();
1308    }
1309
1310    /**
1311     * Returns the tile height in pixels.
1312     * @return the tile height in pixels.
1313     */

1314    public int getTileHeight() {
1315       return raster.getHeight();
1316    }
1317
1318    /**
1319     * Returns the x offset of the tile grid relative to the origin,
1320     * For example, the x coordinate of the location of tile
1321     * (0,&nbsp;0). This is always zero.
1322     * @return the x offset of the tile grid.
1323     */

1324    public int getTileGridXOffset() {
1325        return raster.getSampleModelTranslateX();
1326    }
1327    
1328    /**
1329     * Returns the y offset of the tile grid relative to the origin,
1330     * For example, the y coordinate of the location of tile
1331     * (0,&nbsp;0). This is always zero.
1332     * @return the y offset of the tile grid.
1333     */

1334    public int getTileGridYOffset() {
1335        return raster.getSampleModelTranslateY();
1336    }
1337    
1338    /**
1339     * Returns tile (<code>tileX</code>,&nbsp;<code>tileY</code>). Note
1340     * that <code>tileX</code> and <code>tileY</code> are indices
1341     * into the tile array, not pixel locations. The <code>Raster</code>
1342     * that is returned is live, which means that it is updated if the
1343     * image is changed.
1344     * @param tileX the x index of the requested tile in the tile array
1345     * @param tileY the y index of the requested tile in the tile array
1346     * @return a <code>Raster</code> that is the tile defined by the
1347     * arguments <code>tileX</code> and <code>tileY</code>.
1348     * @exception <code>ArrayIndexOutOfBoundsException</code> if both
1349     * <code>tileX</code> and <code>tileY</code> are not
1350     * equal to 0
1351     */

1352    public Raster JavaDoc getTile(int tileX, int tileY) {
1353        if (tileX == 0 && tileY == 0) {
1354            return raster;
1355        }
1356        throw new ArrayIndexOutOfBoundsException JavaDoc("BufferedImages only have"+
1357             " one tile with index 0,0");
1358    }
1359
1360    /**
1361     * Returns the image as one large tile. The <code>Raster</code>
1362     * returned is a copy of the image data is not updated if the
1363     * image is changed.
1364     * @return a <code>Raster</code> that is a copy of the image data.
1365     * @see #setData(Raster)
1366     */

1367    public Raster JavaDoc getData() {
1368
1369        // REMIND : this allocates a whole new tile if raster is a
1370
// subtile. (It only copies in the requested area)
1371
// We should do something smarter.
1372
int width = raster.getWidth();
1373        int height = raster.getHeight();
1374        int startX = raster.getMinX();
1375        int startY = raster.getMinY();
1376        WritableRaster JavaDoc wr =
1377           Raster.createWritableRaster(raster.getSampleModel(),
1378                         new Point JavaDoc(raster.getSampleModelTranslateX(),
1379                                   raster.getSampleModelTranslateY()));
1380
1381        Object JavaDoc tdata = null;
1382
1383        for (int i = startY; i < startY+height; i++) {
1384            tdata = raster.getDataElements(startX,i,width,1,tdata);
1385            wr.setDataElements(startX,i,width,1, tdata);
1386        }
1387        return wr;
1388    }
1389    
1390    /**
1391     * Computes and returns an arbitrary region of the
1392     * <code>BufferedImage</code>. The <code>Raster</code> returned is a
1393     * copy of the image data and is not updated if the image is
1394     * changed.
1395     * @param rect the region of the <code>BufferedImage</code> to be
1396     * returned.
1397     * @return a <code>Raster</code> that is a copy of the image data of
1398     * the specified region of the <code>BufferedImage</code>
1399     * @see #setData(Raster)
1400     */

1401    public Raster JavaDoc getData(Rectangle JavaDoc rect) {
1402        SampleModel JavaDoc sm = raster.getSampleModel();
1403        SampleModel JavaDoc nsm = sm.createCompatibleSampleModel(rect.width,
1404                                                         rect.height);
1405        WritableRaster JavaDoc wr = Raster.createWritableRaster(nsm,
1406                                                  rect.getLocation());
1407        int width = rect.width;
1408        int height = rect.height;
1409        int startX = rect.x;
1410        int startY = rect.y;
1411
1412        Object JavaDoc tdata = null;
1413
1414        for (int i = startY; i < startY+height; i++) {
1415            tdata = raster.getDataElements(startX,i,width,1,tdata);
1416            wr.setDataElements(startX,i,width,1, tdata);
1417        }
1418        return wr;
1419    }
1420 
1421    /**
1422     * Computes an arbitrary rectangular region of the
1423     * <code>BufferedImage</code> and copies it into a specified
1424     * <code>WritableRaster</code>. The region to be computed is
1425     * determined from the bounds of the specified
1426     * <code>WritableRaster</code>. The specified
1427     * <code>WritableRaster</code> must have a
1428     * <code>SampleModel</code> that is compatible with this image. If
1429     * <code>outRaster</code> is <code>null</code>,
1430     * an appropriate <code>WritableRaster</code> is created.
1431     * @param outRaster a <code>WritableRaster</code> to hold the returned
1432     * part of the image, or <code>null</code>
1433     * @return a reference to the supplied or created
1434     * <code>WritableRaster</code>.
1435     */

1436    public WritableRaster JavaDoc copyData(WritableRaster JavaDoc outRaster) {
1437        if (outRaster == null) {
1438            return (WritableRaster JavaDoc) getData();
1439        }
1440        int width = outRaster.getWidth();
1441        int height = outRaster.getHeight();
1442        int startX = outRaster.getMinX();
1443        int startY = outRaster.getMinY();
1444
1445        Object JavaDoc tdata = null;
1446
1447        for (int i = startY; i < startY+height; i++) {
1448            tdata = raster.getDataElements(startX,i,width,1,tdata);
1449            outRaster.setDataElements(startX,i,width,1, tdata);
1450        }
1451
1452        return outRaster;
1453    }
1454
1455  /**
1456     * Sets a rectangular region of the image to the contents of the
1457     * specified <code>Raster</code> <code>r</code>, which is
1458     * assumed to be in the same coordinate space as the
1459     * <code>BufferedImage</code>. The operation is clipped to the bounds
1460     * of the <code>BufferedImage</code>.
1461     * @param r the specified <code>Raster</code>
1462     * @see #getData
1463     * @see #getData(Rectangle)
1464    */

1465    public void setData(Raster JavaDoc r) {
1466        int width = r.getWidth();
1467        int height = r.getHeight();
1468        int startX = r.getMinX();
1469        int startY = r.getMinY();
1470 
1471        int[] tdata = null;
1472
1473        // Clip to the current Raster
1474
Rectangle JavaDoc rclip = new Rectangle JavaDoc(startX, startY, width, height);
1475        Rectangle JavaDoc bclip = new Rectangle JavaDoc(0, 0, raster.width, raster.height);
1476        Rectangle JavaDoc intersect = rclip.intersection(bclip);
1477        if (intersect.isEmpty()) {
1478            return;
1479        }
1480        width = intersect.width;
1481        height = intersect.height;
1482        startX = intersect.x;
1483        startY = intersect.y;
1484
1485        // remind use get/setDataElements for speed if Rasters are
1486
// compatible
1487
for (int i = startY; i < startY+height; i++) {
1488            tdata = r.getPixels(startX,i,width,1,tdata);
1489            raster.setPixels(startX,i,width,1, tdata);
1490        }
1491    }
1492
1493
1494  /**
1495   * Adds a tile observer. If the observer is already present,
1496   * it receives multiple notifications.
1497   * @param to the specified {@link TileObserver}
1498   */

1499    public void addTileObserver (TileObserver JavaDoc to) {
1500    }
1501    
1502  /**
1503   * Removes a tile observer. If the observer was not registered,
1504   * nothing happens. If the observer was registered for multiple
1505   * notifications, it is now registered for one fewer notification.
1506   * @param to the specified <code>TileObserver</code>.
1507   */

1508    public void removeTileObserver (TileObserver JavaDoc to) {
1509    }
1510   
1511    /**
1512     * Returns whether or not a tile is currently checked out for writing.
1513     * @param tileX the x index of the tile.
1514     * @param tileY the y index of the tile.
1515     * @return <code>true</code> if the tile specified by the specified
1516     * indices is checked out for writing; <code>false</code>
1517     * otherwise.
1518     * @exception <code>ArrayIndexOutOfBoundsException</code> if both
1519     * <code>tileX</code> and <code>tileY</code> are not equal
1520     * to 0
1521     */

1522    public boolean isTileWritable (int tileX, int tileY) {
1523        if (tileX == 0 && tileY == 0) {
1524            return true;
1525        }
1526        throw new IllegalArgumentException JavaDoc("Only 1 tile in image");
1527    }
1528    
1529    /**
1530     * Returns an array of {@link Point} objects indicating which tiles
1531     * are checked out for writing. Returns <code>null</code> if none are
1532     * checked out.
1533     * @return a <code>Point</code> array that indicates the tiles that
1534     * are checked out for writing, or <code>null</code> if no
1535     * tiles are checked out for writing.
1536     */

1537    public Point JavaDoc[] getWritableTileIndices() {
1538        Point JavaDoc[] p = new Point JavaDoc[1];
1539        p[0] = new Point JavaDoc(0, 0);
1540
1541        return p;
1542    }
1543    
1544    /**
1545     * Returns whether or not any tile is checked out for writing.
1546     * Semantically equivalent to
1547     * <pre>
1548     * (getWritableTileIndices() != null).
1549     * </pre>
1550     * @return <code>true</code> if any tile is checked out for writing;
1551     * <code>false</code> otherwise.
1552     */

1553    public boolean hasTileWriters () {
1554        return true;
1555    }
1556
1557  /**
1558   * Checks out a tile for writing. All registered
1559   * <code>TileObservers</code> are notified when a tile goes from having
1560   * no writers to having one writer.
1561   * @param tileX the x index of the tile
1562   * @param tileY the y index of the tile
1563   * @return a <code>WritableRaster</code> that is the tile, indicated by
1564   * the specified indices, to be checked out for writing.
1565   */

1566    public WritableRaster JavaDoc getWritableTile (int tileX, int tileY) {
1567        return raster;
1568    }
1569  
1570  /**
1571   * Relinquishes permission to write to a tile. If the caller
1572   * continues to write to the tile, the results are undefined.
1573   * Calls to this method should only appear in matching pairs
1574   * with calls to {@link #getWritableTile(int, int) getWritableTile(int, int)}. Any other leads
1575   * to undefined results. All registered <code>TileObservers</code>
1576   * are notified when a tile goes from having one writer to having no
1577   * writers.
1578   * @param tileX the x index of the tile
1579   * @param tileY the y index of the tile
1580   */

1581    public void releaseWritableTile (int tileX, int tileY) {
1582    }
1583
1584    /**
1585     * Returns the transparency. Returns either OPAQUE, BITMASK,
1586     * or TRANSLUCENT.
1587     * @return the transparency of this <code>BufferedImage</code>.
1588     * @see Transparency#OPAQUE
1589     * @see Transparency#BITMASK
1590     * @see Transparency#TRANSLUCENT
1591     * @since 1.5
1592     */

1593    public int getTransparency() {
1594    return colorModel.getTransparency();
1595    }
1596
1597    /**
1598     * This overrides Image.getCapabilities(gc) to get the capabilities
1599     * of its surfaceManager. This means that BufferedImage objects that
1600     * are accelerated may return a caps object that will indicate this
1601     * acceleration.
1602     */

1603    public ImageCapabilities JavaDoc getCapabilities(GraphicsConfiguration JavaDoc gc) {
1604    if (surfaceManager != null) {
1605        return surfaceManager.getCapabilities(gc);
1606    }
1607    // should not reach here unless the surfaceManager for this image
1608
// has not yet been created
1609
return super.getCapabilities(gc);
1610    }
1611}
1612
1613
1614
Popular Tags