示例#1
0
  /**
   * Scale an image up/down to the desired width and height, while maintaining the image's aspect
   * ratio (if requested).
   *
   * @param image the source image to scale
   * @param scaleWidth the new width to scale to
   * @param scaleHeight the new height to scale to
   * @param keepAspect true if the aspect ratio should be maintained.
   * @param color the color to fill borders when maintaining aspect ratio (0 = black, 255 = white).
   * @return a scaled image as RenderedOp
   * @see #scaleImage(RenderedOp, int, int)
   */
  public static RenderedOp scaleImage(
      RenderedOp image, int scaleWidth, int scaleHeight, boolean keepAspect, double color) {
    float xScale = (float) scaleWidth / (float) image.getWidth();
    float yScale = (float) scaleHeight / (float) image.getHeight();
    boolean resize = false;

    if (keepAspect) {
      resize = Math.abs(xScale - yScale) < .0000001;
      xScale = Math.min(xScale, yScale);
      yScale = xScale;
    }

    ParameterBlock params = new ParameterBlock();
    params.addSource(image);

    params.add(xScale); // x scale factor
    params.add(yScale); // y scale factor
    params.add(0.0F); // x translate
    params.add(0.0F); // y translate
    params.add(Interpolation.getInstance(Interpolation.INTERP_BICUBIC));

    RenderedOp result = JAI.create("scale", params, ImageToolkit.NOCACHE_HINT); // $NON-NLS-1$
    if (resize) {
      result = resizeImage(result, scaleWidth, scaleHeight, color);
    }

    return result;
  }
示例#2
0
  // This method creates a surrogate image -- one which is
  // used to display data which originally was outside the
  // [0-255] range.
  private RenderedImage createSurrogate(RenderedImage image, double maxValue) {
    ParameterBlock pb = new ParameterBlock();
    pb.addSource(image);
    RenderedOp extrema = JAI.create("extrema", pb);
    // Must get the extrema of all bands.
    double[] allMins = (double[]) extrema.getProperty("minimum");
    // double[] allMaxs = (double[])extrema.getProperty("maximum");
    double minValue = allMins[0];
    // double maxValue = allMaxs[0];
    for (int v = 1; v < allMins.length; v++) {
      if (allMins[v] < minValue) minValue = allMins[v];
      // if (allMaxs[v] > maxValue) maxValue = allMaxs[v];
    }
    // Rescale the image with the parameters
    double[] multiplyBy = new double[1];
    multiplyBy[0] = Model_Main.MAXPIXELVALUE / (maxValue - minValue);
    double[] addThis = new double[1];
    addThis[0] = -minValue * multiplyBy[0];
    // Now we can rescale the pixels gray levels:
    ParameterBlock pbSub = new ParameterBlock();
    pbSub.addSource(image);
    pbSub.add(addThis);
    RenderedImage surrogateImage = (PlanarImage) JAI.create("subtractconst", pbSub, null);
    ParameterBlock pbMult = new ParameterBlock();
    pbMult.addSource(surrogateImage);
    pbMult.add(multiplyBy);
    surrogateImage = (PlanarImage) JAI.create("multiplyconst", pbMult, null);

    return surrogateImage;
  }
示例#3
0
  /**
   * Test Read exploiting JAI-ImageIO tools capabilities and GDAL warp.
   *
   * @throws FileNotFoundException
   * @throws IOException
   */
  @Test
  public void readWithWarp() throws FileNotFoundException, IOException {
    if (!isGDALAvailable) {
      return;
    }
    final ParameterBlockJAI pbjImageRead;
    String fileName = "utmByte.tif";
    final File file = TestData.file(this, fileName);

    SpatialReference destinationReference = new SpatialReference();
    destinationReference.SetProjCS("UTM 17 (WGS84) in northern hemisphere.");
    destinationReference.SetWellKnownGeogCS("WGS84");
    destinationReference.SetUTM(17, 1);

    GDALImageReadParam readParam = new GDALImageReadParam();
    readParam.setDestinationWkt(destinationReference.ExportToWkt());
    readParam.setResampleAlgorithm(ResampleAlgorithm.CUBIC);

    pbjImageRead = new ParameterBlockJAI("ImageRead");
    pbjImageRead.setParameter("Input", new FileImageInputStreamExtImpl(file));
    pbjImageRead.setParameter("Reader", new GeoTiffImageReaderSpi().createReaderInstance());
    pbjImageRead.setParameter("ReadParam", readParam);
    RenderedOp image = JAI.create("ImageRead", pbjImageRead);
    if (TestData.isInteractiveTest()) Viewer.visualizeAllInformation(image, "", true);
    else Assert.assertNotNull(image.getTiles());
  }
示例#4
0
 // If defaultNewIsNull is true, then newIsNull is ignored and it should behave as
 // if newIsNull were false.
 private void runTest(
     WritableRaster source,
     double sourceNoData,
     double newValue,
     boolean defaultNewIsNull,
     boolean newIsNull) {
   ColorModel cm1 = RasterUtils.createColorModel(source);
   java.util.Hashtable<String, Object> arg1Properties = new java.util.Hashtable<String, Object>();
   arg1Properties.put(OpImageUtils.NODATA_PROPERTY, sourceNoData);
   BufferedImage s1 = new BufferedImage(cm1, source, false, arg1Properties);
   RenderedOp op = null;
   if (defaultNewIsNull) {
     op = ReplaceNullDescriptor.create(s1, newValue, null);
   } else {
     op = ReplaceNullDescriptor.create(s1, newValue, newIsNull, null);
   }
   Raster r = op.getData();
   if (!defaultNewIsNull && newIsNull) {
     Assert.assertEquals(newValue, OpImageUtils.getNoData(op, Double.NaN), EPSILON);
   } else {
     Assert.assertTrue(Double.isNaN(OpImageUtils.getNoData(op, Double.NaN)));
   }
   Assert.assertEquals(width, r.getWidth());
   Assert.assertEquals(height, r.getHeight());
   for (int x = 0; x < width; x++) {
     for (int y = 0; y < height; y++) {
       double v = r.getSampleDouble(x, y, 0);
       int pixelId = getPixelId(x, y, width);
       Assert.assertEquals(pixelId, v, EPSILON);
     }
   }
 }
 private RenderedOp createScaledImage(
     RenderedImage sourceImage, S2Resolution resolution, int level) {
   int sourceWidth = sourceImage.getWidth();
   int sourceHeight = sourceImage.getHeight();
   int targetWidth = imageLayouts[0].width >> level;
   int targetHeight = imageLayouts[0].height >> level;
   float scaleX = (float) targetWidth / (float) sourceWidth;
   float scaleY = (float) targetHeight / (float) sourceHeight;
   float corrFactorX = resolution == S2Resolution.R20M ? R20M_X_FACTOR : R60M_X_FACTOR;
   float corrFactorY = resolution == S2Resolution.R20M ? R20M_Y_FACTOR : R60M_Y_FACTOR;
   final Dimension tileDim = getTileDim(targetWidth, targetHeight);
   ImageLayout imageLayout = new ImageLayout();
   imageLayout.setTileWidth(tileDim.width);
   imageLayout.setTileHeight(tileDim.height);
   RenderingHints renderingHints =
       new RenderingHints(
           JAI.KEY_BORDER_EXTENDER, BorderExtender.createInstance(BorderExtender.BORDER_ZERO));
   renderingHints.put(JAI.KEY_IMAGE_LAYOUT, imageLayout);
   RenderedOp scaledImage =
       ScaleDescriptor.create(
           sourceImage,
           scaleX * corrFactorX,
           scaleY * corrFactorY,
           0F,
           0F,
           Interpolation.getInstance(Interpolation.INTERP_NEAREST),
           renderingHints);
   if (scaledImage.getWidth() != targetWidth || scaledImage.getHeight() != targetHeight) {
     return CropDescriptor.create(
         scaledImage, 0.0F, 0.0F, (float) targetWidth, (float) targetHeight, null);
   } else {
     return scaledImage;
   }
 }
