Search in sources :

Example 1 with ResampleProcess

use of org.geotoolkit.processing.coverage.resample.ResampleProcess in project geotoolkit by Geomatys.

the class KmzContextInterpreter method writeCoverageMapLayer.

/**
 * Transforms a CoverageMapLayer into KML GroundOverlay.
 */
private Feature writeCoverageMapLayer(MapLayer coverageMapLayer) throws Exception {
    final Feature groundOverlay = KML_FACTORY.createGroundOverlay();
    final CoordinateReferenceSystem targetCrs = CommonCRS.WGS84.normalizedGeographic();
    final GridCoverageResource ref = (GridCoverageResource) coverageMapLayer.getData();
    final GridCoverage coverage = ref.read(null);
    final GridCoverage targetCoverage = new ResampleProcess(coverage, targetCrs, null, InterpolationCase.NEIGHBOR, null).executeNow();
    final Envelope envelope = targetCoverage.getGridGeometry().getEnvelope();
    final CharSequence name = CoverageUtilities.getName(targetCoverage);
    // Creating image file and Writting referenced image into.
    final Path img = filesDirectory.resolve(name.toString() + ".png");
    try (OutputStream outputStream = Files.newOutputStream(img, CREATE, WRITE, TRUNCATE_EXISTING)) {
        ImageIO.write(targetCoverage.render(null), "png", outputStream);
    }
    final Icon image = KML_FACTORY.createIcon(KML_FACTORY.createLink());
    image.setHref(filesDirectory.getFileName().toString() + File.separator + name);
    groundOverlay.setPropertyValue(KmlConstants.TAG_NAME, name.toString());
    groundOverlay.setPropertyValue(KmlConstants.TAG_ICON, image);
    groundOverlay.setPropertyValue(KmlConstants.TAG_ALTITUDE, 1.0);
    groundOverlay.setPropertyValue(KmlConstants.TAG_ALTITUDE_MODE, EnumAltitudeMode.CLAMP_TO_GROUND);
    final LatLonBox latLonBox = KML_FACTORY.createLatLonBox();
    latLonBox.setNorth(envelope.getMaximum(1));
    latLonBox.setSouth(envelope.getMinimum(1));
    latLonBox.setEast(envelope.getMaximum(0));
    latLonBox.setWest(envelope.getMinimum(0));
    groundOverlay.setPropertyValue(KmlConstants.TAG_LAT_LON_BOX, latLonBox);
    return groundOverlay;
}
Also used : Path(java.nio.file.Path) ResampleProcess(org.geotoolkit.processing.coverage.resample.ResampleProcess) GridCoverage(org.apache.sis.coverage.grid.GridCoverage) ZipOutputStream(java.util.zip.ZipOutputStream) OutputStream(java.io.OutputStream) GridCoverageResource(org.apache.sis.storage.GridCoverageResource) LatLonBox(org.geotoolkit.data.kml.model.LatLonBox) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) Icon(org.geotoolkit.data.kml.model.Icon) Envelope(org.opengis.geometry.Envelope) Feature(org.opengis.feature.Feature)

Example 2 with ResampleProcess

use of org.geotoolkit.processing.coverage.resample.ResampleProcess in project geotoolkit by Geomatys.

the class StraightenProcess method execute.

/**
 * {@inheritDoc}
 */
