Example usage for java.awt.geom AffineTransform concatenate

List of usage examples for java.awt.geom AffineTransform concatenate

Introduction

In this page you can find the example usage for java.awt.geom AffineTransform concatenate.

Prototype

@SuppressWarnings("fallthrough")
public void concatenate(AffineTransform Tx) 

Source Link

Document

Concatenates an AffineTransform Tx to this AffineTransform Cx in the most commonly useful way to provide a new user space that is mapped to the former user space by Tx .

Usage

From source file:org.geotools.coverage.io.util.Utilities.java

/**
 * Retrieves the original grid to world transformation for this {@link AbstractGridCoverage2DReader}.
 * /*from  w w  w .  ja va 2s  . co m*/
 * @param pixInCell specifies the datum of the transformation we want.
 * @return the original grid to world transformation
 */
public static MathTransform getOriginalGridToWorld(MathTransform raster2Model, final PixelInCell pixInCell) {
    // we do not have to change the pixel datum
    if (pixInCell == PixelInCell.CELL_CENTER)
        return raster2Model;

    // we do have to change the pixel datum
    if (raster2Model instanceof AffineTransform) {
        final AffineTransform tr = new AffineTransform((AffineTransform) raster2Model);
        tr.concatenate(AffineTransform.getTranslateInstance(-0.5, -0.5));
        return ProjectiveTransform.create(tr);
    }
    if (raster2Model instanceof IdentityTransform) {
        final AffineTransform tr = new AffineTransform(1, 0, 0, 1, 0, 0);
        tr.concatenate(AffineTransform.getTranslateInstance(-0.5, -0.5));
        return ProjectiveTransform.create(tr);
    }
    throw new IllegalStateException("This grid to world transform is invalud!");
}

From source file:org.geotools.gce.imagemosaic.GranuleDescriptor.java

