/*
 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.sun.imageio.plugins.tiff;

import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.plugins.tiff.TIFFImageReadParam;
import javax.imageio.plugins.tiff.TIFFTagSet;

public class TIFFRenderedImage implements RenderedImage {

    private TIFFImageReader reader;
    private int imageIndex;
    private ImageReadParam tileParam;

    private int subsampleX;
    private int subsampleY;

    private boolean isSubsampling;

    private int width;
    private int height;
    private int tileWidth;
    private int tileHeight;

    private ImageTypeSpecifier its;

    public TIFFRenderedImage(TIFFImageReader reader,
                             int imageIndex,
                             ImageReadParam readParam,
                             int width, int height) throws IOException {
        this.reader = reader;
        this.imageIndex = imageIndex;
        this.tileParam = cloneImageReadParam(readParam, false);

        this.subsampleX = tileParam.getSourceXSubsampling();
        this.subsampleY = tileParam.getSourceYSubsampling();

        this.isSubsampling = this.subsampleX != 1 || this.subsampleY != 1;

        this.width = width/subsampleX;
        this.height = height/subsampleY;

        // If subsampling is being used, we may not match the
        // true tile grid exactly, but everything should still work
        this.tileWidth = reader.getTileWidth(imageIndex)/subsampleX;
        this.tileHeight = reader.getTileHeight(imageIndex)/subsampleY;

        Iterator<ImageTypeSpecifier> iter = reader.getImageTypes(imageIndex);
        this.its = iter.next();
        tileParam.setDestinationType(its);
    }

    
Creates a copy of param. The source subsampling and and bands settings and the destination bands and offset settings are copied. If param is a TIFFImageReadParam then the TIFFDecompressor and TIFFColorConverter settings are also copied; otherwise they are explicitly set to null.
Params:
  • param – the parameters to be copied.
  • copyTagSets – whether the TIFFTagSet settings should be copied if set.
Returns:copied parameters.
/** * Creates a copy of {@code param}. The source subsampling and * and bands settings and the destination bands and offset settings * are copied. If {@code param} is a {@code TIFFImageReadParam} * then the {@code TIFFDecompressor} and * {@code TIFFColorConverter} settings are also copied; otherwise * they are explicitly set to {@code null}. * * @param param the parameters to be copied. * @param copyTagSets whether the {@code TIFFTagSet} settings * should be copied if set. * @return copied parameters. */
private ImageReadParam cloneImageReadParam(ImageReadParam param, boolean copyTagSets) { // Create a new TIFFImageReadParam. TIFFImageReadParam newParam = new TIFFImageReadParam(); // Copy the basic settings. newParam.setSourceSubsampling(param.getSourceXSubsampling(), param.getSourceYSubsampling(), param.getSubsamplingXOffset(), param.getSubsamplingYOffset()); newParam.setSourceBands(param.getSourceBands()); newParam.setDestinationBands(param.getDestinationBands()); newParam.setDestinationOffset(param.getDestinationOffset()); if (param instanceof TIFFImageReadParam && copyTagSets) { // Copy the settings from the input parameter. TIFFImageReadParam tparam = (TIFFImageReadParam) param; List<TIFFTagSet> tagSets = tparam.getAllowedTagSets(); if (tagSets != null) { Iterator<TIFFTagSet> tagSetIter = tagSets.iterator(); if (tagSetIter != null) { while (tagSetIter.hasNext()) { TIFFTagSet tagSet = tagSetIter.next(); newParam.addAllowedTagSet(tagSet); } } } } return newParam; } public Vector<RenderedImage> getSources() { return null; } public Object getProperty(String name) { return java.awt.Image.UndefinedProperty; } public String[] getPropertyNames() { return null; } public ColorModel getColorModel() { return its.getColorModel(); } public SampleModel getSampleModel() { return its.getSampleModel(); } public int getWidth() { return width; } public int getHeight() { return height; } public int getMinX() { return 0; } public int getMinY() { return 0; } public int getNumXTiles() { return (width + tileWidth - 1)/tileWidth; } public int getNumYTiles() { return (height + tileHeight - 1)/tileHeight; } public int getMinTileX() { return 0; } public int getMinTileY() { return 0; } public int getTileWidth() { return tileWidth; } public int getTileHeight() { return tileHeight; } public int getTileGridXOffset() { return 0; } public int getTileGridYOffset() { return 0; } public Raster getTile(int tileX, int tileY) { Rectangle tileRect = new Rectangle(tileX*tileWidth, tileY*tileHeight, tileWidth, tileHeight); return getData(tileRect); } public Raster getData() { return read(new Rectangle(0, 0, getWidth(), getHeight())); } public Raster getData(Rectangle rect) { return read(rect); } // This method needs to be synchronized as it updates the instance // variable 'tileParam'. public synchronized WritableRaster read(Rectangle rect) { tileParam.setSourceRegion(isSubsampling ? new Rectangle(subsampleX*rect.x, subsampleY*rect.y, subsampleX*rect.width, subsampleY*rect.height) : rect); try { BufferedImage bi = reader.read(imageIndex, tileParam); WritableRaster ras = bi.getRaster(); return ras.createWritableChild(0, 0, ras.getWidth(), ras.getHeight(), rect.x, rect.y, null); } catch (IOException e) { throw new RuntimeException(e); } } public WritableRaster copyData(WritableRaster raster) { if (raster == null) { return read(new Rectangle(0, 0, getWidth(), getHeight())); } else { Raster src = read(raster.getBounds()); raster.setRect(src); return raster; } } }