@Override
protected void execute() throws ProcessException {
    final GridCoverage candidate = inputParameters.getValue(StraightenDescriptor.COVERAGE_IN);
    // resample coverage, we want it to be 'straight', no rotation or different axe scale.
    final GridGeometry gridgeom = candidate.getGridGeometry();
    final CoordinateReferenceSystem crs = gridgeom.getCoordinateReferenceSystem();
    final GridExtent gridenv = gridgeom.getExtent();
    final MathTransform gridToCRS = gridgeom.getGridToCRS(PixelInCell.CELL_CORNER);
    try {
        final double[] coords = new double[2 * 5];
        coords[0] = gridenv.getLow(0);
        coords[1] = gridenv.getLow(1);
        coords[2] = gridenv.getLow(0);
        coords[3] = gridenv.getHigh(1) + 1;
        coords[4] = gridenv.getHigh(0) + 1;
        coords[5] = gridenv.getHigh(1) + 1;
        coords[6] = gridenv.getHigh(0) + 1;
        coords[7] = gridenv.getLow(1);
        coords[8] = gridenv.getHigh(0) + 2;
        coords[9] = gridenv.getHigh(1) + 2;
        gridToCRS.transform(coords, 0, coords, 0, 5);
        double minX = Math.min(Math.min(coords[0], coords[2]), Math.min(coords[4], coords[6]));
        double maxX = Math.max(Math.max(coords[0], coords[2]), Math.max(coords[4], coords[6]));
        double minY = Math.min(Math.min(coords[1], coords[3]), Math.min(coords[5], coords[7]));
        double maxY = Math.max(Math.max(coords[1], coords[3]), Math.max(coords[5], coords[7]));
        double spanX = maxX - minX;
        double spanY = maxY - minY;
        double scaleX = spanX / gridenv.getSize(0);
        double scaleY = spanY / gridenv.getSize(1);
        double scale = Math.min(scaleX, scaleY);
        if (coords[0] > coords[6]) {
            // x axe flip
            minX = Math.min(minX, coords[8]);
        }
        if (coords[1] < coords[3]) {
            // y axe flip
            maxY = Math.max(maxY, coords[9]);
        }
        final AffineTransform2D outGridToCRS = new AffineTransform2D(scale, 0, 0, -scale, minX, maxY);
        final GridExtent gridEnv = new GridExtent((long) (spanX / scale), (long) (spanY / scale));
        final GridGeometry outgridGeom = new GridGeometry(gridEnv, PixelInCell.CELL_CORNER, outGridToCRS, crs);
        final GridCoverage outCoverage = new ResampleProcess(candidate, outgridGeom.getCoordinateReferenceSystem(), outgridGeom, InterpolationCase.NEIGHBOR, null).executeNow();
        outputParameters.getOrCreate(StraightenDescriptor.COVERAGE_OUT).setValue(outCoverage);
    } catch (TransformException ex) {
        throw new ProcessException(ex.getMessage(), this, ex);
    }
}
Also used : GridGeometry(org.apache.sis.coverage.grid.GridGeometry) GridExtent(org.apache.sis.coverage.grid.GridExtent) ProcessException(org.geotoolkit.process.ProcessException) ResampleProcess(org.geotoolkit.processing.coverage.resample.ResampleProcess) GridCoverage(org.apache.sis.coverage.grid.GridCoverage) MathTransform(org.opengis.referencing.operation.MathTransform) TransformException(org.opengis.referencing.operation.TransformException) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) AffineTransform2D(org.apache.sis.internal.referencing.j2d.AffineTransform2D)

Example 3 with ResampleProcess

use of org.geotoolkit.processing.coverage.resample.ResampleProcess in project geotoolkit by Geomatys.

the class AbstractCoverageSymbolizerRenderer method getObjectiveCoverage.

/**
 * Returns expected {@linkplain GridCoverage elevation coverage} or {@linkplain GridCoverage coverage}
 * from given {@link ProjectedCoverage}.
 *
 * TODO: add a margin or interpolation parameter. To properly interpolate border on output canvas, we need extra
 *  lines/columns on source image. Their number depends on applied interpolation (bilinear, bicubic, etc.).
 *
 * @param ref coverage resource
 * @param canvasGrid Rendering canvas grid geometry
 * @param isElevation {@code true} if we want elevation coverage, else ({@code false}) for features coverage.
 * @param sourceBands coverage source bands to features
 * @return expected {@linkplain GridCoverage elevation coverage} or {@linkplain GridCoverage coverage}
 * @throws org.geotoolkit.coverage.io.CoverageStoreException if problem during coverage reading.
 * @throws org.opengis.referencing.operation.TransformException if problem during {@link Envelope} transformation.
 * @throws org.opengis.util.FactoryException if problem during {@link Envelope} study.
 * @throws org.geotoolkit.process.ProcessException if problem during resampling processing.
 * @see ProjectedCoverage#getElevationCoverage(org.geotoolkit.coverage.io.GridCoverageReadParam)
 * @see ProjectedCoverage#getCoverage(org.geotoolkit.coverage.io.GridCoverageReadParam)
 */
