001: /*
002: * $RCSfile: AWTImageOpImage.java,v $
003: *
004: * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Use is subject to license terms.
007: *
008: * $Revision: 1.1 $
009: * $Date: 2005/02/11 04:56:10 $
010: * $State: Exp $
011: */
012: package com.sun.media.jai.opimage;
013:
014: import java.awt.Canvas;
015: import java.awt.Image;
016: import java.awt.MediaTracker;
017: import java.awt.Point;
018: import java.awt.Rectangle;
019: import java.awt.image.DataBuffer;
020: import java.awt.image.DataBufferInt;
021: import java.awt.image.ImageObserver;
022: import java.awt.image.PixelGrabber;
023: import java.awt.image.Raster;
024: import java.awt.image.SinglePixelPackedSampleModel;
025: import java.awt.image.WritableRaster;
026: import java.util.Map;
027: import javax.media.jai.ImageLayout;
028: import javax.media.jai.PlanarImage;
029: import javax.media.jai.RasterAccessor;
030: import javax.media.jai.RasterFactory;
031: import javax.media.jai.SourcelessOpImage;
032: import javax.media.jai.RasterFormatTag;
033:
034: /**
035: * An <code>OpImage</code> implementing the "AWTImage" operation as
036: * described in <code>javax.media.jai.operator.AWTImageDescriptor</code>.
037: * It takes a regular java.awt.Image and converts it into a
038: * javax.media.jai.PlanarImage.
039: *
040: * <p> The layout of the PlanarImage may be specified using the
041: * <code>ImageLayout</code> parameter at construction. The image
042: * bounds (minX, minY, width, height), <code>SampleModel</code>, and
043: * <code>ColorModel</code>, if supplied, are ignored. The tile grid
044: * offsets will be ignored if neither of the tile dimensions are
045: * supplied or equal the respective image dimensions.
046: *
047: * <p> The image origin is forced to (0, 0) and the width and height
048: * to the width and height, respectively, of the AWT image parameter.
049: * If a tile dimension is not set it defaults to the corresponding
050: * image dimension. If neither tile dimension is set or both equal the
051: * corresponding image dimensions, the tile grid offsets default to the
052: * image origin.
053: *
054: * <p> The <code>SampleModel</code> is forced to a
055: * <code>SinglePixelPackedSampleModel</code> if the tile dimensions equal
056: * the image dimensions, otherwise it is forced to a
057: * <code>PixelInterleavedSampleModel</code>. In either case the
058: * <code>ColorModel</code> is set using
059: * <code>PlanarImage.createColorModel()</code>.
060: *
061: * @see javax.media.jai.operator.AWTImageDescriptor
062: * @see AWTImageRIF
063: *
064: */
065: final class AWTImageOpImage extends SourcelessOpImage {
066:
067: /* The entire image's pixel values. */
068: private int[] pixels;
069:
070: /* RasterFormatTag for dest sampleModels */
071: private RasterFormatTag rasterFormatTag = null;
072:
073: private static final ImageLayout layoutHelper(ImageLayout layout,
074: Image image) {
075: /* Determine image width and height using MediaTracker. */
076: MediaTracker tracker = new MediaTracker(new Canvas());
077: tracker.addImage(image, 0);
078: try {
079: tracker.waitForID(0);
080: } catch (InterruptedException e) {
081: e.printStackTrace();
082: throw new RuntimeException(JaiI18N
083: .getString("AWTImageOpImage0"));
084: }
085: if (tracker.isErrorID(0)) { // not standard file format
086: throw new RuntimeException(JaiI18N
087: .getString("AWTImageOpImage1"));
088: }
089: tracker.removeImage(image);
090:
091: // Create layout if none supplied.
092: if (layout == null)
093: layout = new ImageLayout();
094:
095: // Override minX, minY, width, height
096: layout.setMinX(0);
097: layout.setMinY(0);
098: layout.setWidth(image.getWidth(null));
099: layout.setHeight(image.getHeight(null));
100:
101: // Override tileWidth, tileHeight if not supplied in layout
102: if (!layout.isValid(ImageLayout.TILE_WIDTH_MASK)) {
103: layout.setTileWidth(layout.getWidth(null));
104: }
105: if (!layout.isValid(ImageLayout.TILE_HEIGHT_MASK)) {
106: layout.setTileHeight(layout.getHeight(null));
107: }
108:
109: // Override sampleModel
110: // TODO: what if bands != 3?
111: if (layout.getTileWidth(null) == layout.getWidth(null)
112: && layout.getTileHeight(null) == layout.getHeight(null)) {
113: // Override tile grid offsets so we have a single tile.
114: layout.setTileGridXOffset(layout.getMinX(null));
115: layout.setTileGridYOffset(layout.getMinY(null));
116:
117: int[] bitMasks = new int[] { 0x00ff0000, 0x0000ff00,
118: 0x000000ff };
119: layout.setSampleModel(new SinglePixelPackedSampleModel(
120: DataBuffer.TYPE_INT, layout.getWidth(null), layout
121: .getHeight(null), bitMasks));
122: } else {
123: layout.setSampleModel(RasterFactory
124: .createPixelInterleavedSampleModel(
125: DataBuffer.TYPE_BYTE, layout
126: .getTileWidth(null), layout
127: .getTileHeight(null), 3));
128: }
129:
130: layout.setColorModel(PlanarImage.createColorModel(layout
131: .getSampleModel(null)));
132:
133: return layout;
134: }
135:
136: /**
137: * Constructs an AWTImageOpImage.
138: *
139: * @param layout Image layout.
140: * @param image The AWT image.
141: */
142: public AWTImageOpImage(Map config, ImageLayout layout, Image image) {
143: // We don't know the width, height, and sample model yet
144: super (layout = layoutHelper(layout, image), config, layout
145: .getSampleModel(null), layout.getMinX(null), layout
146: .getMinY(null), layout.getWidth(null), layout
147: .getHeight(null));
148:
149: // Set the format tag if and only if we will use the RasterAccessor.
150: if (getTileWidth() != getWidth()
151: || getTileHeight() != getHeight()) {
152: rasterFormatTag = new RasterFormatTag(getSampleModel(),
153: RasterAccessor.TAG_BYTE_UNCOPIED);
154: }
155:
156: // Grab the entire image
157: this .pixels = new int[width * height];
158: PixelGrabber grabber = new PixelGrabber(image, 0, 0, width,
159: height, pixels, 0, width);
160: try {
161: if (!grabber.grabPixels()) {
162: if ((grabber.getStatus() & ImageObserver.ABORT) != 0) {
163: throw new RuntimeException(JaiI18N
164: .getString("AWTImageOpImage2"));
165: } else {
166: throw new RuntimeException(grabber.getStatus()
167: + JaiI18N.getString("AWTImageOpImage3"));
168: }
169: }
170: } catch (InterruptedException e) {
171: e.printStackTrace();
172: throw new RuntimeException(JaiI18N
173: .getString("AWTImageOpImage4"));
174: }
175: }
176:
177: public Raster computeTile(int tileX, int tileY) {
178: if (getTileWidth() == getWidth()
179: && getTileHeight() == getHeight()) {
180: DataBuffer dataBuffer = new DataBufferInt(pixels,
181: pixels.length);
182: return Raster.createWritableRaster(getSampleModel(),
183: dataBuffer, new Point(tileXToX(tileX),
184: tileYToY(tileY)));
185: }
186:
187: return super .computeTile(tileX, tileY);
188: }
189:
190: protected void computeRect(PlanarImage[] sources,
191: WritableRaster dest, Rectangle destRect) {
192: RasterAccessor dst = new RasterAccessor(dest, destRect,
193: rasterFormatTag, null);
194:
195: int dwidth = dst.getWidth();
196: int dheight = dst.getHeight();
197:
198: int lineStride = dst.getScanlineStride();
199: int pixelStride = dst.getPixelStride();
200:
201: int lineOffset0 = dst.getBandOffset(0);
202: int lineOffset1 = dst.getBandOffset(1);
203: int lineOffset2 = dst.getBandOffset(2);
204:
205: byte[] data = dst.getByteDataArray(0);
206:
207: int offset = (destRect.y - minY) * width + (destRect.x - minX);
208:
209: for (int h = 0; h < dheight; h++) {
210: int pixelOffset0 = lineOffset0;
211: int pixelOffset1 = lineOffset1;
212: int pixelOffset2 = lineOffset2;
213:
214: lineOffset0 += lineStride;
215: lineOffset1 += lineStride;
216: lineOffset2 += lineStride;
217:
218: int i = offset;
219: offset += width;
220:
221: for (int w = 0; w < dwidth; w++) {
222: data[pixelOffset0] = (byte) ((pixels[i] >> 16) & 0xFF);
223: data[pixelOffset1] = (byte) ((pixels[i] >> 8) & 0xFF);
224: data[pixelOffset2] = (byte) (pixels[i] & 0xFF);
225:
226: pixelOffset0 += pixelStride;
227: pixelOffset1 += pixelStride;
228: pixelOffset2 += pixelStride;
229: i++;
230: }
231: }
232: }
233: }
|