Class ImageFileDirectory

All Implemented Interfaces:
ResourceOnFileSystem, StoreResource, DataSet, GridCoverageResource, Resource

final class ImageFileDirectory extends DataCube
An Image File Directory (FID) in a TIFF image.

Thread-safety

Public methods should be synchronized because they can be invoked directly by users. Package-private methods are not synchronized; synchronization is caller's responsibility.
Since:
0.8
Version:
1.3
See Also:
  • Field Details

    • TILE

      private static final byte TILE
      Possible value for the tileTagFamily field. That field tells whether image tiling was specified using the Tile* family of TIFF tags or the Strip* family. JPEG was also used to have its own set of tags.
      See Also:
    • STRIP

      private static final byte STRIP
      Possible value for the tileTagFamily field. That field tells whether image tiling was specified using the Tile* family of TIFF tags or the Strip* family. JPEG was also used to have its own set of tags.
      See Also:
    • JPEG

      private static final byte JPEG
      Possible value for the tileTagFamily field. That field tells whether image tiling was specified using the Tile* family of TIFF tags or the Strip* family. JPEG was also used to have its own set of tags.
      See Also:
    • SIGNED

      private static final byte SIGNED
      Possible value for sampleFormat specifying how to interpret each data sample in a pixel. Those values are not necessarily the same than the ones documented in Tags.SampleFormat. Default value is UNSIGNED.
      See Also:
    • UNSIGNED

      private static final byte UNSIGNED
      Possible value for sampleFormat specifying how to interpret each data sample in a pixel. Those values are not necessarily the same than the ones documented in Tags.SampleFormat. Default value is UNSIGNED.
      See Also:
    • FLOAT

      private static final byte FLOAT
      Possible value for sampleFormat specifying how to interpret each data sample in a pixel. Those values are not necessarily the same than the ones documented in Tags.SampleFormat. Default value is UNSIGNED.
      See Also:
    • index

      private final int index
      Index of the (potentially pyramided) image containing this Image File Directory (IFD). All reduced-resolution (overviews) images are ignored when computing this index value. If the TIFF file does not contain reduced-resolution (overview) images, then index value is the same as the index of this IFD in the TIFF file.

      If this IFD is a reduced-resolution (overview) image, then this index is off by one. It has the value of the next pyramid. This is an artifact of the way index is computed but should be invisible to user because they should not handle overviews directly.

    • identifier

      private org.opengis.util.GenericName identifier
      The identifier as a sequence number in the namespace of the GeoTiffStore. The first image has the sequence number "1". This is computed when first needed.
      See Also:
    • metadata

      private ImageMetadataBuilder metadata
      Builder for the metadata. This field is reset to null when not needed anymore.
    • hasDeferredEntries

      boolean hasDeferredEntries
      true if this ImageFileDirectory has not yet read all deferred entries. When this flag is true, the ImageFileDirectory is not yet ready for use.
    • isValidated

      private boolean isValidated
      true if validateMandatoryTags() has already been invoked.
    • subfileType

      private int subfileType
      A general indication of the kind of data contained in this subfile, mainly useful when there are multiple subfiles in a single TIFF file. This field is made up of a set of 32 flag bits. Bit 0 is 1 if the image is a reduced-resolution version of another image in this TIFF file. Bit 1 is 1 if the image is a single page of a multi-page image (see PageNumber). Bit 2 is 1 if the image defines a transparency mask for another image in this TIFF file (see PhotometricInterpretation). Bit 4 indicates MRC imaging model as described in ITU-T recommendation T.44 [T.44] (See ImageLayer tag) - RFC 2301.
      See Also:
    • imageWidth

      private long imageWidth
      The size of the image described by this FID, or -1 if the information has not been found. The image may be much bigger than the memory capacity, in which case the image shall be tiled.

      Note: the imageHeight attribute is named ImageLength in TIFF specification.

      See Also:
    • imageHeight

      private long imageHeight
      The size of the image described by this FID, or -1 if the information has not been found. The image may be much bigger than the memory capacity, in which case the image shall be tiled.

      Note: the imageHeight attribute is named ImageLength in TIFF specification.

      See Also:
    • tileWidth

      private int tileWidth
      The size of each tile, or -1 if the information has not be found. Tiles shall be small enough for fitting in memory, typically in a Raster object. The TIFF specification requires that tile width and height must be a multiple of 16, but the SIS reader implementation works for any size. Tiles need not be square.

      Assuming integer arithmetic, the number of tiles in an image can be computed as below (these computed values are not TIFF fields):

      Note that imageWidth can be less than tileWidth and/or imageHeight can be less than tileHeight. Such case means that the tiles are too large or that the tiled image is too small, neither of which is recommended.

      Note: the tileHeight attribute is named TileLength in TIFF specification.

      Strips considered as tiles

      The TIFF specification also defines a RowsPerStrip tag, which is equivalent to the height of tiles having the same width than the image. While the TIFF specification handles "tiles" and "strips" separately, Apache SIS handles strips as a special kind of tiles where only tileHeight is specified and tileWidth defaults to imageWidth.
      See Also:
    • tileHeight

      private int tileHeight
      The size of each tile, or -1 if the information has not be found. Tiles shall be small enough for fitting in memory, typically in a Raster object. The TIFF specification requires that tile width and height must be a multiple of 16, but the SIS reader implementation works for any size. Tiles need not be square.

      Assuming integer arithmetic, the number of tiles in an image can be computed as below (these computed values are not TIFF fields):

      Note that imageWidth can be less than tileWidth and/or imageHeight can be less than tileHeight. Such case means that the tiles are too large or that the tiled image is too small, neither of which is recommended.

      Note: the tileHeight attribute is named TileLength in TIFF specification.

      Strips considered as tiles

      The TIFF specification also defines a RowsPerStrip tag, which is equivalent to the height of tiles having the same width than the image. While the TIFF specification handles "tiles" and "strips" separately, Apache SIS handles strips as a special kind of tiles where only tileHeight is specified and tileWidth defaults to imageWidth.
      See Also:
    • tileOffsets

      private Vector tileOffsets
      For each tile, the byte offset of that tile, as compressed and stored on disk. The offset is specified with respect to the beginning of the TIFF file. Each tile has a location independent of the locations of other tiles

      Offsets are ordered left-to-right and top-to-bottom. If isPlanar is true (i.e. components are stored in separate “component planes”), then the offsets for the first component plane are stored first, followed by all the offsets for the second component plane, and so on.

      Strips considered as tiles

      The TIFF specification also defines a StripOffsets tag, which contains the byte offset of each strip. In Apache SIS implementation, strips are considered as a special kind of tiles having a width equals to imageWidth.
    • tileByteCounts

      private Vector tileByteCounts
      For each tile, the number of (compressed) bytes in that tile. See tileOffsets for a description of how the byte counts are ordered.

      Strips considered as tiles

      The TIFF specification also defines a RowsPerStrip tag, which is the number of bytes in the strip after compression. In Apache SIS implementation, strips are considered as a special kind of tiles having a width equals to imageWidth.
    • tileTagFamily

      private byte tileTagFamily
      Whether the tiling was specified using the Tile* family of TIFF tags or the Strip* family of tags. Value can be TILE, STRIP or 0 if unspecified. This field is used for error detection since each TIFF file shall use exactly one family of tags.
    • isPlanar

      private boolean isPlanar
      If true, the components are stored in separate “component planes”. The default is false, which stands for the "chunky" format (for example RGB data stored as RGBRGBRGB).
    • sampleFormat

      private byte sampleFormat
      How to interpret each data sample in a pixel. Possible values are SIGNED, UNSIGNED or FLOAT.
    • isBitOrderReversed

      private boolean isBitOrderReversed
      Whether the bit order should be reversed. This boolean value is determined from the FillOrder TIFF tag.
      • Value 1 (mapped to false) means that pixels with lower column values are stored in the higher-order bits of the byte. This is the default value.
      • Value 2 (mapped to true) means that pixels with lower column values are stored in the lower-order bits of the byte. In practice, this order is very uncommon and is not recommended.
      Value 1 is mapped to false and 2 is mapped to true.
    • bitsPerSample

      private short bitsPerSample
      Number of bits per component. The TIFF specification allows a different number of bits per component for each component corresponding to a pixel. For example, RGB color data could use a different number of bits per component for each of the three color planes. However, current Apache SIS implementation requires that all components have the same BitsPerSample value.
    • samplesPerPixel

      private short samplesPerPixel
      The number of components per pixel. The samplesPerPixel value is usually 1 for bilevel, grayscale and palette-color images, and 3 for RGB images. If this value is higher, then the ExtraSamples TIFF tag should give an indication of the meaning of the additional channels.
      See Also:
    • extraSamples

      private Vector extraSamples
      Specifies that each pixel has extraSamples.size() extra components whose interpretation is defined by one of the values listed below. When this field is used, the samplesPerPixel field has a value greater than what the photometricInterpretation field suggests. For example, full-color RGB data normally has samplesPerPixel = 3. If samplesPerPixel is greater than 3, then this extraSamples field describes the meaning of the extra samples. If samplesPerPixel is, say, 5 then this extraSamples field will contain 2 values, one for each extra sample.

      Extra components that are present must be stored as the last components in each pixel. For example if samplesPerPixel is 4 and there is 1 extra component, then it is located in the last component location in each pixel.

      ExtraSamples is typically used to include non-color information, such as opacity, in an image. The possible values for each item are:

      • 0 = Unspecified data.
      • 1 = Associated alpha data (with pre-multiplied color).
      • 2 = Unassociated alpha data.
      Associated alpha is generally interpreted as true transparency information. Indeed, the original color values are lost in the case of complete transparency, and rounded in the case of partial transparency. Also, associated alpha is only logically possible as the single extra channel. Unassociated alpha channels, on the other hand, can be used to encode a number of independent masks. The original color data is preserved without rounding. Any number of unassociated alpha channels can accompany an image.

      If an extra sample is used to encode information that has little or nothing to do with alpha, then extraSample = 0 (EXTRASAMPLE_UNSPECIFIED) is recommended.

    • photometricInterpretation

      private byte photometricInterpretation
      The color space of the image data, or -1 if unspecified.
      Color space codes
      Value Label Description
      0 WhiteIsZero For bilevel and grayscale images. 0 is imaged as white.
      1 BlackIsZero For bilevel and grayscale images. 0 is imaged as black.
      2 RGB RGB value of (0,0,0) represents black, and (255,255,255) represents white.
      3 PaletteColor The value of the component is used as an index into the RGB values of the colorMap.
      4 TransparencyMask Defines an irregularly shaped region of another image in the same TIFF file.
    • colorMap

      private Vector colorMap
      A color map for palette color images (photometricInterpretation = 3). This vector defines a Red-Green-Blue color map (often called a lookup table) for palette-color images. In a palette-color image, a pixel value is used to index into an RGB lookup table. For example, a palette-color pixel having a value of 0 would be displayed according to the 0th Red, Green, Blue triplet.

      In a TIFF ColorMap, all the Red values come first, followed by all Green values, then all Blue values. The number of values for each color is 1 << bitsPerSample. Therefore, the ColorMap vector for an 8-bit palette-color image would have 3 * 256 values. 0 represents the minimum intensity and 65535 represents the maximum intensity. Black is represented by 0,0,0 and white by 65535, 65535, 65535.

      ColorMap must be included in all palette-color images. In Specification Supplement 1, support was added for color maps containing other then RGB values. This scheme includes the Indexed tag, with value 1, and a photometricInterpretation different from PaletteColor.

    • minValues

      private Vector minValues
      The minimum or maximum sample value found in the image, with one value per band. May be a vector of length 1 if the same single value applies to all bands.
    • maxValues

      private Vector maxValues
      The minimum or maximum sample value found in the image, with one value per band. May be a vector of length 1 if the same single value applies to all bands.
    • isMinSpecified

      private boolean isMinSpecified
      true if minValues and maxValues have been explicitly specified in the TIFF file, or false if they have been inferred from bitsPerSample.
    • isMaxSpecified

      private boolean isMaxSpecified
      true if minValues and maxValues have been explicitly specified in the TIFF file, or false if they have been inferred from bitsPerSample.
    • noData

      private double noData
      The "no data" or background pixel value, or NaN if undefined.
      See Also:
    • compression

      private Compression compression
      The compression method, or null if unspecified. If the compression method is unknown or unsupported we cannot read the image, but we still can read the metadata.
      See Also:
    • predictor

      private Predictor predictor
      Mathematical operator that is applied to the image data before an encoding scheme is applied. This is used mostly with LZW compression. Current values are:
      • 1: No prediction scheme used before coding.
      • 2: Horizontal differencing.
      See Also:
    • referencing

      private GridGeometryBuilder referencing
      A helper class for building Coordinate Reference System and complete related metadata. Contains the following information:
      See Also:
    • gridGeometry

      private GridGeometry gridGeometry
      The grid geometry created by GridGeometryBuilder.build(Reader, long, long). It has 2 or 3 dimensions, depending on whether the CRS declares a vertical axis or not.
      See Also:
    • sampleDimensions

      private List<SampleDimension> sampleDimensions
      The sample dimensions, or null if not yet created.
      See Also:
    • sampleModel

      private SampleModel sampleModel
      The image sample model, created when first needed. The raster size is the tile size. Sample models with different size and number of bands can be derived from this model.
      See Also:
    • colorModel

      private ColorModel colorModel
      The image color model, created when first needed.
      See Also:
  • Constructor Details

    • ImageFileDirectory

      ImageFileDirectory(Reader reader, int index)
      Creates a new image file directory. The index arguments is used for metadata identifier only.
      Parameters:
      reader - information about the input stream to read, the metadata and the character encoding.
      index - the pyramided image index as a sequence number starting with 0 for the first pyramid.
  • Method Details

    • referencing

      private GridGeometryBuilder referencing()
      Returns referencing, created when first needed. We delay its creation since this object is not needed for ordinary TIFF files (i.e. without the GeoTIFF extension). This method is invoked only during the parsing of TIFF tags. If no GeoTIFF information is found, then this field keeps the null value.
    • input

      private ChannelDataInput input()
      Shortcut for a frequently requested information.
    • encoding

      private Charset encoding()
      Shortcut for a frequently requested information.
    • getImageIndex

      final String getImageIndex()
      Returns the image index used in the default identifier.
    • getIdentifier

      public Optional<org.opengis.util.GenericName> getIdentifier()
      Returns the identifier in the namespace of the GeoTiffStore. The first image has the sequence number "1", optionally customized. If this image is an overview, then its namespace should be the name of the base image and the tip should be "overview-level" where "level" is a number starting at 1.

      The returned value should never be empty. An empty value would be a failure to initialize overviews.

      Specified by:
      getIdentifier in interface Resource
      Specified by:
      getIdentifier in class DataCube
      Returns:
      a persistent identifier unique within the data store, or absent if this resource has no such identifier.
      See Also:
    • setOverviewIdentifier

      final void setOverviewIdentifier(org.opengis.util.NameSpace base, int overview)
      Sets the identifier for an overview level. This is used only for a pyramid. The image with finest resolution is used as the namespace for all overviews.
      Parameters:
      base - name of the image with finest resolution.
      overview - 1 for the first overview, 2 for the next one, etc.
    • addEntry

      Object addEntry(short tag, Type type, long count) throws Exception
      Adds the value read from the current position in the given stream for the entry identified by the given GeoTIFF tag. This method may store the value either in a field of this class, or directly in the ImageMetadataBuilder. However, in the latter case, this method should not write anything under the "metadata/contentInfo" node.
      Parameters:
      tag - the GeoTIFF tag to decode.
      type - the GeoTIFF type of the value to read.
      count - the number of values to read.
      Returns:
      null on success, or the unrecognized value otherwise.
      Throws:
      IOException - if an error occurred while reading the stream.
      ParseException - if the value need to be parsed as date and the parsing failed.
      NumberFormatException - if the value need to be parsed as number and the parsing failed.
      ArithmeticException - if the value cannot be represented in the expected Java type.
      IllegalArgumentException - if a value which was expected to be a singleton is not.
      UnsupportedOperationException - if the given type is Type.UNDEFINED.
      DataStoreException - if a logical error is found or an unsupported TIFF feature is used.
      Exception
    • setTileTagFamily

      private void setTileTagFamily(byte family) throws DataStoreContentException
      Sets the tileTagFamily field to the given value if it does not conflict with previous value.
      Parameters:
      family - either TILE or STRIP.
      Throws:
      DataStoreContentException - if tileTagFamily is already set to another value.
    • extremum

      private static Vector extremum(Vector a, Vector b, boolean max)
      Computes the minimal or maximal values of the given vector. Those vectors do not need to have the same length. One of those two vector will be modified in-place.
      Parameters:
      a - the first vector, or null if none.
      b - the new vector to combine with the existing one. Cannot be null.
      max - true for computing the maximal values, or false for the minimal value.
    • pixelToByteCount

      private long pixelToByteCount(long value)
      Multiplies the given value by the number of bytes in one pixel, or return 0 if the result is not an integer.
      Throws:
      ArithmeticException - if the result overflows.
    • computeTileSize

      private int computeTileSize(int knownSize)
      Computes the tile width or height from the other size, or returns a negative number if the size cannot be computed.
      Parameters:
      knownSize - the tile width or height.
      Returns:
      the tile width if the known size was height, or the tile height if the known size was width, or a negative number if the width or height cannot be computed.
      Throws:
      ArithmeticException - if the result overflows.
    • validateMandatoryTags

      final boolean validateMandatoryTags() throws DataStoreContentException
      Verifies that the mandatory tags are present and consistent with each others. If a mandatory tag is absent, then there is a choice:
      • If the tag can be inferred from other tag values, performs that computation and logs a warning.
      • Otherwise throws an exception.
      This method opportunistically computes default value of optional fields when those values can be computed from other (usually mandatory) fields.
      Returns:
      true if the method has been invoked for the first time.
      Throws:
      DataStoreContentException - if a mandatory tag is missing and cannot be inferred.
    • createMetadata

      protected org.opengis.metadata.Metadata createMetadata() throws DataStoreException
      Builds the metadata with the information stored in the fields of this IFD. This method is invoked only if the user requested the ISO 19115 metadata.
      Overrides:
      createMetadata in class AbstractGridCoverageResource
      Returns:
      the newly created metadata, or null if unknown.
      Throws:
      DataStoreException - if an error occurred while reading metadata from the data store.
    • isReducedResolution

      final boolean isReducedResolution()
      Returns true if this image is a reduced resolution (overview) version of another image in this TIFF file.
    • initReducedResolution

      final void initReducedResolution(ImageFileDirectory fullResolution, double[] scales) throws DataStoreException, org.opengis.referencing.operation.TransformException
      If this IFD has no grid geometry information, derives a grid geometry by applying a scale factor on the grid geometry of another IFD. Information about bands are also copied if compatible. This method should be invoked only when isReducedResolution() is true.
      Parameters:
      fullResolution - the full-resolution image.
      scales - size of full resolution image / size of this image for each grid axis.
      Throws:
      DataStoreException
      org.opengis.referencing.operation.TransformException
    • getGridGeometry

      public GridGeometry getGridGeometry() throws DataStoreContentException
      Returns an object containing the image size, the CRS and the conversion from pixel indices to CRS coordinates. The grid geometry has 2 or 3 dimensions, depending on whether the CRS declares a vertical axis or not.

      Thread-safety

      This method is thread-safe because it can be invoked directly by user.
      Returns:
      extent of grid coordinates together with their mapping to "real world" coordinates.
      Throws:
      DataStoreContentException
      See Also:
    • getExtent

      final GridExtent getExtent()
      Returns the image width and height without building the full grid geometry.
      See Also:
    • getSampleDimensions

      public List<SampleDimension> getSampleDimensions() throws DataStoreContentException
      Returns the ranges of sample values together with the conversion from samples to real values.

      Thread-safety

      This method is thread-safe because it can be invoked directly by user.
      Returns:
      ranges of sample values together with their mapping to "real values".
      Throws:
      DataStoreContentException
      See Also:
    • getSampleModel

      protected SampleModel getSampleModel() throws DataStoreContentException
      Returns the Java2D sample model describing pixel type and layout. The raster size is the tile size and the number of bands is samplesPerPixel. A sample model of different size or number of bands can be derived after construction by call to one of SampleModel.create… methods.
      Specified by:
      getSampleModel in class TiledGridResource
      Returns:
      the sample model for tiles at full resolution with all their bands.
      Throws:
      DataStoreContentException - if the data type is not supported.
      See Also:
    • getNumBands

      protected int getNumBands()
      Returns the number of components per pixel.
      Specified by:
      getNumBands in class DataCube
      See Also:
    • getTileSize

      protected int[] getTileSize()
      Returns the size of tiles. This is also the size of the image sample model. The number of dimensions is always 2 for ImageFileDirectory.
      Specified by:
      getTileSize in class TiledGridResource
      Returns:
      the size of tiles (in pixels) in this resource.
      See Also:
    • getNumTiles

      final long getNumTiles()
      Returns the total number of tiles. The formulas used in this method are derived from the formulas documented in the TIFF specification and reproduced in tileWidth and tileHeight fields javadoc.
      Specified by:
      getNumTiles in class DataCube
    • getDataType

      private DataType getDataType() throws DataStoreContentException
      Returns the type of raster data. The enumeration values are restricted to types compatible with Java2D, at the cost of using more bits than bitsPerSample if there is no exact match.
      Throws:
      DataStoreContentException - if the type is not recognized.
    • getColorModel

      protected ColorModel getColorModel() throws DataStoreContentException
      Returns the Java2D color model.
      Specified by:
      getColorModel in class TiledGridResource
      Returns:
      a color model compatible with TiledGridResource.getSampleModel(), or null if none.
      Throws:
      DataStoreContentException - if the data type is not supported.
      See Also:
    • getFillValue

      protected Number getFillValue()
      Returns the value to use for filling empty spaces in the raster, or null if none, not different than zero or not valid for the target data type. The zero value is excluded because tiles are already initialized to zero by default.
      Specified by:
      getFillValue in class TiledGridResource
      Returns:
      the value to use for filling empty spaces in rasters.
    • getFillValue

      private Number getFillValue(boolean acceptZero)
      Returns the value to use for filling empty spaces in the raster, or null if none, The exclusion of zero value is optional, controlled by the acceptZero argument.
      Parameters:
      acceptZero - whether to return a number for the zero value.
    • getTileArrayInfo

      Vector[] getTileArrayInfo()
      Gets the stream position or the length in bytes of compressed tile arrays in the GeoTIFF file. Values in the returned vector are long primitive type.
      Specified by:
      getTileArrayInfo in class DataCube
      Returns:
      stream position (relative to file beginning) and length of compressed tile arrays, in bytes.
    • isBitOrderReversed

      boolean isBitOrderReversed()
      Returns true if Integer.reverseBytes(int) should be invoked on each byte read. This mode is very rare and should apply only to uncompressed image or CCITT 1D/2D compressions.
      Specified by:
      isBitOrderReversed in class DataCube
    • getCompression

      Compression getCompression()
      Returns the compression method, or null if unspecified.
      Specified by:
      getCompression in class DataCube
    • getPredictor

      Predictor getPredictor()
      Returns the mathematical operator that is applied to the image data before an encoding scheme is applied.
      Specified by:
      getPredictor in class DataCube
    • warning

      private void warning(Level level, short key, Object... parameters)
      Reports a warning with a message created from the given resource keys and parameters. Note that the log record will not necessarily be sent to the logging framework; if the user has registered at least one listener, then the record will be sent to the listeners instead.

      This method sets the source class name and source method name to hard-coded values. Those values assume that the warnings occurred indirectly from a call to GeoTiffStore.components(). We do not report private classes or methods as the source of warnings.

      Parameters:
      level - the logging level for the message to log.
      key - the Resources key of the message to format.
      parameters - the parameters to put in the message.
    • ensureSameLength

      private void ensureSameLength(short tag1, short tag2, int actual, int expected)
      Verifies that the given tags have the same length and reports a warning if they do not.
      Parameters:
      tag1 - the TIFF tag with inconsistent length.
      tag2 - the TIFF tag used as a reference.
      actual - length of list associated to tag1.
      expected - length of list associated to tag2.
    • missingTag

      private void missingTag(short missing, Object value, boolean computed, boolean warning)
      Reports a warning for a missing TIFF tag for which a default value can be computed.
      Parameters:
      missing - the numerical value of the missing tag.
      value - the default value or the computed value.
      computed - whether the default value has been computed.
      warning - whether the problem should be reported as a warning.
    • unsupportedTagValue

      private void unsupportedTagValue(short tag, Object value)
      Reports a warning for an unsupported TIFF tag value.
      Parameters:
      tag - the numerical value of the tag.
      value - the unsupported value.
    • missingTag

      private DataStoreContentException missingTag(short missing)
      Builds an exception for a missing TIFF tag for which no default value can be computed.
      Parameters:
      missing - the numerical value of the missing tag.