/**
   * *****************************************************************************************************************
   *
   * @param iis
   * @return
   * @throws IOException
   *     <p>*****************************************************************************
   */
  protected boolean canDecodeInput(@Nonnull final RAWImageInputStream iis) throws IOException {
    iis.seek(0);
    NEFHeaderProcessor headerProcessor = new NEFHeaderProcessor();
    headerProcessor.process(iis);
    long ifdOffset = TIFFImageReaderSupport.processHeader(iis, headerProcessor);

    if (ifdOffset
        == 20) // TODO: bad fix for NDF files, must test for NDF instead - headerProcessor.isNDF()
    {
      ifdOffset -= NEFHeaderProcessor.NDF_OFFSET;
      iis.setBaseOffset(
          NEFHeaderProcessor
              .NDF_OFFSET); // TODO: move this behaviour as generic, with hproc.getBaseOffset()
    }

    IFD primaryIFD = new IFD();
    primaryIFD.load(iis, ifdOffset);

    if (primaryIFD.isDNGVersionAvailable()) {
      logger.finest(">>>> FAILING, isDNGVersionAvailable returning true");
      return false;
    }

    String make = primaryIFD.getMake();
    String model = primaryIFD.getModel();
    logger.finest("Make: %s, Model: %s", make, model);
    //
    // Beware that TIFF files out of Nikon scanners are tagged as Nikon.
    // Check the model name too.
    //
    if ((make == null)
        || !make.toUpperCase().startsWith("NIKON")
        || (model == null)
        || (!model.toUpperCase().startsWith("NIKON D")
            && !supportedModels.contains(model.toUpperCase()))) {
      logger.finest(">>>> FAILING, supportedModels: %s", supportedModels);
      return false;
    }

    return true;
  }
  @Override
  protected WritableRaster loadRAWRaster() throws IOException {
    final IFD rasterIFD = ((TIFFMetadataSupport) metadata).getPrimaryIFD();
    final RasterReader rasterReader = new Grey12RasterReader();
    final int width = rasterIFD.getImageWidth();
    final int height = rasterIFD.getImageLength();
    final int bitsPerSample = rasterIFD.getBitsPerSample()[0];
    initializeRasterReader(width, height, bitsPerSample, rasterReader);

    if (!rasterIFD.isTileWidthAvailable()) {
      iis.seek(
          rasterIFD.getStripOffsets()); // FIXME: move, it's responsibility of the rreader to seek
    }

    final WritableRaster raster = rasterReader.loadRaster(iis, this);

    return raster;
  }
  @Override
  protected void initializeRasterReader(
      int width, int height, int bitsPerSample, RasterReader rasterReader) {
    IFD rasterIFD = ((TIFFMetadataSupport) metadata).getRasterIFD();
    rasterReader.setWidth(width);
    rasterReader.setHeight(height);
    rasterReader.setBitsPerSample(bitsPerSample);
    //		if (rasterReader instanceof Gray12RasterReader) {
    //			IFD primaryIFD = ((TIFFMetadataSupport) metadata).getPrimaryIFD();
    //			((Gray12RasterReader) rasterReader).setStripsOffset(primaryIFD.getStripOffsets());
    //		}

    if ((rasterIFD != null) && rasterIFD.isCompressionAvailable()) {
      rasterReader.setCompression(rasterIFD.getCompression().intValue());
    }

    if ((rasterIFD != null) && rasterIFD.isStripByteCountsAvailable()) {
      rasterReader.setStripByteCount(rasterIFD.getStripByteCounts());
    }

    if ((rasterIFD != null) && rasterIFD.isTileWidthAvailable()) {
      int imageWidth = rasterIFD.getImageWidth();
      int imageLength = rasterIFD.getImageLength();
      int tileWidth = rasterIFD.getTileWidth();
      int tileLength = rasterIFD.getTileLength();
      rasterReader.setTileWidth(tileWidth);
      rasterReader.setTileHeight(tileLength);
      rasterReader.setTilesAcross((imageWidth + tileWidth - 1) / tileWidth);
      rasterReader.setTilesDown((imageLength + tileLength - 1) / tileLength);
      rasterReader.setTileOffsets(rasterIFD.getTileOffsets());
      // int[] tileByteCounts = imageIFD.getTileByteCounts();
    }
  }