/**
* Load a specified a raster as a portion of the granule describe by this {@link GranuleDescriptor}.
* 
* @param imageReadParameters the {@link ImageReadParam} to use for reading.
* @param index the index to use for the {@link ImageReader}.
* @param cropBBox the bbox to use for cropping. 
* @param mosaicWorldToGrid the cropping grid to world transform.
* @param request the incoming request to satisfy.
* @param hints {@link Hints} to be used for creating this raster.
* @return a specified a raster as a portion of the granule describe by this {@link GranuleDescriptor}.
* @throws IOException in case an error occurs.
*///  www  .  j  av  a  2s  .  c o m
public GranuleLoadingResult loadRaster(final ImageReadParam imageReadParameters, final int index,
        final ReferencedEnvelope cropBBox, final MathTransform2D mosaicWorldToGrid,
        final RasterLayerRequest request, final Hints hints) throws IOException {

    if (LOGGER.isLoggable(java.util.logging.Level.FINER)) {
        final String name = Thread.currentThread().getName();
        LOGGER.finer("Thread:" + name + " Loading raster data for granuleDescriptor " + this.toString());
    }
    ImageReadParam readParameters = null;
    int imageIndex;
    final boolean useFootprint = roiProvider != null
            && request.getFootprintBehavior() != FootprintBehavior.None;
    Geometry inclusionGeometry = useFootprint ? roiProvider.getFootprint() : null;
    final ReferencedEnvelope bbox = useFootprint
            ? new ReferencedEnvelope(granuleBBOX.intersection(inclusionGeometry.getEnvelopeInternal()),
                    granuleBBOX.getCoordinateReferenceSystem())
            : granuleBBOX;
    boolean doFiltering = false;
    if (filterMe && useFootprint) {
        doFiltering = Utils.areaIsDifferent(inclusionGeometry, baseGridToWorld, granuleBBOX);
    }

    // intersection of this tile bound with the current crop bbox
    final ReferencedEnvelope intersection = new ReferencedEnvelope(bbox.intersection(cropBBox),
            cropBBox.getCoordinateReferenceSystem());
    if (intersection.isEmpty()) {
        if (LOGGER.isLoggable(java.util.logging.Level.FINE)) {
            LOGGER.fine(new StringBuilder("Got empty intersection for granule ").append(this.toString())
                    .append(" with request ").append(request.toString())
                    .append(" Resulting in no granule loaded: Empty result").toString());
        }
        return null;
    }

    // check if the requested bbox intersects or overlaps the requested area 
    if (useFootprint && inclusionGeometry != null && !JTS.toGeometry(cropBBox).intersects(inclusionGeometry)) {
        if (LOGGER.isLoggable(java.util.logging.Level.FINE)) {
            LOGGER.fine(new StringBuilder("Got empty intersection for granule ").append(this.toString())
                    .append(" with request ").append(request.toString())
                    .append(" Resulting in no granule loaded: Empty result").toString());
        }
        return null;
    }

    ImageInputStream inStream = null;
    ImageReader reader = null;
    try {
        //
        //get info about the raster we have to read
        //

        // get a stream
        assert cachedStreamSPI != null : "no cachedStreamSPI available!";
        inStream = cachedStreamSPI.createInputStreamInstance(granuleUrl, ImageIO.getUseCache(),
                ImageIO.getCacheDirectory());
        if (inStream == null)
            return null;

        // get a reader and try to cache the relevant SPI
        if (cachedReaderSPI == null) {
            reader = ImageIOExt.getImageioReader(inStream);
            if (reader != null)
                cachedReaderSPI = reader.getOriginatingProvider();
        } else
            reader = cachedReaderSPI.createReaderInstance();
        if (reader == null) {
            if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) {
                LOGGER.warning(new StringBuilder("Unable to get s reader for granuleDescriptor ")
                        .append(this.toString()).append(" with request ").append(request.toString())
                        .append(" Resulting in no granule loaded: Empty result").toString());
            }
            return null;
        }
        // set input
        customizeReaderInitialization(reader, hints);
        reader.setInput(inStream);

        // Checking for heterogeneous granules
        if (request.isHeterogeneousGranules()) {
            // create read parameters
            readParameters = new ImageReadParam();

            //override the overviews controller for the base layer
            imageIndex = ReadParamsController.setReadParams(
                    request.spatialRequestHelper.getRequestedResolution(), request.getOverviewPolicy(),
                    request.getDecimationPolicy(), readParameters, request.rasterManager, overviewsController);
        } else {
            imageIndex = index;
            readParameters = imageReadParameters;
        }

        //get selected level and base level dimensions
        final GranuleOverviewLevelDescriptor selectedlevel = getLevel(imageIndex, reader);

        // now create the crop grid to world which can be used to decide
        // which source area we need to crop in the selected level taking
        // into account the scale factors imposed by the selection of this
        // level together with the base level grid to world transformation
        AffineTransform2D cropWorldToGrid = new AffineTransform2D(selectedlevel.gridToWorldTransformCorner);
        cropWorldToGrid = (AffineTransform2D) cropWorldToGrid.inverse();
        // computing the crop source area which lives into the
        // selected level raster space, NOTICE that at the end we need to
        // take into account the fact that we might also decimate therefore
        // we cannot just use the crop grid to world but we need to correct
        // it.
        final Rectangle sourceArea = CRS.transform(cropWorldToGrid, intersection).toRectangle2D().getBounds();
        //gutter
        if (selectedlevel.baseToLevelTransform.isIdentity()) {
            sourceArea.grow(2, 2);
        }
        XRectangle2D.intersect(sourceArea, selectedlevel.rasterDimensions, sourceArea);//make sure roundings don't bother us
        // is it empty??
        if (sourceArea.isEmpty()) {
            if (LOGGER.isLoggable(java.util.logging.Level.FINE)) {
                LOGGER.fine("Got empty area for granuleDescriptor " + this.toString() + " with request "
                        + request.toString() + " Resulting in no granule loaded: Empty result");

            }
            return null;

        } else if (LOGGER.isLoggable(java.util.logging.Level.FINER)) {
            LOGGER.finer("Loading level " + imageIndex + " with source region: " + sourceArea + " subsampling: "
                    + readParameters.getSourceXSubsampling() + "," + readParameters.getSourceYSubsampling()
                    + " for granule:" + granuleUrl);
        }

        // Setting subsampling 
        int newSubSamplingFactor = 0;
        final String pluginName = cachedReaderSPI.getPluginClassName();
        if (pluginName != null && pluginName.equals(ImageUtilities.DIRECT_KAKADU_PLUGIN)) {
            final int ssx = readParameters.getSourceXSubsampling();
            final int ssy = readParameters.getSourceYSubsampling();
            newSubSamplingFactor = ImageIOUtilities.getSubSamplingFactor2(ssx, ssy);
            if (newSubSamplingFactor != 0) {
                if (newSubSamplingFactor > maxDecimationFactor && maxDecimationFactor != -1) {
                    newSubSamplingFactor = maxDecimationFactor;
                }
                readParameters.setSourceSubsampling(newSubSamplingFactor, newSubSamplingFactor, 0, 0);
            }
        }

        // set the source region
        readParameters.setSourceRegion(sourceArea);
        RenderedImage raster;
        try {
            // read
            raster = request.getReadType().read(readParameters, imageIndex, granuleUrl,
                    selectedlevel.rasterDimensions, reader, hints, false);

        } catch (Throwable e) {
            if (LOGGER.isLoggable(java.util.logging.Level.FINE)) {
                LOGGER.log(java.util.logging.Level.FINE,
                        "Unable to load raster for granuleDescriptor " + this.toString() + " with request "
                                + request.toString() + " Resulting in no granule loaded: Empty result",
                        e);
            }
            return null;
        }

        // use fixed source area
        sourceArea.setRect(readParameters.getSourceRegion());

        //
        // setting new coefficients to define a new affineTransformation
        // to be applied to the grid to world transformation
        // -----------------------------------------------------------------------------------
        //
        // With respect to the original envelope, the obtained planarImage
        // needs to be rescaled. The scaling factors are computed as the
        // ratio between the cropped source region sizes and the read
        // image sizes.
        //
        // place it in the mosaic using the coords created above;
        double decimationScaleX = ((1.0 * sourceArea.width) / raster.getWidth());
        double decimationScaleY = ((1.0 * sourceArea.height) / raster.getHeight());
        final AffineTransform decimationScaleTranform = XAffineTransform.getScaleInstance(decimationScaleX,
                decimationScaleY);

        // keep into account translation  to work into the selected level raster space
        final AffineTransform afterDecimationTranslateTranform = XAffineTransform
                .getTranslateInstance(sourceArea.x, sourceArea.y);

        // now we need to go back to the base level raster space
        final AffineTransform backToBaseLevelScaleTransform = selectedlevel.baseToLevelTransform;

        // now create the overall transform
        final AffineTransform finalRaster2Model = new AffineTransform(baseGridToWorld);
        finalRaster2Model.concatenate(CoverageUtilities.CENTER_TO_CORNER);

        if (!XAffineTransform.isIdentity(backToBaseLevelScaleTransform, Utils.AFFINE_IDENTITY_EPS))
            finalRaster2Model.concatenate(backToBaseLevelScaleTransform);
        if (!XAffineTransform.isIdentity(afterDecimationTranslateTranform, Utils.AFFINE_IDENTITY_EPS))
            finalRaster2Model.concatenate(afterDecimationTranslateTranform);
        if (!XAffineTransform.isIdentity(decimationScaleTranform, Utils.AFFINE_IDENTITY_EPS))
            finalRaster2Model.concatenate(decimationScaleTranform);

        // adjust roi
        if (useFootprint) {

            ROIGeometry transformed;
            try {
                transformed = roiProvider.getTransformedROI(finalRaster2Model.createInverse());
                if (transformed.getAsGeometry().isEmpty()) {
                    // inset might have killed the geometry fully
                    return null;
                }

                PlanarImage pi = PlanarImage.wrapRenderedImage(raster);
                if (!transformed.intersects(pi.getBounds())) {
                    return null;
                }
                pi.setProperty("ROI", transformed);
                raster = pi;

            } catch (NoninvertibleTransformException e) {
                if (LOGGER.isLoggable(java.util.logging.Level.INFO))
                    LOGGER.info("Unable to create a granuleDescriptor " + this.toString()
                            + " due to a problem when managing the ROI");
                return null;
            }

        }
        // keep into account translation factors to place this tile
        finalRaster2Model.preConcatenate((AffineTransform) mosaicWorldToGrid);
        final Interpolation interpolation = request.getInterpolation();

        //paranoiac check to avoid that JAI freaks out when computing its internal layouT on images that are too small
        Rectangle2D finalLayout = ImageUtilities.layoutHelper(raster, (float) finalRaster2Model.getScaleX(),
                (float) finalRaster2Model.getScaleY(), (float) finalRaster2Model.getTranslateX(),
                (float) finalRaster2Model.getTranslateY(), interpolation);
        if (finalLayout.isEmpty()) {
            if (LOGGER.isLoggable(java.util.logging.Level.INFO))
                LOGGER.info("Unable to create a granuleDescriptor " + this.toString()
                        + " due to jai scale bug creating a null source area");
            return null;
        }

        // apply the affine transform  conserving indexed color model
        final RenderingHints localHints = new RenderingHints(JAI.KEY_REPLACE_INDEX_COLOR_MODEL,
                interpolation instanceof InterpolationNearest ? Boolean.FALSE : Boolean.TRUE);
        if (XAffineTransform.isIdentity(finalRaster2Model, Utils.AFFINE_IDENTITY_EPS)) {
            return new GranuleLoadingResult(raster, null, granuleUrl, doFiltering, pamDataset);
        } else {
            //
            // In case we are asked to use certain tile dimensions we tile
            // also at this stage in case the read type is Direct since
            // buffered images comes up untiled and this can affect the
            // performances of the subsequent affine operation.
            //
            final Dimension tileDimensions = request.getTileDimensions();
            if (tileDimensions != null && request.getReadType().equals(ReadType.DIRECT_READ)) {
                final ImageLayout layout = new ImageLayout();
                layout.setTileHeight(tileDimensions.width).setTileWidth(tileDimensions.height);
                localHints.add(new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout));
            } else {
                if (hints != null && hints.containsKey(JAI.KEY_IMAGE_LAYOUT)) {
                    final Object layout = hints.get(JAI.KEY_IMAGE_LAYOUT);
                    if (layout != null && layout instanceof ImageLayout) {
                        localHints
                                .add(new RenderingHints(JAI.KEY_IMAGE_LAYOUT, ((ImageLayout) layout).clone()));
                    }
                }
            }
            if (hints != null && hints.containsKey(JAI.KEY_TILE_CACHE)) {
                final Object cache = hints.get(JAI.KEY_TILE_CACHE);
                if (cache != null && cache instanceof TileCache)
                    localHints.add(new RenderingHints(JAI.KEY_TILE_CACHE, (TileCache) cache));
            }
            if (hints != null && hints.containsKey(JAI.KEY_TILE_SCHEDULER)) {
                final Object scheduler = hints.get(JAI.KEY_TILE_SCHEDULER);
                if (scheduler != null && scheduler instanceof TileScheduler)
                    localHints.add(new RenderingHints(JAI.KEY_TILE_SCHEDULER, (TileScheduler) scheduler));
            }
            boolean addBorderExtender = true;
            if (hints != null && hints.containsKey(JAI.KEY_BORDER_EXTENDER)) {
                final Object extender = hints.get(JAI.KEY_BORDER_EXTENDER);
                if (extender != null && extender instanceof BorderExtender) {
                    localHints.add(new RenderingHints(JAI.KEY_BORDER_EXTENDER, (BorderExtender) extender));
                    addBorderExtender = false;
                }
            }
            // BORDER extender
            if (addBorderExtender) {
                localHints.add(ImageUtilities.BORDER_EXTENDER_HINTS);
            }

            ImageWorker iw = new ImageWorker(raster);
            iw.setRenderingHints(localHints);
            iw.affine(finalRaster2Model, interpolation, request.getBackgroundValues());
            return new GranuleLoadingResult(iw.getRenderedImage(), null, granuleUrl, doFiltering, pamDataset);
        }

    } catch (IllegalStateException e) {
        if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) {
            LOGGER.log(java.util.logging.Level.WARNING,
                    new StringBuilder("Unable to load raster for granuleDescriptor ").append(this.toString())
                            .append(" with request ").append(request.toString())
                            .append(" Resulting in no granule loaded: Empty result").toString(),
                    e);
        }
        return null;
    } catch (org.opengis.referencing.operation.NoninvertibleTransformException e) {
        if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) {
            LOGGER.log(java.util.logging.Level.WARNING,
                    new StringBuilder("Unable to load raster for granuleDescriptor ").append(this.toString())
                            .append(" with request ").append(request.toString())
                            .append(" Resulting in no granule loaded: Empty result").toString(),
                    e);
        }
        return null;
    } catch (TransformException e) {
        if (LOGGER.isLoggable(java.util.logging.Level.WARNING)) {
            LOGGER.log(java.util.logging.Level.WARNING,
                    new StringBuilder("Unable to load raster for granuleDescriptor ").append(this.toString())
                            .append(" with request ").append(request.toString())
                            .append(" Resulting in no granule loaded: Empty result").toString(),
                    e);
        }
        return null;

    } finally {
        try {
            if (request.getReadType() != ReadType.JAI_IMAGEREAD && inStream != null) {
                inStream.close();
            }
        } finally {
            if (request.getReadType() != ReadType.JAI_IMAGEREAD && reader != null) {
                reader.dispose();
            }
        }
    }
}