示例#6
0
  /**
   * Test Writing capabilities.
   *
   * @throws FileNotFoundException
   * @throws IOException
   */
  @Test
  public void write() throws IOException, FileNotFoundException {
    if (!isGDALAvailable) {
      return;
    }
    final File outputFile = TestData.temp(this, "writetest.tif", false);
    outputFile.deleteOnExit();
    final File inputFile = TestData.file(this, "utmByte.tif");

    ImageReadParam rparam = new ImageReadParam();
    rparam.setSourceRegion(new Rectangle(1, 1, 300, 500));
    rparam.setSourceSubsampling(1, 2, 0, 0);
    ImageReader reader = new GeoTiffImageReaderSpi().createReaderInstance();
    reader.setInput(inputFile);
    final IIOMetadata metadata = reader.getImageMetadata(0);

    final ParameterBlockJAI pbjImageRead = new ParameterBlockJAI("ImageRead");
    pbjImageRead.setParameter("Input", inputFile);
    pbjImageRead.setParameter("reader", reader);
    pbjImageRead.setParameter("readParam", rparam);

    final ImageLayout l = new ImageLayout();
    l.setTileGridXOffset(0).setTileGridYOffset(0).setTileHeight(256).setTileWidth(256);

    RenderedOp image =
        JAI.create("ImageRead", pbjImageRead, new RenderingHints(JAI.KEY_IMAGE_LAYOUT, l));

    if (TestData.isInteractiveTest()) Viewer.visualizeAllInformation(image, "geotiff");

    // ////////////////////////////////////////////////////////////////
    // preparing to write
    // ////////////////////////////////////////////////////////////////
    final ParameterBlockJAI pbjImageWrite = new ParameterBlockJAI("ImageWrite");
    ImageWriter writer = new GeoTiffImageWriterSpi().createWriterInstance();
    pbjImageWrite.setParameter("Output", outputFile);
    pbjImageWrite.setParameter("writer", writer);
    pbjImageWrite.setParameter("ImageMetadata", metadata);
    pbjImageWrite.setParameter("Transcode", false);
    ImageWriteParam param = new ImageWriteParam(Locale.getDefault());
    param.setSourceRegion(new Rectangle(10, 10, 100, 100));
    param.setSourceSubsampling(2, 1, 0, 0);
    pbjImageWrite.setParameter("writeParam", param);

    pbjImageWrite.addSource(image);
    final RenderedOp op = JAI.create("ImageWrite", pbjImageWrite);
    final ImageWriter writer2 =
        (ImageWriter) op.getProperty(ImageWriteDescriptor.PROPERTY_NAME_IMAGE_WRITER);
    writer2.dispose();

    // ////////////////////////////////////////////////////////////////
    // preparing to read again
    // ////////////////////////////////////////////////////////////////
    final ParameterBlockJAI pbjImageReRead = new ParameterBlockJAI("ImageRead");
    pbjImageReRead.setParameter("Input", outputFile);
    pbjImageReRead.setParameter("Reader", new GeoTiffImageReaderSpi().createReaderInstance());
    final RenderedOp image2 = JAI.create("ImageRead", pbjImageReRead);
    if (TestData.isInteractiveTest()) Viewer.visualizeAllInformation(image2, "geotif2");
    else Assert.assertNotNull(image2.getTiles());
  }
示例#7
0
  /**
   * Test Read on a Paletted Image
   *
   * @throws FileNotFoundException
   * @throws IOException
   */
  @Test
  public void palette() throws FileNotFoundException, IOException {
    if (!isGDALAvailable) {
      return;
    }
    final File outputFile = TestData.temp(this, "writetest.tif", false);
    outputFile.deleteOnExit();
    final File inputFile = TestData.file(this, "paletted.tif");

    ImageReader reader = new GeoTiffImageReaderSpi().createReaderInstance();
    reader.setInput(inputFile);
    final IIOMetadata metadata = reader.getImageMetadata(0);

    final ParameterBlockJAI pbjImageRead = new ParameterBlockJAI("ImageRead");
    pbjImageRead.setParameter("Input", inputFile);
    pbjImageRead.setParameter("reader", reader);

    final ImageLayout l = new ImageLayout();
    l.setTileGridXOffset(0).setTileGridYOffset(0).setTileHeight(256).setTileWidth(256);

    RenderedOp image =
        JAI.create("ImageRead", pbjImageRead, new RenderingHints(JAI.KEY_IMAGE_LAYOUT, l));

    if (TestData.isInteractiveTest()) Viewer.visualizeAllInformation(image, "Paletted image read");

    // ////////////////////////////////////////////////////////////////
    // preparing to write
    // ////////////////////////////////////////////////////////////////
    final ParameterBlockJAI pbjImageWrite = new ParameterBlockJAI("ImageWrite");
    ImageWriter writer = new GeoTiffImageWriterSpi().createWriterInstance();
    pbjImageWrite.setParameter("Output", outputFile);
    pbjImageWrite.setParameter("writer", writer);
    pbjImageWrite.setParameter("ImageMetadata", metadata);
    pbjImageWrite.setParameter("Transcode", false);
    pbjImageWrite.addSource(image);
    final RenderedOp op = JAI.create("ImageWrite", pbjImageWrite);
    final ImageWriter writer2 =
        (ImageWriter) op.getProperty(ImageWriteDescriptor.PROPERTY_NAME_IMAGE_WRITER);
    writer2.dispose();

    // ////////////////////////////////////////////////////////////////
    // preparing to read again
    // ////////////////////////////////////////////////////////////////
    final ParameterBlockJAI pbjImageReRead = new ParameterBlockJAI("ImageRead");
    pbjImageReRead.setParameter("Input", outputFile);
    pbjImageReRead.setParameter("Reader", new GeoTiffImageReaderSpi().createReaderInstance());
    final RenderedOp image2 = JAI.create("ImageRead", pbjImageReRead);
    if (TestData.isInteractiveTest())
      Viewer.visualizeAllInformation(image2, "Paletted image read back after writing");
    else Assert.assertNotNull(image2.getTiles());
    ImageIOUtilities.disposeImage(image2);
    ImageIOUtilities.disposeImage(image);
  }
  @Test
  public void rectanglePolyAcrossTiles() throws Exception {
    final int margin = 3;
    final int Ntiles = 3;

    int minx = margin;
    int miny = minx;
    int maxx = TILE_WIDTH * Ntiles - 2 * margin;
    int maxy = maxx;

    String wkt =
        String.format(
            "POLYGON((%d %d, %d %d, %d %d, %d %d, %d %d))",
            minx, miny, minx, maxy, maxx, maxy, maxx, miny, minx, miny);

    Polygon poly = (Polygon) reader.read(wkt);

    ParameterBlockJAI pb = new ParameterBlockJAI("VectorBinarize");
    pb.setParameter("width", Ntiles * TILE_WIDTH);
    pb.setParameter("height", Ntiles * TILE_WIDTH);
    pb.setParameter("geometry", poly);

    RenderedOp dest = JAI.create("VectorBinarize", pb);

    CoordinateSequence2D testPointCS = new CoordinateSequence2D(1);
    Point testPoint = gf.createPoint(testPointCS);

    for (int ytile = 0; ytile < Ntiles; ytile++) {
      for (int xtile = 0; xtile < Ntiles; xtile++) {
        Raster tile = dest.getTile(xtile, ytile);
        for (int y = tile.getMinY(), iy = 0; iy < tile.getHeight(); y++, iy++) {
          testPointCS.setY(0, y + 0.5);
          for (int x = tile.getMinX(), ix = 0; ix < tile.getWidth(); x++, ix++) {
            testPointCS.setX(0, x + 0.5);
            testPoint.geometryChanged();
            int expected = poly.intersects(testPoint) ? 1 : 0;
            assertEquals(
                "Failed test at position "
                    + x
                    + ", "
                    + y
                    + ", "
                    + "expected "
                    + expected
                    + " but got "
                    + tile.getSample(x, y, 0),
                expected,
                tile.getSample(x, y, 0));
          }
        }
      }
    }
  }
