1 /* 2 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.sun.imageio.plugins.tiff; 26 27 import java.awt.Rectangle; 28 import java.awt.image.BufferedImage; 29 import java.awt.image.ColorModel; 30 import java.awt.image.Raster; 31 import java.awt.image.RenderedImage; 32 import java.awt.image.SampleModel; 33 import java.awt.image.WritableRaster; 34 import java.io.IOException; 35 import java.util.Iterator; 36 import java.util.List; 37 import java.util.Vector; 38 import javax.imageio.ImageReadParam; 39 import javax.imageio.ImageTypeSpecifier; 40 import javax.imageio.plugins.tiff.TIFFImageReadParam; 41 import javax.imageio.plugins.tiff.TIFFTagSet; 42 43 public class TIFFRenderedImage implements RenderedImage { 44 45 private TIFFImageReader reader; 46 private int imageIndex; 47 private ImageReadParam tileParam; 48 49 private int subsampleX; 50 private int subsampleY; 51 52 private boolean isSubsampling; 53 54 private int width; 55 private int height; 56 private int tileWidth; 57 private int tileHeight; 58 59 private ImageTypeSpecifier its; 60 TIFFRenderedImage(TIFFImageReader reader, int imageIndex, ImageReadParam readParam, int width, int height)61 public TIFFRenderedImage(TIFFImageReader reader, 62 int imageIndex, 63 ImageReadParam readParam, 64 int width, int height) throws IOException { 65 this.reader = reader; 66 this.imageIndex = imageIndex; 67 this.tileParam = cloneImageReadParam(readParam, false); 68 69 this.subsampleX = tileParam.getSourceXSubsampling(); 70 this.subsampleY = tileParam.getSourceYSubsampling(); 71 72 this.isSubsampling = this.subsampleX != 1 || this.subsampleY != 1; 73 74 this.width = width/subsampleX; 75 this.height = height/subsampleY; 76 77 // If subsampling is being used, we may not match the 78 // true tile grid exactly, but everything should still work 79 this.tileWidth = reader.getTileWidth(imageIndex)/subsampleX; 80 this.tileHeight = reader.getTileHeight(imageIndex)/subsampleY; 81 82 Iterator<ImageTypeSpecifier> iter = reader.getImageTypes(imageIndex); 83 this.its = iter.next(); 84 tileParam.setDestinationType(its); 85 } 86 87 /** 88 * Creates a copy of {@code param}. The source subsampling and 89 * and bands settings and the destination bands and offset settings 90 * are copied. If {@code param} is a {@code TIFFImageReadParam} 91 * then the {@code TIFFDecompressor} and 92 * {@code TIFFColorConverter} settings are also copied; otherwise 93 * they are explicitly set to {@code null}. 94 * 95 * @param param the parameters to be copied. 96 * @param copyTagSets whether the {@code TIFFTagSet} settings 97 * should be copied if set. 98 * @return copied parameters. 99 */ cloneImageReadParam(ImageReadParam param, boolean copyTagSets)100 private ImageReadParam cloneImageReadParam(ImageReadParam param, 101 boolean copyTagSets) { 102 // Create a new TIFFImageReadParam. 103 TIFFImageReadParam newParam = new TIFFImageReadParam(); 104 105 // Copy the basic settings. 106 newParam.setSourceSubsampling(param.getSourceXSubsampling(), 107 param.getSourceYSubsampling(), 108 param.getSubsamplingXOffset(), 109 param.getSubsamplingYOffset()); 110 newParam.setSourceBands(param.getSourceBands()); 111 newParam.setDestinationBands(param.getDestinationBands()); 112 newParam.setDestinationOffset(param.getDestinationOffset()); 113 114 if (param instanceof TIFFImageReadParam && copyTagSets) { 115 // Copy the settings from the input parameter. 116 TIFFImageReadParam tparam = (TIFFImageReadParam) param; 117 118 List<TIFFTagSet> tagSets = tparam.getAllowedTagSets(); 119 if (tagSets != null) { 120 Iterator<TIFFTagSet> tagSetIter = tagSets.iterator(); 121 if (tagSetIter != null) { 122 while (tagSetIter.hasNext()) { 123 TIFFTagSet tagSet = tagSetIter.next(); 124 newParam.addAllowedTagSet(tagSet); 125 } 126 } 127 } 128 } 129 130 return newParam; 131 } 132 getSources()133 public Vector<RenderedImage> getSources() { 134 return null; 135 } 136 getProperty(String name)137 public Object getProperty(String name) { 138 return java.awt.Image.UndefinedProperty; 139 } 140 getPropertyNames()141 public String[] getPropertyNames() { 142 return null; 143 } 144 getColorModel()145 public ColorModel getColorModel() { 146 return its.getColorModel(); 147 } 148 getSampleModel()149 public SampleModel getSampleModel() { 150 return its.getSampleModel(); 151 } 152 getWidth()153 public int getWidth() { 154 return width; 155 } 156 getHeight()157 public int getHeight() { 158 return height; 159 } 160 getMinX()161 public int getMinX() { 162 return 0; 163 } 164 getMinY()165 public int getMinY() { 166 return 0; 167 } 168 getNumXTiles()169 public int getNumXTiles() { 170 return (width + tileWidth - 1)/tileWidth; 171 } 172 getNumYTiles()173 public int getNumYTiles() { 174 return (height + tileHeight - 1)/tileHeight; 175 } 176 getMinTileX()177 public int getMinTileX() { 178 return 0; 179 } 180 getMinTileY()181 public int getMinTileY() { 182 return 0; 183 } 184 getTileWidth()185 public int getTileWidth() { 186 return tileWidth; 187 } 188 getTileHeight()189 public int getTileHeight() { 190 return tileHeight; 191 } 192 getTileGridXOffset()193 public int getTileGridXOffset() { 194 return 0; 195 } 196 getTileGridYOffset()197 public int getTileGridYOffset() { 198 return 0; 199 } 200 getTile(int tileX, int tileY)201 public Raster getTile(int tileX, int tileY) { 202 Rectangle tileRect = new Rectangle(tileX*tileWidth, 203 tileY*tileHeight, 204 tileWidth, 205 tileHeight); 206 return getData(tileRect); 207 } 208 getData()209 public Raster getData() { 210 return read(new Rectangle(0, 0, getWidth(), getHeight())); 211 } 212 getData(Rectangle rect)213 public Raster getData(Rectangle rect) { 214 return read(rect); 215 } 216 217 // This method needs to be synchronized as it updates the instance 218 // variable 'tileParam'. read(Rectangle rect)219 public synchronized WritableRaster read(Rectangle rect) { 220 tileParam.setSourceRegion(isSubsampling ? 221 new Rectangle(subsampleX*rect.x, 222 subsampleY*rect.y, 223 subsampleX*rect.width, 224 subsampleY*rect.height) : 225 rect); 226 227 try { 228 BufferedImage bi = reader.read(imageIndex, tileParam); 229 WritableRaster ras = bi.getRaster(); 230 return ras.createWritableChild(0, 0, 231 ras.getWidth(), ras.getHeight(), 232 rect.x, rect.y, 233 null); 234 } catch (IOException e) { 235 throw new RuntimeException(e); 236 } 237 } 238 copyData(WritableRaster raster)239 public WritableRaster copyData(WritableRaster raster) { 240 if (raster == null) { 241 return read(new Rectangle(0, 0, getWidth(), getHeight())); 242 } else { 243 Raster src = read(raster.getBounds()); 244 raster.setRect(src); 245 return raster; 246 } 247 } 248 } 249