From source file:org.geotools.gce.imagemosaic.RasterLayerResponse.java

private RenderedImage postProcessRaster(RenderedImage image) {
    // alpha on the final mosaic
    if (finalTransparentColor != null) {
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine("Support for alpha on final mosaic");
        return ImageUtilities.maskColor(finalTransparentColor, image);

    }// w w w. j  a  v a2  s  .c o m
    if (!needsReprojection) {
        try {

            // creating source grid to world corrected to the pixel corner
            final AffineTransform sourceGridToWorld = new AffineTransform(
                    (AffineTransform) finalGridToWorldCorner);

            // target world to grid at the corner
            final AffineTransform targetGridToWorld = new AffineTransform(request.getRequestedGridToWorld());
            targetGridToWorld.concatenate(CoverageUtilities.CENTER_TO_CORNER);

            // target world to grid at the corner
            final AffineTransform targetWorldToGrid = targetGridToWorld.createInverse();
            // final complete transformation
            targetWorldToGrid.concatenate(sourceGridToWorld);

            //update final grid to world
            finalGridToWorldCorner = new AffineTransform2D(targetGridToWorld);
            //
            // Check and see if the affine transform is doing a copy.
            // If so call the copy operation.
            //
            // we are in raster space here, so 1E-3 is safe
            if (XAffineTransform.isIdentity(targetWorldToGrid, Utils.AFFINE_IDENTITY_EPS))
                return image;

            // create final image
            // TODO this one could be optimized further depending on how the affine is created
            //
            // In case we are asked to use certain tile dimensions we tile
            // also at this stage in case the read type is Direct since
            // buffered images comes up untiled and this can affect the
            // performances of the subsequent affine operation.
            //
            final Hints localHints = new Hints(hints);
            if (hints != null && !hints.containsKey(JAI.KEY_BORDER_EXTENDER)) {
                final Object extender = hints.get(JAI.KEY_BORDER_EXTENDER);
                if (!(extender != null && extender instanceof BorderExtender)) {
                    localHints.add(ImageUtilities.EXTEND_BORDER_BY_COPYING);
                }
            }

            //                         image = AffineDescriptor.create(image, targetWorldToGrid , interpolation, backgroundValues, localHints);
            ImageWorker iw = new ImageWorker(image);
            iw.setRenderingHints(localHints);
            iw.affine(targetWorldToGrid, interpolation, backgroundValues);
            image = iw.getRenderedImage();
        } catch (NoninvertibleTransformException e) {
            if (LOGGER.isLoggable(Level.SEVERE)) {
                LOGGER.log(Level.SEVERE, "Unable to create the requested mosaic ", e);
            }
        }
    }
    return image;
}