示例#9
0
  protected RenderedOp resizeJAI(
      int thumbWidth, int thumbHeight, RenderedOp image, boolean scaleComputed) {
    double scale = 1.0;
    if (!scaleComputed) {
      int imageWidth = image.getWidth();
      int imageHeight = image.getHeight();

      scale = computeEvenResizeScale(thumbWidth, thumbHeight, imageWidth, imageHeight);
    }

    RenderingHints qualityHints =
        new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    return JAI.create("SubsampleAverage", image, scale, scale, qualityHints);
  }
示例#10
0
  /**
   * Crop down an image to smaller dimensions. Used by resizeImage() when an image dimension is
   * smaller.
   *
   * @param image the source image to crop
   * @param toWidth the new width to crop to
   * @param toHeight the new height to crop to
   * @return a cropped image as RenderedOp
   * @see #resizeImage(RenderedOp, int, int)
   */
  public static RenderedOp cropImage(RenderedOp image, int toWidth, int toHeight) {
    int width = image.getWidth();
    int height = image.getHeight();
    int xOffset = (width - toWidth) / 2;
    int yOffset = (height - toHeight) / 2;
    ParameterBlock params = new ParameterBlock();
    params.addSource(image);

    params.add((float) xOffset); // x origin
    params.add((float) yOffset); // y origin
    params.add((float) toWidth); // width
    params.add((float) toHeight); // height

    return JAI.create("crop", params, null); // $NON-NLS-1$
  }
示例#11
0
  @Test
  public void testRoundTripTiledImage() throws Exception {
    BufferedImage input = ImageIO.read(sourceFile);

    // prepare a tiled image layout
    ImageLayout il = new ImageLayout(input);
    il.setTileWidth(8);
    il.setTileHeight(8);

    RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, il);
    RenderedOp tiled = FormatDescriptor.create(input, input.getSampleModel().getDataType(), hints);
    assertEquals(8, tiled.getTileWidth());
    assertEquals(8, tiled.getTileHeight());

    roundTripPNGJ(input, tiled);
  }
示例#12
0
  /**
   * Test Read exploiting JAI-ImageIO tools capabilities
   *
   * @throws FileNotFoundException
   * @throws IOException
   */
  @Test
  public void read() throws FileNotFoundException, IOException {
    if (!isGDALAvailable) {
      return;
    }
    final ParameterBlockJAI pbjImageRead;
    String fileName = "utmByte.tif";
    final File file = TestData.file(this, fileName);

    pbjImageRead = new ParameterBlockJAI("ImageRead");
    pbjImageRead.setParameter("Input", new FileImageInputStreamExtImpl(file));
    pbjImageRead.setParameter("Reader", new GeoTiffImageReaderSpi().createReaderInstance());
    RenderedOp image = JAI.create("ImageRead", pbjImageRead);
    if (TestData.isInteractiveTest()) Viewer.visualizeAllInformation(image, "", true);
    else Assert.assertNotNull(image.getTiles());
  }
示例#13
0
  // 이미지 폭
  public int getImageWidth(String pathname) {
    int width = -1;

    File file = new File(pathname);
    if (!file.exists()) return width;

    ParameterBlock pb = new ParameterBlock();
    pb.add(pathname);
    RenderedOp rOp = JAI.create("fileload", pb);

    BufferedImage bi = rOp.getAsBufferedImage();

    width = bi.getWidth();

    return width;
  }
示例#14
0
  // 이미지 높이
  public int getImageHeight(String pathname) {
    int height = -1;

    File file = new File(pathname);
    if (!file.exists()) return height;

    ParameterBlock pb = new ParameterBlock();
    pb.add(pathname);
    RenderedOp rOp = JAI.create("fileload", pb);

    BufferedImage bi = rOp.getAsBufferedImage();

    height = bi.getHeight();

    return height;
  }
  private void extremaOp(TiffMeta surface, GridCoverage2D gridCoverage2D) {
    double min = Double.MAX_VALUE;
    double max = Double.MIN_VALUE;

    RenderedImage img = gridCoverage2D.getRenderedImage();

    RenderedOp extremaOp = ExtremaDescriptor.create(img, null, 10, 10, false, 1, null);
    double[] allMins = (double[]) extremaOp.getProperty("minimum");
    min = Doubles.min(allMins);

    double[] allMaxs = (double[]) extremaOp.getProperty("maximum");
    max = Doubles.max(allMaxs);

    surface.setMaxVal(max);
    surface.setMinVal(min);
  }
示例#16
0
  public static void main(String[] args) {
    final File swapDir = new File("swap");
    swapDir.mkdir();
    final Logger logger = Logger.getAnonymousLogger();
    final ConsoleHandler consoleHandler = new ConsoleHandler();
    consoleHandler.setLevel(Level.ALL);
    logger.addHandler(consoleHandler);
    logger.setLevel(Level.ALL);
    final DefaultSwapSpace swapSpace = new DefaultSwapSpace(swapDir, logger);
    final SwappingTileCache tileCache = new SwappingTileCache(64 * M, swapSpace);
    JAI.getDefaultInstance().setTileCache(tileCache);

    RenderedImage sourceImage;
    if (args.length == 0) {
      sourceImage = DFTTestMain.createTestImage(512, 512);
    } else {
      sourceImage = FileLoadDescriptor.create(args[0], null, false, null);
    }

    sourceImage = DFTConvolveRIF.toFloat(sourceImage, null);

    BorderExtender extender = BorderExtender.createInstance(BorderExtender.BORDER_COPY);
    RenderingHints hints = new RenderingHints(JAI.KEY_BORDER_EXTENDER, extender);
    KernelJAI kernel = createBlurrKernel(33);
    RenderedOp convolvedImage = ConvolveDescriptor.create(sourceImage, kernel, hints);
    RenderedOp dftConvolvedImage = DFTConvolveDescriptor.create(sourceImage, kernel, null, hints);
    RenderedOp deltaImage =
        MultiplyConstDescriptor.create(
            SubtractDescriptor.create(convolvedImage, dftConvolvedImage, null),
            new double[] {2},
            null);
    showImage(sourceImage, "sourceImage");
    showImage(convolvedImage, "convolvedImage");
    showImage(dftConvolvedImage, "dftConvolvedImage");
    showImage(deltaImage, "deltaImage");

    final Object o = dftConvolvedImage.getProperty("kernelFT");
    System.out.println("o = " + o);

    System.out.println("Kernel\tConvolve\tDFTConvolve\tPerfGain");
    for (int i = 3; i <= 201; i += 2) {
      KernelJAI k = createBlurrKernel(i);
      double t1 = getRenderTime(ConvolveDescriptor.create(sourceImage, k, hints));
      double t2 = getRenderTime(DFTConvolveDescriptor.create(sourceImage, k, null, hints));
      System.out.println(i + "\t" + t1 + "\t" + t2 + "\t" + t1 / t2);
    }
  }
示例#17
0
  /**
   * Resize an image to the new dimensions - no scaling is performed on the image, but the canvas
   * size is changed. Any empty areas are filled with white.
   *
   * @param image the source image to resize
   * @param toWidth the new width to resize to
   * @param toHeight the new height to resize to
   * @param color the color to fill borders when resizing up.
   * @return the resized image as RenderedOp
   */
  public static RenderedOp resizeImage(RenderedOp image, int toWidth, int toHeight, double color) {
    int width = image.getWidth();
    int height = image.getHeight();

    if (width > toWidth || height > toHeight) {
      image = cropImage(image, Math.min(width, toWidth), Math.min(height, toHeight));
    }

    if (width < toWidth || height < toHeight) {
      int w = Math.max((toWidth - width) / 2, 0);
      int h = Math.max((toHeight - height) / 2, 0);

      image = borderImage(image, w, w, h, h, color);
    }

    return image;
  }
