/**
   * renders one point to the submitted graphic context considering the also submitted projection
   *
   * @param g
   * @param point
   * @param projection
   * @param image
   * @param dis displacement
   */
  private void drawPoint(
      Graphics2D g, Point point, GeoTransform projection, Image image, double[] dis) {
    Envelope destSize = projection.getDestRect();
    Position source = point.getPosition();
    int x = (int) Math.round(projection.getDestX(source.getX()) + 0.5 + dis[0]);
    int y = (int) Math.round(projection.getDestY(source.getY()) + 0.5 + dis[1]);

    int x_ = x - (image.getWidth(null) >> 1);
    int y_ = y - (image.getHeight(null) >> 1);

    int dx = Math.min(image.getWidth(null), (int) destSize.getWidth() - x_);
    int dy = Math.min(image.getHeight(null), (int) destSize.getHeight() - y_);
    int tx = Math.min((int) destSize.getWidth(), x_ + image.getWidth(null));
    int ty = Math.min((int) destSize.getHeight(), y_ + image.getHeight(null));

    g.drawImage(image, x_, y_, tx, ty, 0, 0, dx, dy, null);
  }
  /**
   * returns the region of the source image that intersects with the GridCoverage to be created as
   * Rectangle as well as the Envelope of the region in the native CRS and the LonLatEnvelope of
   * this region. For ECW files these values reflect exactly the desired result, as the library will
   * cut and sample the source image during read.
   *
   * @param reqwidth width of the requested region
   * @param reqheight height of the requested region
   * @return the region of the source image that intersects with the GridCoverage to be created as
   *     Rectangle as well as the Envelope of the region in the native CRS and the LonLatEnvelope of
   *     this region.
   */
  private Object[] getECWImageRegion(int reqwidth, int reqheight) {

    Envelope imgenvelope = getLLEAsEnvelope();
    Envelope dstenvelope = envelope.createIntersection(imgenvelope);

    // In case of ECW files, we calculate the rectangle according
    // to the desired result, not according to the source image,
    // as clipping and sampling will be done by the ECW library.
    // Hence dstenvelope and srcenvelope are the same and width/height
    // must be clipped with our grid-cell (if necessary).
    double dWidth = (dstenvelope.getWidth() * reqwidth) / envelope.getWidth();
    double dHeight = (dstenvelope.getHeight() * reqheight) / envelope.getHeight();
    return calcRegionRectangle(dstenvelope, dstenvelope, dWidth, dHeight);
  }
  private static void transformRasterFile(
      String inFile,
      String inCRS,
      String outFile,
      String outCRS,
      Float imageQuality,
      int ppgridsize,
      int polynomOrder)
      throws Exception {

    System.out.println("Loading raster " + inFile);
    BufferedImage image = ImageUtils.loadImage(inFile);

    CoordinateSystem sourceCRS = CRSFactory.create(inCRS);
    CoordinateSystem targetCRS = CRSFactory.create(outCRS);

    WorldFile worldFile = WorldFile.readWorldFile(inFile, WorldFile.TYPE.CENTER, image);
    Envelope inEnvelope = worldFile.getEnvelope();

    // create minimal CoverageOffering for ImageGridCoverage
    // most parts are not used
    DomainSet ds = new DomainSet(new SpatialDomain(new Envelope[] {inEnvelope}));
    RangeSet rs = new RangeSet("", "");
    CodeList[] dummyCodeList = new CodeList[] {new CodeList("", new String[] {})};
    CodeList[] nativeSRSCodeList = new CodeList[] {new CodeList("", new String[] {inCRS})};

    SupportedSRSs supSRSs =
        new SupportedSRSs(dummyCodeList, dummyCodeList, dummyCodeList, nativeSRSCodeList);

    SupportedFormats supFormats = new SupportedFormats(dummyCodeList);

    CoverageOffering coverageOffering =
        new CoverageOffering("", "", "", null, null, null, ds, rs, supSRSs, supFormats, null, null);

    ImageGridCoverage igc = new ImageGridCoverage(coverageOffering, inEnvelope, image);

    GeoTransformer gt = new GeoTransformer(targetCRS);

    Envelope outEnvelope = gt.transform(inEnvelope, sourceCRS, true);

    // calculate new output size
    // use square pixels for output, ie. the aspect ratio changes
    double deltaX = outEnvelope.getWidth();
    double deltaY = outEnvelope.getHeight();
    double diagSize = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
    // pixelSize for calculation of the new image size
    double pixelSize =
        diagSize / Math.sqrt(Math.pow(image.getWidth(), 2) + Math.pow(image.getHeight(), 2));
    int height = (int) (deltaY / pixelSize + 0.5);
    int width = (int) (deltaX / pixelSize + 0.5);
    // realPixelSize for center type world files, etc.
    double realPixelSize =
        diagSize
            / Math.sqrt(Math.pow(image.getWidth() - 1, 2) + Math.pow(image.getHeight() - 1, 2));

    System.out.println("Transforming raster from " + inCRS + " to " + outCRS);
    igc =
        (ImageGridCoverage)
            gt.transform(
                igc,
                outEnvelope,
                width,
                height,
                ppgridsize,
                polynomOrder,
                new InterpolationNearest());

    image = igc.getAsImage(-1, -1);

    System.out.println("Saving raster " + outFile);
    ImageUtils.saveImage(image, outFile, imageQuality);

    // save new WorldFile
    WorldFile outWorldFile = new WorldFile(realPixelSize, realPixelSize, 0.0f, 0.0f, outEnvelope);
    String basename = outFile.substring(0, outFile.lastIndexOf("."));
    WorldFile.writeWorldFile(outWorldFile, basename);
  }