source: trunk/gcc/libjava/java/awt/image/BufferedImage.java

Last change on this file was 2, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 13.5 KB
Line 
1/* Copyright (C) 2000, 2002 Free Software Foundation
2
3This file is part of GNU Classpath.
4
5GNU Classpath is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 2, or (at your option)
8any later version.
9
10GNU Classpath is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with GNU Classpath; see the file COPYING. If not, write to the
17Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
1802111-1307 USA.
19
20Linking this library statically or dynamically with other modules is
21making a combined work based on this library. Thus, the terms and
22conditions of the GNU General Public License cover the whole
23combination.
24
25As a special exception, the copyright holders of this library give you
26permission to link this library with independent modules to produce an
27executable, regardless of the license terms of these independent
28modules, and to copy and distribute the resulting executable under
29terms of your choice, provided that you also meet, for each linked
30independent module, the terms and conditions of the license of that
31module. An independent module is a module which is not derived from
32or based on this library. If you modify this library, you may extend
33this exception to your version of the library, but you are not
34obligated to do so. If you do not wish to do so, delete this
35exception statement from your version. */
36
37
38package java.awt.image;
39
40import java.awt.*;
41import java.awt.color.*;
42import java.util.*;
43
44import gnu.java.awt.ComponentDataBlitOp;
45
46/**
47 * A buffered image always starts at coordinates (0, 0).
48 *
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.
53 *
54 * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
55 */
56public class BufferedImage extends java.awt.Image
57 //implements java.awt.image.WritableRenderedImage
58{
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;
73
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 };
78
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};
91
92 public BufferedImage(int w, int h, int type)
93 {
94 ColorModel cm = null;
95
96 boolean alpha = false;
97 boolean premultiplied = false;
98 switch (type)
99 {
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;
107 }
108
109 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
110 switch (type)
111 {
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)
119 {
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;
131 }
132
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
141 );
142 break;
143
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);
151
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;
174 }
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
189 }
190
191 init(cm,
192 cm.createCompatibleWritableRaster(w, h),
193 premultiplied,
194 null, // no properties
195 type
196 );
197 }
198
199 public BufferedImage(int w, int h, int type,
200 IndexColorModel indexcolormodel)
201 {
202 if ((type != TYPE_BYTE_BINARY) && (type != TYPE_BYTE_INDEXED))
203 throw new IllegalArgumentException("type must be binary or indexed");
204
205 init(indexcolormodel,
206 indexcolormodel.createCompatibleWritableRaster(w, h),
207 false, // not premultiplied (guess)
208 null, // no properties
209 type);
210 }
211
212 public BufferedImage(ColorModel colormodel,
213 WritableRaster writableraster,
214 boolean premultiplied,
215 Hashtable properties)
216 {
217 init(colormodel, writableraster, premultiplied, properties,
218 TYPE_CUSTOM);
219 // TODO: perhaps try to identify type?
220 }
221
222 WritableRaster raster;
223 ColorModel colorModel;
224 Hashtable properties;
225 boolean isPremultiplied;
226 int type;
227
228 private void init(ColorModel cm,
229 WritableRaster writableraster,
230 boolean premultiplied,
231 Hashtable properties,
232 int type)
233 {
234 raster = writableraster;
235 colorModel = cm;
236 this.properties = properties;
237 isPremultiplied = premultiplied;
238 this.type = type;
239 }
240
241 //public void addTileObserver(TileObserver tileobserver) {}
242
243 public void coerceData(boolean premultiplied)
244 {
245 colorModel = colorModel.coerceData(raster, premultiplied);
246 }
247
248 public WritableRaster copyData(WritableRaster dest)
249 {
250 if (dest == null)
251 dest = raster.createCompatibleWritableRaster();
252
253 int x = dest.getMinX();
254 int y = dest.getMinY();
255 int w = dest.getWidth();
256 int h = dest.getHeight();
257
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
262 );
263
264 // Refer to ComponentDataBlitOp for optimized data blitting:
265 ComponentDataBlitOp.INSTANCE.filter(src, dest);
266 return dest;
267 }
268
269 public Graphics2D createGraphics()
270 {
271 throw new UnsupportedOperationException("not implemented");
272 // will require a lot of effort to implement
273 }
274
275 public void flush() {
276 }
277
278 public WritableRaster getAlphaRaster()
279 {
280 return colorModel.getAlphaRaster(raster);
281 }
282
283 public ColorModel getColorModel()
284 {
285 return colorModel;
286 }
287
288 public Raster getData()
289 {
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. */
293 }
294
295 public Raster getData(Rectangle rectangle)
296 {
297 WritableRaster dest =
298 raster.createCompatibleWritableRaster(rectangle);
299 return copyData(dest);
300 }
301
302 public Graphics getGraphics()
303 {
304 return createGraphics();
305 }
306
307 public int getHeight()
308 {
309 return raster.getHeight();
310 }
311
312 public int getHeight(ImageObserver imageobserver)
313 {
314 return getHeight();
315 }
316
317 public int getMinTileX()
318 {
319 return 0;
320 }
321
322 public int getMinTileY()
323 {
324 return 0;
325 }
326
327 public int getMinX()
328 {
329 return 0;
330 }
331
332 public int getMinY()
333 {
334 return 0;
335 }
336
337 public int getNumXTiles()
338 {
339 return 1;
340 }
341
342 public int getNumYTiles()
343 {
344 return 1;
345 }
346
347 public Object getProperty(String string)
348 {
349 if (properties == null)
350 return null;
351 return properties.get(string);
352 }
353
354 public Object getProperty(String string, ImageObserver imageobserver)
355 {
356 return getProperty(string);
357 }
358
359
360 public String[] getPropertyNames()
361 {
362 // FIXME: implement
363 return null;
364 }
365
366 public int getRGB(int x, int y)
367 {
368 Object rgbElem = raster.getDataElements(x, y,
369 null // create as needed
370 );
371 return colorModel.getRGB(rgbElem);
372 }
373
374 public int[] getRGB(int startX, int startY, int w, int h,
375 int[] rgbArray,
376 int offset, int scanlineStride)
377 {
378 if (rgbArray == null)
379 {
380 /*
381 000000000000000000
382 00000[#######----- [ = start
383 -----########----- ] = end
384 -----#######]00000
385 000000000000000000 */
386 int size = (h-1)*scanlineStride + w;
387 rgbArray = new int[size];
388 }
389
390 int endX = startX + w;
391 int endY = startY + h;
392
393 /* *TODO*:
394 Opportunity for optimization by examining color models...
395
396 Perhaps wrap the rgbArray up in a WritableRaster with packed
397 sRGB color model and perform optimized rendering into the
398 array. */
399
400 Object rgbElem = null;
401 for (int y=startY; y<endY; y++)
402 {
403 int xoffset = offset;
404 for (int x=startX; x<endX; x++)
405 {
406 int rgb;
407 rgbElem = raster.getDataElements(x, y, rgbElem);
408 rgb = colorModel.getRGB(rgbElem);
409 rgbArray[xoffset++] = rgb;
410 }
411 offset += scanlineStride;
412 }
413 return rgbArray;
414 }
415
416 public WritableRaster getRaster()
417 {
418 return raster;
419 }
420
421 public SampleModel getSampleModel()
422 {
423 return raster.getSampleModel();
424 }
425
426 public ImageProducer getSource()
427 {
428 throw new UnsupportedOperationException("not implemented");
429 }
430
431 public Vector getSources()
432 {
433 return null;
434 }
435
436 public BufferedImage getSubimage(int x, int y, int w, int h)
437 {
438 WritableRaster subRaster =
439 getRaster().createWritableChild(x, y, w, h, 0, 0, null);
440
441 return new BufferedImage(getColorModel(),
442 subRaster,
443 isPremultiplied,
444 properties);
445 }
446
447 public Raster getTile(int tileX, int tileY)
448 {
449 return getWritableTile(tileX, tileY);
450 }
451
452 public int getTileGridXOffset()
453 {
454 return 0; // according to javadocs
455 }
456
457 public int getTileGridYOffset()
458 {
459 return 0; // according to javadocs
460 }
461
462 public int getTileHeight()
463 {
464 return getHeight(); // image is one big tile
465 }
466
467 public int getTileWidth()
468 {
469 return getWidth(); // image is one big tile
470 }
471
472 public int getType()
473 {
474 return type;
475 }
476
477 public int getWidth()
478 {
479 return raster.getWidth();
480 }
481
482 public int getWidth(ImageObserver imageobserver)
483 {
484 return getWidth();
485 }
486
487 public WritableRaster getWritableTile(int tileX, int tileY)
488 {
489 isTileWritable(tileX, tileY); // for exception
490 return raster;
491 }
492
493 private static final Point[] tileIndices = { new Point() };
494
495 public Point[] getWritableTileIndices()
496 {
497 return tileIndices;
498 }
499
500 public boolean hasTileWriters()
501 {
502 return true;
503 }
504
505 public boolean isAlphaPremultiplied()
506 {
507 return isPremultiplied;
508 }
509
510 public boolean isTileWritable(int tileX, int tileY)
511 {
512 if ((tileX != 0) || (tileY != 0))
513 throw new ArrayIndexOutOfBoundsException("only tile is (0,0)");
514 return true;
515 }
516
517 public void releaseWritableTile(int tileX, int tileY)
518 {
519 isTileWritable(tileX, tileY); // for exception
520 }
521
522 //public void removeTileObserver(TileObserver tileobserver) {}
523
524 public void setData(Raster src)
525 {
526 int x = src.getMinX();
527 int y = src.getMinY();
528 int w = src.getWidth();
529 int h = src.getHeight();
530
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
535 );
536
537 // Refer to ComponentDataBlitOp for optimized data blitting:
538 ComponentDataBlitOp.INSTANCE.filter(src, dest);
539 }
540
541 public void setRGB(int x, int y, int argb)
542 {
543 Object rgbElem = colorModel.getDataElements(argb, null);
544 raster.setDataElements(x, y, rgbElem);
545 }
546
547 public void setRGB(int startX, int startY, int w, int h,
548 int[] argbArray, int offset, int scanlineStride)
549 {
550 int endX = startX + w;
551 int endY = startY + h;
552
553 Object rgbElem = null;
554 for (int y=startY; y<endY; y++)
555 {
556 int xoffset = offset;
557 for (int x=startX; x<endX; x++)
558 {
559 int argb = argbArray[xoffset++];
560 rgbElem = colorModel.getDataElements(argb, rgbElem);
561 raster.setDataElements(x, y, rgbElem);
562 }
563 offset += scanlineStride;
564 }
565 }
566
567 public String toString()
568 {
569 // FIXME: implement:
570 return super.toString();
571 }
572}
Note: See TracBrowser for help on using the repository browser.