From source file:org.geotools.gce.imagemosaic.RasterLayerResponse.java

/**
 * This method loads the granules which overlap the requested
 * {@link GeneralEnvelope} using the provided values for alpha and input
 * ROI.//from  w  ww.  ja va  2 s . c  o  m
 * @return
 * @throws DataSourceException
 */
private RenderedImage prepareResponse() throws DataSourceException {

    try {

        //
        // prepare the params for executing a mosaic operation.
        //
        // It might important to set the mosaic type to blend otherwise
        // sometimes strange results jump in.

        // select the relevant overview, notice that at this time we have
        // relaxed a bit the requirement to have the same exact resolution
        // for all the overviews, but still we do not allow for reading the
        // various grid to world transform directly from the input files,
        // therefore we are assuming that each granuleDescriptor has a scale and
        // translate only grid to world that can be deduced from its base
        // level dimension and envelope. The grid to world transforms for
        // the other levels can be computed accordingly knowing the scale
        // factors.
        if (request.getRequestedBBox() != null && request.getRequestedRasterArea() != null
                && !request.isHeterogeneousGranules())
            imageChoice = ReadParamsController.setReadParams(request.getRequestedResolution(),
                    request.getOverviewPolicy(), request.getDecimationPolicy(), baseReadParameters,
                    request.rasterManager, request.rasterManager.overviewsController); // use general overviews controller
        else
            imageChoice = 0;
        assert imageChoice >= 0;
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine(new StringBuffer("Loading level ").append(imageChoice)
                    .append(" with subsampling factors ").append(baseReadParameters.getSourceXSubsampling())
                    .append(" ").append(baseReadParameters.getSourceYSubsampling()).toString());

        // ok we got something to return, let's load records from the index
        final BoundingBox cropBBOX = request.getCropBBox();
        if (cropBBOX != null)
            mosaicBBox = ReferencedEnvelope.reference(cropBBOX);
        else
            mosaicBBox = new ReferencedEnvelope(coverageEnvelope);

        //compute final world to grid
        // base grid to world for the center of pixels
        final AffineTransform g2w;
        final OverviewLevel baseLevel = rasterManager.overviewsController.resolutionsLevels.get(0);
        final OverviewLevel selectedLevel = rasterManager.overviewsController.resolutionsLevels
                .get(imageChoice);
        final double resX = baseLevel.resolutionX;
        final double resY = baseLevel.resolutionY;
        final double[] requestRes = request.getRequestedResolution();

        g2w = new AffineTransform((AffineTransform) baseGridToWorld);
        g2w.concatenate(CoverageUtilities.CENTER_TO_CORNER);

        if ((requestRes[0] < resX || requestRes[1] < resY)) {
            // Using the best available resolution
            oversampledRequest = true;
        } else {

            // SG going back to working on a per level basis to do the composition
            // g2w = new AffineTransform(request.getRequestedGridToWorld());
            g2w.concatenate(
                    AffineTransform.getScaleInstance(selectedLevel.scaleFactor, selectedLevel.scaleFactor));
            g2w.concatenate(AffineTransform.getScaleInstance(baseReadParameters.getSourceXSubsampling(),
                    baseReadParameters.getSourceYSubsampling()));
        }

        // move it to the corner
        finalGridToWorldCorner = new AffineTransform2D(g2w);
        finalWorldToGridCorner = finalGridToWorldCorner.inverse();// compute raster bounds
        final GeneralEnvelope tempRasterBounds = CRS.transform(finalWorldToGridCorner, mosaicBBox);
        rasterBounds = tempRasterBounds.toRectangle2D().getBounds();

        //          SG using the above may lead to problems since the reason is that  may be a little (1 px) bigger
        //          than what we need. The code below is a bit better since it uses a proper logic (see GridEnvelope
        //          Javadoc)
        //         rasterBounds = new GridEnvelope2D(new Envelope2D(tempRasterBounds), PixelInCell.CELL_CORNER);
        if (rasterBounds.width == 0)
            rasterBounds.width++;
        if (rasterBounds.height == 0)
            rasterBounds.height++;
        if (oversampledRequest)
            rasterBounds.grow(2, 2);

        // make sure we do not go beyond the raster dimensions for this layer
        final GeneralEnvelope levelRasterArea_ = CRS.transform(finalWorldToGridCorner,
                rasterManager.spatialDomainManager.coverageBBox);
        final GridEnvelope2D levelRasterArea = new GridEnvelope2D(new Envelope2D(levelRasterArea_),
                PixelInCell.CELL_CORNER);
        XRectangle2D.intersect(levelRasterArea, rasterBounds, rasterBounds);

        // create the index visitor and visit the feature
        final MosaicBuilder visitor = new MosaicBuilder(request);
        final List times = request.getRequestedTimes();
        final List elevations = request.getElevation();
        final Map<String, List> additionalDomains = request.getRequestedAdditionalDomains();
        final Filter filter = request.getFilter();
        final boolean hasTime = (times != null && times.size() > 0);
        final boolean hasElevation = (elevations != null && elevations.size() > 0);
        final boolean hasAdditionalDomains = additionalDomains.size() > 0;
        final boolean hasFilter = filter != null && !Filter.INCLUDE.equals(filter);

        // create query
        final SimpleFeatureType type = rasterManager.granuleCatalog.getType();
        Query query = null;
        Filter bbox = null;
        if (type != null) {
            query = new Query(rasterManager.granuleCatalog.getType().getTypeName());
            bbox = FeatureUtilities.DEFAULT_FILTER_FACTORY.bbox(
                    FeatureUtilities.DEFAULT_FILTER_FACTORY
                            .property(rasterManager.granuleCatalog.getType().getGeometryDescriptor().getName()),
                    mosaicBBox);
            query.setFilter(bbox);
        } else {
            throw new IllegalStateException("GranuleCatalog feature type was null!!!");
        }

        // prepare eventual filter for filtering granules
        // handle elevation indexing first since we then combine this with the max in case we are asking for current in time
        if (hasElevation) {

            final Filter elevationF = rasterManager.parent.elevationDomainManager
                    .createFilter(ImageMosaicReader.ELEVATION_DOMAIN, elevations);
            query.setFilter(FeatureUtilities.DEFAULT_FILTER_FACTORY.and(query.getFilter(), elevationF));
        }

        // handle generic filter since we then combine this with the max in case we are asking for current in time
        if (hasFilter) {
            query.setFilter(FeatureUtilities.DEFAULT_FILTER_FACTORY.and(query.getFilter(), filter));
        }

        // fuse time query with the bbox query
        if (hasTime) {
            final Filter timeFilter = this.rasterManager.parent.timeDomainManager
                    .createFilter(ImageMosaicReader.TIME_DOMAIN, times);
            query.setFilter(FeatureUtilities.DEFAULT_FILTER_FACTORY.and(query.getFilter(), timeFilter));
        }

        if (hasAdditionalDomains) {
            final List<Filter> additionalFilter = new ArrayList<Filter>();
            for (Entry<String, List> entry : additionalDomains.entrySet()) {

                // build a filter for each dimension
                final String domainName = entry.getKey() + DomainDescriptor.DOMAIN_SUFFIX;
                additionalFilter.add(
                        rasterManager.parent.domainsManager.createFilter(domainName, (List) entry.getValue()));

            }
            // merge with existing ones
            query.setFilter(FeatureUtilities.DEFAULT_FILTER_FACTORY.and(query.getFilter(),
                    FeatureUtilities.DEFAULT_FILTER_FACTORY.and(additionalFilter)));
        }

        //
        // handle secondary query parameters
        //

        // max number of elements
        if (request.getMaximumNumberOfGranules() > 0) {
            query.setMaxFeatures(request.getMaximumNumberOfGranules());
        }

        // sort by clause
        final String sortByClause = request.getSortClause();
        if (sortByClause != null && sortByClause.length() > 0) {
            final String[] elements = sortByClause.split(",");
            if (elements != null && elements.length > 0) {
                final List<SortBy> clauses = new ArrayList<SortBy>(elements.length);
                for (String element : elements) {
                    // check
                    if (element == null || element.length() <= 0) {
                        continue;// next, please!
                    }
                    try {
                        // which clause?
                        // ASCENDING
                        element = element.trim();
                        if (element.endsWith(Utils.ASCENDING_ORDER_IDENTIFIER)) {
                            String attribute = element.substring(0, element.length() - 2);
                            clauses.add(
                                    new SortByImpl(FeatureUtilities.DEFAULT_FILTER_FACTORY.property(attribute),
                                            SortOrder.ASCENDING));
                        } else
                        // DESCENDING
                        if (element.contains(Utils.DESCENDING_ORDER_IDENTIFIER)) {
                            String attribute = element.substring(0, element.length() - 2);
                            clauses.add(
                                    new SortByImpl(FeatureUtilities.DEFAULT_FILTER_FACTORY.property(attribute),
                                            SortOrder.DESCENDING));
                        }
                        //                        if(element.startsWith(Utils.ASCENDING_ORDER_IDENTIFIER)){
                        //                           String attribute=element.substring(Utils.ASCENDING_ORDER_IDENTIFIER.length()+1);
                        //                           attribute=attribute.substring(0, attribute.length()-1);
                        //                           clauses.add(new SortByImpl(FeatureUtilities.DEFAULT_FILTER_FACTORY.property(attribute),SortOrder.ASCENDING));
                        //                        } else 
                        //                           // DESCENDING
                        //                           if(element.startsWith(Utils.DESCENDING_ORDER_IDENTIFIER)){
                        //                               String attribute=element.substring(Utils.DESCENDING_ORDER_IDENTIFIER.length()+1);
                        //                               attribute=attribute.substring(0, attribute.length()-1);
                        //                               clauses.add(new SortByImpl(FeatureUtilities.DEFAULT_FILTER_FACTORY.property(attribute),SortOrder.DESCENDING));
                        //                        } else {
                        else {
                            if (LOGGER.isLoggable(Level.FINE)) {
                                LOGGER.fine("Ignoring sort clause :" + element);
                            }
                        }
                    } catch (Exception e) {
                        if (LOGGER.isLoggable(Level.INFO)) {
                            LOGGER.log(Level.INFO, e.getLocalizedMessage(), e);
                        }
                    }
                }

                // assign to query if sorting is supported!
                final SortBy[] sb = clauses.toArray(new SortBy[] {});
                if (rasterManager.granuleCatalog.getQueryCapabilities().supportsSorting(sb)) {
                    query.setSortBy(sb);
                }
            }
        }

        // collect granules
        rasterManager.getGranules(query, visitor);

        // get those granules
        visitor.produce();

        //
        // Did we actually load anything?? Notice that it might happen that
        // either we have holes inside the definition area for the mosaic
        // or we had some problem with missing tiles, therefore it might
        // happen that for some bboxes we don't have anything to load.
        //
        RenderedImage returnValue = null;
        if (visitor.granulesNumber >= 1) {

            //
            // Create the mosaic image by doing a crop if necessary and also
            // managing the transparent color if applicable. Be aware that
            // management of the transparent color involves removing
            // transparency information from the input images.
            //          
            returnValue = buildMosaic(visitor);
            if (returnValue != null) {
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.fine("Loaded bbox " + mosaicBBox.toString() + " while crop bbox "
                            + request.getCropBBox().toString());
                return returnValue;
            }

        }

        // Redo the query without filter to check whether we got no granules due
        // to a filter. In that case we need to return null
        if (hasTime || hasElevation || hasFilter || hasAdditionalDomains) {
            query.setFilter(bbox);
            rasterManager.getGranules(query, visitor);
            // get those granules
            visitor.produce();
            if (visitor.granulesNumber >= 1) {
                // It means the previous lack of granule was due to a filter excluding all the results. Then we return null
                return null;
            }
        }

        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine("Creating constant image for area with no data");

        // if we get here that means that we do not have anything to load
        // but still we are inside the definition area for the mosaic,
        // therefore we create a fake coverage using the background values,
        // if provided (defaulting to 0), as well as the compute raster
        // bounds, envelope and grid to world.

        final Number[] values = ImageUtilities.getBackgroundValues(rasterManager.defaultSM, backgroundValues);
        // create a constant image with a proper layout
        RenderedImage finalImage = ConstantDescriptor.create(Float.valueOf(rasterBounds.width),
                Float.valueOf(rasterBounds.height), values, null);
        if (rasterBounds.x != 0 || rasterBounds.y != 0) {
            finalImage = TranslateDescriptor.create(finalImage, Float.valueOf(rasterBounds.x),
                    Float.valueOf(rasterBounds.y), Interpolation.getInstance(Interpolation.INTERP_NEAREST),
                    null);
        }
        if (rasterManager.defaultCM != null) {
            final ImageLayout2 il = new ImageLayout2();
            il.setColorModel(rasterManager.defaultCM);
            Dimension tileSize = request.getTileDimensions();
            if (tileSize == null) {
                tileSize = JAI.getDefaultTileSize();
            }
            il.setSampleModel(
                    rasterManager.defaultCM.createCompatibleSampleModel(tileSize.width, tileSize.height));
            il.setTileGridXOffset(0).setTileGridYOffset(0).setTileWidth((int) tileSize.getWidth())
                    .setTileHeight((int) tileSize.getHeight());
            return FormatDescriptor.create(finalImage, Integer.valueOf(il.getSampleModel(null).getDataType()),
                    new RenderingHints(JAI.KEY_IMAGE_LAYOUT, il));
        }
        return finalImage;

    } catch (Exception e) {
        throw new DataSourceException("Unable to create this mosaic", e);
    }
}