示例#18
0
  @Test
  public void test2BandsBug() {
    // build a transparent image
    BufferedImage image = new BufferedImage(256, 256, BufferedImage.TYPE_BYTE_GRAY);
    RenderedOp img = BandMergeDescriptor.create(null, 0, false, null, image, image);

    image = img.getAsBufferedImage();

    // create a palette out of it
    RenderedImage indexed = quantize(image);
    assertTrue(indexed.getColorModel() instanceof IndexColorModel);
    IndexColorModel icm = (IndexColorModel) indexed.getColorModel();

    // png encoder go mad if they get a one element palette, we need at
    // least two
    assertEquals(2, icm.getMapSize());
  }
  /**
   * This method downscales a band by a given factor
   *
   * @param inputBand - the input band
   * @param scalingFactor - the scaling factor
   * @return Band - the downscaled band
   */
  public static Band downscaleBand(Band inputBand, float scalingFactor) {
    final RenderedImage sourceImage = inputBand.getSourceImage();
    final RenderedOp downscaledImage =
        ScaleDescriptor.create(
            sourceImage,
            1.0f / scalingFactor,
            1.0f / scalingFactor,
            0.0f,
            0.0f,
            Interpolation.getInstance(Interpolation.INTERP_NEAREST),
            null);
    Band downscaledBand =
        new Band(
            inputBand.getName(), inputBand.getDataType(),
            downscaledImage.getWidth(), downscaledImage.getHeight());

    downscaledBand.setSourceImage(downscaledImage);
    return downscaledBand;
  }
示例#20
0
 public static ImageHeader load(Properties imageProperties, File imageDir) throws IOException {
   int dataType = Integer.parseInt(imageProperties.getProperty("dataType"));
   int minX = Integer.parseInt(imageProperties.getProperty("minX", "0"));
   int minY = Integer.parseInt(imageProperties.getProperty("minY", "0"));
   int width = Integer.parseInt(imageProperties.getProperty("width"));
   int height = Integer.parseInt(imageProperties.getProperty("height"));
   int tileGridXOffset = Integer.parseInt(imageProperties.getProperty("tileGridXOffset", "0"));
   int tileGridYOffset = Integer.parseInt(imageProperties.getProperty("tileGridYOffset", "0"));
   int tileWidth = Integer.parseInt(imageProperties.getProperty("tileWidth"));
   int tileHeight = Integer.parseInt(imageProperties.getProperty("tileHeight"));
   int numberOfBits = Integer.parseInt(imageProperties.getProperty("numberOfBits", "0"));
   String tileFormat = imageProperties.getProperty("tileFormat", "raw.zip");
   SampleModel sampleModel;
   ColorModel colorModel;
   if (tileFormat.startsWith("raw")) {
     if (numberOfBits == 1 || numberOfBits == 2 || numberOfBits == 4) {
       sampleModel =
           new MultiPixelPackedSampleModel(dataType, tileWidth, tileHeight, numberOfBits);
     } else {
       sampleModel = ImageUtils.createSingleBandedSampleModel(dataType, tileWidth, tileHeight);
     }
     colorModel = null;
   } else {
     RenderedOp tile00 =
         FileLoadDescriptor.create(
             new File(imageDir, "0-0." + tileFormat).getPath(), null, true, null);
     sampleModel = tile00.getSampleModel().createCompatibleSampleModel(tileWidth, tileHeight);
     colorModel = tile00.getColorModel();
   }
   ImageLayout imageLayout =
       new ImageLayout(
           minX,
           minY,
           width,
           height,
           tileGridXOffset,
           tileGridYOffset,
           tileWidth,
           tileHeight,
           sampleModel,
           colorModel);
   return new ImageHeader(imageLayout, tileFormat);
 }
示例#21
0
  protected boolean writeImage(String dstPath, String type, RenderedOp image) {
    boolean success = false;
    //		JAI doesn't natively support GIF encoding, but Java ImageIO does.
    if (type.toLowerCase().equals("gif")) {
      File dst = new File(dstPath);
      // if the file doesn't exist, create it and make sure we can write to it.
      if (!dst.exists()) {
        try {
          dst.createNewFile();
        } catch (IOException ioe) {
          this.core.app.logError(
              ErrorReporter.errorMsg(this.getClass(), "resizeImg")
                  + "Failed to create tmp img at \""
                  + dstPath
                  + "\".",
              ioe);
        }
      }
      if (!dst.canWrite()) {
        dst.setWritable(true);
      }

      try {
        ImageIO.write(image, type.toUpperCase(), dst);
      } catch (IOException ioe) {
        this.core.app.logError(
            ErrorReporter.errorMsg(this.getClass(), "resizeImg")
                + "Failed to write image data to \""
                + dstPath
                + "\".",
            ioe);
      }

      // clean up file handle
      dst = null;
    } else {
      if (type.toLowerCase().equals("jpg")) {
        type = "jpeg";
      }

      JAI.create("filestore", image, dstPath, type);
    }

    if (image != null && new File(dstPath).exists()) {
      success = true;
    }

    // JAI Cleanup
    image.dispose();
    image = null;
    type = null;

    return success;
  }
  @Test
  public void testAddAndGetTile() throws InterruptedException, FileNotFoundException, IOException {
    // Input stream to use
    ImageInputStream stream_in = null;
    try {
      stream_in = new FileImageInputStream(TestData.file(this, "world.tiff"));
      // Input RenderedImage to use
      final RenderedOp input =
          ImageReadDescriptor.create(
              stream_in, 0, false, false, false, null, null, null, null, null);

      // Boolean used for checking if the conditions are passed
      final AtomicBoolean passed = new AtomicBoolean(true);
      // Cache creation
      final ConcurrentTileCacheMultiMap cache =
          new ConcurrentTileCacheMultiMap(1000 * 1000, false, 1f, 4);
      // Selection of one tile from the image
      Raster data = input.getTile(input.getMinTileX(), input.getMinTileY());
      // Setting the tile inside the cache
      cache.add(input, input.getMinTileX(), input.getMinTileY(), data);
      // Thread pool to use for doing concurrent access on the cache
      ThreadPoolExecutor executor =
          new ThreadPoolExecutor(
              TOTAL, TOTAL, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1000000));
      // Latch used for waiting all the threads to end their work
      final CountDownLatch latch = new CountDownLatch(TOTAL);
      // Cycle for launching various requests
      int counter = TOTAL;
      while (counter > 0) {

        executor.execute(
            new Runnable() {

              public void run() {
                // Get the tile to use
                Raster data = cache.getTile(input, input.getMinTileX(), input.getMinTileY());
                if (data == null) {
                  passed.getAndSet(false);
                }
                latch.countDown();
              }
            });
        // Counter update
        counter--;
      }
      // Waiting all threads to finish
      latch.await();
      // Ensure that all the threads have found the tile
      Assert.assertTrue(passed.get());
    } finally {
      try {
        if (stream_in != null) {
          stream_in.flush();
          stream_in.close();
        }
      } catch (Throwable t) {
        //
      }
    }
  }
  @Test
  public void testOptimizedWarp() throws Exception {
    // do it again, make sure the image does not turn black since
    GridCoverage2D ushortCoverage = EXAMPLES.get(5);
    GridCoverage2D coverage =
        project(ushortCoverage, CRS.parseWKT(GOOGLE_MERCATOR_WKT), null, "nearest", null, true);
    RenderedImage ri = coverage.getRenderedImage();

    ImageWorker.WARP_REDUCTION_ENABLED = false;
    AffineTransform at = new AffineTransform(0.4, 0, 0, 0.5, -200, -200);
    RenderedOp fullChain =
        (RenderedOp)
            new ImageWorker(ri)
                .affine(
                    at, Interpolation.getInstance(Interpolation.INTERP_NEAREST), new double[] {0})
                .getRenderedImage();
    assertEquals("Scale", fullChain.getOperationName());
    fullChain.getTiles();

    ImageWorker.WARP_REDUCTION_ENABLED = true;
    RenderedOp reduced =
        (RenderedOp)
            new ImageWorker(ri)
                .affine(
                    at, Interpolation.getInstance(Interpolation.INTERP_NEAREST), new double[] {0})
                .getRenderedImage();
    // force computation, to make sure it does not throw exceptions
    reduced.getTiles();
    // check the chain has been reduced
    assertEquals("Warp", reduced.getOperationName());
    assertEquals(1, reduced.getSources().size());
    assertSame(ushortCoverage.getRenderedImage(), reduced.getSourceImage(0));

    // check the bounds of the output image has not changed
    assertEquals(fullChain.getBounds(), reduced.getBounds());
  }
