@Override
    protected void loadUncompressedRaster(
        final RAWImageInputStream iis, final WritableRaster raster, final RAWImageReaderSupport ir)
        throws IOException {

      final DataBufferUShort dataBuffer = (DataBufferUShort) raster.getDataBuffer();
      final short[] data = dataBuffer.getData();
      final int width = raster.getWidth();
      final int height = raster.getHeight();
      final int pixelStride = 1;
      final int scanStride = width * pixelStride;
      setBitsPerSample(12);
      selectBitReader(iis, raster, 12);
      //
      // We can rely on the fact that the array has been zeroed by the JVM, so we just set nonzero
      // samples.
      //
      for (int y = 0; y < height; y++) {
        final int row = getRow(y, height);
        int i = row * scanStride;

        for (int x = 0; x < width; x++) {
          int sample = (int) iis.readBits(12);

          data[i] = (short) sample;
          endOfColumn(x, iis);
          i += pixelStride;
        }

        ir.processImageProgress((100.0f * y) / height);
        endOfRow(y, iis);
      }
    }
  /**
   * *****************************************************************************************************************
   *
   * <p>****************************************************************************************************************
   */
  private boolean canDecodeInput(ImageInputStream source) throws IOException {
    RAWImageInputStream iis = new RAWImageInputStreamImpl(source);
    iis
        .setDontCloseDelegate(); // otherwise the garbage collector will close it together with the
                                 // original source!!

    try {
      iis.mark();
      return canDecodeInput(iis);
    } catch (Exception e) {
      return false;
    } finally {
      iis.setBaseOffset(0);
      iis.reset();
    }
  }
  /**
   * *****************************************************************************************************************
   *
   * @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;
  }
  public int decode(
      final @Nonnegative int bitCount,
      final boolean useTable,
      final @Nonnull RAWImageInputStream iis,
      final boolean zeroAfterFF)
      throws IOException {
    if ((bitCount == 0) || (availableBitCount < 0)) {
      return 0;
    }

    int value;

    // TODO: RAWImageInputStream supports zeroAfterFF - use it and simplify this loop
    // while (!reset && (availableBitCount < bitCount) && ((value = iis.read() & 0xff) != 0xff) &&
    // // more correct, but breaks
    while (!reset
        && (availableBitCount < bitCount)
        && ((value = iis.read() & 0xff) != -1)
        && !(reset = zeroAfterFF && (value == 0xff) && (iis.read() != 0))) {
      bitBuffer = (bitBuffer << 8) | value; // (uchar)c
      availableBitCount += 8;
    }

    value = (bitBuffer << (32 - availableBitCount)) >>> (32 - bitCount);

    if (useTable) {
      availableBitCount -= bitCountTable[value];
      value = byteTable[value] & 0xff; // (uchar)...
    } else {
      availableBitCount -= bitCount;
    }

    assert (availableBitCount >= 0);

    //        logger.finest("getbithuff: returning c: %d, bitbuf: %x, vbits: %d", c, bitbuf, vbits);
    return value;
  }