1 /* Copyright (C) 2000, 2002, 2003 Free Software Foundation
3 This file is part of GNU Classpath.
5 GNU Classpath is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
10 GNU Classpath is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNU Classpath; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 Linking this library statically or dynamically with other modules is
21 making a combined work based on this library. Thus, the terms and
22 conditions of the GNU General Public License cover the whole
25 As a special exception, the copyright holders of this library give you
26 permission to link this library with independent modules to produce an
27 executable, regardless of the license terms of these independent
28 modules, and to copy and distribute the resulting executable under
29 terms of your choice, provided that you also meet, for each linked
30 independent module, the terms and conditions of the license of that
31 module. An independent module is a module which is not derived from
32 or based on this library. If you modify this library, you may extend
33 this exception to your version of the library, but you are not
34 obligated to do so. If you do not wish to do so, delete this
35 exception statement from your version. */
38 package java
.awt
.image
;
40 import java
.awt
.Graphics
;
41 import java
.awt
.Graphics2D
;
42 import java
.awt
.Image
;
43 import java
.awt
.Point
;
44 import java
.awt
.Rectangle
;
45 import java
.awt
.Transparency
;
46 import java
.awt
.color
.ColorSpace
;
47 import java
.util
.Hashtable
;
48 import java
.util
.Vector
;
49 import gnu
.java
.awt
.ComponentDataBlitOp
;
52 * A buffered image always starts at coordinates (0, 0).
54 * The buffered image is not subdivided into multiple tiles. Instead,
55 * the image consists of one large tile (0,0) with the width and
56 * height of the image. This tile is always considered to be checked
59 * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
61 public class BufferedImage
extends Image
62 implements WritableRenderedImage
64 public static final int TYPE_CUSTOM
= 0,
67 TYPE_INT_ARGB_PRE
= 3,
71 TYPE_4BYTE_ABGR_PRE
= 7,
72 TYPE_USHORT_565_RGB
= 8,
73 TYPE_USHORT_555_RGB
= 9,
75 TYPE_USHORT_GRAY
= 11,
76 TYPE_BYTE_BINARY
= 12,
77 TYPE_BYTE_INDEXED
= 13;
79 final static int[] bits3
= { 8, 8, 8 };
80 final static int[] bits4
= { 8, 8, 8 };
81 final static int[] bits1byte
= { 8 };
82 final static int[] bits1ushort
= { 16 };
84 final static int[] masks_int
= { 0x00ff0000,
87 DataBuffer
.TYPE_INT
};
88 final static int[] masks_565
= { 0xf800,
91 DataBuffer
.TYPE_USHORT
};
92 final static int[] masks_555
= { 0x7c00,
95 DataBuffer
.TYPE_USHORT
};
99 public BufferedImage(int w
, int h
, int type
)
101 ColorModel cm
= null;
103 boolean alpha
= false;
104 boolean premultiplied
= false;
107 case TYPE_4BYTE_ABGR_PRE
:
108 case TYPE_INT_ARGB_PRE
:
109 premultiplied
= true;
112 case TYPE_4BYTE_ABGR
:
116 ColorSpace cs
= ColorSpace
.getInstance(ColorSpace
.CS_sRGB
);
121 case TYPE_INT_ARGB_PRE
:
122 case TYPE_USHORT_565_RGB
:
123 case TYPE_USHORT_555_RGB
:
129 case TYPE_INT_ARGB_PRE
:
132 case TYPE_USHORT_565_RGB
:
135 case TYPE_USHORT_555_RGB
:
140 cm
= new DirectColorModel(cs
,
141 32, // 32 bits in an int
145 alpha ?
0xff000000 : 0,
147 masks
[3] // data type
153 "FIXME: Programmer is confused. Why (and how) does a " +
154 "TYPE_INT_BGR image use ComponentColorModel to store " +
155 "8-bit values? Is data type TYPE_INT or TYPE_BYTE. What " +
156 "is the difference between TYPE_INT_BGR and TYPE_3BYTE_BGR?";
157 throw new UnsupportedOperationException(msg
);
160 case TYPE_4BYTE_ABGR
:
161 case TYPE_4BYTE_ABGR_PRE
:
163 case TYPE_USHORT_GRAY
:
165 int dataType
= DataBuffer
.TYPE_BYTE
;
170 case TYPE_4BYTE_ABGR
:
171 case TYPE_4BYTE_ABGR_PRE
:
177 case TYPE_USHORT_GRAY
:
179 dataType
= DataBuffer
.TYPE_USHORT
;
182 cm
= new ComponentColorModel(cs
, bits
, alpha
, premultiplied
,
184 Transparency
.TRANSLUCENT
:
188 case TYPE_BYTE_BINARY
:
189 byte[] vals
= { 0, (byte) 0xff };
190 cm
= new IndexColorModel(8, 2, vals
, vals
, vals
);
192 case TYPE_BYTE_INDEXED
:
193 String msg2
= "type not implemented yet";
194 throw new UnsupportedOperationException(msg2
);
195 // FIXME: build color-cube and create color model
199 cm
.createCompatibleWritableRaster(w
, h
),
201 null, // no properties
206 public BufferedImage(int w
, int h
, int type
,
207 IndexColorModel indexcolormodel
)
209 if ((type
!= TYPE_BYTE_BINARY
) && (type
!= TYPE_BYTE_INDEXED
))
210 throw new IllegalArgumentException("type must be binary or indexed");
212 init(indexcolormodel
,
213 indexcolormodel
.createCompatibleWritableRaster(w
, h
),
214 false, // not premultiplied (guess)
215 null, // no properties
219 public BufferedImage(ColorModel colormodel
,
220 WritableRaster writableraster
,
221 boolean premultiplied
,
222 Hashtable properties
)
224 init(colormodel
, writableraster
, premultiplied
, properties
,
226 // TODO: perhaps try to identify type?
229 WritableRaster raster
;
230 ColorModel colorModel
;
231 Hashtable properties
;
232 boolean isPremultiplied
;
235 private void init(ColorModel cm
,
236 WritableRaster writableraster
,
237 boolean premultiplied
,
238 Hashtable properties
,
241 raster
= writableraster
;
243 this.properties
= properties
;
244 isPremultiplied
= premultiplied
;
248 //public void addTileObserver(TileObserver tileobserver) {}
250 public void coerceData(boolean premultiplied
)
252 colorModel
= colorModel
.coerceData(raster
, premultiplied
);
255 public WritableRaster
copyData(WritableRaster dest
)
258 dest
= raster
.createCompatibleWritableRaster();
260 int x
= dest
.getMinX();
261 int y
= dest
.getMinY();
262 int w
= dest
.getWidth();
263 int h
= dest
.getHeight();
265 // create a src child that has the right bounds...
267 raster
.createWritableChild(x
, y
, w
, h
, x
, y
,
270 if (src
.getSampleModel () instanceof ComponentSampleModel
271 && dest
.getSampleModel () instanceof ComponentSampleModel
)
272 // Refer to ComponentDataBlitOp for optimized data blitting:
273 ComponentDataBlitOp
.INSTANCE
.filter(src
, dest
);
277 int samples
[] = src
.getPixels (x
, y
, w
, h
, (int [])null);
278 dest
.setPixels (x
, y
, w
, h
, samples
);
283 public Graphics2D
createGraphics()
285 throw new UnsupportedOperationException("not implemented");
286 // will require a lot of effort to implement
289 public void flush() {
292 public WritableRaster
getAlphaRaster()
294 return colorModel
.getAlphaRaster(raster
);
297 public ColorModel
getColorModel()
302 public Raster
getData()
304 return copyData(null);
305 /* TODO: this might be optimized by returning the same
306 raster (not writable) as long as image data doesn't change. */
309 public Raster
getData(Rectangle rectangle
)
311 WritableRaster dest
=
312 raster
.createCompatibleWritableRaster(rectangle
);
313 return copyData(dest
);
316 public Graphics
getGraphics()
318 return createGraphics();
321 public int getHeight()
323 return raster
.getHeight();
326 public int getHeight(ImageObserver imageobserver
)
331 public int getMinTileX()
336 public int getMinTileY()
351 public int getNumXTiles()
356 public int getNumYTiles()
361 public Object
getProperty(String string
)
363 if (properties
== null)
365 return properties
.get(string
);
368 public Object
getProperty(String string
, ImageObserver imageobserver
)
370 return getProperty(string
);
374 public String
[] getPropertyNames()
380 public int getRGB(int x
, int y
)
382 Object rgbElem
= raster
.getDataElements(x
, y
,
383 null // create as needed
385 return colorModel
.getRGB(rgbElem
);
388 public int[] getRGB(int startX
, int startY
, int w
, int h
,
390 int offset
, int scanlineStride
)
392 if (rgbArray
== null)
396 00000[#######----- [ = start
397 -----########----- ] = end
399 000000000000000000 */
400 int size
= (h
-1)*scanlineStride
+ w
;
401 rgbArray
= new int[size
];
404 int endX
= startX
+ w
;
405 int endY
= startY
+ h
;
408 Opportunity for optimization by examining color models...
410 Perhaps wrap the rgbArray up in a WritableRaster with packed
411 sRGB color model and perform optimized rendering into the
414 Object rgbElem
= null;
415 for (int y
=startY
; y
<endY
; y
++)
417 int xoffset
= offset
;
418 for (int x
=startX
; x
<endX
; x
++)
421 rgbElem
= raster
.getDataElements(x
, y
, rgbElem
);
422 rgb
= colorModel
.getRGB(rgbElem
);
423 rgbArray
[xoffset
++] = rgb
;
425 offset
+= scanlineStride
;
430 public WritableRaster
getRaster()
435 public SampleModel
getSampleModel()
437 return raster
.getSampleModel();
440 public ImageProducer
getSource()
442 throw new UnsupportedOperationException("not implemented");
445 public Vector
getSources()
450 public BufferedImage
getSubimage(int x
, int y
, int w
, int h
)
452 WritableRaster subRaster
=
453 getRaster().createWritableChild(x
, y
, w
, h
, 0, 0, null);
455 return new BufferedImage(getColorModel(),
461 public Raster
getTile(int tileX
, int tileY
)
463 return getWritableTile(tileX
, tileY
);
466 public int getTileGridXOffset()
468 return 0; // according to javadocs
471 public int getTileGridYOffset()
473 return 0; // according to javadocs
476 public int getTileHeight()
478 return getHeight(); // image is one big tile
481 public int getTileWidth()
483 return getWidth(); // image is one big tile
491 public int getWidth()
493 return raster
.getWidth();
496 public int getWidth(ImageObserver imageobserver
)
501 public WritableRaster
getWritableTile(int tileX
, int tileY
)
503 isTileWritable(tileX
, tileY
); // for exception
507 private static final Point
[] tileIndices
= { new Point() };
509 public Point
[] getWritableTileIndices()
514 public boolean hasTileWriters()
519 public boolean isAlphaPremultiplied()
521 return isPremultiplied
;
524 public boolean isTileWritable(int tileX
, int tileY
)
526 if ((tileX
!= 0) || (tileY
!= 0))
527 throw new ArrayIndexOutOfBoundsException("only tile is (0,0)");
531 public void releaseWritableTile(int tileX
, int tileY
)
533 isTileWritable(tileX
, tileY
); // for exception
536 //public void removeTileObserver(TileObserver tileobserver) {}
538 public void setData(Raster src
)
540 int x
= src
.getMinX();
541 int y
= src
.getMinY();
542 int w
= src
.getWidth();
543 int h
= src
.getHeight();
545 // create a dest child that has the right bounds...
546 WritableRaster dest
=
547 raster
.createWritableChild(x
, y
, w
, h
, x
, y
,
551 if (src
.getSampleModel () instanceof ComponentSampleModel
552 && dest
.getSampleModel () instanceof ComponentSampleModel
)
554 // Refer to ComponentDataBlitOp for optimized data blitting:
555 ComponentDataBlitOp
.INSTANCE
.filter(src
, dest
);
559 int samples
[] = src
.getPixels (x
, y
, w
, h
, (int [])null);
560 dest
.setPixels (x
, y
, w
, h
, samples
);
564 public void setRGB(int x
, int y
, int argb
)
566 Object rgbElem
= colorModel
.getDataElements(argb
, null);
567 raster
.setDataElements(x
, y
, rgbElem
);
570 public void setRGB(int startX
, int startY
, int w
, int h
,
571 int[] argbArray
, int offset
, int scanlineStride
)
573 int endX
= startX
+ w
;
574 int endY
= startY
+ h
;
576 Object rgbElem
= null;
577 for (int y
=startY
; y
<endY
; y
++)
579 int xoffset
= offset
;
580 for (int x
=startX
; x
<endX
; x
++)
582 int argb
= argbArray
[xoffset
++];
583 rgbElem
= colorModel
.getDataElements(argb
, rgbElem
);
584 raster
.setDataElements(x
, y
, rgbElem
);
586 offset
+= scanlineStride
;
590 public String
toString()
594 buf
= new StringBuffer(/* estimated length */ 120);
595 buf
.append("BufferedImage@");
596 buf
.append(Integer
.toHexString(hashCode()));
597 buf
.append(": type=");
600 buf
.append(colorModel
);
604 return buf
.toString();
609 * Adds a tile observer. If the observer is already present, it receives
610 * multiple notifications.
612 * @param to The TileObserver to add.
614 public void addTileObserver (TileObserver to
)
616 if (observers
== null)
617 observers
= new Vector ();
623 * Removes a tile observer. If the observer was not registered,
624 * nothing happens. If the observer was registered for multiple
625 * notifications, it is now registered for one fewer notification.
627 * @param to The TileObserver to remove.
629 public void removeTileObserver (TileObserver to
)
631 if (observers
== null)
634 observers
.remove (to
);