示例#24
0
 public static RenderedImage getImageOp(RenderedImage image, String opName) {
   if (image instanceof RenderedOp) {
     RenderedOp op = (RenderedOp) image;
     if (op.getOperationName().equalsIgnoreCase(opName)) {
       return image;
     }
     while (op.getNumSources() > 0) {
       try {
         PlanarImage img = op.getSourceImage(0);
         if (image instanceof RenderedOp) {
           RenderedOp op2 = (RenderedOp) img;
           if (op2.getOperationName().equalsIgnoreCase(opName)) {
             return img;
           }
         }
       } catch (Exception ex) {
         return null;
       }
     }
   }
   return null;
 }
示例#25
0
  // This method is similar to the testBandMerge method but it tests the ExtendedBandMergeOpImage
  // class
  private void testExtendedBandMerge(RenderedImage[] sources, boolean noDataUsed, boolean roiUsed) {
    // Optional No Data Range used
    Range[] noData;
    // Source image data type
    int dataType = sources[0].getSampleModel().getDataType();
    // If no Data are present, the No Data Range associated is used
    if (noDataUsed) {

      switch (dataType) {
        case DataBuffer.TYPE_BYTE:
          noData = noDataByte;
          break;
        case DataBuffer.TYPE_USHORT:
          noData = noDataUShort;
          break;
        case DataBuffer.TYPE_SHORT:
          noData = noDataShort;
          break;
        case DataBuffer.TYPE_INT:
          noData = noDataInt;
          break;
        case DataBuffer.TYPE_FLOAT:
          noData = noDataFloat;
          break;
        case DataBuffer.TYPE_DOUBLE:
          noData = noDataDouble;
          break;
        default:
          throw new IllegalArgumentException("Wrong data type");
      }
    } else {
      noData = null;
    }

    // ROI to use
    ROI roi = null;
    if (roiUsed) {
      roi = roiData;
    }

    // New array ofr the transformed source images
    RenderedOp[] translated = new RenderedOp[sources.length];

    List<AffineTransform> transform = new ArrayList<AffineTransform>();

    for (int i = 0; i < sources.length; i++) {
      // Translation coefficients
      int xTrans = (int) (Math.random() * 10);
      int yTrans = (int) (Math.random() * 10);
      // Translation operation
      AffineTransform tr = AffineTransform.getTranslateInstance(xTrans, yTrans);
      // Addition to the transformations list
      transform.add(tr);
      // Translation of the image
      translated[i] =
          TranslateDescriptor.create(sources[i], (float) xTrans, (float) yTrans, null, null);
    }
    // Definition of the final image dimensions
    ImageLayout layout = new ImageLayout();
    layout.setMinX(sources[0].getMinX());
    layout.setMinY(sources[0].getMinY());
    layout.setWidth(sources[0].getWidth());
    layout.setHeight(sources[0].getHeight());

    RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);

    // BandMerge operation
    RenderedOp merged =
        BandMergeDescriptor.create(noData, destNoData, hints, transform, roi, translated);

    Assert.assertNotNull(merged.getTiles());
    // Check if the bands number is the same
    assertEquals(BAND_NUMBER, merged.getNumBands());
    // Upper-Left tile indexes
    int minTileX = merged.getMinTileX();
    int minTileY = merged.getMinTileY();
    // Raster object
    Raster upperLeftTile = merged.getTile(minTileX, minTileY);
    // Tile bounds
    int minX = upperLeftTile.getMinX();
    int minY = upperLeftTile.getMinY();
    int maxX = upperLeftTile.getWidth() + minX;
    int maxY = upperLeftTile.getHeight() + minY;

    // Source corners
    final int dstMinX = merged.getMinX();
    final int dstMinY = merged.getMinY();
    final int dstMaxX = merged.getMaxX();
    final int dstMaxY = merged.getMaxY();

    Point2D ptDst = new Point2D.Double(0, 0);
    Point2D ptSrc = new Point2D.Double(0, 0);

    // Cycle on all the tile Bands
    for (int b = 0; b < BAND_NUMBER; b++) {
      RandomIter iter = RandomIterFactory.create(translated[b], null);

      // Source corners
      final int srcMinX = translated[b].getMinX();
      final int srcMinY = translated[b].getMinY();
      final int srcMaxX = translated[b].getMaxX();
      final int srcMaxY = translated[b].getMaxY();

      // Cycle on the y-axis
      for (int x = minX; x < maxX; x++) {
        // Cycle on the x-axis
        for (int y = minY; y < maxY; y++) {
          // Calculated value
          double value = upperLeftTile.getSampleDouble(x, y, b);
          // If the tile pixels are outside the image bounds, then no data is set.
          if (x < dstMinX || x >= dstMaxX || y < dstMinY || y >= dstMaxY) {
            value = destNoData;
          }

          // Set the x,y destination pixel location
          ptDst.setLocation(x, y);
          // Map destination pixel to source pixel
          transform.get(b).transform(ptDst, ptSrc);
          // Source pixel indexes
          int srcX = round(ptSrc.getX());
          int srcY = round(ptSrc.getY());

          double valueOld = destNoData;

          // Check if the pixel is inside the source bounds
          if (!(srcX < srcMinX || srcX >= srcMaxX || srcY < srcMinY || srcY >= srcMaxY)) {
            // Old band value
            valueOld = iter.getSampleDouble(srcX, srcY, 0);
          }

          // ROI CHECK
          boolean contained = true;
          if (roiUsed) {
            if (!roi.contains(x, y)) {
              contained = false;
              // Comparison if the final value is not inside a ROI
              assertEquals(value, destNoData, TOLERANCE);
            }
          }

          if (contained) {
            // If no Data are present, no data check is performed
            if (noDataUsed) {
              switch (dataType) {
                case DataBuffer.TYPE_BYTE:
                  byte sampleB = ImageUtil.clampRoundByte(value);
                  byte sampleBOld = ImageUtil.clampRoundByte(valueOld);
                  if (noData[0].contains(sampleBOld)) {
                    assertEquals(sampleB, destNoData, TOLERANCE);
                  } else {
                    assertEquals(sampleB, valueOld, TOLERANCE);
                  }
                  break;
                case DataBuffer.TYPE_USHORT:
                  short sampleUS = ImageUtil.clampRoundUShort(value);
                  short sampleUSOld = ImageUtil.clampRoundUShort(valueOld);
                  if (noData[0].contains(sampleUSOld)) {
                    assertEquals(sampleUS, destNoData, TOLERANCE);
                  } else {
                    assertEquals(sampleUS, valueOld, TOLERANCE);
                  }
                  break;
                case DataBuffer.TYPE_SHORT:
                  short sampleS = ImageUtil.clampRoundShort(value);
                  short sampleSOld = ImageUtil.clampRoundShort(valueOld);
                  if (noData[0].contains(sampleSOld)) {
                    assertEquals(sampleS, destNoData, TOLERANCE);
                  } else {
                    assertEquals(sampleS, valueOld, TOLERANCE);
                  }
                  break;
                case DataBuffer.TYPE_INT:
                  int sampleI = ImageUtil.clampRoundInt(value);
                  int sampleIOld = ImageUtil.clampRoundInt(valueOld);
                  if (noData[0].contains(sampleIOld)) {
                    assertEquals(sampleI, destNoData, TOLERANCE);
                  } else {
                    assertEquals(sampleI, valueOld, TOLERANCE);
                  }
                  break;
                case DataBuffer.TYPE_FLOAT:
                  float sampleF = ImageUtil.clampFloat(value);
                  float sampleFOld = ImageUtil.clampFloat(valueOld);
                  if (noData[0].contains(sampleFOld)) {
                    assertEquals(sampleF, destNoData, TOLERANCE);
                  } else {
                    assertEquals(sampleF, valueOld, TOLERANCE);
                  }
                  break;
                case DataBuffer.TYPE_DOUBLE:
                  if (noData[0].contains(valueOld)) {
                    assertEquals(value, destNoData, TOLERANCE);
                  } else {
                    assertEquals(value, valueOld, TOLERANCE);
                  }
                  break;
                default:
                  throw new IllegalArgumentException("Wrong data type");
              }
            } else {
              // Else a simple value comparison is done
              assertEquals(value, valueOld, TOLERANCE);
            }
          }
        }
      }
    }
    // Disposal of the output image
    merged.dispose();
  }
