FSF GCC merge 02/23/03
[official-gcc.git] / libjava / java / awt / image / BufferedImage.java
blobbf6c45cab9986c56ff10629abcb84ae33e547e76
1 /* Copyright (C) 2000, 2002 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)
8 any later version.
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
18 02111-1307 USA.
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
23 combination.
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.*;
41 import java.awt.color.*;
42 import java.util.*;
44 import gnu.java.awt.ComponentDataBlitOp;
46 /**
47 * A buffered image always starts at coordinates (0, 0).
49 * The buffered image is not subdivided into multiple tiles. Instead,
50 * the image consists of one large tile (0,0) with the width and
51 * height of the image. This tile is always considered to be checked
52 * out.
54 * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
56 public class BufferedImage extends java.awt.Image
57 //implements java.awt.image.WritableRenderedImage
59 public static final int TYPE_CUSTOM = 0,
60 TYPE_INT_RGB = 1,
61 TYPE_INT_ARGB = 2,
62 TYPE_INT_ARGB_PRE = 3,
63 TYPE_INT_BGR = 4,
64 TYPE_3BYTE_BGR = 5,
65 TYPE_4BYTE_ABGR = 6,
66 TYPE_4BYTE_ABGR_PRE = 7,
67 TYPE_USHORT_565_RGB = 8,
68 TYPE_USHORT_555_RGB = 9,
69 TYPE_BYTE_GRAY = 10,
70 TYPE_USHORT_GRAY = 11,
71 TYPE_BYTE_BINARY = 12,
72 TYPE_BYTE_INDEXED = 13;
74 final static int[] bits3 = { 8, 8, 8 };
75 final static int[] bits4 = { 8, 8, 8 };
76 final static int[] bits1byte = { 8 };
77 final static int[] bits1ushort = { 16 };
79 final static int[] masks_int = { 0x00ff0000,
80 0x0000ff00,
81 0x000000ff,
82 DataBuffer.TYPE_INT };
83 final static int[] masks_565 = { 0xf800,
84 0x07e0,
85 0x001f,
86 DataBuffer.TYPE_USHORT};
87 final static int[] masks_555 = { 0x7c00,
88 0x03e0,
89 0x001f,
90 DataBuffer.TYPE_USHORT};
92 public BufferedImage(int w, int h, int type)
94 ColorModel cm = null;
96 boolean alpha = false;
97 boolean premultiplied = false;
98 switch (type)
100 case TYPE_4BYTE_ABGR_PRE:
101 case TYPE_INT_ARGB_PRE:
102 premultiplied = true;
103 // fall through
104 case TYPE_INT_ARGB:
105 case TYPE_4BYTE_ABGR:
106 alpha = true;
109 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
110 switch (type)
112 case TYPE_INT_RGB:
113 case TYPE_INT_ARGB:
114 case TYPE_INT_ARGB_PRE:
115 case TYPE_USHORT_565_RGB:
116 case TYPE_USHORT_555_RGB:
117 int[] masks = null;
118 switch (type)
120 case TYPE_INT_RGB:
121 case TYPE_INT_ARGB:
122 case TYPE_INT_ARGB_PRE:
123 masks = masks_int;
124 break;
125 case TYPE_USHORT_565_RGB:
126 masks = masks_565;
127 break;
128 case TYPE_USHORT_555_RGB:
129 masks = masks_555;
130 break;
133 cm = new DirectColorModel(cs,
134 32, // 32 bits in an int
135 masks[0], // r
136 masks[1], // g
137 masks[2], // b
138 alpha ? 0xff000000 : 0,
139 premultiplied,
140 masks[3] // data type
142 break;
144 case TYPE_INT_BGR:
145 String msg =
146 "FIXME: Programmer is confused. Why (and how) does a " +
147 "TYPE_INT_BGR image use ComponentColorModel to store " +
148 "8-bit values? Is data type TYPE_INT or TYPE_BYTE. What " +
149 "is the difference between TYPE_INT_BGR and TYPE_3BYTE_BGR?";
150 throw new UnsupportedOperationException(msg);
152 case TYPE_3BYTE_BGR:
153 case TYPE_4BYTE_ABGR:
154 case TYPE_4BYTE_ABGR_PRE:
155 case TYPE_BYTE_GRAY:
156 case TYPE_USHORT_GRAY:
157 int[] bits = null;
158 int dataType = DataBuffer.TYPE_BYTE;
159 switch (type) {
160 case TYPE_3BYTE_BGR:
161 bits = bits3;
162 break;
163 case TYPE_4BYTE_ABGR:
164 case TYPE_4BYTE_ABGR_PRE:
165 bits = bits4;
166 break;
167 case TYPE_BYTE_GRAY:
168 bits = bits1byte;
169 break;
170 case TYPE_USHORT_GRAY:
171 bits = bits1ushort;
172 dataType = DataBuffer.TYPE_USHORT;
173 break;
175 cm = new ComponentColorModel(cs, bits, alpha, premultiplied,
176 alpha ?
177 Transparency.TRANSLUCENT:
178 Transparency.OPAQUE,
179 dataType);
180 break;
181 case TYPE_BYTE_BINARY:
182 byte[] vals = { 0, (byte) 0xff };
183 cm = new IndexColorModel(8, 2, vals, vals, vals);
184 break;
185 case TYPE_BYTE_INDEXED:
186 String msg2 = "type not implemented yet";
187 throw new UnsupportedOperationException(msg2);
188 // FIXME: build color-cube and create color model
191 init(cm,
192 cm.createCompatibleWritableRaster(w, h),
193 premultiplied,
194 null, // no properties
195 type
199 public BufferedImage(int w, int h, int type,
200 IndexColorModel indexcolormodel)
202 if ((type != TYPE_BYTE_BINARY) && (type != TYPE_BYTE_INDEXED))
203 throw new IllegalArgumentException("type must be binary or indexed");
205 init(indexcolormodel,
206 indexcolormodel.createCompatibleWritableRaster(w, h),
207 false, // not premultiplied (guess)
208 null, // no properties
209 type);
212 public BufferedImage(ColorModel colormodel,
213 WritableRaster writableraster,
214 boolean premultiplied,
215 Hashtable properties)
217 init(colormodel, writableraster, premultiplied, properties,
218 TYPE_CUSTOM);
219 // TODO: perhaps try to identify type?
222 WritableRaster raster;
223 ColorModel colorModel;
224 Hashtable properties;
225 boolean isPremultiplied;
226 int type;
228 private void init(ColorModel cm,
229 WritableRaster writableraster,
230 boolean premultiplied,
231 Hashtable properties,
232 int type)
234 raster = writableraster;
235 colorModel = cm;
236 this.properties = properties;
237 isPremultiplied = premultiplied;
238 this.type = type;
241 //public void addTileObserver(TileObserver tileobserver) {}
243 public void coerceData(boolean premultiplied)
245 colorModel = colorModel.coerceData(raster, premultiplied);
248 public WritableRaster copyData(WritableRaster dest)
250 if (dest == null)
251 dest = raster.createCompatibleWritableRaster();
253 int x = dest.getMinX();
254 int y = dest.getMinY();
255 int w = dest.getWidth();
256 int h = dest.getHeight();
258 // create a src child that has the right bounds...
259 WritableRaster src =
260 raster.createWritableChild(x, y, w, h, x, y,
261 null // same bands
264 // Refer to ComponentDataBlitOp for optimized data blitting:
265 ComponentDataBlitOp.INSTANCE.filter(src, dest);
266 return dest;
269 public Graphics2D createGraphics()
271 throw new UnsupportedOperationException("not implemented");
272 // will require a lot of effort to implement
275 public void flush() {
278 public WritableRaster getAlphaRaster()
280 return colorModel.getAlphaRaster(raster);
283 public ColorModel getColorModel()
285 return colorModel;
288 public Raster getData()
290 return copyData(null);
291 /* TODO: this might be optimized by returning the same
292 raster (not writable) as long as image data doesn't change. */
295 public Raster getData(Rectangle rectangle)
297 WritableRaster dest =
298 raster.createCompatibleWritableRaster(rectangle);
299 return copyData(dest);
302 public Graphics getGraphics()
304 return createGraphics();
307 public int getHeight()
309 return raster.getHeight();
312 public int getHeight(ImageObserver imageobserver)
314 return getHeight();
317 public int getMinTileX()
319 return 0;
322 public int getMinTileY()
324 return 0;
327 public int getMinX()
329 return 0;
332 public int getMinY()
334 return 0;
337 public int getNumXTiles()
339 return 1;
342 public int getNumYTiles()
344 return 1;
347 public Object getProperty(String string)
349 if (properties == null)
350 return null;
351 return properties.get(string);
354 public Object getProperty(String string, ImageObserver imageobserver)
356 return getProperty(string);
360 public String[] getPropertyNames()
362 // FIXME: implement
363 return null;
366 public int getRGB(int x, int y)
368 Object rgbElem = raster.getDataElements(x, y,
369 null // create as needed
371 return colorModel.getRGB(rgbElem);
374 public int[] getRGB(int startX, int startY, int w, int h,
375 int[] rgbArray,
376 int offset, int scanlineStride)
378 if (rgbArray == null)
381 000000000000000000
382 00000[#######----- [ = start
383 -----########----- ] = end
384 -----#######]00000
385 000000000000000000 */
386 int size = (h-1)*scanlineStride + w;
387 rgbArray = new int[size];
390 int endX = startX + w;
391 int endY = startY + h;
393 /* *TODO*:
394 Opportunity for optimization by examining color models...
396 Perhaps wrap the rgbArray up in a WritableRaster with packed
397 sRGB color model and perform optimized rendering into the
398 array. */
400 Object rgbElem = null;
401 for (int y=startY; y<endY; y++)
403 int xoffset = offset;
404 for (int x=startX; x<endX; x++)
406 int rgb;
407 rgbElem = raster.getDataElements(x, y, rgbElem);
408 rgb = colorModel.getRGB(rgbElem);
409 rgbArray[xoffset++] = rgb;
411 offset += scanlineStride;
413 return rgbArray;
416 public WritableRaster getRaster()
418 return raster;
421 public SampleModel getSampleModel()
423 return raster.getSampleModel();
426 public ImageProducer getSource()
428 throw new UnsupportedOperationException("not implemented");
431 public Vector getSources()
433 return null;
436 public BufferedImage getSubimage(int x, int y, int w, int h)
438 WritableRaster subRaster =
439 getRaster().createWritableChild(x, y, w, h, 0, 0, null);
441 return new BufferedImage(getColorModel(),
442 subRaster,
443 isPremultiplied,
444 properties);
447 public Raster getTile(int tileX, int tileY)
449 return getWritableTile(tileX, tileY);
452 public int getTileGridXOffset()
454 return 0; // according to javadocs
457 public int getTileGridYOffset()
459 return 0; // according to javadocs
462 public int getTileHeight()
464 return getHeight(); // image is one big tile
467 public int getTileWidth()
469 return getWidth(); // image is one big tile
472 public int getType()
474 return type;
477 public int getWidth()
479 return raster.getWidth();
482 public int getWidth(ImageObserver imageobserver)
484 return getWidth();
487 public WritableRaster getWritableTile(int tileX, int tileY)
489 isTileWritable(tileX, tileY); // for exception
490 return raster;
493 private static final Point[] tileIndices = { new Point() };
495 public Point[] getWritableTileIndices()
497 return tileIndices;
500 public boolean hasTileWriters()
502 return true;
505 public boolean isAlphaPremultiplied()
507 return isPremultiplied;
510 public boolean isTileWritable(int tileX, int tileY)
512 if ((tileX != 0) || (tileY != 0))
513 throw new ArrayIndexOutOfBoundsException("only tile is (0,0)");
514 return true;
517 public void releaseWritableTile(int tileX, int tileY)
519 isTileWritable(tileX, tileY); // for exception
522 //public void removeTileObserver(TileObserver tileobserver) {}
524 public void setData(Raster src)
526 int x = src.getMinX();
527 int y = src.getMinY();
528 int w = src.getWidth();
529 int h = src.getHeight();
531 // create a dest child that has the right bounds...
532 WritableRaster dest =
533 raster.createWritableChild(x, y, w, h, x, y,
534 null // same bands
537 // Refer to ComponentDataBlitOp for optimized data blitting:
538 ComponentDataBlitOp.INSTANCE.filter(src, dest);
541 public void setRGB(int x, int y, int argb)
543 Object rgbElem = colorModel.getDataElements(argb, null);
544 raster.setDataElements(x, y, rgbElem);
547 public void setRGB(int startX, int startY, int w, int h,
548 int[] argbArray, int offset, int scanlineStride)
550 int endX = startX + w;
551 int endY = startY + h;
553 Object rgbElem = null;
554 for (int y=startY; y<endY; y++)
556 int xoffset = offset;
557 for (int x=startX; x<endX; x++)
559 int argb = argbArray[xoffset++];
560 rgbElem = colorModel.getDataElements(argb, rgbElem);
561 raster.setDataElements(x, y, rgbElem);
563 offset += scanlineStride;
567 public String toString()
569 // FIXME: implement:
570 return super.toString();