From source file:org.openstreetmap.josm.gui.layer.geoimage.ThumbsLoader.java

private BufferedImage loadThumb(ImageEntry entry) {
    final String cacheIdent = entry.getFile().toString() + ':' + maxSize;

    if (!cacheOff && cache != null) {
        try {//from  w w  w.  j a v a 2s.  c  o m
            BufferedImageCacheEntry cacheEntry = cache.get(cacheIdent);
            if (cacheEntry != null && cacheEntry.getImage() != null) {
                Logging.debug(" from cache");
                return cacheEntry.getImage();
            }
        } catch (IOException e) {
            Logging.warn(e);
        }
    }

    Image img = Toolkit.getDefaultToolkit().createImage(entry.getFile().getPath());
    tracker.addImage(img, 0);
    try {
        tracker.waitForID(0);
    } catch (InterruptedException e) {
        Logging.error(" InterruptedException while loading thumb");
        Thread.currentThread().interrupt();
        return null;
    }
    if (tracker.isErrorID(1) || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) {
        Logging.error(" Invalid image");
        return null;
    }

    final int w = img.getWidth(null);
    final int h = img.getHeight(null);
    final int hh, ww;
    final Integer exifOrientation = entry.getExifOrientation();
    if (exifOrientation != null && ExifReader.orientationSwitchesDimensions(exifOrientation)) {
        ww = h;
        hh = w;
    } else {
        ww = w;
        hh = h;
    }

    Rectangle targetSize = ImageDisplay.calculateDrawImageRectangle(new Rectangle(0, 0, ww, hh),
            new Rectangle(0, 0, maxSize, maxSize));
    BufferedImage scaledBI = new BufferedImage(targetSize.width, targetSize.height, BufferedImage.TYPE_INT_RGB);
    Graphics2D g = scaledBI.createGraphics();

    final AffineTransform scale = AffineTransform.getScaleInstance((double) targetSize.width / ww,
            (double) targetSize.height / hh);
    if (exifOrientation != null) {
        final AffineTransform restoreOrientation = ExifReader.getRestoreOrientationTransform(exifOrientation, w,
                h);
        scale.concatenate(restoreOrientation);
    }

    while (!g.drawImage(img, scale, null)) {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            Logging.warn("InterruptedException while drawing thumb");
            Thread.currentThread().interrupt();
        }
    }
    g.dispose();
    tracker.removeImage(img);

    if (scaledBI.getWidth() <= 0 || scaledBI.getHeight() <= 0) {
        Logging.error(" Invalid image");
        return null;
    }

    if (!cacheOff && cache != null) {
        try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
            ImageIO.write(scaledBI, "png", output);
            cache.put(cacheIdent, new BufferedImageCacheEntry(output.toByteArray()));
        } catch (IOException e) {
            Logging.warn("Failed to save geoimage thumb to cache");
            Logging.warn(e);
        }
    }

    return scaledBI;
}