protected GridCoverage getObjectiveCoverage(final GridCoverageResource ref, GridGeometry canvasGrid, final boolean isElevation, int[] sourceBands) throws DataStoreException, TransformException, FactoryException, ProcessException {
    ArgumentChecks.ensureNonNull("projectedCoverage", ref);
    final InterpolationCase interpolation = InterpolationCase.BILINEAR;
    final GridGeometry refGG = ref.getGridGeometry();
    // fast envelope intersection in 2D
    if (refGG.isDefined(GridGeometry.ENVELOPE)) {
        Envelope bbox = renderingContext.getCanvasObjectiveBounds2D();
        Envelope refEnv = Envelopes.transform(refGG.getEnvelope(), bbox.getCoordinateReferenceSystem());
        if (!AbstractEnvelope.castOrCopy(bbox).intersects(refEnv, true)) {
            throw new DisjointExtentException("Coverage resource envelope do not intersect canvas");
        }
    }
    final GridGeometry baseGG = trySubGrid(refGG, canvasGrid);
    final GridGeometry slice = extractSlice(baseGG, canvasGrid, computeMargin2D(interpolation), true);
    if (sourceBands != null && sourceBands.length < 1)
        sourceBands = null;
    GridCoverage coverage = ref.read(slice, sourceBands);
    if (coverage instanceof GridCoverageStack) {
        Logger.getLogger("org.geotoolkit.display2d.primitive").log(Level.WARNING, "Coverage reader return more than one slice.");
    }
    while (coverage instanceof GridCoverageStack) {
        // pick the first slice
        coverage = ((GridCoverageStack) coverage).coverageAtIndex(0);
    }
    // we remove all other dimension to simplify any following operation
    if (coverage.getCoordinateReferenceSystem().getCoordinateSystem().getDimension() > 2) {
        coverage = new ReducedGridCoverage(coverage, 0, 1);
    }
    final CoordinateReferenceSystem crs2d = CRS.getHorizontalComponent(canvasGrid.getCoordinateReferenceSystem());
    if (Utilities.equalsIgnoreMetadata(crs2d, coverage.getCoordinateReferenceSystem())) {
        return coverage;
    } else {
        coverage = prepareCoverageToResampling(coverage, symbol);
        // resample
        final double[] fill = new double[coverage.getSampleDimensions().size()];
        Arrays.fill(fill, Double.NaN);
        // ///// HACK FOR 0/360 /////////////////////////////////////////
        GeneralEnvelope ge = new GeneralEnvelope(coverage.getGridGeometry().getEnvelope());
        try {
            GeneralEnvelope cdt = GeneralEnvelope.castOrCopy(Envelopes.transform(coverage.getGridGeometry().getEnvelope(), CommonCRS.WGS84.normalizedGeographic()));
            cdt.normalize();
            if (!cdt.isEmpty()) {
                ge = cdt;
            }
        } catch (ProjectionException ex) {
            LOGGER.log(Level.INFO, ex.getMessage(), ex);
        }
        GridGeometry resampleGrid = canvasGrid;
        try {
            resampleGrid = resampleGrid.derive().rounding(GridRoundingMode.ENCLOSING).subgrid(ge).build().reduce(0, 1);
        } catch (DisjointExtentException ex) {
        // don't log, still continue
        } catch (IllegalGridGeometryException ex) {
            LOGGER.log(Level.INFO, ex.getMessage(), ex);
        }
        resampleGrid = CoverageUtilities.forceLowerToZero(resampleGrid);
        // ///// HACK FOR 0/360 /////////////////////////////////////////
        final MathTransform gridToCRS = coverage.getGridGeometry().getGridToCRS(PixelInCell.CELL_CENTER);
        if (isNonLinear(gridToCRS)) {
            final GridGeometry slice2 = extractSlice(refGG, canvasGrid, computeMargin2D(interpolation), false);
            coverage = ref.read(slice2, sourceBands);
            // we remove all other dimension to simplify any following operation
            if (coverage.getCoordinateReferenceSystem().getCoordinateSystem().getDimension() > 2) {
                coverage = new ReducedGridCoverage(coverage, 0, 1);
            }
            return forwardResample(coverage, resampleGrid);
        } else {
            ResampleProcess process = new ResampleProcess(coverage, crs2d, resampleGrid, interpolation, fill);
            // do not extrapolate values, can cause large areas of incorrect values
            process.getInput().parameter(ResampleDescriptor.IN_BORDER_COMPORTEMENT_TYPE.getName().getCode()).setValue(ResampleBorderComportement.FILL_VALUE);
            return process.executeNow();
        }
    }
}
Also used : GridGeometry(org.apache.sis.coverage.grid.GridGeometry) DisjointExtentException(org.apache.sis.coverage.grid.DisjointExtentException) ResampleProcess(org.geotoolkit.processing.coverage.resample.ResampleProcess) MathTransform(org.opengis.referencing.operation.MathTransform) ReducedGridCoverage(org.geotoolkit.coverage.ReducedGridCoverage) InterpolationCase(org.geotoolkit.image.interpolation.InterpolationCase) Envelope(org.opengis.geometry.Envelope) AbstractEnvelope(org.apache.sis.geometry.AbstractEnvelope) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope) GridCoverageStack(org.geotoolkit.coverage.grid.GridCoverageStack) ProjectionException(org.apache.sis.referencing.operation.projection.ProjectionException) ReducedGridCoverage(org.geotoolkit.coverage.ReducedGridCoverage) GridCoverage(org.apache.sis.coverage.grid.GridCoverage) IllegalGridGeometryException(org.apache.sis.coverage.grid.IllegalGridGeometryException) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope)