示例#26
0
  private void testBandMerge(RenderedImage[] sources, boolean noDataUsed, boolean roiUsed) {
    // Optional No Data Range used
    Range[] noData;
    // Source image data type
    int dataType = sources[0].getSampleModel().getDataType();
    // If no Data are present, the No Data Range associated is used
    if (noDataUsed) {

      switch (dataType) {
        case DataBuffer.TYPE_BYTE:
          noData = noDataByte;
          break;
        case DataBuffer.TYPE_USHORT:
          noData = noDataUShort;
          break;
        case DataBuffer.TYPE_SHORT:
          noData = noDataShort;
          break;
        case DataBuffer.TYPE_INT:
          noData = noDataInt;
          break;
        case DataBuffer.TYPE_FLOAT:
          noData = noDataFloat;
          break;
        case DataBuffer.TYPE_DOUBLE:
          noData = noDataDouble;
          break;
        default:
          throw new IllegalArgumentException("Wrong data type");
      }
    } else {
      noData = null;
    }

    // ROI to use
    ROI roi = null;
    if (roiUsed) {
      roi = roiData;
    }

    // BandMerge operation
    RenderedOp merged = BandMergeDescriptor.create(noData, destNoData, null, null, roi, sources);
    // Check if the bands number is the same
    assertEquals(BAND_NUMBER, merged.getNumBands());
    // Upper-Left tile indexes
    int minTileX = merged.getMinTileX();
    int minTileY = merged.getMinTileY();
    // Raster object
    Raster upperLeftTile = merged.getTile(minTileX, minTileY);
    // Tile bounds
    int minX = upperLeftTile.getMinX();
    int minY = upperLeftTile.getMinY();
    int maxX = upperLeftTile.getWidth() + minX;
    int maxY = upperLeftTile.getHeight() + minY;
    // Cycle on all the tile Bands
    for (int b = 0; b < BAND_NUMBER; b++) {
      // Selection of the source raster associated with the band
      Raster bandRaster = sources[b].getTile(minTileX, minTileY);
      // Cycle on the y-axis
      for (int x = minX; x < maxX; x++) {
        // Cycle on the x-axis
        for (int y = minY; y < maxY; y++) {
          // Calculated value
          double value = upperLeftTile.getSampleDouble(x, y, b);
          // Old band value
          double valueOld = bandRaster.getSampleDouble(x, y, 0);

          // ROI CHECK
          boolean contained = true;
          if (roiUsed) {
            if (!roi.contains(x, y)) {
              contained = false;
              // Comparison if the final value is not inside a ROI
              assertEquals(value, destNoData, TOLERANCE);
            }
          }

          if (contained) {
            // If no Data are present, no data check is performed
            if (noDataUsed) {
              switch (dataType) {
                case DataBuffer.TYPE_BYTE:
                  byte sampleB = ImageUtil.clampRoundByte(value);
                  byte sampleBOld = ImageUtil.clampRoundByte(valueOld);
                  if (noData[0].contains(sampleBOld)) {
                    assertEquals(sampleB, destNoData, TOLERANCE);
                  } else {
                    assertEquals(sampleB, valueOld, TOLERANCE);
                  }
                  break;
                case DataBuffer.TYPE_USHORT:
                  short sampleUS = ImageUtil.clampRoundUShort(value);
                  short sampleUSOld = ImageUtil.clampRoundUShort(valueOld);
                  if (noData[0].contains(sampleUSOld)) {
                    assertEquals(sampleUS, destNoData, TOLERANCE);
                  } else {
                    assertEquals(sampleUS, valueOld, TOLERANCE);
                  }
                  break;
                case DataBuffer.TYPE_SHORT:
                  short sampleS = ImageUtil.clampRoundShort(value);
                  short sampleSOld = ImageUtil.clampRoundShort(valueOld);
                  if (noData[0].contains(sampleSOld)) {
                    assertEquals(sampleS, destNoData, TOLERANCE);
                  } else {
                    assertEquals(sampleS, valueOld, TOLERANCE);
                  }
                  break;
                case DataBuffer.TYPE_INT:
                  int sampleI = ImageUtil.clampRoundInt(value);
                  int sampleIOld = ImageUtil.clampRoundInt(valueOld);
                  if (noData[0].contains(sampleIOld)) {
                    assertEquals(sampleI, destNoData, TOLERANCE);
                  } else {
                    assertEquals(sampleI, valueOld, TOLERANCE);
                  }
                  break;
                case DataBuffer.TYPE_FLOAT:
                  float sampleF = ImageUtil.clampFloat(value);
                  float sampleFOld = ImageUtil.clampFloat(valueOld);
                  if (noData[0].contains(sampleFOld)) {
                    assertEquals(sampleF, destNoData, TOLERANCE);
                  } else {
                    assertEquals(sampleF, valueOld, TOLERANCE);
                  }
                  break;
                case DataBuffer.TYPE_DOUBLE:
                  if (noData[0].contains(valueOld)) {
                    assertEquals(value, destNoData, TOLERANCE);
                  } else {
                    assertEquals(value, valueOld, TOLERANCE);
                  }
                  break;
                default:
                  throw new IllegalArgumentException("Wrong data type");
              }
            } else {
              // Else a simple value comparison is done
              assertEquals(value, valueOld, TOLERANCE);
            }
          }
        }
      }
    }
    // Disposal of the output image
    merged.dispose();
  }
  @DescribeResult(name = "result", description = "The contours feature collection")
  public SimpleFeatureCollection execute(
      @DescribeParameter(name = "data", description = "The raster to be used as the source")
          GridCoverage2D gc2d,
      @DescribeParameter(
              name = "band",
              description = "The source image band to process",
              min = 0,
              max = 1)
          Integer band,
      @DescribeParameter(name = "levels", description = "Values for which to generate contours")
          double[] levels,
      @DescribeParameter(
              name = "interval",
              description = "Interval between contour values (ignored if levels arg is supplied)",
              min = 0)
          Double interval,
      @DescribeParameter(
              name = "simplify",
              description = "Values for which to generate contours",
              min = 0)
          Boolean simplify,
      @DescribeParameter(
              name = "smooth",
              description = "Values for which to generate contours",
              min = 0)
          Boolean smooth,
      @DescribeParameter(
              name = "roi",
              description = "The geometry used to delineate the area of interest in model space",
              min = 0)
          Geometry roi,
      ProgressListener progressListener)
      throws ProcessException {

    //
    // initial checks
    //
    if (gc2d == null) {
      throw new ProcessException("Invalid input, source grid coverage should be not null");
    }
    if (band != null && (band < 0 || band >= gc2d.getNumSampleDimensions())) {
      throw new ProcessException("Invalid input, invalid band number:" + band);
    }
    boolean hasValues = !(levels == null || levels.length == 0);
    if (!hasValues && interval == null) {
      throw new ProcessException("One between interval and values must be valid");
    }

    // switch to geophisics if necessary
    gc2d = gc2d.view(ViewType.GEOPHYSICS);

    //
    // GRID TO WORLD preparation
    //
    final AffineTransform mt2D =
        (AffineTransform) gc2d.getGridGeometry().getGridToCRS2D(PixelOrientation.CENTER);

    // get the list of nodata, if any
    List<Object> noDataList = new ArrayList<Object>();
    for (GridSampleDimension sd : gc2d.getSampleDimensions()) {
      // grab all the explicit nodata
      final double[] sdNoData = sd.getNoDataValues();
      if (sdNoData != null) {
        for (double nodata : sdNoData) {
          noDataList.add(nodata);
        }
      }

      // handle also readers setting up nodata in a category with a specific name
      if (sd.getCategories() != null) {
        for (Category cat : sd.getCategories()) {
          if (cat.getName().equals(NO_DATA)) {
            final NumberRange<? extends Number> catRange = cat.getRange();
            if (catRange.getMinimum() == catRange.getMaximum()) {
              noDataList.add(catRange.getMinimum());
            } else {
              Range<Double> noData =
                  new Range<Double>(
                      catRange.getMinimum(),
                      catRange.isMinIncluded(),
                      catRange.getMaximum(),
                      catRange.isMaxIncluded());
              noDataList.add(noData);
            }
          }
        }
      }
    }

    // get the rendered image
    final RenderedImage raster = gc2d.getRenderedImage();

    // perform jai operation
    ParameterBlockJAI pb = new ParameterBlockJAI("Contour");
    pb.setSource("source0", raster);

    if (roi != null) {
      pb.setParameter("roi", CoverageUtilities.prepareROI(roi, mt2D));
    }
    if (band != null) {
      pb.setParameter("band", band);
    }
    if (interval != null) {
      pb.setParameter("interval", interval);
    } else {
      final ArrayList<Double> elements = new ArrayList<Double>(levels.length);
      for (double level : levels) elements.add(level);
      pb.setParameter("levels", elements);
    }
    if (simplify != null) {
      pb.setParameter("simplify", simplify);
    }
    if (smooth != null) {
      pb.setParameter("smooth", smooth);
    }
    if (noDataList != null) {
      pb.setParameter("nodata", noDataList);
    }

    final RenderedOp dest = JAI.create("Contour", pb);
    @SuppressWarnings("unchecked")
    final Collection<LineString> prop =
        (Collection<LineString>) dest.getProperty(ContourDescriptor.CONTOUR_PROPERTY_NAME);

    // wrap as a feature collection and return
    final SimpleFeatureType schema = CoverageUtilities.createFeatureType(gc2d, LineString.class);
    final SimpleFeatureBuilder builder = new SimpleFeatureBuilder(schema);
    int i = 0;
    final ListFeatureCollection featureCollection = new ListFeatureCollection(schema);
    final AffineTransformation jtsTransformation =
        new AffineTransformation(
            mt2D.getScaleX(),
            mt2D.getShearX(),
            mt2D.getTranslateX(),
            mt2D.getShearY(),
            mt2D.getScaleY(),
            mt2D.getTranslateY());
    for (LineString line : prop) {

      // get value
      Double value = (Double) line.getUserData();
      line.setUserData(null);
      // filter coordinates in place
      line.apply(jtsTransformation);

      // create feature and add to list
      builder.set("the_geom", line);
      builder.set("value", value);

      featureCollection.add(builder.buildFeature(String.valueOf(i++)));
    }

    // return value

    return featureCollection;
  }
  /**
   * Quick method for populating the {@link CUDABean} instance provided.
   *
   * @param bean
   * @param reference
   * @param coverage
   * @param geo
   * @param transform
   * @throws IOException
   * @throws MismatchedDimensionException
   * @throws TransformException
   */
  private void populateBean(
      CUDABean bean,
      boolean reference,
      GridCoverage2D coverage,
      Geometry geo,
      MathTransform transform,
      int buffer)
      throws IOException, MismatchedDimensionException, TransformException {

    RenderedImage image = coverage.getRenderedImage();

    // 0) Check if a buffer must be applied
    Geometry originalGeo = (Geometry) geo.clone();
    if (buffer > 0) {
      try {
        if (!"EPSG:4326"
            .equals(CRS.lookupIdentifier(coverage.getCoordinateReferenceSystem(), false))) {
          geo = geo.buffer(buffer);
        } else {
          geo = geo.buffer(buffer / 111.128);
        }
      } catch (FactoryException e) {
        geo = geo.buffer(buffer);
      }
    }

    // 1) Crop the two coverages with the selected Geometry
    GridCoverage2D crop = CROP.execute(coverage, geo, null);
    transform =
        ProjectiveTransform.create(
                (AffineTransform) crop.getGridGeometry().getGridToCRS(PixelInCell.CELL_CORNER))
            .inverse();

    // 2) Extract the BufferedImage from each image
    image = crop.getRenderedImage();

    Rectangle rectIMG =
        new Rectangle(image.getMinX(), image.getMinY(), image.getWidth(), image.getHeight());
    ImageWorker w = new ImageWorker(image);
    BufferedImage buf = w.getBufferedImage();
    if (image instanceof RenderedOp) {
      ((RenderedOp) image).dispose();
    }

    // 3) Generate an array of data from each image
    Raster data = buf.getData();
    final DataBufferByte db = (DataBufferByte) data.getDataBuffer();
    byte[] byteData = db.getData();

    if (reference) {
      // 4) Transform the Geometry to Raster space
      Geometry rs = JTS.transform(geo, transform);
      Geometry rsFilter = JTS.transform(geo.difference(originalGeo), transform);
      ROI roiGeo = new ROIGeometry(rs);
      ROI roiFilter = new ROIGeometry(rsFilter);

      // 5) Extract an array of data from the transformed ROI
      byte[] roiData = getROIData((buffer > 0 ? roiFilter : roiGeo), rectIMG);
      bean.setRoi(roiData);
      bean.setRoiObj(roiGeo);

      // 6) Setting the Coverage data array
      bean.setReferenceImage(byteData);

      // 7) Setting the Image dimensions
      bean.setHeight(rectIMG.height);
      bean.setWidth(rectIMG.width);
      bean.setMinX(rectIMG.x);
      bean.setMinY(rectIMG.y);
    } else {
      // 6) Setting the Coverage data array
      bean.setCurrentImage(byteData);
    }

    // 7) Store the Reference Covergae containing the geospatial info
    bean.setReferenceCoverage(coverage);
  }
