001: /*
002: * $RCSfile: TIFFRenderedImage.java,v $
003: *
004: *
005: * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * - Redistribution of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * - Redistribution in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * Neither the name of Sun Microsystems, Inc. or the names of
020: * contributors may be used to endorse or promote products derived
021: * from this software without specific prior written permission.
022: *
023: * This software is provided "AS IS," without a warranty of any
024: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
025: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
026: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027: * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
028: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
029: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
031: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035: * POSSIBILITY OF SUCH DAMAGES.
036: *
037: * You acknowledge that this software is not designed or intended for
038: * use in the design, construction, operation or maintenance of any
039: * nuclear facility.
040: *
041: * $Revision: 1.2 $
042: * $Date: 2006/02/22 22:06:23 $
043: * $State: Exp $
044: */
045: package com.sun.media.imageioimpl.plugins.tiff;
046:
047: import java.awt.Rectangle;
048: import java.awt.image.BufferedImage;
049: import java.awt.image.ColorModel;
050: import java.awt.image.Raster;
051: import java.awt.image.RenderedImage;
052: import java.awt.image.SampleModel;
053: import java.awt.image.WritableRaster;
054: import java.io.IOException;
055: import java.util.Iterator;
056: import java.util.List;
057: import java.util.Vector;
058: import javax.imageio.ImageReadParam;
059: import javax.imageio.ImageTypeSpecifier;
060: import com.sun.media.imageio.plugins.tiff.TIFFImageReadParam;
061: import com.sun.media.imageio.plugins.tiff.TIFFTagSet;
062:
063: public class TIFFRenderedImage implements RenderedImage {
064:
065: TIFFImageReader reader;
066: int imageIndex;
067: ImageReadParam tileParam;
068:
069: int subsampleX;
070: int subsampleY;
071:
072: boolean isSubsampling;
073:
074: int width;
075: int height;
076: int tileWidth;
077: int tileHeight;
078:
079: ImageTypeSpecifier its;
080:
081: public TIFFRenderedImage(TIFFImageReader reader, int imageIndex,
082: ImageReadParam readParam, int width, int height)
083: throws IOException {
084: this .reader = reader;
085: this .imageIndex = imageIndex;
086: this .tileParam = cloneImageReadParam(readParam, false);
087:
088: this .subsampleX = tileParam.getSourceXSubsampling();
089: this .subsampleY = tileParam.getSourceYSubsampling();
090:
091: this .isSubsampling = this .subsampleX != 1
092: || this .subsampleY != 1;
093:
094: this .width = width / subsampleX;
095: this .height = height / subsampleY;
096:
097: // If subsampling is being used, we may not match the
098: // true tile grid exactly, but everything should still work
099: this .tileWidth = reader.getTileWidth(imageIndex) / subsampleX;
100: this .tileHeight = reader.getTileHeight(imageIndex) / subsampleY;
101:
102: Iterator iter = reader.getImageTypes(imageIndex);
103: this .its = (ImageTypeSpecifier) iter.next();
104: tileParam.setDestinationType(its);
105: }
106:
107: /**
108: * Creates a copy of <code>param</code>. The source subsampling and
109: * and bands settings and the destination bands and offset settings
110: * are copied. If <code>param</code> is a <code>TIFFImageReadParam</code>
111: * then the <code>TIFFDecompressor</code> and
112: * <code>TIFFColorConverter</code> settings are also copied; otherwise
113: * they are explicitly set to <code>null</code>.
114: *
115: * @param param the parameters to be copied.
116: * @param copyTagSets whether the <code>TIFFTagSet</code> settings
117: * should be copied if set.
118: * @return copied parameters.
119: */
120: private ImageReadParam cloneImageReadParam(ImageReadParam param,
121: boolean copyTagSets) {
122: // Create a new TIFFImageReadParam.
123: TIFFImageReadParam newParam = new TIFFImageReadParam();
124:
125: // Copy the basic settings.
126: newParam.setSourceSubsampling(param.getSourceXSubsampling(),
127: param.getSourceYSubsampling(), param
128: .getSubsamplingXOffset(), param
129: .getSubsamplingYOffset());
130: newParam.setSourceBands(param.getSourceBands());
131: newParam.setDestinationBands(param.getDestinationBands());
132: newParam.setDestinationOffset(param.getDestinationOffset());
133:
134: // Set the decompressor and color converter.
135: if (param instanceof TIFFImageReadParam) {
136: // Copy the settings from the input parameter.
137: TIFFImageReadParam tparam = (TIFFImageReadParam) param;
138: newParam.setTIFFDecompressor(tparam.getTIFFDecompressor());
139: newParam.setColorConverter(tparam.getColorConverter());
140:
141: if (copyTagSets) {
142: List tagSets = tparam.getAllowedTagSets();
143: if (tagSets != null) {
144: Iterator tagSetIter = tagSets.iterator();
145: if (tagSetIter != null) {
146: while (tagSetIter.hasNext()) {
147: TIFFTagSet tagSet = (TIFFTagSet) tagSetIter
148: .next();
149: newParam.addAllowedTagSet(tagSet);
150: }
151: }
152: }
153: }
154: } else {
155: // Set the decompressor and color converter to null.
156: newParam.setTIFFDecompressor(null);
157: newParam.setColorConverter(null);
158: }
159:
160: return newParam;
161: }
162:
163: public Vector getSources() {
164: return null;
165: }
166:
167: public Object getProperty(String name) {
168: return java.awt.Image.UndefinedProperty;
169: }
170:
171: public String[] getPropertyNames() {
172: return null;
173: }
174:
175: public ColorModel getColorModel() {
176: return its.getColorModel();
177: }
178:
179: public SampleModel getSampleModel() {
180: return its.getSampleModel();
181: }
182:
183: public int getWidth() {
184: return width;
185: }
186:
187: public int getHeight() {
188: return height;
189: }
190:
191: public int getMinX() {
192: return 0;
193: }
194:
195: public int getMinY() {
196: return 0;
197: }
198:
199: public int getNumXTiles() {
200: return (width + tileWidth - 1) / tileWidth;
201: }
202:
203: public int getNumYTiles() {
204: return (height + tileHeight - 1) / tileHeight;
205: }
206:
207: public int getMinTileX() {
208: return 0;
209: }
210:
211: public int getMinTileY() {
212: return 0;
213: }
214:
215: public int getTileWidth() {
216: return tileWidth;
217: }
218:
219: public int getTileHeight() {
220: return tileHeight;
221: }
222:
223: public int getTileGridXOffset() {
224: return 0;
225: }
226:
227: public int getTileGridYOffset() {
228: return 0;
229: }
230:
231: public Raster getTile(int tileX, int tileY) {
232: Rectangle tileRect = new Rectangle(tileX * tileWidth, tileY
233: * tileHeight, tileWidth, tileHeight);
234: return getData(tileRect);
235: }
236:
237: public Raster getData() {
238: return read(new Rectangle(0, 0, getWidth(), getHeight()));
239: }
240:
241: public Raster getData(Rectangle rect) {
242: return read(rect);
243: }
244:
245: // This method needs to be synchronized as it updates the instance
246: // variable 'tileParam'.
247: public synchronized WritableRaster read(Rectangle rect) {
248: // XXX Does this need to consider the subsampling offsets or is
249: // that handled implicitly by the reader?
250: tileParam.setSourceRegion(isSubsampling ? new Rectangle(
251: subsampleX * rect.x, subsampleY * rect.y, subsampleX
252: * rect.width, subsampleY * rect.height) : rect);
253:
254: try {
255: BufferedImage bi = reader.read(imageIndex, tileParam);
256: WritableRaster ras = bi.getRaster();
257: return ras.createWritableChild(0, 0, ras.getWidth(), ras
258: .getHeight(), rect.x, rect.y, null);
259: } catch (IOException e) {
260: throw new RuntimeException(e);
261: }
262: }
263:
264: public WritableRaster copyData(WritableRaster raster) {
265: if (raster == null) {
266: return read(new Rectangle(0, 0, getWidth(), getHeight()));
267: } else {
268: Raster src = read(raster.getBounds());
269: raster.setRect(src);
270: return raster;
271: }
272: }
273: }
|