From source file:org.pentaho.reporting.engine.classic.core.modules.output.pageable.pdf.internal.PdfGraphics2D.java

@Override
public void drawString(final String s, final float x, float y) {
    if (s.length() == 0) {
        return;/*w  w w. j  a v  a  2 s .  c  om*/
    }
    setFillPaint();
    setStrokePaint();

    final AffineTransform at = getTransform();
    final AffineTransform at2 = getTransform();
    at2.translate(x, y);
    at2.concatenate(font.getTransform());
    setTransform(at2);
    final AffineTransform inverse = this.normalizeMatrix();
    final AffineTransform flipper = FLIP_TRANSFORM;
    inverse.concatenate(flipper);
    final double[] mx = new double[6];
    inverse.getMatrix(mx);
    cb.beginText();

    final float fontSize = font.getSize2D();
    if (lastBaseFont == null) {
        final String fontName = font.getName();
        final boolean bold = font.isBold();
        final boolean italic = font.isItalic();

        final BaseFontFontMetrics fontMetrics = metaData.getBaseFontFontMetrics(fontName, fontSize, bold,
                italic, null, metaData.isFeatureSupported(OutputProcessorFeature.EMBED_ALL_FONTS), false);
        final FontNativeContext nativeContext = fontMetrics.getNativeContext();
        lastBaseFont = fontMetrics.getBaseFont();

        cb.setFontAndSize(lastBaseFont, fontSize);
        if (fontMetrics.isTrueTypeFont() && bold && nativeContext.isNativeBold() == false) {
            final float strokeWidth = font.getSize2D() / 30.0f; // right from iText ...
            if (strokeWidth == 1) {
                cb.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL);
            } else {
                cb.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE);
                cb.setLineWidth(strokeWidth);
            }
        } else {
            cb.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL);
        }
    } else {
        cb.setFontAndSize(lastBaseFont, fontSize);
    }

    cb.setTextMatrix((float) mx[0], (float) mx[1], (float) mx[2], (float) mx[3], (float) mx[4], (float) mx[5]);
    double width = 0;
    if (fontSize > 0) {
        final float scale = 1000 / fontSize;
        final Font font = this.font.deriveFont(AffineTransform.getScaleInstance(scale, scale));
        final Rectangle2D stringBounds = font.getStringBounds(s, getFontRenderContext());
        width = stringBounds.getWidth() / scale;
    }
    if (s.length() > 1) {
        final float adv = ((float) width - lastBaseFont.getWidthPoint(s, fontSize)) / (s.length() - 1);
        cb.setCharacterSpacing(adv);
    }
    cb.showText(s);
    if (s.length() > 1) {
        cb.setCharacterSpacing(0);
    }
    cb.endText();
    setTransform(at);
    if (underline) {
        // These two are supposed to be taken from the .AFM file
        // int UnderlinePosition = -100;
        final int UnderlineThickness = 50;
        //
        final double d = PdfGraphics2D.asPoints(UnderlineThickness, (int) fontSize);
        setStroke(new BasicStroke((float) d));
        y = (float) ((y) + PdfGraphics2D.asPoints((UnderlineThickness), (int) fontSize));
        final Line2D line = new Line2D.Double(x, y, (width + x), y);
        draw(line);
    }
}

