1:
37:
38:
39: package ;
40:
41: import ;
42:
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53:
54:
64: public class BufferedImage extends Image
65: implements WritableRenderedImage, Transparency
66: {
67: public static final int TYPE_CUSTOM = 0,
68: TYPE_INT_RGB = 1,
69: TYPE_INT_ARGB = 2,
70: TYPE_INT_ARGB_PRE = 3,
71: TYPE_INT_BGR = 4,
72: TYPE_3BYTE_BGR = 5,
73: TYPE_4BYTE_ABGR = 6,
74: TYPE_4BYTE_ABGR_PRE = 7,
75: TYPE_USHORT_565_RGB = 8,
76: TYPE_USHORT_555_RGB = 9,
77: TYPE_BYTE_GRAY = 10,
78: TYPE_USHORT_GRAY = 11,
79: TYPE_BYTE_BINARY = 12,
80: TYPE_BYTE_INDEXED = 13;
81:
82: static final int[] bits3 = { 8, 8, 8 };
83: static final int[] bits4 = { 8, 8, 8, 8 };
84: static final int[] bits1byte = { 8 };
85: static final int[] bits1ushort = { 16 };
86:
87: static final int[] masks_int = { 0x00ff0000,
88: 0x0000ff00,
89: 0x000000ff,
90: DataBuffer.TYPE_INT };
91: static final int[] masks_565 = { 0xf800,
92: 0x07e0,
93: 0x001f,
94: DataBuffer.TYPE_USHORT};
95: static final int[] masks_555 = { 0x7c00,
96: 0x03e0,
97: 0x001f,
98: DataBuffer.TYPE_USHORT};
99:
100: Vector observers;
101:
102:
131: public BufferedImage(int w, int h, int type)
132: {
133: ColorModel cm = null;
134:
135: boolean alpha = false;
136: boolean premultiplied = false;
137: switch (type)
138: {
139: case TYPE_4BYTE_ABGR_PRE:
140: case TYPE_INT_ARGB_PRE:
141: premultiplied = true;
142:
143: case TYPE_INT_ARGB:
144: case TYPE_4BYTE_ABGR:
145: alpha = true;
146: }
147:
148: ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
149: switch (type)
150: {
151: case TYPE_INT_RGB:
152: case TYPE_INT_ARGB:
153: case TYPE_INT_ARGB_PRE:
154: case TYPE_USHORT_565_RGB:
155: case TYPE_USHORT_555_RGB:
156: int[] masks = null;
157: switch (type)
158: {
159: case TYPE_INT_RGB:
160: case TYPE_INT_ARGB:
161: case TYPE_INT_ARGB_PRE:
162: masks = masks_int;
163: break;
164: case TYPE_USHORT_565_RGB:
165: masks = masks_565;
166: break;
167: case TYPE_USHORT_555_RGB:
168: masks = masks_555;
169: break;
170: }
171:
172: cm = new DirectColorModel(cs,
173: 32,
174: masks[0],
175: masks[1],
176: masks[2],
177: alpha ? 0xff000000 : 0,
178: premultiplied,
179: masks[3]
180: );
181: break;
182:
183: case TYPE_INT_BGR:
184: String msg =
185: "FIXME: Programmer is confused. Why (and how) does a " +
186: "TYPE_INT_BGR image use ComponentColorModel to store " +
187: "8-bit values? Is data type TYPE_INT or TYPE_BYTE. What " +
188: "is the difference between TYPE_INT_BGR and TYPE_3BYTE_BGR?";
189: throw new UnsupportedOperationException(msg);
190:
191: case TYPE_3BYTE_BGR:
192: case TYPE_4BYTE_ABGR:
193: case TYPE_4BYTE_ABGR_PRE:
194: case TYPE_BYTE_GRAY:
195: case TYPE_USHORT_GRAY:
196: int[] bits = null;
197: int dataType = DataBuffer.TYPE_BYTE;
198: switch (type) {
199: case TYPE_3BYTE_BGR:
200: bits = bits3;
201: break;
202: case TYPE_4BYTE_ABGR:
203: case TYPE_4BYTE_ABGR_PRE:
204: bits = bits4;
205: break;
206: case TYPE_BYTE_GRAY:
207: bits = bits1byte;
208: cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
209: break;
210: case TYPE_USHORT_GRAY:
211: bits = bits1ushort;
212: cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
213: dataType = DataBuffer.TYPE_USHORT;
214: break;
215: }
216: cm = new ComponentColorModel(cs, bits, alpha, premultiplied,
217: alpha ?
218: Transparency.TRANSLUCENT:
219: Transparency.OPAQUE,
220: dataType);
221: break;
222: case TYPE_BYTE_BINARY:
223: byte[] vals = { 0, (byte) 0xff };
224: cm = new IndexColorModel(8, 2, vals, vals, vals);
225: break;
226: case TYPE_BYTE_INDEXED:
227: String msg2 = "type not implemented yet";
228: throw new UnsupportedOperationException(msg2);
229:
230: default:
231: throw new IllegalArgumentException("Unknown image type " + type);
232: }
233:
234: init(cm,
235: cm.createCompatibleWritableRaster(w, h),
236: premultiplied,
237: null,
238: type
239: );
240: }
241:
242: public BufferedImage(int w, int h, int type,
243: IndexColorModel indexcolormodel)
244: {
245: if ((type != TYPE_BYTE_BINARY) && (type != TYPE_BYTE_INDEXED))
246: throw new IllegalArgumentException("type must be binary or indexed");
247:
248: init(indexcolormodel,
249: indexcolormodel.createCompatibleWritableRaster(w, h),
250: false,
251: null,
252: type);
253: }
254:
255: public BufferedImage(ColorModel colormodel,
256: WritableRaster writableraster,
257: boolean premultiplied,
258: Hashtable properties)
259: {
260: init(colormodel, writableraster, premultiplied, properties,
261: TYPE_CUSTOM);
262:
263: }
264:
265: WritableRaster raster;
266: ColorModel colorModel;
267: Hashtable properties;
268: boolean isPremultiplied;
269: int type;
270:
271: private void init(ColorModel cm,
272: WritableRaster writableraster,
273: boolean premultiplied,
274: Hashtable properties,
275: int type)
276: {
277: raster = writableraster;
278: colorModel = cm;
279: this.properties = properties;
280: isPremultiplied = premultiplied;
281: this.type = type;
282: }
283:
284:
285:
286: public void coerceData(boolean premultiplied)
287: {
288: colorModel = colorModel.coerceData(raster, premultiplied);
289: }
290:
291: public WritableRaster copyData(WritableRaster dest)
292: {
293: if (dest == null)
294: dest = raster.createCompatibleWritableRaster(getMinX(), getMinY(),
295: getWidth(),getHeight());
296:
297: int x = dest.getMinX();
298: int y = dest.getMinY();
299: int w = dest.getWidth();
300: int h = dest.getHeight();
301:
302:
303: WritableRaster src =
304: raster.createWritableChild(x, y, w, h, x, y,
305: null
306: );
307: if (src.getSampleModel () instanceof ComponentSampleModel
308: && dest.getSampleModel () instanceof ComponentSampleModel)
309:
310: ComponentDataBlitOp.INSTANCE.filter(src, dest);
311: else
312: {
313:
314: int samples[] = src.getPixels (x, y, w, h, (int [])null);
315: dest.setPixels (x, y, w, h, samples);
316: }
317: return dest;
318: }
319:
320: public Graphics2D createGraphics()
321: {
322: GraphicsEnvironment env;
323: env = GraphicsEnvironment.getLocalGraphicsEnvironment ();
324: return env.createGraphics (this);
325: }
326:
327: public void flush() {
328: }
329:
330: public WritableRaster getAlphaRaster()
331: {
332: return colorModel.getAlphaRaster(raster);
333: }
334:
335: public ColorModel getColorModel()
336: {
337: return colorModel;
338: }
339:
340: public Raster getData()
341: {
342: return copyData(null);
343:
345: }
346:
347: public Raster getData(Rectangle rectangle)
348: {
349: WritableRaster dest =
350: raster.createCompatibleWritableRaster(rectangle);
351: return copyData(dest);
352: }
353:
354: public Graphics getGraphics()
355: {
356: return createGraphics();
357: }
358:
359: public int getHeight()
360: {
361: return raster.getHeight();
362: }
363:
364: public int getHeight(ImageObserver imageobserver)
365: {
366: return getHeight();
367: }
368:
369: public int getMinTileX()
370: {
371: return 0;
372: }
373:
374: public int getMinTileY()
375: {
376: return 0;
377: }
378:
379: public int getMinX()
380: {
381: return 0;
382: }
383:
384: public int getMinY()
385: {
386: return 0;
387: }
388:
389: public int getNumXTiles()
390: {
391: return 1;
392: }
393:
394: public int getNumYTiles()
395: {
396: return 1;
397: }
398:
399:
409: public Object getProperty(String string)
410: {
411: if (string == null)
412: throw new NullPointerException("The property name cannot be null.");
413: Object result = Image.UndefinedProperty;
414: if (properties != null)
415: {
416: Object v = properties.get(string);
417: if (v != null)
418: result = v;
419: }
420: return result;
421: }
422:
423: public Object getProperty(String string, ImageObserver imageobserver)
424: {
425: return getProperty(string);
426: }
427:
428:
433: public String[] getPropertyNames()
434: {
435:
436:
437: return null;
438: }
439:
440: public int getRGB(int x, int y)
441: {
442: Object rgbElem = raster.getDataElements(x, y,
443: null
444: );
445: return colorModel.getRGB(rgbElem);
446: }
447:
448: public int[] getRGB(int startX, int startY, int w, int h,
449: int[] rgbArray,
450: int offset, int scanlineStride)
451: {
452: if (rgbArray == null)
453: {
454:
460: int size = (h-1)*scanlineStride + w;
461: rgbArray = new int[size];
462: }
463:
464: int endX = startX + w;
465: int endY = startY + h;
466:
467:
473:
474: Object rgbElem = null;
475: for (int y=startY; y<endY; y++)
476: {
477: int xoffset = offset;
478: for (int x=startX; x<endX; x++)
479: {
480: int rgb;
481: rgbElem = raster.getDataElements(x, y, rgbElem);
482: rgb = colorModel.getRGB(rgbElem);
483: rgbArray[xoffset++] = rgb;
484: }
485: offset += scanlineStride;
486: }
487: return rgbArray;
488: }
489:
490: public WritableRaster getRaster()
491: {
492: return raster;
493: }
494:
495: public SampleModel getSampleModel()
496: {
497: return raster.getSampleModel();
498: }
499:
500: public ImageProducer getSource()
501: {
502: return new ImageProducer() {
503:
504: Vector consumers = new Vector();
505:
506: public void addConsumer(ImageConsumer ic)
507: {
508: if(!consumers.contains(ic))
509: consumers.add(ic);
510: }
511:
512: public boolean isConsumer(ImageConsumer ic)
513: {
514: return consumers.contains(ic);
515: }
516:
517: public void removeConsumer(ImageConsumer ic)
518: {
519: consumers.remove(ic);
520: }
521:
522: public void startProduction(ImageConsumer ic)
523: {
524: int x = 0;
525: int y = 0;
526: int width = getWidth();
527: int height = getHeight();
528: int stride = width;
529: int offset = 0;
530: int[] pixels = getRGB(x, y,
531: width, height,
532: (int[])null, offset, stride);
533:
534:
535: ColorModel model = new DirectColorModel(32, 0xff0000, 0xff00, 0xff,
536: 0xff000000);
537:
538: consumers.add(ic);
539:
540: for(int i=0;i<consumers.size();i++)
541: {
542: ImageConsumer c = (ImageConsumer) consumers.elementAt(i);
543: c.setHints(ImageConsumer.SINGLEPASS);
544: c.setDimensions(getWidth(), getHeight());
545: c.setPixels(x, y, width, height, model, pixels, offset, stride);
546: c.imageComplete(ImageConsumer.STATICIMAGEDONE);
547: }
548: }
549:
550: public void requestTopDownLeftRightResend(ImageConsumer ic)
551: {
552: startProduction(ic);
553: }
554:
555: };
556: }
557:
558: public Vector getSources()
559: {
560: return null;
561: }
562:
563: public BufferedImage getSubimage(int x, int y, int w, int h)
564: {
565: WritableRaster subRaster =
566: getRaster().createWritableChild(x, y, w, h, 0, 0, null);
567:
568: return new BufferedImage(getColorModel(),
569: subRaster,
570: isPremultiplied,
571: properties);
572: }
573:
574: public Raster getTile(int tileX, int tileY)
575: {
576: return getWritableTile(tileX, tileY);
577: }
578:
579: public int getTileGridXOffset()
580: {
581: return 0;
582: }
583:
584: public int getTileGridYOffset()
585: {
586: return 0;
587: }
588:
589: public int getTileHeight()
590: {
591: return getHeight();
592: }
593:
594: public int getTileWidth()
595: {
596: return getWidth();
597: }
598:
599: public int getType()
600: {
601: return type;
602: }
603:
604: public int getWidth()
605: {
606: return raster.getWidth();
607: }
608:
609: public int getWidth(ImageObserver imageobserver)
610: {
611: return getWidth();
612: }
613:
614: public WritableRaster getWritableTile(int tileX, int tileY)
615: {
616: isTileWritable(tileX, tileY);
617: return raster;
618: }
619:
620: private static final Point[] tileIndices = { new Point() };
621:
622: public Point[] getWritableTileIndices()
623: {
624: return tileIndices;
625: }
626:
627: public boolean hasTileWriters()
628: {
629: return true;
630: }
631:
632: public boolean isAlphaPremultiplied()
633: {
634: return isPremultiplied;
635: }
636:
637: public boolean isTileWritable(int tileX, int tileY)
638: {
639: if ((tileX != 0) || (tileY != 0))
640: throw new ArrayIndexOutOfBoundsException("only tile is (0,0)");
641: return true;
642: }
643:
644: public void releaseWritableTile(int tileX, int tileY)
645: {
646: isTileWritable(tileX, tileY);
647: }
648:
649:
650:
651: public void setData(Raster src)
652: {
653: int x = src.getMinX();
654: int y = src.getMinY();
655: int w = src.getWidth();
656: int h = src.getHeight();
657:
658:
659: WritableRaster dest =
660: raster.createWritableChild(x, y, w, h, x, y,
661: null
662: );
663:
664: if (src.getSampleModel () instanceof ComponentSampleModel
665: && dest.getSampleModel () instanceof ComponentSampleModel)
666:
667:
668: ComponentDataBlitOp.INSTANCE.filter(src, dest);
669: else
670: {
671:
672: int samples[] = src.getPixels (x, y, w, h, (int [])null);
673: dest.setPixels (x, y, w, h, samples);
674: }
675: }
676:
677: public void setRGB(int x, int y, int argb)
678: {
679: Object rgbElem = colorModel.getDataElements(argb, null);
680: raster.setDataElements(x, y, rgbElem);
681: }
682:
683: public void setRGB(int startX, int startY, int w, int h,
684: int[] argbArray, int offset, int scanlineStride)
685: {
686: int endX = startX + w;
687: int endY = startY + h;
688:
689: Object rgbElem = null;
690: for (int y=startY; y<endY; y++)
691: {
692: int xoffset = offset;
693: for (int x=startX; x<endX; x++)
694: {
695: int argb = argbArray[xoffset++];
696: rgbElem = colorModel.getDataElements(argb, rgbElem);
697: raster.setDataElements(x, y, rgbElem);
698: }
699: offset += scanlineStride;
700: }
701: }
702:
703: public String toString()
704: {
705: StringBuffer buf;
706:
707: buf = new StringBuffer( 120);
708: buf.append("BufferedImage@");
709: buf.append(Integer.toHexString(hashCode()));
710: buf.append(": type=");
711: buf.append(type);
712: buf.append(' ');
713: buf.append(colorModel);
714: buf.append(' ');
715: buf.append(raster);
716:
717: return buf.toString();
718: }
719:
720:
721:
727: public void addTileObserver (TileObserver to)
728: {
729: if (observers == null)
730: observers = new Vector ();
731:
732: observers.add (to);
733: }
734:
735:
742: public void removeTileObserver (TileObserver to)
743: {
744: if (observers == null)
745: return;
746:
747: observers.remove (to);
748: }
749:
750:
757: public int getTransparency()
758: {
759: return colorModel.getTransparency();
760: }
761: }