Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SEDONA-426] Change raster cloning to be able to include metadata. #1080

Merged
merged 23 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
43a448e
Refactor notebooks to include SedonaKepler and Sedona 1.5.0
iGN5117 Oct 16, 2023
2f11a38
temp commit changing notebook and binder Pipfile
iGN5117 Oct 19, 2023
0e55f85
Merge branch 'master' of https://github.com/apache/sedona into sedona…
iGN5117 Nov 2, 2023
f5353ba
Merge branch 'master' of https://github.com/apache/sedona into sedona…
iGN5117 Nov 2, 2023
120c177
temp push adding new RasterUtils
iGN5117 Nov 9, 2023
ed4e35f
Add provision of setting a new noDataVal
iGN5117 Nov 9, 2023
a2f074a
Make use of new RasterUtils create functions in MapAlgebra()
iGN5117 Nov 9, 2023
83ed859
revert changes to examples
iGN5117 Nov 9, 2023
31e0fb2
revert changes to Pipfile
iGN5117 Nov 9, 2023
81b09fe
Fix nullPointerException when checking for noDataValue
iGN5117 Nov 9, 2023
00acb3d
Add a variable controlling metadata creation in RasterUtils
iGN5117 Nov 14, 2023
ffeee5d
Refactor MapAlgebra tests
iGN5117 Nov 14, 2023
1a34444
move creation of default colorModel
iGN5117 Nov 14, 2023
3e68c96
Missed adding complete bogus colorspace creation code to else
iGN5117 Nov 14, 2023
97460a7
Merge branch 'sedona_master' into develop_Nilesh_Raster_Clone_Bug
iGN5117 Nov 15, 2023
458ada3
Add new RasterUtils functions to create rasters. Retired old functions
iGN5117 Nov 16, 2023
74ac8bb
Kept references of old rasters to be usable for making empty rasters
iGN5117 Nov 16, 2023
3ebf682
renamed create to clone for the newly added functions
iGN5117 Nov 16, 2023
d348fd8
Removed unused originalNoDataValue
iGN5117 Nov 16, 2023
6b5d757
Formatting changes
iGN5117 Nov 16, 2023
5a42f33
Remove old create references
iGN5117 Nov 16, 2023
b9988d7
Remove experimental test
iGN5117 Nov 16, 2023
7a463fc
Update documentation to add explanation for keepMetadata
iGN5117 Nov 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,14 @@ public static GridCoverage2D mapAlgebra(GridCoverage2D gridCoverage2D, String pi
int rasterDataType = pixelType != null? RasterUtils.getDataTypeCode(pixelType) : renderedImage.getSampleModel().getDataType();
int width = renderedImage.getWidth();
int height = renderedImage.getHeight();
ColorModel originalColorModel = renderedImage.getColorModel();
// ImageUtils.createConstantImage is slow, manually constructing a buffered image proved to be faster.
// It also eliminates the data-copying overhead when converting raster data types after running jiffle script.
WritableRaster resultRaster = RasterFactory.createBandedRaster(DataBuffer.TYPE_DOUBLE, width, height, 1, null);
ColorModel cm = PlanarImage.createColorModel(resultRaster.getSampleModel());
if (originalColorModel.isCompatibleRaster(resultRaster)) {
cm = originalColorModel;
}
WritableRenderedImage resultImage = new BufferedImage(cm, resultRaster, false, null);
try {
String prevScript = previousScript.get();
Expand Down Expand Up @@ -164,10 +168,10 @@ public static GridCoverage2D mapAlgebra(GridCoverage2D gridCoverage2D, String pi
WritableRaster convertedRaster = RasterFactory.createBandedRaster(rasterDataType, width, height, 1, null);
double[] samples = resultRaster.getSamples(0, 0, width, height, 0, (double[]) null);
convertedRaster.setSamples(0, 0, width, height, 0, samples);
return RasterUtils.create(convertedRaster, gridCoverage2D.getGridGeometry(), null, noDataValue);
return RasterUtils.create(convertedRaster, gridCoverage2D, noDataValue, false);
} else {
// build a new GridCoverage2D from the resultImage
return RasterUtils.create(resultImage, gridCoverage2D.getGridGeometry(), null, noDataValue);
return RasterUtils.create(resultImage, gridCoverage2D, noDataValue, false);
}
} catch (Exception e) {
throw new RuntimeException("Failed to run map algebra", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.sun.media.imageioimpl.common.BogusColorSpace;
import org.apache.sedona.common.FunctionsGeoTools;
import org.apache.sedona.common.raster.RasterAccessors;
import org.apache.sedona.common.raster.RasterBandAccessors;
import org.geotools.coverage.Category;
import org.geotools.coverage.CoverageFactoryFinder;
import org.geotools.coverage.GridSampleDimension;
Expand Down Expand Up @@ -57,9 +58,7 @@
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;

/**
* Utility functions for working with GridCoverage2D objects.
Expand All @@ -80,6 +79,88 @@ public static GridCoverage2D create(WritableRaster raster, GridGeometry2D gridGe
return create(raster, gridGeometry, bands, null);
}

/**
* Create a new raster, cloning all metadata from the passed reference raster.
* @param raster The raster object to be wrapped as an image.
* @param referenceRaster The reference raster to clone, all metadata is cloned
* @param noDataValue Optionally, a new noDataValue, if passed null, noDataVal of the reference raster is used.
* @return cloned raster
*/
public static GridCoverage2D create(WritableRaster raster, GridCoverage2D referenceRaster, Double noDataValue, boolean keepMetadata) {
GridSampleDimension[] bands = keepMetadata ? referenceRaster.getSampleDimensions() : null;
if (Objects.isNull(noDataValue)) {
noDataValue = RasterBandAccessors.getBandNoDataValue(referenceRaster, 1); //resort to using noDataValue of the original raster.
}
Map propertyMap = null;
if (keepMetadata) {
propertyMap = referenceRaster.getProperties();
}
ColorModel originalColorModel = referenceRaster.getRenderedImage().getColorModel();
GridGeometry2D gridGeometry = referenceRaster.getGridGeometry();
int numBand = raster.getNumBands();
int rasterDataType = raster.getDataBuffer().getDataType();

final ColorSpace cs = new BogusColorSpace(numBand);
final int[] nBits = new int[numBand];
Arrays.fill(nBits, DataBuffer.getDataTypeSize(rasterDataType));
Kontinuation marked this conversation as resolved.
Show resolved Hide resolved
ColorModel colorModel =
new ComponentColorModel(cs, nBits, false, true, Transparency.OPAQUE, rasterDataType);
Kontinuation marked this conversation as resolved.
Show resolved Hide resolved
if (originalColorModel.isCompatibleRaster(raster)) {
colorModel = originalColorModel;
}
if (noDataValue != null) {
GridSampleDimension[] newBands = new GridSampleDimension[numBand];
for (int k = 0; k < numBand; k++) {
if (bands != null) {
newBands[k] = createSampleDimensionWithNoDataValue(bands[k], noDataValue);
} else {
newBands[k] = createSampleDimensionWithNoDataValue("band_" + k, noDataValue);
}
}
bands = newBands;
}

GridCoverage2D[] referenceRasterSources = keepMetadata ? referenceRaster.getSources().toArray(new GridCoverage2D[0]) : null;
CharSequence rasterName = keepMetadata ? referenceRaster.getName() : "genericCoverage";

final RenderedImage image = new BufferedImage(colorModel, raster, false, null);
return gridCoverageFactory.create(rasterName, image, gridGeometry, bands, referenceRasterSources, propertyMap);

}

/**
* Create a new raster, cloning all metadata from the passed reference raster.
* @param image The RenderedImage to be used as data for the created GridCoverage2D
* @param referenceRaster The reference raster to clone, all metadata is cloned
* @param noDataValue Optionally, a new noDataValue, if passed null, noDataVal of the reference raster is used.
* @return cloned raster
*/
public static GridCoverage2D create(RenderedImage image, GridCoverage2D referenceRaster, Double noDataValue, boolean keepMetadata) {
int numBand = image.getSampleModel().getNumBands();
if (Objects.isNull(noDataValue)) {
noDataValue = RasterBandAccessors.getBandNoDataValue(referenceRaster, 1); //resort to using noDataValue of the original raster.
}
GridSampleDimension[] bands = keepMetadata ? referenceRaster.getSampleDimensions() : null;
GridGeometry2D gridGeometry = referenceRaster.getGridGeometry();
if (noDataValue != null) {
GridSampleDimension[] newBands = new GridSampleDimension[numBand];
for (int k = 0; k < numBand; k++) {
if (bands != null) {
newBands[k] = createSampleDimensionWithNoDataValue(bands[k], noDataValue);
} else {
newBands[k] = createSampleDimensionWithNoDataValue("band_" + k, noDataValue);
}
}
bands = newBands;
}
GridCoverage2D[] referenceRasterSources = keepMetadata ? referenceRaster.getSources().toArray(new GridCoverage2D[0]) : null;
Map propertyMap = null;
if (keepMetadata) {
propertyMap = referenceRaster.getProperties();
} CharSequence rasterName = keepMetadata ? referenceRaster.getName() : "genericCoverage";
Kontinuation marked this conversation as resolved.
Show resolved Hide resolved
return gridCoverageFactory.create(rasterName, image, gridGeometry, bands, referenceRasterSources, propertyMap);
}

/**
* Create a new empty raster from the given WritableRaster object.
* @param raster The raster object to be wrapped as an image.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1040,7 +1040,8 @@ class rasteralgebraTest extends TestBaseScala with BeforeAndAfter with GivenWhen
}
assert(rast2.getRenderedImage.getSampleModel.getDataType == dataType)
val noDataValue = RasterUtils.getNoDataValue(rast2.getSampleDimension(0))
assert(noDataValue.isNaN)
val originalNoDataValue = RasterUtils.getNoDataValue(rast.getSampleDimension(0))
Kontinuation marked this conversation as resolved.
Show resolved Hide resolved
assert(noDataValue.equals(originalNoDataValue))
val band = MapAlgebra.bandAsArray(rast, 1)
val band2 = MapAlgebra.bandAsArray(rast2, 1)
assert(band.size == band2.size)
Expand Down
Loading