1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54:
55:
65: public class BufferedImage extends Image
66: implements WritableRenderedImage, Transparency
67: {
68: public static final int TYPE_CUSTOM = 0,
69: TYPE_INT_RGB = 1,
70: TYPE_INT_ARGB = 2,
71: TYPE_INT_ARGB_PRE = 3,
72: TYPE_INT_BGR = 4,
73: TYPE_3BYTE_BGR = 5,
74: TYPE_4BYTE_ABGR = 6,
75: TYPE_4BYTE_ABGR_PRE = 7,
76: TYPE_USHORT_565_RGB = 8,
77: TYPE_USHORT_555_RGB = 9,
78: TYPE_BYTE_GRAY = 10,
79: TYPE_USHORT_GRAY = 11,
80: TYPE_BYTE_BINARY = 12,
81: TYPE_BYTE_INDEXED = 13;
82:
83:
86: Vector<TileObserver> tileObservers;
87:
88:
91: WritableRaster raster;
92:
93:
96: ColorModel colorModel;
97:
98:
101: Hashtable properties;
102:
103:
106: boolean isPremultiplied;
107:
108:
111: int type;
112:
113:
142: public BufferedImage(int width, int height, int type)
143: {
144: SampleModel sm = null;
145: ColorModel cm = null;
146: boolean premultiplied = (type == BufferedImage.TYPE_INT_ARGB_PRE
147: || type == BufferedImage.TYPE_4BYTE_ABGR_PRE);
148:
149: switch( type )
150: {
151: case BufferedImage.TYPE_INT_RGB:
152: sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT,
153: width, height,
154: new int[]{ 0x00FF0000,
155: 0x0000FF00,
156: 0x000000FF } ) ;
157: cm = new DirectColorModel( 24, 0xff0000, 0xff00, 0xff );
158: break;
159:
160: case BufferedImage.TYPE_3BYTE_BGR:
161: sm = new PixelInterleavedSampleModel( DataBuffer.TYPE_BYTE,
162: width, height,
163: 3, width * 3,
164: new int[]{ 2, 1, 0 } );
165: cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
166: false, false,
167: BufferedImage.OPAQUE,
168: DataBuffer.TYPE_BYTE);
169: break;
170:
171: case BufferedImage.TYPE_INT_ARGB:
172: case BufferedImage.TYPE_INT_ARGB_PRE:
173: sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT,
174: width, height,
175: new int[]{ 0x00FF0000,
176: 0x0000FF00,
177: 0x000000FF,
178: 0xFF000000 } );
179: if (premultiplied)
180: cm = new DirectColorModel( ColorSpace.getInstance(ColorSpace.CS_sRGB),
181: 32, 0xff0000, 0xff00, 0xff, 0xff000000,
182: true,
183: Buffers.smallestAppropriateTransferType(32));
184: else
185: cm = new DirectColorModel( 32, 0xff0000, 0xff00, 0xff, 0xff000000 );
186:
187: break;
188:
189: case BufferedImage.TYPE_4BYTE_ABGR:
190: case BufferedImage.TYPE_4BYTE_ABGR_PRE:
191: sm = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE,
192: width, height,
193: 4, 4*width,
194: new int[]{3, 2, 1, 0});
195: cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
196: true, premultiplied,
197: BufferedImage.TRANSLUCENT,
198: DataBuffer.TYPE_BYTE);
199: break;
200:
201: case BufferedImage.TYPE_INT_BGR:
202: sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_INT,
203: width, height,
204: new int[]{ 0x000000FF,
205: 0x0000FF00,
206: 0x00FF0000 } ) ;
207: cm = new DirectColorModel( 24, 0xff, 0xff00, 0xff0000 );
208: break;
209:
210: case BufferedImage.TYPE_USHORT_565_RGB:
211: sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_USHORT,
212: width, height,
213: new int[]{ 0xF800,
214: 0x7E0,
215: 0x1F } ) ;
216: cm = new DirectColorModel( 16, 0xF800, 0x7E0, 0x1F );
217: break;
218:
219: case BufferedImage.TYPE_USHORT_555_RGB:
220: sm = new SinglePixelPackedSampleModel( DataBuffer.TYPE_USHORT,
221: width, height,
222: new int[]{ 0x7C00,
223: 0x3E0,
224: 0x1F } ) ;
225: cm = new DirectColorModel( 15, 0x7C00, 0x3E0, 0x1F );
226: break;
227:
228: case BufferedImage.TYPE_BYTE_INDEXED:
229: cm = createDefaultIndexedColorModel( false );
230:
231: case BufferedImage.TYPE_BYTE_GRAY:
232: sm = new PixelInterleavedSampleModel( DataBuffer.TYPE_BYTE,
233: width, height,
234: 1, width, new int[]{ 0 } );
235: break;
236:
237: case BufferedImage.TYPE_USHORT_GRAY:
238: sm = new PixelInterleavedSampleModel( DataBuffer.TYPE_USHORT,
239: width, height,
240: 1, width, new int[]{ 0 } );
241: break;
242:
243: case BufferedImage.TYPE_BYTE_BINARY:
244: cm = createDefaultIndexedColorModel( true );
245: sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
246: width, height, 1);
247: break;
248:
249: default:
250: sm = null;
251: }
252:
253: if( sm == null )
254: throw new IllegalArgumentException("Unknown predefined image type.");
255:
256: if( cm == null )
257: {
258: int buftype;
259: int[] bits = new int[1];
260: if( type == BufferedImage.TYPE_BYTE_GRAY )
261: {
262: buftype = DataBuffer.TYPE_BYTE;
263: bits[0] = 8;
264: }
265: else
266: {
267: buftype = DataBuffer.TYPE_USHORT;
268: bits[0] = 16;
269: }
270: ColorSpace graySpace = ColorSpace.getInstance( ColorSpace.CS_GRAY );
271:
272: cm = new ComponentColorModel( graySpace, bits, false, false,
273: Transparency.OPAQUE, buftype );
274: }
275:
276: WritableRaster rst = null;
277:
278:
279: GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
280: if (env instanceof ClasspathGraphicsEnvironment)
281: rst = ((ClasspathGraphicsEnvironment)env).createRaster(cm, sm);
282:
283:
284: if (rst == null)
285: rst = Raster.createWritableRaster(sm, new Point( 0, 0 ) );
286:
287: init(cm, rst, premultiplied,
288: null,
289: type );
290: }
291:
292: public BufferedImage(int w, int h, int type, IndexColorModel indexcolormodel)
293: {
294: if ((type != TYPE_BYTE_BINARY) && (type != TYPE_BYTE_INDEXED))
295: throw new IllegalArgumentException("Type must be TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED");
296: if( indexcolormodel.getMapSize() > 16 && type == TYPE_BYTE_BINARY )
297: throw new IllegalArgumentException("Type TYPE_BYTE_BINARY cannot have a larger than 16-color palette.");
298: if( indexcolormodel.getMapSize() > 256 )
299: throw new IllegalArgumentException("Byte type cannot have a larger than 256-color palette.");
300:
301: init( indexcolormodel,
302: indexcolormodel.createCompatibleWritableRaster(w, h),
303: indexcolormodel.isAlphaPremultiplied(),
304: null,
305: type );
306: }
307:
308: public BufferedImage(ColorModel colormodel, WritableRaster writableraster,
309: boolean premultiplied, Hashtable<?,?> properties)
310: {
311: init(colormodel, writableraster, premultiplied, properties, TYPE_CUSTOM);
312: }
313:
314:
315: private void init(ColorModel cm, WritableRaster writableraster,
316: boolean premultiplied, Hashtable properties, int type)
317: {
318: raster = writableraster;
319: colorModel = cm;
320: this.properties = properties;
321: isPremultiplied = premultiplied;
322: this.type = type;
323: }
324:
325:
332: private IndexColorModel createDefaultIndexedColorModel( boolean binary )
333: {
334: if( binary )
335: {
336: byte[] t = new byte[]{ 0, (byte)255 };
337: return new IndexColorModel( 1, 2, t, t, t );
338: }
339:
340: byte[] r = new byte[256];
341: byte[] g = new byte[256];
342: byte[] b = new byte[256];
343:
344: int index = 0;
345: for( int i = 0; i < 6; i++ )
346: for( int j = 0; j < 6; j++ )
347: for( int k = 0; k < 6; k++ )
348: {
349: r[ index ] = (byte)(i * 51);
350: g[ index ] = (byte)(j * 51);
351: b[ index ] = (byte)(k * 51);
352: index++;
353: }
354:
355: while( index < 256 )
356: {
357: r[ index ] = g[ index ] = b[ index ] =
358: (byte)(18 + (index - 216) * 6);
359: index++;
360: }
361:
362: return new IndexColorModel( 8, 256, r, g, b );
363: }
364:
365: public void coerceData(boolean premultiplied)
366: {
367: colorModel = colorModel.coerceData(raster, premultiplied);
368: isPremultiplied = premultiplied;
369: }
370:
371: public WritableRaster copyData(WritableRaster dest)
372: {
373: if (dest == null)
374: dest = raster.createCompatibleWritableRaster(getMinX(), getMinY(),
375: getWidth(),getHeight());
376:
377: int x = dest.getMinX();
378: int y = dest.getMinY();
379: int w = dest.getWidth();
380: int h = dest.getHeight();
381:
382:
383: WritableRaster src =
384: raster.createWritableChild(x, y, w, h, x, y,
385: null);
386:
387: if (src.getSampleModel () instanceof ComponentSampleModel
388: && dest.getSampleModel () instanceof ComponentSampleModel)
389:
390: ComponentDataBlitOp.INSTANCE.filter(src, dest);
391:
392: else
393: {
394:
395: int samples[] = src.getPixels (x, y, w, h, (int [])null);
396: dest.setPixels (x, y, w, h, samples);
397: }
398: return dest;
399: }
400:
401: public Graphics2D createGraphics()
402: {
403: GraphicsEnvironment env;
404: env = GraphicsEnvironment.getLocalGraphicsEnvironment ();
405: return env.createGraphics (this);
406: }
407:
408: public void flush()
409: {
410: }
411:
412: public WritableRaster getAlphaRaster()
413: {
414: return colorModel.getAlphaRaster(raster);
415: }
416:
417: public ColorModel getColorModel()
418: {
419: return colorModel;
420: }
421:
422: public Raster getData()
423: {
424: return copyData(null);
425:
427: }
428:
429: public Raster getData(Rectangle rectangle)
430: {
431: WritableRaster dest =
432: raster.createCompatibleWritableRaster(rectangle);
433: return copyData(dest);
434: }
435:
436: public Graphics getGraphics()
437: {
438: return createGraphics();
439: }
440:
441: public int getHeight()
442: {
443: return raster.getHeight();
444: }
445:
446: public int getHeight(ImageObserver imageobserver)
447: {
448: return getHeight();
449: }
450:
451: public int getMinTileX()
452: {
453: return 0;
454: }
455:
456: public int getMinTileY()
457: {
458: return 0;
459: }
460:
461: public int getMinX()
462: {
463: return 0;
464: }
465:
466: public int getMinY()
467: {
468: return 0;
469: }
470:
471: public int getNumXTiles()
472: {
473: return 1;
474: }
475:
476: public int getNumYTiles()
477: {
478: return 1;
479: }
480:
481:
491: public Object getProperty(String string)
492: {
493: if (string == null)
494: throw new NullPointerException("The property name cannot be null.");
495: Object result = Image.UndefinedProperty;
496: if (properties != null)
497: {
498: Object v = properties.get(string);
499: if (v != null)
500: result = v;
501: }
502: return result;
503: }
504:
505: public Object getProperty(String string, ImageObserver imageobserver)
506: {
507: return getProperty(string);
508: }
509:
510:
515: public String[] getPropertyNames()
516: {
517:
518:
519: return null;
520: }
521:
522: public int getRGB(int x, int y)
523: {
524: Object rgbElem = raster.getDataElements(x, y, null);
525: return colorModel.getRGB(rgbElem);
526: }
527:
528: public int[] getRGB(int startX, int startY, int w, int h, int[] rgbArray,
529: int offset, int scanlineStride)
530: {
531: if (rgbArray == null)
532: {
533:
540: int size = (h-1)*scanlineStride + w;
541: rgbArray = new int[size];
542: }
543:
544: int endX = startX + w;
545: int endY = startY + h;
546:
547:
553:
554: Object rgbElem = null;
555: for (int y=startY; y<endY; y++)
556: {
557: int xoffset = offset;
558: for (int x=startX; x<endX; x++)
559: {
560: int rgb;
561: rgbElem = raster.getDataElements(x, y, rgbElem);
562: rgb = colorModel.getRGB(rgbElem);
563: rgbArray[xoffset++] = rgb;
564: }
565: offset += scanlineStride;
566: }
567: return rgbArray;
568: }
569:
570: public WritableRaster getRaster()
571: {
572: return raster;
573: }
574:
575: public SampleModel getSampleModel()
576: {
577: return raster.getSampleModel();
578: }
579:
580: public ImageProducer getSource()
581: {
582: return new ImageProducer()
583: {
584: Vector<ImageConsumer> consumers = new Vector<ImageConsumer>();
585:
586: public void addConsumer(ImageConsumer ic)
587: {
588: if(!consumers.contains(ic))
589: consumers.add(ic);
590: }
591:
592: public boolean isConsumer(ImageConsumer ic)
593: {
594: return consumers.contains(ic);
595: }
596:
597: public void removeConsumer(ImageConsumer ic)
598: {
599: consumers.remove(ic);
600: }
601:
602: public void startProduction(ImageConsumer ic)
603: {
604: int x = 0;
605: int y = 0;
606: int width = getWidth();
607: int height = getHeight();
608: int stride = width;
609: int offset = 0;
610: int[] pixels = getRGB(x, y,
611: width, height,
612: (int[])null, offset, stride);
613:
614:
615: ColorModel model = new DirectColorModel(32, 0xff0000, 0xff00, 0xff,
616: 0xff000000);
617:
618: consumers.add(ic);
619:
620: for(int i = 0; i < consumers.size(); i++)
621: {
622: ImageConsumer c = consumers.elementAt(i);
623: c.setHints(ImageConsumer.SINGLEPASS);
624: c.setDimensions(getWidth(), getHeight());
625: c.setPixels(x, y, width, height, model, pixels, offset, stride);
626: c.imageComplete(ImageConsumer.STATICIMAGEDONE);
627: }
628: }
629:
630: public void requestTopDownLeftRightResend(ImageConsumer ic)
631: {
632: startProduction(ic);
633: }
634:
635: };
636: }
637:
638: public Vector<RenderedImage> getSources()
639: {
640: return null;
641: }
642:
643: public BufferedImage getSubimage(int x, int y, int w, int h)
644: {
645: WritableRaster subRaster =
646: getRaster().createWritableChild(x, y, w, h, 0, 0, null);
647:
648: return new BufferedImage(getColorModel(), subRaster, isPremultiplied,
649: properties);
650: }
651:
652: public Raster getTile(int tileX, int tileY)
653: {
654: return getWritableTile(tileX, tileY);
655: }
656:
657: public int getTileGridXOffset()
658: {
659: return 0;
660: }
661:
662: public int getTileGridYOffset()
663: {
664: return 0;
665: }
666:
667: public int getTileHeight()
668: {
669: return getHeight();
670: }
671:
672: public int getTileWidth()
673: {
674: return getWidth();
675: }
676:
677: public int getType()
678: {
679: return type;
680: }
681:
682: public int getWidth()
683: {
684: return raster.getWidth();
685: }
686:
687: public int getWidth(ImageObserver imageobserver)
688: {
689: return getWidth();
690: }
691:
692: public WritableRaster getWritableTile(int tileX, int tileY)
693: {
694: isTileWritable(tileX, tileY);
695: return raster;
696: }
697:
698: private static final Point[] tileIndices = { new Point() };
699:
700: public Point[] getWritableTileIndices()
701: {
702: return tileIndices;
703: }
704:
705: public boolean hasTileWriters()
706: {
707: return true;
708: }
709:
710: public boolean isAlphaPremultiplied()
711: {
712: return isPremultiplied;
713: }
714:
715: public boolean isTileWritable(int tileX, int tileY)
716: {
717: if ((tileX != 0) || (tileY != 0))
718: throw new ArrayIndexOutOfBoundsException("only tile is (0,0)");
719: return true;
720: }
721:
722: public void releaseWritableTile(int tileX, int tileY)
723: {
724: isTileWritable(tileX, tileY);
725: }
726:
727:
728:
729: public void setData(Raster src)
730: {
731: int x = src.getMinX();
732: int y = src.getMinY();
733: int w = src.getWidth();
734: int h = src.getHeight();
735:
736:
737: WritableRaster dest =
738: raster.createWritableChild(x, y, w, h, x, y, null);
739:
740: if (src.getSampleModel () instanceof ComponentSampleModel
741: && dest.getSampleModel () instanceof ComponentSampleModel)
742:
743:
744: ComponentDataBlitOp.INSTANCE.filter(src, dest);
745: else
746: {
747:
748: int samples[] = src.getPixels (x, y, w, h, (int [])null);
749: dest.setPixels (x, y, w, h, samples);
750: }
751: }
752:
753: public void setRGB(int x, int y, int argb)
754: {
755: Object rgbElem = colorModel.getDataElements(argb, null);
756: raster.setDataElements(x, y, rgbElem);
757: }
758:
759: public void setRGB(int startX, int startY, int w, int h,
760: int[] argbArray, int offset, int scanlineStride)
761: {
762: int endX = startX + w;
763: int endY = startY + h;
764:
765: Object rgbElem = null;
766: for (int y=startY; y<endY; y++)
767: {
768: int xoffset = offset;
769: for (int x=startX; x<endX; x++)
770: {
771: int argb = argbArray[xoffset++];
772: rgbElem = colorModel.getDataElements(argb, rgbElem);
773: raster.setDataElements(x, y, rgbElem);
774: }
775: offset += scanlineStride;
776: }
777: }
778:
779: public String toString()
780: {
781: StringBuffer buf;
782:
783: buf = new StringBuffer( 120);
784: buf.append("BufferedImage@");
785: buf.append(Integer.toHexString(hashCode()));
786: buf.append(": type=");
787: buf.append(type);
788: buf.append(' ');
789: buf.append(colorModel);
790: buf.append(' ');
791: buf.append(raster);
792:
793: return buf.toString();
794: }
795:
796:
797:
803: public void addTileObserver (TileObserver to)
804: {
805: if (tileObservers == null)
806: tileObservers = new Vector<TileObserver>();
807:
808: tileObservers.add (to);
809: }
810:
811:
818: public void removeTileObserver (TileObserver to)
819: {
820: if (tileObservers == null)
821: return;
822:
823: tileObservers.remove (to);
824: }
825:
826:
833: public int getTransparency()
834: {
835: return colorModel.getTransparency();
836: }
837: }