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 */ 045package com.github.jaiimageio.impl.plugins.tiff; 046 047import java.awt.Rectangle; 048import java.awt.image.BufferedImage; 049import java.awt.image.ColorModel; 050import java.awt.image.Raster; 051import java.awt.image.RenderedImage; 052import java.awt.image.SampleModel; 053import java.awt.image.WritableRaster; 054import java.io.IOException; 055import java.util.Iterator; 056import java.util.List; 057import java.util.Vector; 058 059import javax.imageio.ImageReadParam; 060import javax.imageio.ImageTypeSpecifier; 061 062import com.github.jaiimageio.plugins.tiff.TIFFImageReadParam; 063import com.github.jaiimageio.plugins.tiff.TIFFTagSet; 064 065public class TIFFRenderedImage implements RenderedImage { 066 067 TIFFImageReader reader; 068 int imageIndex; 069 ImageReadParam tileParam; 070 071 int subsampleX; 072 int subsampleY; 073 074 boolean isSubsampling; 075 076 int width; 077 int height; 078 int tileWidth; 079 int tileHeight; 080 081 ImageTypeSpecifier its; 082 083 public TIFFRenderedImage(TIFFImageReader reader, 084 int imageIndex, 085 ImageReadParam readParam, 086 int width, int height) throws IOException { 087 this.reader = reader; 088 this.imageIndex = imageIndex; 089 this.tileParam = cloneImageReadParam(readParam, false); 090 091 this.subsampleX = tileParam.getSourceXSubsampling(); 092 this.subsampleY = tileParam.getSourceYSubsampling(); 093 094 this.isSubsampling = this.subsampleX != 1 || this.subsampleY != 1; 095 096 this.width = width/subsampleX; 097 this.height = height/subsampleY; 098 099 // If subsampling is being used, we may not match the 100 // true tile grid exactly, but everything should still work 101 this.tileWidth = reader.getTileWidth(imageIndex)/subsampleX; 102 this.tileHeight = reader.getTileHeight(imageIndex)/subsampleY; 103 104 Iterator iter = reader.getImageTypes(imageIndex); 105 this.its = (ImageTypeSpecifier)iter.next(); 106 tileParam.setDestinationType(its); 107 } 108 109 /** 110 * Creates a copy of <code>param</code>. The source subsampling and 111 * and bands settings and the destination bands and offset settings 112 * are copied. If <code>param</code> is a <code>TIFFImageReadParam</code> 113 * then the <code>TIFFDecompressor</code> and 114 * <code>TIFFColorConverter</code> settings are also copied; otherwise 115 * they are explicitly set to <code>null</code>. 116 * 117 * @param param the parameters to be copied. 118 * @param copyTagSets whether the <code>TIFFTagSet</code> settings 119 * should be copied if set. 120 * @return copied parameters. 121 */ 122 private ImageReadParam cloneImageReadParam(ImageReadParam param, 123 boolean copyTagSets) { 124 // Create a new TIFFImageReadParam. 125 TIFFImageReadParam newParam = new TIFFImageReadParam(); 126 127 // Copy the basic settings. 128 newParam.setSourceSubsampling(param.getSourceXSubsampling(), 129 param.getSourceYSubsampling(), 130 param.getSubsamplingXOffset(), 131 param.getSubsamplingYOffset()); 132 newParam.setSourceBands(param.getSourceBands()); 133 newParam.setDestinationBands(param.getDestinationBands()); 134 newParam.setDestinationOffset(param.getDestinationOffset()); 135 136 // Set the decompressor and color converter. 137 if(param instanceof TIFFImageReadParam) { 138 // Copy the settings from the input parameter. 139 TIFFImageReadParam tparam = (TIFFImageReadParam)param; 140 newParam.setTIFFDecompressor(tparam.getTIFFDecompressor()); 141 newParam.setColorConverter(tparam.getColorConverter()); 142 143 if(copyTagSets) { 144 List tagSets = tparam.getAllowedTagSets(); 145 if(tagSets != null) { 146 Iterator tagSetIter = tagSets.iterator(); 147 if(tagSetIter != null) { 148 while(tagSetIter.hasNext()) { 149 TIFFTagSet tagSet = (TIFFTagSet)tagSetIter.next(); 150 newParam.addAllowedTagSet(tagSet); 151 } 152 } 153 } 154 } 155 } else { 156 // Set the decompressor and color converter to null. 157 newParam.setTIFFDecompressor(null); 158 newParam.setColorConverter(null); 159 } 160 161 return newParam; 162 } 163 164 public Vector getSources() { 165 return null; 166 } 167 168 public Object getProperty(String name) { 169 return java.awt.Image.UndefinedProperty; 170 } 171 172 public String[] getPropertyNames() { 173 return null; 174 } 175 176 public ColorModel getColorModel() { 177 return its.getColorModel(); 178 } 179 180 public SampleModel getSampleModel() { 181 return its.getSampleModel(); 182 } 183 184 public int getWidth() { 185 return width; 186 } 187 188 public int getHeight() { 189 return height; 190 } 191 192 public int getMinX() { 193 return 0; 194 } 195 196 public int getMinY() { 197 return 0; 198 } 199 200 public int getNumXTiles() { 201 return (width + tileWidth - 1)/tileWidth; 202 } 203 204 public int getNumYTiles() { 205 return (height + tileHeight - 1)/tileHeight; 206 } 207 208 public int getMinTileX() { 209 return 0; 210 } 211 212 public int getMinTileY() { 213 return 0; 214 } 215 216 public int getTileWidth() { 217 return tileWidth; 218 } 219 220 public int getTileHeight() { 221 return tileHeight; 222 } 223 224 public int getTileGridXOffset() { 225 return 0; 226 } 227 228 public int getTileGridYOffset() { 229 return 0; 230 } 231 232 public Raster getTile(int tileX, int tileY) { 233 Rectangle tileRect = new Rectangle(tileX*tileWidth, 234 tileY*tileHeight, 235 tileWidth, 236 tileHeight); 237 return getData(tileRect); 238 } 239 240 public Raster getData() { 241 return read(new Rectangle(0, 0, getWidth(), getHeight())); 242 } 243 244 public Raster getData(Rectangle rect) { 245 return read(rect); 246 } 247 248 // This method needs to be synchronized as it updates the instance 249 // variable 'tileParam'. 250 public synchronized WritableRaster read(Rectangle rect) { 251 // XXX Does this need to consider the subsampling offsets or is 252 // that handled implicitly by the reader? 253 tileParam.setSourceRegion(isSubsampling ? 254 new Rectangle(subsampleX*rect.x, 255 subsampleY*rect.y, 256 subsampleX*rect.width, 257 subsampleY*rect.height) : 258 rect); 259 260 try { 261 BufferedImage bi = reader.read(imageIndex, tileParam); 262 WritableRaster ras = bi.getRaster(); 263 return ras.createWritableChild(0, 0, 264 ras.getWidth(), ras.getHeight(), 265 rect.x, rect.y, 266 null); 267 } catch (IOException e) { 268 throw new RuntimeException(e); 269 } 270 } 271 272 public WritableRaster copyData(WritableRaster raster) { 273 if (raster == null) { 274 return read(new Rectangle(0, 0, getWidth(), getHeight())); 275 } else { 276 Raster src = read(raster.getBounds()); 277 raster.setRect(src); 278 return raster; 279 } 280 } 281}