public Rectangle getBounds() {
   if (npoints == 0) return new Rectangle();
   if (bounds == null) calculateBounds(xpoints, ypoints, npoints);
   return bounds.getBounds();
 }
Example #2
0
  /**
   * Applies the band select operation to a grid coverage.
   *
   * @param cropEnvelope the target envelope; always not null
   * @param cropROI the target ROI shape; nullable
   * @param roiTolerance; as read from op's params
   * @param sourceCoverage is the source {@link GridCoverage2D} that we want to crop.
   * @param hints A set of rendering hints, or {@code null} if none.
   * @param sourceGridToWorldTransform is the 2d grid-to-world transform for the source coverage.
   * @return The result as a grid coverage.
   */
  private static GridCoverage2D buildResult(
      final GeneralEnvelope cropEnvelope,
      final Geometry cropROI,
      final double roiTolerance,
      final boolean forceMosaic,
      final Hints hints,
      final GridCoverage2D sourceCoverage,
      final AffineTransform sourceGridToWorldTransform) {

    //
    // Getting the source coverage and its child geolocation objects
    //
    final RenderedImage sourceImage = sourceCoverage.getRenderedImage();
    final GridGeometry2D sourceGridGeometry = ((GridGeometry2D) sourceCoverage.getGridGeometry());
    final GridEnvelope2D sourceGridRange = sourceGridGeometry.getGridRange2D();

    //
    // Now we try to understand if we have a simple scale and translate or a
    // more elaborated grid-to-world transformation n which case a simple
    // crop could not be enough, but we may need a more elaborated chain of
    // operation in order to do a good job. As an instance if we
    // have a rotation which is not multiple of PI/2 we have to use
    // the mosaic with a ROI
    //
    final boolean isSimpleTransform =
        CoverageUtilities.isSimpleGridToWorldTransform(sourceGridToWorldTransform, EPS);

    // Do we need to explode the Palette to RGB(A)?
    //
    int actionTaken = 0;

    // //
    //
    // Layout
    //
    // //
    final RenderingHints targetHints = new RenderingHints(null);
    if (hints != null) targetHints.add(hints);
    final ImageLayout layout = initLayout(sourceImage, targetHints);
    targetHints.put(JAI.KEY_IMAGE_LAYOUT, layout);

    //
    // prepare the processor to use for this operation
    //
    final JAI processor = OperationJAI.getJAI(targetHints);
    final boolean useProvidedProcessor = !processor.equals(JAI.getDefaultInstance());

    try {

      if (cropROI != null) {
        // replace the cropEnvelope with the envelope of the intersection
        // of the ROI and the cropEnvelope.
        // Remember that envelope(intersection(roi,cropEnvelope)) != intersection(cropEnvelope,
        // envelope(roi))
        final Polygon modelSpaceROI = FeatureUtilities.getPolygon(cropEnvelope, GFACTORY);
        Geometry intersection = IntersectUtils.intersection(cropROI, modelSpaceROI);
        Envelope2D e2d =
            JTS.getEnvelope2D(
                intersection.getEnvelopeInternal(), cropEnvelope.getCoordinateReferenceSystem());
        GeneralEnvelope ge = new GeneralEnvelope((org.opengis.geometry.Envelope) e2d);
        cropEnvelope.setEnvelope(ge);
      }

      // //
      //
      // Build the new range by keeping into
      // account translation of grid geometry constructor for respecting
      // OGC PIXEL-IS-CENTER ImageDatum assumption.
      //
      // //
      final AffineTransform sourceWorldToGridTransform = sourceGridToWorldTransform.createInverse();

      // //
      //
      // finalRasterArea will hold the smallest rectangular integer raster area that contains the
      // floating point raster
      // area which we obtain when applying the world-to-grid transform to the cropEnvelope. Note
      // that we need to intersect
      // such an area with the area covered by the source coverage in order to be sure we do not try
      // to crop outside the
      // bounds of the source raster.
      //
      // //
      final Rectangle2D finalRasterAreaDouble =
          XAffineTransform.transform(
              sourceWorldToGridTransform, cropEnvelope.toRectangle2D(), null);
      final Rectangle finalRasterArea = finalRasterAreaDouble.getBounds();

      // intersection with the original range in order to not try to crop outside the image bounds
      Rectangle.intersect(finalRasterArea, sourceGridRange, finalRasterArea);
      if (finalRasterArea.isEmpty())
        throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP));

      // //
      //
      // It is worth to point out that doing a crop the G2W transform
      // should not change while the envelope might change as
      // a consequence of the rounding of the underlying image datum
      // which uses integer factors or in case the G2W is very
      // complex. Note that we will always strive to
      // conserve the original grid-to-world transform.
      //
      // //

      // we do not have to crop in this case (should not really happen at
      // this time)
      if (finalRasterArea.equals(sourceGridRange) && isSimpleTransform && cropROI == null)
        return sourceCoverage;

      // //
      //
      // if I get here I have something to crop
      // using the world-to-grid transform for going from envelope to the
      // new grid range.
      //
      // //
      final double minX = finalRasterArea.getMinX();
      final double minY = finalRasterArea.getMinY();
      final double width = finalRasterArea.getWidth();
      final double height = finalRasterArea.getHeight();

      // //
      //
      // Check if we need to use mosaic or crop
      //
      // //
      final PlanarImage croppedImage;
      final ParameterBlock pbj = new ParameterBlock();
      pbj.addSource(sourceImage);
      java.awt.Polygon rasterSpaceROI = null;
      String operatioName = null;
      if (!isSimpleTransform || cropROI != null) {
        // /////////////////////////////////////////////////////////////////////
        //
        // We don't have a simple scale and translate transform, JAI
        // crop MAY NOT suffice. Let's decide whether or not we'll use
        // the Mosaic.
        //
        // /////////////////////////////////////////////////////////////////////
        Polygon modelSpaceROI = FeatureUtilities.getPolygon(cropEnvelope, GFACTORY);

        // //
        //
        // Now convert this polygon back into a shape for the source
        // raster space.
        //
        // //
        final List<Point2D> points = new ArrayList<Point2D>(5);
        rasterSpaceROI =
            FeatureUtilities.convertPolygonToPointArray(
                modelSpaceROI, ProjectiveTransform.create(sourceWorldToGridTransform), points);
        if (rasterSpaceROI == null || rasterSpaceROI.getBounds().isEmpty())
          if (finalRasterArea.isEmpty())
            throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP));
        final boolean doMosaic =
            forceMosaic
                ? true
                : decideJAIOperation(roiTolerance, rasterSpaceROI.getBounds2D(), points);
        if (doMosaic || cropROI != null) {
          // prepare the params for the mosaic
          final ROI[] roiarr;
          try {
            if (cropROI != null) {
              final LiteShape2 cropRoiLS2 =
                  new LiteShape2(
                      cropROI, ProjectiveTransform.create(sourceWorldToGridTransform), null, false);
              ROI cropRS = new ROIShape(cropRoiLS2);
              Rectangle2D rt = cropRoiLS2.getBounds2D();
              if (!hasIntegerBounds(rt)) {
                // Approximate Geometry
                Geometry geo = (Geometry) cropRoiLS2.getGeometry().clone();
                transformGeometry(geo);
                cropRS = new ROIShape(new LiteShape2(geo, null, null, false));
              }
              roiarr = new ROI[] {cropRS};
            } else {
              final ROIShape roi = new ROIShape(rasterSpaceROI);
              roiarr = new ROI[] {roi};
            }
          } catch (FactoryException ex) {
            throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP), ex);
          }
          pbj.add(MosaicDescriptor.MOSAIC_TYPE_OVERLAY);
          pbj.add(null);
          pbj.add(roiarr);
          pbj.add(null);
          pbj.add(CoverageUtilities.getBackgroundValues(sourceCoverage));

          // prepare the final layout
          final Rectangle bounds = rasterSpaceROI.getBounds2D().getBounds();
          Rectangle.intersect(bounds, sourceGridRange, bounds);
          if (bounds.isEmpty()) throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP));

          // we do not have to crop in this case (should not really happen at
          // this time)
          if (!doMosaic && bounds.getBounds().equals(sourceGridRange) && isSimpleTransform)
            return sourceCoverage;

          // nice trick, we use the layout to do the actual crop
          final Rectangle boundsInt = bounds.getBounds();
          layout.setMinX(boundsInt.x);
          layout.setWidth(boundsInt.width);
          layout.setMinY(boundsInt.y);
          layout.setHeight(boundsInt.height);
          operatioName = "Mosaic";
        }
      }

      // do we still have to set the operation name? If so that means we have to go for crop.
      if (operatioName == null) {
        // executing the crop
        pbj.add((float) minX);
        pbj.add((float) minY);
        pbj.add((float) width);
        pbj.add((float) height);
        operatioName = "GTCrop";
      }
      // //
      //
      // Apply operation
      //
      // //
      if (!useProvidedProcessor) {
        croppedImage = JAI.create(operatioName, pbj, targetHints);
      } else {
        croppedImage = processor.createNS(operatioName, pbj, targetHints);
      }

      // conserve the input grid to world transformation
      Map sourceProperties = sourceCoverage.getProperties();
      Map properties = null;
      if (sourceProperties != null && !sourceProperties.isEmpty()) {
        properties = new HashMap(sourceProperties);
      }
      if (rasterSpaceROI != null) {
        if (properties != null) {
          properties.put("GC_ROI", rasterSpaceROI);
        } else {
          properties = Collections.singletonMap("GC_ROI", rasterSpaceROI);
        }
      }

      return new GridCoverageFactory(hints)
          .create(
              sourceCoverage.getName(),
              croppedImage,
              new GridGeometry2D(
                  new GridEnvelope2D(croppedImage.getBounds()),
                  sourceGridGeometry.getGridToCRS2D(PixelOrientation.CENTER),
                  sourceCoverage.getCoordinateReferenceSystem()),
              (GridSampleDimension[])
                  (actionTaken == 1 ? null : sourceCoverage.getSampleDimensions().clone()),
              new GridCoverage[] {sourceCoverage},
              properties);

    } catch (TransformException e) {
      throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP), e);
    } catch (NoninvertibleTransformException e) {
      throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP), e);
    }
  }
 private final void paintImage(Point pt) {
   tree.paintImmediately(rect2D.getBounds());
   rect2D.setRect((int) pt.getX(), (int) pt.getY(), image.getWidth(), image.getHeight());
   tree.getGraphics().drawImage(image, (int) pt.getX(), (int) pt.getY(), tree);
 }
 private final void clearImage() {
   tree.paintImmediately(rect2D.getBounds());
 }
  /*
   * (non-Javadoc)
   *
   * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
   */
  @Override
  public void paintComponent(Graphics g) {
    // if (this.isPalette) {
    // this.paintPalette(g);
    // return;
    // }

    DecorationAreaType decorationType = getThisDecorationType();

    Graphics2D graphics = (Graphics2D) g.create();
    // Desktop icon is translucent.
    final float coef = (this.getParent() instanceof JDesktopIcon) ? 0.6f : 1.0f;
    graphics.setComposite(LafWidgetUtilities.getAlphaComposite(this.frame, coef, g));

    boolean leftToRight = this.frame.getComponentOrientation().isLeftToRight();

    int width = this.getWidth();
    int height = this.getHeight() + 2;

    SubstanceColorScheme scheme =
        SubstanceCoreUtilities.getSkin(this.frame).getEnabledColorScheme(decorationType);
    JInternalFrame hostFrame =
        (JInternalFrame) SwingUtilities.getAncestorOfClass(JInternalFrame.class, this);
    JComponent hostForColorization = hostFrame;
    if (hostFrame == null) {
      // try desktop icon
      JDesktopIcon desktopIcon =
          (JDesktopIcon) SwingUtilities.getAncestorOfClass(JDesktopIcon.class, this);
      if (desktopIcon != null) hostFrame = desktopIcon.getInternalFrame();
      hostForColorization = desktopIcon;
    }
    // if ((hostFrame != null) && SubstanceCoreUtilities.hasColorization(
    // this)) {
    Color backgr = hostFrame.getBackground();
    if (!(backgr instanceof UIResource)) {
      double colorization = SubstanceCoreUtilities.getColorizationFactor(hostForColorization);
      scheme = ShiftColorScheme.getShiftedScheme(scheme, backgr, colorization, null, 0.0);
    }
    // }
    String theTitle = this.frame.getTitle();

    // offset of border
    int xOffset;
    int leftEnd;
    int rightEnd;

    if (leftToRight) {
      xOffset = 5;
      Icon icon = this.frame.getFrameIcon();
      if (icon != null) {
        xOffset += icon.getIconWidth() + 5;
      }

      leftEnd = (this.menuBar == null) ? 0 : (this.menuBar.getWidth() + 5);
      xOffset += leftEnd;
      if (icon != null) leftEnd += (icon.getIconWidth() + 5);

      rightEnd = width - 5;

      // find the leftmost button for the right end
      AbstractButton leftmostButton = null;
      if (this.frame.isIconifiable()) {
        leftmostButton = this.iconButton;
      } else {
        if (this.frame.isMaximizable()) {
          leftmostButton = this.maxButton;
        } else {
          if (this.frame.isClosable()) {
            leftmostButton = this.closeButton;
          }
        }
      }

      if (leftmostButton != null) {
        Rectangle rect = leftmostButton.getBounds();
        rightEnd = rect.getBounds().x - 5;
      }
      if (theTitle != null) {
        FontMetrics fm = this.frame.getFontMetrics(graphics.getFont());
        int titleWidth = rightEnd - leftEnd;
        String clippedTitle = SubstanceCoreUtilities.clipString(fm, titleWidth, theTitle);
        // show tooltip with full title only if necessary
        if (theTitle.equals(clippedTitle)) this.setToolTipText(null);
        else this.setToolTipText(theTitle);
        theTitle = clippedTitle;
      }
    } else {
      xOffset = width - 5;

      Icon icon = this.frame.getFrameIcon();
      if (icon != null) {
        xOffset -= (icon.getIconWidth() + 5);
      }

      rightEnd = (this.menuBar == null) ? xOffset : xOffset - this.menuBar.getWidth() - 5;

      // find the rightmost button for the left end
      AbstractButton rightmostButton = null;
      if (this.frame.isIconifiable()) {
        rightmostButton = this.iconButton;
      } else {
        if (this.frame.isMaximizable()) {
          rightmostButton = this.maxButton;
        } else {
          if (this.frame.isClosable()) {
            rightmostButton = this.closeButton;
          }
        }
      }

      leftEnd = 5;
      if (rightmostButton != null) {
        Rectangle rect = rightmostButton.getBounds();
        leftEnd = rect.getBounds().x + 5;
      }
      if (theTitle != null) {
        FontMetrics fm = this.frame.getFontMetrics(graphics.getFont());
        int titleWidth = rightEnd - leftEnd;
        String clippedTitle = SubstanceCoreUtilities.clipString(fm, titleWidth, theTitle);
        // show tooltip with full title only if necessary
        if (theTitle.equals(clippedTitle)) {
          this.setToolTipText(null);
        } else {
          this.setToolTipText(theTitle);
        }
        theTitle = clippedTitle;
        xOffset = rightEnd - fm.stringWidth(theTitle);
      }
    }

    BackgroundPaintingUtils.update(
        graphics, SubstanceInternalFrameTitlePane.this, false, decorationType);
    // DecorationPainterUtils.paintDecorationBackground(graphics,
    // SubstanceInternalFrameTitlePane.this, false);

    // draw the title (if needed)
    if (theTitle != null) {
      JRootPane rootPane = this.getRootPane();
      FontMetrics fm = rootPane.getFontMetrics(graphics.getFont());
      int yOffset = ((height - fm.getHeight()) / 2) + fm.getAscent();

      SubstanceTextUtilities.paintTextWithDropShadow(
          this,
          graphics,
          SubstanceColorUtilities.getForegroundColor(scheme),
          theTitle,
          width,
          height,
          xOffset,
          yOffset);
    }

    Icon icon = this.frame.getFrameIcon();
    if (icon != null) {
      if (leftToRight) {
        int iconY = ((height / 2) - (icon.getIconHeight() / 2));
        icon.paintIcon(this.frame, graphics, 5, iconY);
      } else {
        int iconY = ((height / 2) - (icon.getIconHeight() / 2));
        icon.paintIcon(this.frame, graphics, width - 5 - icon.getIconWidth(), iconY);
      }
    }

    graphics.dispose();
  }