private void determineProductDimensions(final MetadataElement absRoot) throws IOException {
    int totalWidth = 0, maxHeight = 0, k = 0;
    String pol = null;
    for (Map.Entry<String, ImageIOFile> stringImageIOFileEntry : bandImageFileMap.entrySet()) {
      final ImageIOFile img = stringImageIOFileEntry.getValue();
      final String imgName = img.getName().toLowerCase();
      final String bandMetadataName = imgBandMetadataMap.get(imgName);
      if (bandMetadataName == null) {
        throw new IOException("Metadata for measurement dataset " + imgName + " not found");
      }

      if (k == 0) {
        pol = bandMetadataName.substring(bandMetadataName.lastIndexOf("_") + 1);
      } else if (!bandMetadataName.substring(bandMetadataName.lastIndexOf("_") + 1).equals(pol)) {
        continue;
      }
      k++;

      final MetadataElement bandMetadata = absRoot.getElement(bandMetadataName);
      int width = bandMetadata.getAttributeInt(AbstractMetadata.num_samples_per_line);
      int height = bandMetadata.getAttributeInt(AbstractMetadata.num_output_lines);
      totalWidth += width;
      if (height > maxHeight) {
        maxHeight = height;
      }
    }

    if (isSLC() && isTOPSAR()) { // approximate does not account for overlap
      absRoot.setAttributeInt(AbstractMetadata.num_samples_per_line, totalWidth);
      absRoot.setAttributeInt(AbstractMetadata.num_output_lines, maxHeight);
    }
  }
  protected void addImageFile(final String imgPath) throws IOException {
    final String name =
        imgPath.substring(imgPath.lastIndexOf('/') + 1, imgPath.length()).toLowerCase();
    if ((name.endsWith("tiff"))) {
      final InputStream inStream = getInputStream(imgPath);
      final ImageInputStream imgStream = ImageIO.createImageInputStream(inStream);
      if (imgStream == null) throw new IOException("Unable to open " + imgPath);

      final ImageIOFile img;
      if (isSLC()) {
        img =
            new ImageIOFile(
                name,
                imgStream,
                ImageIOFile.getTiffIIOReader(imgStream),
                1,
                1,
                ProductData.TYPE_INT32);
      } else {
        img =
            new ImageIOFile(
                name,
                imgStream,
                ImageIOFile.getTiffIIOReader(imgStream),
                1,
                1,
                ProductData.TYPE_INT32);
      }
      bandImageFileMap.put(img.getName(), img);
    }
  }
  @Override
  protected void addBands(final Product product) {

    String bandName;
    boolean real = true;
    Band lastRealBand = null;
    String unit;

    final MetadataElement absRoot = AbstractMetadata.getAbstractedMetadata(product);
    for (Map.Entry<String, ImageIOFile> stringImageIOFileEntry : bandImageFileMap.entrySet()) {
      final ImageIOFile img = stringImageIOFileEntry.getValue();
      final String imgName = img.getName().toLowerCase();
      final MetadataElement bandMetadata = absRoot.getElement(imgBandMetadataMap.get(imgName));
      final String swath = bandMetadata.getAttributeString(AbstractMetadata.swath);
      final String pol = bandMetadata.getAttributeString(AbstractMetadata.polarization);
      final int width = bandMetadata.getAttributeInt(AbstractMetadata.num_samples_per_line);
      final int height = bandMetadata.getAttributeInt(AbstractMetadata.num_output_lines);

      String tpgPrefix = "";
      String suffix = pol;
      if (isSLC() && isTOPSAR()) {
        suffix = swath + '_' + pol;
        tpgPrefix = swath;
      }

      int numImages = img.getNumImages();
      if (isSLC()) {
        numImages *= 2; // real + imaginary
      }
      for (int i = 0; i < numImages; ++i) {

        if (isSLC()) {
          for (int b = 0; b < img.getNumBands(); ++b) {
            if (real) {
              bandName = "i" + '_' + suffix;
              unit = Unit.REAL;
            } else {
              bandName = "q" + '_' + suffix;
              unit = Unit.IMAGINARY;
            }

            final Band band = new Band(bandName, ProductData.TYPE_INT16, width, height);
            band.setUnit(unit);

            product.addBand(band);
            bandMap.put(band, new ImageIOFile.BandInfo(band, img, i, b));
            AbstractMetadata.addBandToBandMap(bandMetadata, bandName);

            if (real) {
              lastRealBand = band;
            } else {
              ReaderUtils.createVirtualIntensityBand(product, lastRealBand, band, '_' + suffix);
            }
            real = !real;

            // add tiepointgrids and geocoding for band
            addTiePointGrids(band, imgName, tpgPrefix);

            // reset to null so it doesn't adopt a geocoding from the bands
            product.setGeoCoding(null);
          }
        } else {
          for (int b = 0; b < img.getNumBands(); ++b) {
            bandName = "Amplitude" + '_' + suffix;
            final Band band = new Band(bandName, ProductData.TYPE_INT32, width, height);
            band.setUnit(Unit.AMPLITUDE);

            product.addBand(band);
            bandMap.put(band, new ImageIOFile.BandInfo(band, img, i, b));
            AbstractMetadata.addBandToBandMap(bandMetadata, bandName);

            SARReader.createVirtualIntensityBand(product, band, '_' + suffix);

            // add tiepointgrids and geocoding for band
            addTiePointGrids(band, imgName, tpgPrefix);
          }
        }
      }
    }
  }