From source file:org.pentaho.reporting.engine.classic.core.modules.output.pageable.pdf.internal.PdfGraphics2D.java

private AffineTransform normalizeMatrix() {
    final double[] mx = new double[6];
    AffineTransform result = AffineTransform.getTranslateInstance(0, 0);
    result.getMatrix(mx);/*from w  w  w .ja v a 2 s . com*/
    mx[3] = -1;
    mx[5] = height;
    result = new AffineTransform(mx);
    result.concatenate(transform);
    return result;
}

From source file:org.pentaho.reporting.engine.classic.core.modules.output.pageable.pdf.internal.PdfGraphics2D.java

public boolean drawPdfImage(final com.lowagie.text.Image image, final Image img, AffineTransform xform,
        final ImageObserver obs) {
    if (img == null) {
        throw new NullPointerException("Image must not be null.");
    }/*from  www  .j a  v a  2s . com*/
    if (image == null) {
        throw new NullPointerException("Image must not be null.");
    }
    if (xform == null) {
        xform = AffineTransform.getTranslateInstance(0, 0);
    }

    xform.translate(0, img.getHeight(obs));
    xform.scale(img.getWidth(obs), img.getHeight(obs));

    final AffineTransform inverse = this.normalizeMatrix();
    final AffineTransform flipper = FLIP_TRANSFORM;
    inverse.concatenate(xform);
    inverse.concatenate(flipper);

    try {
        final double[] mx = new double[6];
        inverse.getMatrix(mx);
        if (currentFillGState != 255) {
            PdfGState gs = fillGState[255];
            if (gs == null) {
                gs = new PdfGState();
                gs.setFillOpacity(1);
                fillGState[255] = gs;
            }
            cb.setGState(gs);
        }

        cb.addImage(image, (float) mx[0], (float) mx[1], (float) mx[2], (float) mx[3], (float) mx[4],
                (float) mx[5]);
    } catch (Exception ex) {
        PdfGraphics2D.logger.error("Failed to draw the image: ", ex);
        // throw new IllegalArgumentException("Failed to draw the image");
    } finally {
        if (currentFillGState != 255) {
            final PdfGState gs = fillGState[currentFillGState];
            cb.setGState(gs);
        }
    }
    return true;
}

