use of org.geotoolkit.process.ProcessException in project geotoolkit by Geomatys.
the class DefaultPortrayalService method portrayAsCoverage.
/**
* Detect single raster layers with a default raster style and no special parameters
* if so we can directly use the grid coverage writer and avoid the rendering chain.
* It significantly reduce memory usage (minus the buffered image size and graphic objects)
* and time (minus ~35%).
*
* @return true if the optimization have been applied.
* @throws PortrayalException
*/
private static boolean portrayAsCoverage(final CanvasDef canvasDef, final SceneDef sceneDef, final OutputDef outputDef) throws PortrayalException {
// works for one layer only
final List<MapLayer> layers = MapBuilder.getLayers(sceneDef.getContext());
if (layers.size() != 1)
return false;
// layer must be a coverage
final MapLayer layer = layers.get(0);
final Resource resource = layer.getData();
if (!(resource instanceof GridCoverageResource))
return false;
// we must not have extensions
if (!sceneDef.extensions().isEmpty())
return false;
// style must be a default raster style = native original style
final List<? extends FeatureTypeStyle> ftss = layer.getStyle().featureTypeStyles();
if (ftss.size() != 1)
return false;
final List<? extends Rule> rules = ftss.get(0).rules();
if (rules.size() != 1)
return false;
final List<? extends Symbolizer> symbols = rules.get(0).symbolizers();
if (symbols.size() != 1)
return false;
final Symbolizer s = symbols.get(0);
if (!GO2Utilities.isDefaultRasterSymbolizer(s))
return false;
// we can bypass the renderer
try {
final GridCoverageResource ref = (GridCoverageResource) resource;
final String mime = outputDef.getMime();
final Envelope env = canvasDef.getEnvelope();
final Dimension dim = canvasDef.getDimension();
final double[] resolution = new double[] { env.getSpan(0) / (double) dim.width, env.getSpan(1) / (double) dim.height };
GridGeometry query = ref.getGridGeometry().derive().subgrid(env, resolution).sliceByRatio(0.5, 0, 1).build();
GridCoverage coverage = ref.read(query);
final RenderedImage image = coverage.render(null);
// HACK TO FIX COLOR ERROR ON JPEG /////////////////////////////////
if (mime.contains("jpeg") || mime.contains("jpg")) {
if (image.getColorModel().hasAlpha()) {
final int nbBands = image.getSampleModel().getNumBands();
if (nbBands > 3) {
// we can remove the fourth band assuming it is the alpha
coverage = new BandSelectProcess(coverage, new int[] { 0, 1, 2 }).executeNow();
}
}
}
// //////////////////////////////////////////////////////////////////
writeCoverage(coverage, env, resolution, outputDef, canvasDef.getBackground());
} catch (DisjointExtentException ex) {
return false;
} catch (DataStoreException | ProcessException ex) {
throw new PortrayalException(ex);
}
return true;
}
use of org.geotoolkit.process.ProcessException in project geotoolkit by Geomatys.
the class RasterPresentation method renderCoverage.
private boolean renderCoverage(RenderingContext2D renderingContext, org.apache.sis.coverage.grid.GridCoverage coverage, MathTransform trs2D) throws PortrayalException {
final Graphics2D g2d = renderingContext.getGraphics();
final CanvasMonitor monitor = renderingContext.getMonitor();
boolean dataRendered = false;
RenderedImage img = coverage.render(null);
/*
* Try to prefetch image before rendering
* resampled image or mosaic have deferred tiles
* java2d render tiles one by one which can be slow when working with
* computed coverages or distant services like WMTS or TMS
*/
if ((img.getWidth() * img.getHeight()) < 5000 * 5000) {
ImageProcessor processor = new ImageProcessor();
processor.setExecutionMode(ImageProcessor.Mode.PARALLEL);
img = processor.prefetch(img, null);
}
final InterpolationCase interpolationCase = (InterpolationCase) renderingContext.getRenderingHints().get(GO2Hints.KEY_INTERPOLATION);
if (interpolationCase != null) {
switch(interpolationCase) {
case NEIGHBOR:
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
break;
case BILINEAR:
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
break;
case BICUBIC:
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
break;
default:
// resample image ourself
try {
GridCoverage cov = new ResampleProcess(coverage, renderingContext.getGridGeometry().getCoordinateReferenceSystem(), renderingContext.getGridGeometry2D(), interpolationCase, null).executeNow();
trs2D = renderingTransform(cov.getGridGeometry());
img = cov.render(null);
} catch (ProcessException ex) {
throw new PortrayalException(ex);
}
break;
}
}
if (trs2D instanceof AffineTransform) {
try {
g2d.drawRenderedImage(RenderingWorkaround.wrap(img), (AffineTransform) trs2D);
dataRendered = true;
} catch (Exception ex) {
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
if (ex instanceof ArrayIndexOutOfBoundsException) {
// we can recover when it's an inapropriate componentcolormodel
final StackTraceElement[] eles = ex.getStackTrace();
if (eles.length > 0 && ComponentColorModel.class.getName().equalsIgnoreCase(eles[0].getClassName())) {
try {
final Map<String, Object> analyze = StatisticOp.analyze(img);
final double[] minArray = (double[]) analyze.get(StatisticOp.MINIMUM);
final double[] maxArray = (double[]) analyze.get(StatisticOp.MAXIMUM);
final double min = findExtremum(minArray, true);
final double max = findExtremum(maxArray, false);
final List<InterpolationPoint> values = new ArrayList<>();
values.add(new DefaultInterpolationPoint(Double.NaN, GO2Utilities.STYLE_FACTORY.literal(new Color(0, 0, 0, 0))));
values.add(new DefaultInterpolationPoint(min, GO2Utilities.STYLE_FACTORY.literal(Color.BLACK)));
values.add(new DefaultInterpolationPoint(max, GO2Utilities.STYLE_FACTORY.literal(Color.WHITE)));
final Literal lookup = StyleConstants.DEFAULT_CATEGORIZE_LOOKUP;
final Literal fallback = StyleConstants.DEFAULT_FALLBACK;
final Expression function = GO2Utilities.STYLE_FACTORY.interpolateFunction(lookup, values, Method.COLOR, Mode.LINEAR, fallback);
final CompatibleColorModel model = new CompatibleColorModel(img.getColorModel().getPixelSize(), function);
final ImageLayout layout = new ImageLayout().setColorModel(model);
img = new NullOpImage(img, layout, null, OpImage.OP_COMPUTE_BOUND);
g2d.drawRenderedImage(RenderingWorkaround.wrap(img), (AffineTransform) trs2D);
dataRendered = true;
} catch (Exception e) {
// plenty of errors can happen when painting an image
monitor.exceptionOccured(e, Level.WARNING);
// raise the original error
monitor.exceptionOccured(ex, Level.WARNING);
}
} else {
// plenty of errors can happen when painting an image
monitor.exceptionOccured(ex, Level.WARNING);
}
} else {
// plenty of errors can happen when painting an image
monitor.exceptionOccured(ex, Level.WARNING);
}
}
} else if (trs2D instanceof LinearTransform) {
final LinearTransform lt = (LinearTransform) trs2D;
final int col = lt.getMatrix().getNumCol();
final int row = lt.getMatrix().getNumRow();
// TODO using only the first parameters of the linear transform
throw new PortrayalException("Could not render image, GridToCRS is a not an AffineTransform, found a " + trs2D.getClass());
} else {
throw new PortrayalException("Could not render image, GridToCRS is a not an AffineTransform, found a " + trs2D.getClass());
}
return dataRendered;
}
use of org.geotoolkit.process.ProcessException in project geotoolkit by Geomatys.
the class CachedPatternSymbolizer method getMasks.
public Map.Entry<FeatureSet, MutableStyle> getMasks(final GridCoverage coverage) throws IOException, TransformException {
final List<Feature> features = new ArrayList<>();
final Map<NumberRange, List<Symbolizer>> styles = new LinkedHashMap<>();
final Map<NumberRange, Integer> stylesIndexes = new LinkedHashMap<>();
final Map<Expression, List<Symbolizer>> categorizes = styleElement.getRanges();
final Expression[] steps = categorizes.keySet().toArray(new Expression[categorizes.size()]);
Arrays.sort(steps, new Comparator<Expression>() {
@Override
public int compare(Expression t1, Expression t2) {
if (t1 == null) {
return -1;
} else if (t2 == null) {
return +1;
}
double d1 = ((Number) t1.apply(null)).doubleValue();
double d2 = ((Number) t2.apply(null)).doubleValue();
double res = d1 - d2;
if (res < 0) {
return -1;
} else if (res > 0) {
return +1;
} else {
return 0;
}
}
});
// fill the numberranges ------------------------------------------------
double last = Double.NEGATIVE_INFINITY;
double end = Double.POSITIVE_INFINITY;
NumberRange interval;
int i = 0;
int index = 0;
for (; i < steps.length - 1; i++) {
end = ((Number) steps[i + 1].apply(null)).doubleValue();
interval = NumberRange.create(last, true, end, false);
styles.put(interval, categorizes.get(steps[i]));
stylesIndexes.put(interval, index++);
last = end;
}
// last element
end = Double.POSITIVE_INFINITY;
NumberRange<Double> lastRange = NumberRange.create(last, true, end, true);
styles.put(lastRange, categorizes.get(steps[i]));
stylesIndexes.put(lastRange, index++);
// calculate the polygons -----------------------------------------------
final ProcessDescriptor descriptor = CoverageToVectorDescriptor.INSTANCE;
final Integer band = ((Number) styleElement.getChannel().apply(null)).intValue();
final ParameterValueGroup input = descriptor.getInputDescriptor().createValue();
input.parameter(CoverageToVectorDescriptor.COVERAGE.getName().getCode()).setValue(coverage);
final Set<NumberRange> nrs = styles.keySet();
input.parameter(CoverageToVectorDescriptor.RANGES.getName().getCode()).setValue(nrs.toArray(new NumberRange[nrs.size()]));
input.parameter(CoverageToVectorDescriptor.BAND.getName().getCode()).setValue(band);
final Process process = descriptor.createProcess(input);
final Geometry[] polygons;
try {
polygons = (Geometry[]) process.call().parameter(CoverageToVectorDescriptor.GEOMETRIES.getName().getCode()).getValue();
} catch (ProcessException ex) {
Logger.getLogger("org.geotoolkit.display2d.ext.pattern").log(Level.WARNING, null, ex);
throw new IOException(ex.getMessage(), ex);
}
// build the global style -----------------------------------------------
final MutableStyle style = GO2Utilities.STYLE_FACTORY.style();
final MutableFeatureTypeStyle fts = GO2Utilities.STYLE_FACTORY.featureTypeStyle();
style.featureTypeStyles().add(fts);
int idx = 0;
for (List<Symbolizer> lst : styles.values()) {
MutableRule rule = GO2Utilities.STYLE_FACTORY.rule();
rule.symbolizers().addAll(lst);
rule.setFilter(GO2Utilities.FILTER_FACTORY.equal(GO2Utilities.FILTER_FACTORY.property("category"), GO2Utilities.FILTER_FACTORY.literal(idx), true, MatchAction.ANY));
fts.rules().add(rule);
idx++;
}
// build the features ---------------------------------------------------
final CoordinateReferenceSystem crs = coverage.getCoordinateReferenceSystem();
final FeatureTypeBuilder sftBuilder = new FeatureTypeBuilder();
final String geometryField = "geometry";
sftBuilder.setName("DynamicFeature");
sftBuilder.addAttribute(Integer.class).setName("id").addRole(AttributeRole.IDENTIFIER_COMPONENT);
sftBuilder.addAttribute(Geometry.class).setName(geometryField).setCRS(crs).addRole(AttributeRole.DEFAULT_GEOMETRY);
sftBuilder.addAttribute(Integer.class).setName("category");
final FeatureType sft = sftBuilder.build();
int id = 0;
for (Geometry entry : polygons) {
if (entry == null)
continue;
NumberRange numberRange = (NumberRange) entry.getUserData();
idx = stylesIndexes.get(numberRange);
entry.setUserData(crs);
final Feature feature = sft.newInstance();
feature.setPropertyValue(geometryField, entry);
feature.setPropertyValue("id", id++);
feature.setPropertyValue("category", idx);
features.add(feature);
}
return new AbstractMap.SimpleEntry<>(new InMemoryFeatureSet(sft, features), style);
}
use of org.geotoolkit.process.ProcessException in project geotoolkit by Geomatys.
the class MapfileFilterToOGCFilterProcess method parse.
private Object parse(final Expression ref, final List<Token> tokens) throws ProcessException {
int index = 0;
Object result = null;
while (index < tokens.size()) {
Token token = tokens.get(index);
if ("(".equals(token.value)) {
// a block, find the block end ad parse it's content
index++;
final int blockEnd = getBlockEnd(tokens, index);
final List<Token> content = tokens.subList(index, blockEnd);
index = blockEnd + 1;
result = parse(null, content);
} else if ("[".equals(token.value)) {
// a property name
index++;
final String propName = tokens.get(index).value;
index++;
// check it's a ']'
final String v = tokens.get(index).value;
if (!"]".equals(v)) {
throw new ProcessException("Was expecting a ']' but was : " + v, this, null);
}
index++;
result = FF.property(propName);
} else if ("/".equals(token.value)) {
// a list of values
final List<Filter> filters = new ArrayList<Filter>();
while (true) {
token = tokens.get(++index);
final Filter f = FF.equal(ref, FF.literal(token.value));
filters.add(f);
token = tokens.get(++index);
if ("/".equals(token.value)) {
break;
}
}
index++;
result = FF.or(filters);
} else if ("=".equals(token.value)) {
// and equality test
// left side
final Expression left = (Expression) result;
// right side
index++;
final Expression right;
final Token next = tokens.get(index);
if ("(".equals(next.value)) {
// a sub expression
index++;
final int blockEnd = getBlockEnd(tokens, index);
final List<Token> content = tokens.subList(index, blockEnd);
index = blockEnd + 1;
right = (Expression) parse(null, content);
} else {
// a literal value
final List<Token> content = tokens.subList(index, index + 1);
right = (Expression) parse(null, content);
index++;
}
result = FF.equal(left, right);
} else if ("and".equalsIgnoreCase(token.value)) {
// and operand
// left side
final Filter left = (Filter) result;
// right side
index++;
final List<Token> content = tokens.subList(index, tokens.size());
final Filter right = (Filter) parse(null, content);
index = tokens.size();
result = FF.and(left, right);
} else if ("or".equalsIgnoreCase(token.value)) {
// or operand
// left side
final Filter left = (Filter) result;
// right side
index++;
final List<Token> content = tokens.subList(index, tokens.size());
final Filter right = (Filter) parse(null, content);
index = tokens.size();
result = FF.or(left, right);
} else {
index++;
String text = token.value;
if (text.startsWith("\"") || text.startsWith("'")) {
text = text.substring(1, text.length() - 1);
}
final Expression literal = toExpression(text);
// a single value
if (ref != null) {
// it's a property equal to
result = FF.equal(ref, literal);
} else {
// it's a literal
result = literal;
}
}
}
return result;
}
use of org.geotoolkit.process.ProcessException in project geotoolkit by Geomatys.
the class MapfileToSLDProcess method execute.
@Override
protected void execute() throws ProcessException {
final File mapfile = inputParameters.getValue(IN_FILE);
final File sldfile = inputParameters.getValue(IN_OUTPUT);
final MapfileReader reader = new MapfileReader();
reader.setInput(mapfile);
try {
mapfileFeature = reader.read();
final MutableStyledLayerDescriptor sld = SLDF.createSLD();
// convert it
convert(sld, mapfileFeature);
// avoid memory leak
mapfileFeature = null;
// write the sld
final StyleXmlIO utils = new StyleXmlIO();
utils.writeSLD(sldfile, sld, StyledLayerDescriptor.V_1_1_0);
} catch (IOException ex) {
throw new ProcessException(ex.getMessage(), this, ex);
} catch (JAXBException ex) {
throw new ProcessException(ex.getMessage(), this, ex);
}
}
Aggregations