示例#29
0
  /**
   * Overrides to use the same method to slice the tiles than {@code MetatileMapOutputFormat} so the
   * GeoServer settings such as use native accel are leveraged in the same way when calling {@link
   * RenderedImageMapResponse#formatImageOutputStream},
   *
   * @see org.geowebcache.layer.MetaTile#createTile(int, int, int, int)
   */
  @Override
  public RenderedImage createTile(
      final int x, final int y, final int tileWidth, final int tileHeight) {
    // check image type
    final int type;
    if (metaTileImage instanceof PlanarImage) {
      type = 1;
    } else if (metaTileImage instanceof BufferedImage) {
      type = 2;
    } else {
      type = 0;
    }

    // now do the splitting
    RenderedImage tile;
    switch (type) {
      case 0:
        // do a crop, and then turn it into a buffered image so that we can release
        // the image chain
        RenderedOp cropped =
            GTCropDescriptor.create(
                metaTileImage,
                Float.valueOf(x),
                Float.valueOf(y),
                Float.valueOf(tileWidth),
                Float.valueOf(tileHeight),
                NO_CACHE);
        tile = cropped.getAsBufferedImage();
        disposeLater(cropped);
        break;
      case 1:
        final PlanarImage pImage = (PlanarImage) metaTileImage;
        final WritableRaster wTile =
            WritableRaster.createWritableRaster(
                pImage.getSampleModel().createCompatibleSampleModel(tileWidth, tileHeight),
                new Point(x, y));
        Rectangle sourceArea = new Rectangle(x, y, tileWidth, tileHeight);
        sourceArea = sourceArea.intersection(pImage.getBounds());

        // copying the data to ensure we don't have side effects when we clean the cache
        pImage.copyData(wTile);
        if (wTile.getMinX() != 0 || wTile.getMinY() != 0) {
          tile =
              new BufferedImage(
                  pImage.getColorModel(),
                  (WritableRaster) wTile.createTranslatedChild(0, 0),
                  pImage.getColorModel().isAlphaPremultiplied(),
                  null);
        } else {
          tile =
              new BufferedImage(
                  pImage.getColorModel(),
                  wTile,
                  pImage.getColorModel().isAlphaPremultiplied(),
                  null);
        }
        break;
      case 2:
        final BufferedImage image = (BufferedImage) metaTileImage;
        tile = image.getSubimage(x, y, tileWidth, tileHeight);
        break;
      default:
        throw new IllegalStateException(
            Errors.format(
                ErrorKeys.ILLEGAL_ARGUMENT_$2,
                "metaTile class",
                metaTileImage.getClass().toString()));
    }

    return tile;
  }
  /**
   * Executes the raster to vector process.
   *
   * @param coverage the input grid coverage
   * @param band the coverage band to process; defaults to 0 if {@code null}
   * @param insideEdges whether boundaries between raster regions with data values (ie. not NODATA)
   *     should be returned; defaults to {@code true} if {@code null}
   * @param roi optional polygonal {@code Geometry} to define a sub-area within which vectorizing
   *     will be done
   * @param noDataValues optional list of values to treat as NODATA; regions with these values will
   *     not be represented in the returned features; if {@code null}, 0 is used as the single
   *     NODATA value; ignored if {@code classificationRanges} is provided
   * @param classificationRanges optional list of {@code Range} objects to pre-classify the input
   *     coverage prior to vectorizing; values not included in the list will be treated as NODATA;
   *     values in the first {@code Range} are classified to 1, those in the second {@code Range} to
   *     2 etc.
   * @param progressListener an optional listener
   * @return a feature collection where each feature has a {@code Polygon} ("the_geom") and an
   *     attribute "value" with value of the corresponding region in either {@code coverage} or the
   *     classified coverage (when {@code classificationRanges} is used)
   * @throws ProcessException
   */
  @DescribeResult(name = "result", description = "The polygon feature collection")
  public SimpleFeatureCollection execute(
      @DescribeParameter(name = "data", description = "The raster to be used as the source")
          GridCoverage2D coverage,
      @DescribeParameter(
              name = "band",
              description = "(Integer, default=0) the source image band to process",
              min = 0)
          Integer band,
      @DescribeParameter(
              name = "insideEdges",
              description =
                  "(Boolean, default=true) whether to vectorize boundaries between adjacent regions with non-outside values",
              min = 0)
          Boolean insideEdges,
      @DescribeParameter(
              name = "roi",
              description = "The geometry used to delineate the area of interest in model space",
              min = 0)
          Geometry roi,
      @DescribeParameter(
              name = "nodata",
              description = "Collection<Number>, default={0}) values to treat as NODATA",
              collectionType = Number.class,
              min = 0)
          Collection<Number> noDataValues,
      @DescribeParameter(
              name = "ranges",
              description =
                  "The list of ranges to be applied. \n"
                      + "Each range is expressed as 'OPEN START ; END CLOSE'\n"
                      + "where 'OPEN:=(|[, CLOSE=)|]',\n "
                      + "START is the low value, or nothing to imply -INF,\n"
                      + "CLOSE is the biggest value, or nothing to imply +INF",
              collectionType = Range.class,
              min = 0)
          List<Range> classificationRanges,
      ProgressListener progressListener)
      throws ProcessException {

    //
    // initial checks
    //
    if (coverage == null) {
      throw new ProcessException("Invalid input, source grid coverage should be not null");
    }

    if (band == null) {
      band = 0;
    } else if (band < 0 || band >= coverage.getNumSampleDimensions()) {
      throw new ProcessException("Invalid input, invalid band number:" + band);
    }

    // do we have classification ranges?
    boolean hasClassificationRanges =
        classificationRanges != null && classificationRanges.size() > 0;

    // apply the classification by setting 0 as the default value and using 1, ..., numClasses for
    // the other classes.
    // we use 0 also as the noData for the resulting coverage.
    if (hasClassificationRanges) {

      final RangeLookupProcess lookup = new RangeLookupProcess();
      coverage = lookup.execute(coverage, band, classificationRanges, progressListener);
    }

    // Use noDataValues to set the "outsideValues" parameter of the Vectorize
    // operation unless classificationRanges are in use, in which case the
    // noDataValues arg is ignored.
    List<Number> outsideValues = new ArrayList<Number>();
    if (noDataValues != null && !hasClassificationRanges) {
      outsideValues.addAll(noDataValues);
    } else {
      outsideValues.add(0);
    }

    //
    // GRID TO WORLD preparation
    //
    final AffineTransform mt2D =
        (AffineTransform) coverage.getGridGeometry().getGridToCRS2D(PixelOrientation.UPPER_LEFT);

    // get the rendered image
    final RenderedImage raster = coverage.getRenderedImage();

    // perform jai operation
    ParameterBlockJAI pb = new ParameterBlockJAI("Vectorize");
    pb.setSource("source0", raster);

    if (roi != null) {
      pb.setParameter("roi", CoverageUtilities.prepareROI(roi, mt2D));
    }
    pb.setParameter("band", band);
    pb.setParameter("outsideValues", outsideValues);
    if (insideEdges != null) {
      pb.setParameter("insideEdges", insideEdges);
    }
    // pb.setParameter("removeCollinear", false);

    final RenderedOp dest = JAI.create("Vectorize", pb);
    @SuppressWarnings("unchecked")
    final Collection<Polygon> prop =
        (Collection<Polygon>) dest.getProperty(VectorizeDescriptor.VECTOR_PROPERTY_NAME);

    // wrap as a feature collection and return
    final SimpleFeatureType featureType =
        CoverageUtilities.createFeatureType(coverage, Polygon.class);
    final SimpleFeatureBuilder builder = new SimpleFeatureBuilder(featureType);
    int i = 0;
    final ListFeatureCollection featureCollection = new ListFeatureCollection(featureType);
    final AffineTransformation jtsTransformation =
        new AffineTransformation(
            mt2D.getScaleX(),
            mt2D.getShearX(),
            mt2D.getTranslateX(),
            mt2D.getShearY(),
            mt2D.getScaleY(),
            mt2D.getTranslateY());
    for (Polygon polygon : prop) {
      // get value
      Double value = (Double) polygon.getUserData();
      polygon.setUserData(null);
      // filter coordinates in place
      polygon.apply(jtsTransformation);

      // create feature and add to list
      builder.set("the_geom", polygon);
      builder.set("value", value);

      featureCollection.add(builder.buildFeature(String.valueOf(i++)));
    }

    // return value
    return featureCollection;
  }