private boolean isBadTiling() throws IOException {
   final int imageHeight = imageReader.getHeight(FIRST_IMAGE);
   final int tileHeight = imageReader.getTileHeight(FIRST_IMAGE);
   final int imageWidth = imageReader.getWidth(FIRST_IMAGE);
   final int tileWidth = imageReader.getTileWidth(FIRST_IMAGE);
   return tileWidth <= 1
       || tileHeight <= 1
       || imageWidth == tileWidth
       || imageHeight == tileHeight;
 }
 private void addBandsToProduct(TiffFileInfo tiffInfo, Product product) throws IOException {
   final ImageReadParam readParam = imageReader.getDefaultReadParam();
   TIFFRenderedImage baseImage =
       (TIFFRenderedImage) imageReader.readAsRenderedImage(FIRST_IMAGE, readParam);
   SampleModel sampleModel = baseImage.getSampleModel();
   final int numBands = sampleModel.getNumBands();
   final int productDataType = ImageManager.getProductDataType(sampleModel.getDataType());
   bandMap = new HashMap<>(numBands);
   for (int i = 0; i < numBands; i++) {
     final String bandName = String.format("band_%d", i + 1);
     final Band band = product.addBand(bandName, productDataType);
     if (tiffInfo.containsField(BaselineTIFFTagSet.TAG_COLOR_MAP)
         && baseImage.getColorModel() instanceof IndexColorModel) {
       band.setImageInfo(createIndexedImageInfo(product, baseImage, band));
     }
     bandMap.put(band, i);
   }
 }
  private synchronized Raster readRect(
      int sourceOffsetX,
      int sourceOffsetY,
      int sourceStepX,
      int sourceStepY,
      int destOffsetX,
      int destOffsetY,
      int destWidth,
      int destHeight)
      throws IOException {
    ImageReadParam readParam = imageReader.getDefaultReadParam();
    int subsamplingXOffset = sourceOffsetX % sourceStepX;
    int subsamplingYOffset = sourceOffsetY % sourceStepY;
    readParam.setSourceSubsampling(
        sourceStepX, sourceStepY, subsamplingXOffset, subsamplingYOffset);
    RenderedImage subsampledImage = imageReader.readAsRenderedImage(FIRST_IMAGE, readParam);

    return subsampledImage.getData(new Rectangle(destOffsetX, destOffsetY, destWidth, destHeight));
  }
 private void setPreferredTiling(Product product) throws IOException {
   final Dimension dimension;
   if (isBadTiling()) {
     dimension =
         JAIUtils.computePreferredTileSize(
             imageReader.getWidth(FIRST_IMAGE), imageReader.getHeight(FIRST_IMAGE), 1);
   } else {
     dimension =
         new Dimension(
             imageReader.getTileWidth(FIRST_IMAGE), imageReader.getTileHeight(FIRST_IMAGE));
   }
   if (isGlobalShifted180) {
     product.setPreferredTileSize(
         new Dimension(imageReader.getWidth(FIRST_IMAGE), imageReader.getHeight(FIRST_IMAGE)));
   } else {
     product.setPreferredTileSize(dimension);
   }
 }
  Product readGeoTIFFProduct(final ImageInputStream stream, final File inputFile)
      throws IOException {
    Iterator<ImageReader> imageReaders = ImageIO.getImageReaders(stream);
    while (imageReaders.hasNext()) {
      final ImageReader reader = imageReaders.next();
      if (reader instanceof TIFFImageReader) {
        imageReader = (TIFFImageReader) reader;
        break;
      }
    }
    if (imageReader == null) {
      throw new IOException("GeoTiff imageReader not found");
    }

    imageReader.setInput(stream);

    Product product = null;

    final TIFFImageMetadata imageMetadata =
        (TIFFImageMetadata) imageReader.getImageMetadata(FIRST_IMAGE);
    final TiffFileInfo tiffInfo = new TiffFileInfo(imageMetadata.getRootIFD());
    final TIFFField field = tiffInfo.getField(Utils.PRIVATE_BEAM_TIFF_TAG_NUMBER);
    if (field != null && field.getType() == TIFFTag.TIFF_ASCII) {
      final String s = field.getAsString(0).trim();
      if (s.contains("<Dimap_Document")) { // with DIMAP header
        InputStream is = null;
        try {
          final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
          final DocumentBuilder builder = factory.newDocumentBuilder();
          is = new ByteArrayInputStream(s.getBytes());
          final Document document = new DOMBuilder().build(builder.parse(is));
          product = DimapProductHelpers.createProduct(document);
          removeGeoCodingAndTiePointGrids(product);
          initBandsMap(product);
        } catch (ParserConfigurationException | SAXException ignore) {
          // ignore if it can not be read
        } finally {
          if (is != null) {
            is.close();
          }
        }
      }
    }

    if (product == null) { // without DIMAP header
      final String productName;
      if (tiffInfo.containsField(BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION)) {
        final TIFFField field1 = tiffInfo.getField(BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION);
        productName = field1.getAsString(0);
      } else if (inputFile != null) {
        productName = FileUtils.getFilenameWithoutExtension(inputFile);
      } else {
        productName = "geotiff";
      }
      final String productType = getReaderPlugIn().getFormatNames()[0];

      final int width = imageReader.getWidth(FIRST_IMAGE);
      final int height = imageReader.getHeight(FIRST_IMAGE);
      product = new Product(productName, productType, width, height, this);
      addBandsToProduct(tiffInfo, product);
    }

    if (tiffInfo.isGeotiff()) {
      applyGeoCoding(tiffInfo, imageMetadata, product);
    }

    TiffTagToMetadataConverter.addTiffTagsToMetadata(
        imageMetadata, tiffInfo, product.getMetadataRoot());

    if (inputFile != null) {
      product.setFileLocation(inputFile);
    }
    setPreferredTiling(product);

    return product;
  }