Example 4 with ResampleProcess

use of org.geotoolkit.processing.coverage.resample.ResampleProcess in project geotoolkit by Geomatys.

the class PatternRenderer method presentations.

@Override
public Stream<Presentation> presentations(MapLayer layer, Resource resource) {
    if (!(resource instanceof GridCoverageResource)) {
        return Stream.empty();
    }
    final GridCoverageResource gcr = (GridCoverageResource) resource;
    GridCoverage dataCoverage;
    try {
        dataCoverage = gcr.read(renderingContext.getGridGeometry());
    } catch (NoSuchDataException ex) {
        return Stream.empty();
    } catch (DataStoreException ex) {
        ExceptionPresentation ep = new ExceptionPresentation(ex);
        ep.setLayer(layer);
        ep.setResource(resource);
        return Stream.of(ep);
    }
    if (!Utilities.equalsIgnoreMetadata(CRS.getHorizontalComponent(dataCoverage.getCoordinateReferenceSystem()), renderingContext.getObjectiveCRS())) {
        // coverage is not in objective crs, resample it
        try {
            // we resample the native view of the coverage only, the style will be applied later.
            dataCoverage = new ResampleProcess(dataCoverage, renderingContext.getObjectiveCRS(), null, InterpolationCase.NEIGHBOR, null).executeNow();
        } catch (Exception ex) {
            LOGGER.log(Level.WARNING, "ERROR resample in raster symbolizer renderer", ex);
        }
    }
    final Map.Entry<FeatureSet, MutableStyle> entry;
    try {
        entry = symbol.getMasks(dataCoverage);
    } catch (IOException | TransformException ex) {
        ExceptionPresentation ep = new ExceptionPresentation(ex);
        ep.setLayer(layer);
        ep.setResource(resource);
        return Stream.of(ep);
    }
    final MapLayer subLayer = MapBuilder.createLayer(entry.getKey());
    subLayer.setStyle(entry.getValue());
    return DefaultPortrayalService.present(subLayer, entry.getKey(), renderingContext);
}
Also used : DataStoreException(org.apache.sis.storage.DataStoreException) ResampleProcess(org.geotoolkit.processing.coverage.resample.ResampleProcess) MapLayer(org.apache.sis.portrayal.MapLayer) TransformException(org.opengis.referencing.operation.TransformException) IOException(java.io.IOException) NoSuchDataException(org.apache.sis.storage.NoSuchDataException) IOException(java.io.IOException) NoSuchDataException(org.apache.sis.storage.NoSuchDataException) DataStoreException(org.apache.sis.storage.DataStoreException) TransformException(org.opengis.referencing.operation.TransformException) GridCoverage(org.apache.sis.coverage.grid.GridCoverage) MutableStyle(org.geotoolkit.style.MutableStyle) ExceptionPresentation(org.apache.sis.internal.map.ExceptionPresentation) GridCoverageResource(org.apache.sis.storage.GridCoverageResource) FeatureSet(org.apache.sis.storage.FeatureSet) Map(java.util.Map)

