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 };
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: public BufferedImage(int w, int h, int type)
103: {
104: ColorModel cm = null;
105:
106: boolean alpha = false;
107: boolean premultiplied = false;
108: switch (type)
109: {
110: case TYPE_4BYTE_ABGR_PRE:
111: case TYPE_INT_ARGB_PRE:
112: premultiplied = true;
113:
114: case TYPE_INT_ARGB:
115: case TYPE_4BYTE_ABGR:
116: alpha = true;
117: }
118:
119: ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
120: switch (type)
121: {
122: case TYPE_INT_RGB:
123: case TYPE_INT_ARGB:
124: case TYPE_INT_ARGB_PRE:
125: case TYPE_USHORT_565_RGB:
126: case TYPE_USHORT_555_RGB:
127: int[] masks = null;
128: switch (type)
129: {
130: case TYPE_INT_RGB:
131: case TYPE_INT_ARGB:
132: case TYPE_INT_ARGB_PRE:
133: masks = masks_int;
134: break;
135: case TYPE_USHORT_565_RGB:
136: masks = masks_565;
137: break;
138: case TYPE_USHORT_555_RGB:
139: masks = masks_555;
140: break;
141: }
142:
143: cm = new DirectColorModel(cs,
144: 32,
145: masks[0],
146: masks[1],
147: masks[2],
148: alpha ? 0xff000000 : 0,
149: premultiplied,
150: masks[3]
151: );
152: break;
153:
154: case TYPE_INT_BGR:
155: String msg =
156: "FIXME: Programmer is confused. Why (and how) does a " +
157: "TYPE_INT_BGR image use ComponentColorModel to store " +
158: "8-bit values? Is data type TYPE_INT or TYPE_BYTE. What " +
159: "is the difference between TYPE_INT_BGR and TYPE_3BYTE_BGR?";
160: throw new UnsupportedOperationException(msg);
161:
162: case TYPE_3BYTE_BGR:
163: case TYPE_4BYTE_ABGR:
164: case TYPE_4BYTE_ABGR_PRE:
165: case TYPE_BYTE_GRAY:
166: case TYPE_USHORT_GRAY:
167: int[] bits = null;
168: int dataType = DataBuffer.TYPE_BYTE;
169: switch (type) {
170: case TYPE_3BYTE_BGR:
171: bits = bits3;
172: break;
173: case TYPE_4BYTE_ABGR:
174: case TYPE_4BYTE_ABGR_PRE:
175: bits = bits4;
176: break;
177: case TYPE_BYTE_GRAY:
178: bits = bits1byte;
179: break;
180: case TYPE_USHORT_GRAY:
181: bits = bits1ushort;
182: dataType = DataBuffer.TYPE_USHORT;
183: break;
184: }
185: cm = new ComponentColorModel(cs, bits, alpha, premultiplied,
186: alpha ?
187: Transparency.TRANSLUCENT:
188: Transparency.OPAQUE,
189: dataType);
190: break;
191: case TYPE_BYTE_BINARY:
192: byte[] vals = { 0, (byte) 0xff };
193: cm = new IndexColorModel(8, 2, vals, vals, vals);
194: break;
195: case TYPE_BYTE_INDEXED:
196: String msg2 = "type not implemented yet";
197: throw new UnsupportedOperationException(msg2);
198:
199: }
200:
201: init(cm,
202: cm.createCompatibleWritableRaster(w, h),
203: premultiplied,
204: null,
205: type
206: );
207: }
208:
209: public BufferedImage(int w, int h, int type,
210: IndexColorModel indexcolormodel)
211: {
212: if ((type != TYPE_BYTE_BINARY) && (type != TYPE_BYTE_INDEXED))
213: throw new IllegalArgumentException("type must be binary or indexed");
214:
215: init(indexcolormodel,
216: indexcolormodel.createCompatibleWritableRaster(w, h),
217: false,
218: null,
219: type);
220: }
221:
222: public BufferedImage(ColorModel colormodel,
223: WritableRaster writableraster,
224: boolean premultiplied,
225: Hashtable properties)
226: {
227: init(colormodel, writableraster, premultiplied, properties,
228: TYPE_CUSTOM);
229:
230: }
231:
232: WritableRaster raster;
233: ColorModel colorModel;
234: Hashtable properties;
235: boolean isPremultiplied;
236: int type;
237:
238: private void init(ColorModel cm,
239: WritableRaster writableraster,
240: boolean premultiplied,
241: Hashtable properties,
242: int type)
243: {
244: raster = writableraster;
245: colorModel = cm;
246: this.properties = properties;
247: isPremultiplied = premultiplied;
248: this.type = type;
249: }
250:
251:
252:
253: public void coerceData(boolean premultiplied)
254: {
255: colorModel = colorModel.coerceData(raster, premultiplied);
256: }
257:
258: public WritableRaster copyData(WritableRaster dest)
259: {
260: if (dest == null)
261: dest = raster.createCompatibleWritableRaster(getMinX(), getMinY(),
262: getWidth(),getHeight());
263:
264: int x = dest.getMinX();
265: int y = dest.getMinY();
266: int w = dest.getWidth();
267: int h = dest.getHeight();
268:
269:
270: WritableRaster src =
271: raster.createWritableChild(x, y, w, h, x, y,
272: null
273: );
274: if (src.getSampleModel () instanceof ComponentSampleModel
275: && dest.getSampleModel () instanceof ComponentSampleModel)
276:
277: ComponentDataBlitOp.INSTANCE.filter(src, dest);
278: else
279: {
280:
281: int samples[] = src.getPixels (x, y, w, h, (int [])null);
282: dest.setPixels (x, y, w, h, samples);
283: }
284: return dest;
285: }
286:
287: public Graphics2D createGraphics()
288: {
289: GraphicsEnvironment env;
290: env = GraphicsEnvironment.getLocalGraphicsEnvironment ();
291: return env.createGraphics (this);
292: }
293:
294: public void flush() {
295: }
296:
297: public WritableRaster getAlphaRaster()
298: {
299: return colorModel.getAlphaRaster(raster);
300: }
301:
302: public ColorModel getColorModel()
303: {
304: return colorModel;
305: }
306:
307: public Raster getData()
308: {
309: return copyData(null);
310:
312: }
313:
314: public Raster getData(Rectangle rectangle)
315: {
316: WritableRaster dest =
317: raster.createCompatibleWritableRaster(rectangle);
318: return copyData(dest);
319: }
320:
321: public Graphics getGraphics()
322: {
323: return createGraphics();
324: }
325:
326: public int getHeight()
327: {
328: return raster.getHeight();
329: }
330:
331: public int getHeight(ImageObserver imageobserver)
332: {
333: return getHeight();
334: }
335:
336: public int getMinTileX()
337: {
338: return 0;
339: }
340:
341: public int getMinTileY()
342: {
343: return 0;
344: }
345:
346: public int getMinX()
347: {
348: return 0;
349: }
350:
351: public int getMinY()
352: {
353: return 0;
354: }
355:
356: public int getNumXTiles()
357: {
358: return 1;
359: }
360:
361: public int getNumYTiles()
362: {
363: return 1;
364: }
365:
366: public Object getProperty(String string)
367: {
368: if (properties == null)
369: return null;
370: return properties.get(string);
371: }
372:
373: public Object getProperty(String string, ImageObserver imageobserver)
374: {
375: return getProperty(string);
376: }
377:
378:
379: public String[] getPropertyNames()
380: {
381:
382: return null;
383: }
384:
385: public int getRGB(int x, int y)
386: {
387: Object rgbElem = raster.getDataElements(x, y,
388: null
389: );
390: return colorModel.getRGB(rgbElem);
391: }
392:
393: public int[] getRGB(int startX, int startY, int w, int h,
394: int[] rgbArray,
395: int offset, int scanlineStride)
396: {
397: if (rgbArray == null)
398: {
399:
405: int size = (h-1)*scanlineStride + w;
406: rgbArray = new int[size];
407: }
408:
409: int endX = startX + w;
410: int endY = startY + h;
411:
412:
418:
419: Object rgbElem = null;
420: for (int y=startY; y<endY; y++)
421: {
422: int xoffset = offset;
423: for (int x=startX; x<endX; x++)
424: {
425: int rgb;
426: rgbElem = raster.getDataElements(x, y, rgbElem);
427: rgb = colorModel.getRGB(rgbElem);
428: rgbArray[xoffset++] = rgb;
429: }
430: offset += scanlineStride;
431: }
432: return rgbArray;
433: }
434:
435: public WritableRaster getRaster()
436: {
437: return raster;
438: }
439:
440: public SampleModel getSampleModel()
441: {
442: return raster.getSampleModel();
443: }
444:
445: public ImageProducer getSource()
446: {
447: return new ImageProducer() {
448:
449: Vector consumers = new Vector();
450:
451: public void addConsumer(ImageConsumer ic)
452: {
453: if(!consumers.contains(ic))
454: consumers.add(ic);
455: }
456:
457: public boolean isConsumer(ImageConsumer ic)
458: {
459: return consumers.contains(ic);
460: }
461:
462: public void removeConsumer(ImageConsumer ic)
463: {
464: consumers.remove(ic);
465: }
466:
467: public void startProduction(ImageConsumer ic)
468: {
469: int x = 0;
470: int y = 0;
471: int width = getWidth();
472: int height = getHeight();
473: int stride = width;
474: int offset = 0;
475: int[] pixels = getRGB(x, y,
476: width, height,
477: (int[])null, offset, stride);
478: ColorModel model = getColorModel();
479:
480: consumers.add(ic);
481:
482: for(int i=0;i<consumers.size();i++)
483: {
484: ImageConsumer c = (ImageConsumer) consumers.elementAt(i);
485: c.setHints(ImageConsumer.SINGLEPASS);
486: c.setDimensions(getWidth(), getHeight());
487: c.setPixels(x, y, width, height, model, pixels, offset, stride);
488: c.imageComplete(ImageConsumer.STATICIMAGEDONE);
489: }
490: }
491:
492: public void requestTopDownLeftRightResend(ImageConsumer ic)
493: {
494: startProduction(ic);
495: }
496:
497: };
498: }
499:
500: public Vector getSources()
501: {
502: return null;
503: }
504:
505: public BufferedImage getSubimage(int x, int y, int w, int h)
506: {
507: WritableRaster subRaster =
508: getRaster().createWritableChild(x, y, w, h, 0, 0, null);
509:
510: return new BufferedImage(getColorModel(),
511: subRaster,
512: isPremultiplied,
513: properties);
514: }
515:
516: public Raster getTile(int tileX, int tileY)
517: {
518: return getWritableTile(tileX, tileY);
519: }
520:
521: public int getTileGridXOffset()
522: {
523: return 0;
524: }
525:
526: public int getTileGridYOffset()
527: {
528: return 0;
529: }
530:
531: public int getTileHeight()
532: {
533: return getHeight();
534: }
535:
536: public int getTileWidth()
537: {
538: return getWidth();
539: }
540:
541: public int getType()
542: {
543: return type;
544: }
545:
546: public int getWidth()
547: {
548: return raster.getWidth();
549: }
550:
551: public int getWidth(ImageObserver imageobserver)
552: {
553: return getWidth();
554: }
555:
556: public WritableRaster getWritableTile(int tileX, int tileY)
557: {
558: isTileWritable(tileX, tileY);
559: return raster;
560: }
561:
562: private static final Point[] tileIndices = { new Point() };
563:
564: public Point[] getWritableTileIndices()
565: {
566: return tileIndices;
567: }
568:
569: public boolean hasTileWriters()
570: {
571: return true;
572: }
573:
574: public boolean isAlphaPremultiplied()
575: {
576: return isPremultiplied;
577: }
578:
579: public boolean isTileWritable(int tileX, int tileY)
580: {
581: if ((tileX != 0) || (tileY != 0))
582: throw new ArrayIndexOutOfBoundsException("only tile is (0,0)");
583: return true;
584: }
585:
586: public void releaseWritableTile(int tileX, int tileY)
587: {
588: isTileWritable(tileX, tileY);
589: }
590:
591:
592:
593: public void setData(Raster src)
594: {
595: int x = src.getMinX();
596: int y = src.getMinY();
597: int w = src.getWidth();
598: int h = src.getHeight();
599:
600:
601: WritableRaster dest =
602: raster.createWritableChild(x, y, w, h, x, y,
603: null
604: );
605:
606: if (src.getSampleModel () instanceof ComponentSampleModel
607: && dest.getSampleModel () instanceof ComponentSampleModel)
608:
609:
610: ComponentDataBlitOp.INSTANCE.filter(src, dest);
611: else
612: {
613:
614: int samples[] = src.getPixels (x, y, w, h, (int [])null);
615: dest.setPixels (x, y, w, h, samples);
616: }
617: }
618:
619: public void setRGB(int x, int y, int argb)
620: {
621: Object rgbElem = colorModel.getDataElements(argb, null);
622: raster.setDataElements(x, y, rgbElem);
623: }
624:
625: public void setRGB(int startX, int startY, int w, int h,
626: int[] argbArray, int offset, int scanlineStride)
627: {
628: int endX = startX + w;
629: int endY = startY + h;
630:
631: Object rgbElem = null;
632: for (int y=startY; y<endY; y++)
633: {
634: int xoffset = offset;
635: for (int x=startX; x<endX; x++)
636: {
637: int argb = argbArray[xoffset++];
638: rgbElem = colorModel.getDataElements(argb, rgbElem);
639: raster.setDataElements(x, y, rgbElem);
640: }
641: offset += scanlineStride;
642: }
643: }
644:
645: public String toString()
646: {
647: StringBuffer buf;
648:
649: buf = new StringBuffer( 120);
650: buf.append("BufferedImage@");
651: buf.append(Integer.toHexString(hashCode()));
652: buf.append(": type=");
653: buf.append(type);
654: buf.append(' ');
655: buf.append(colorModel);
656: buf.append(' ');
657: buf.append(raster);
658:
659: return buf.toString();
660: }
661:
662:
663:
669: public void addTileObserver (TileObserver to)
670: {
671: if (observers == null)
672: observers = new Vector ();
673:
674: observers.add (to);
675: }
676:
677:
684: public void removeTileObserver (TileObserver to)
685: {
686: if (observers == null)
687: return;
688:
689: observers.remove (to);
690: }
691:
692:
699: public int getTransparency()
700: {
701: return colorModel.getTransparency();
702: }
703: }