From source file:org.zkoss.poi.ss.util.SheetUtil.java

/**
 * Compute width of a single cell/*from w w w .  j  ava 2s.  c o m*/
 *
 * @param cell the cell whose width is to be calculated
 * @param defaultCharWidth the width of a single character
 * @param formatter formatter used to prepare the text to be measured
 * @param useMergedCells    whether to use merged cells
 * @return  the width in pixels
 */
public static double getCellWidth(Cell cell, int defaultCharWidth, DataFormatter formatter,
        boolean useMergedCells) {

    Sheet sheet = cell.getSheet();
    Workbook wb = sheet.getWorkbook();
    Row row = cell.getRow();
    int column = cell.getColumnIndex();

    int colspan = 1;
    for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
        CellRangeAddress region = sheet.getMergedRegion(i);
        if (containsCell(region, row.getRowNum(), column)) {
            if (!useMergedCells) {
                // If we're not using merged cells, skip this one and move on to the next.
                return -1;
            }
            cell = row.getCell(region.getFirstColumn());
            colspan = 1 + region.getLastColumn() - region.getFirstColumn();
        }
    }

    CellStyle style = cell.getCellStyle();
    int cellType = cell.getCellType();

    // for formula cells we compute the cell width for the cached formula result
    if (cellType == Cell.CELL_TYPE_FORMULA)
        cellType = cell.getCachedFormulaResultType();

    Font font = wb.getFontAt(style.getFontIndex());

    AttributedString str;
    TextLayout layout;

    double width = -1;
    if (cellType == Cell.CELL_TYPE_STRING) {
        RichTextString rt = cell.getRichStringCellValue();
        String[] lines = rt.getString().split("\\n");
        for (int i = 0; i < lines.length; i++) {
            String txt = lines[i] + defaultChar;

            str = new AttributedString(txt);
            copyAttributes(font, str, 0, txt.length());

            if (rt.numFormattingRuns() > 0) {
                // TODO: support rich text fragments
            }

            layout = new TextLayout(str.getIterator(), fontRenderContext);
            if (style.getRotation() != 0) {
                /*
                 * Transform the text using a scale so that it's height is increased by a multiple of the leading,
                 * and then rotate the text before computing the bounds. The scale results in some whitespace around
                 * the unrotated top and bottom of the text that normally wouldn't be present if unscaled, but
                 * is added by the standard Excel autosize.
                 */
                AffineTransform trans = new AffineTransform();
                trans.concatenate(
                        AffineTransform.getRotateInstance(style.getRotation() * 2.0 * Math.PI / 360.0));
                trans.concatenate(AffineTransform.getScaleInstance(1, fontHeightMultiple));
                width = Math.max(width,
                        ((layout.getOutline(trans).getBounds().getWidth() / colspan) / defaultCharWidth)
                                + cell.getCellStyle().getIndention());
            } else {
                width = Math.max(width, ((layout.getBounds().getWidth() / colspan) / defaultCharWidth)
                        + cell.getCellStyle().getIndention());
            }
        }
    } else {
        String sval = null;
        if (cellType == Cell.CELL_TYPE_NUMERIC) {
            // Try to get it formatted to look the same as excel
            try {
                sval = formatter.formatCellValue(cell, dummyEvaluator);
            } catch (Exception e) {
                sval = String.valueOf(cell.getNumericCellValue());
            }
        } else if (cellType == Cell.CELL_TYPE_BOOLEAN) {
            sval = String.valueOf(cell.getBooleanCellValue()).toUpperCase();
        }
        if (sval != null) {
            String txt = sval + defaultChar;
            str = new AttributedString(txt);
            copyAttributes(font, str, 0, txt.length());

            layout = new TextLayout(str.getIterator(), fontRenderContext);
            if (style.getRotation() != 0) {
                /*
                 * Transform the text using a scale so that it's height is increased by a multiple of the leading,
                 * and then rotate the text before computing the bounds. The scale results in some whitespace around
                 * the unrotated top and bottom of the text that normally wouldn't be present if unscaled, but
                 * is added by the standard Excel autosize.
                 */
                AffineTransform trans = new AffineTransform();
                trans.concatenate(
                        AffineTransform.getRotateInstance(style.getRotation() * 2.0 * Math.PI / 360.0));
                trans.concatenate(AffineTransform.getScaleInstance(1, fontHeightMultiple));
                width = Math.max(width,
                        ((layout.getOutline(trans).getBounds().getWidth() / colspan) / defaultCharWidth)
                                + cell.getCellStyle().getIndention());
            } else {
                width = Math.max(width, ((layout.getBounds().getWidth() / colspan) / defaultCharWidth)
                        + cell.getCellStyle().getIndention());
            }
        }
    }
    return width;
}

From source file:tufts.vue.LWComponent.java

/**
 * Transform the given AffineTransform down from our parent to us, the child.
 *//*from www  .ja v  a  2  s.  c o m*/
protected AffineTransform transformDownA(final AffineTransform a) {
    if (mTemporaryTransform != null) {
        a.concatenate(mTemporaryTransform);
    } else {
        a.translate(this.x, this.y);
        if (this.scale != 1)
            a.scale(this.scale, this.scale);
    }

    return a;
}