Example 5 with ResampleProcess

use of org.geotoolkit.processing.coverage.resample.ResampleProcess 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;
}
Also used : CompatibleColorModel(org.geotoolkit.style.function.CompatibleColorModel) ResampleProcess(org.geotoolkit.processing.coverage.resample.ResampleProcess) ComponentColorModel(java.awt.image.ComponentColorModel) ImageProcessor(org.apache.sis.image.ImageProcessor) StringWriter(java.io.StringWriter) Literal(org.opengis.filter.Literal) List(java.util.List) ArrayList(java.util.ArrayList) ImageLayout(javax.media.jai.ImageLayout) PrintWriter(java.io.PrintWriter) Color(java.awt.Color) InterpolationCase(org.geotoolkit.image.interpolation.InterpolationCase) NullOpImage(javax.media.jai.NullOpImage) LinearTransform(org.apache.sis.referencing.operation.transform.LinearTransform) PortrayalException(org.geotoolkit.display.PortrayalException) TransformException(org.opengis.referencing.operation.TransformException) FactoryException(org.opengis.util.FactoryException) MismatchedDimensionException(org.opengis.geometry.MismatchedDimensionException) ProcessException(org.geotoolkit.process.ProcessException) Graphics2D(java.awt.Graphics2D) ProcessException(org.geotoolkit.process.ProcessException) GridCoverage(org.apache.sis.coverage.grid.GridCoverage) CanvasMonitor(org.geotoolkit.display.canvas.control.CanvasMonitor) Expression(org.opengis.filter.Expression) AffineTransform(java.awt.geom.AffineTransform) RenderedImage(java.awt.image.RenderedImage) Map(java.util.Map) PortrayalException(org.geotoolkit.display.PortrayalException) DefaultInterpolationPoint(org.geotoolkit.style.function.DefaultInterpolationPoint)

Aggregations

GridCoverage (org.apache.sis.coverage.grid.GridCoverage)5 ResampleProcess (org.geotoolkit.processing.coverage.resample.ResampleProcess)5 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)3 TransformException (org.opengis.referencing.operation.TransformException)3 Map (java.util.Map)2 GridGeometry (org.apache.sis.coverage.grid.GridGeometry)2 GridCoverageResource (org.apache.sis.storage.GridCoverageResource)2 InterpolationCase (org.geotoolkit.image.interpolation.InterpolationCase)2 ProcessException (org.geotoolkit.process.ProcessException)2 Envelope (org.opengis.geometry.Envelope)2 MathTransform (org.opengis.referencing.operation.MathTransform)2 Color (java.awt.Color)1 Graphics2D (java.awt.Graphics2D)1 AffineTransform (java.awt.geom.AffineTransform)1 ComponentColorModel (java.awt.image.ComponentColorModel)1 RenderedImage (java.awt.image.RenderedImage)1 IOException (java.io.IOException)1 OutputStream (java.io.OutputStream)1 PrintWriter (java.io.PrintWriter)1 StringWriter (java.io.StringWriter)1