TexturePaintContext(ColorModel cm, AffineTransform xform, int bWidth, int bHeight, int maxw) { this.colorModel = getInternedColorModel(cm); this.bWidth = bWidth; this.bHeight = bHeight; this.maxWidth = maxw; try { xform = xform.createInverse(); } catch (NoninvertibleTransformException e) { xform.setToScale(0, 0); } this.incXAcross = mod(xform.getScaleX(), bWidth); this.incYAcross = mod(xform.getShearY(), bHeight); this.incXDown = mod(xform.getShearX(), bWidth); this.incYDown = mod(xform.getScaleY(), bHeight); this.xOrg = xform.getTranslateX(); this.yOrg = xform.getTranslateY(); this.colincx = (int) incXAcross; this.colincy = (int) incYAcross; this.colincxerr = fractAsInt(incXAcross); this.colincyerr = fractAsInt(incYAcross); this.rowincx = (int) incXDown; this.rowincy = (int) incYDown; this.rowincxerr = fractAsInt(incXDown); this.rowincyerr = fractAsInt(incYDown); }
public AffineRed(CachableRed src, AffineTransform src2me, RenderingHints hints) { super(); // We _must_ call init... this.src2me = src2me; this.hints = hints; try { me2src = src2me.createInverse(); } catch (NoninvertibleTransformException nite) { me2src = null; } // Calculate my bounds by applying the affine transform to // my input data..codec/ Rectangle srcBounds = src.getBounds(); // srcBounds.grow(-1,-1); Rectangle myBounds; myBounds = src2me.createTransformedShape(srcBounds).getBounds(); // If the output buffer is not premultiplied in certain cases it // fails to properly divide out the Alpha (it always does // the affine on premultiplied data), hence you get ugly // back aliasing effects... ColorModel cm = fixColorModel(src); // fix my sample model so it makes sense given my size. SampleModel sm = fixSampleModel(src, cm, myBounds); Point2D pt = new Point2D.Float(src.getTileGridXOffset(), src.getTileGridYOffset()); pt = src2me.transform(pt, null); // Finish initializing our base class... init(src, myBounds, cm, sm, (int) pt.getX(), (int) pt.getY(), null); }
/** @see Graphics#getClip() */ public Shape getClip() { try { return transform.createInverse().createTransformedShape(clip); } catch (NoninvertibleTransformException e) { return null; } }
/** * Calculate the affine transforms used to convert between world and pixel coordinates. The * calculations here are very basic and assume a cartesian reference system. * * <p>Tne transform is calculated such that {@code envelope} will be centred in the display * * @param envelope the current map extent (world coordinates) * @param paintArea the current map pane extent (screen units) */ private void setTransforms(final Envelope envelope, final Rectangle paintArea) { ReferencedEnvelope refEnv = null; if (envelope != null) { refEnv = new ReferencedEnvelope(envelope); } else { refEnv = worldEnvelope(); // FIXME content.setCoordinateReferenceSystem(DefaultGeographicCRS.WGS84); } java.awt.Rectangle awtPaintArea = Utils.toAwtRectangle(paintArea); double xscale = awtPaintArea.getWidth() / refEnv.getWidth(); double yscale = awtPaintArea.getHeight() / refEnv.getHeight(); double scale = Math.min(xscale, yscale); double xoff = refEnv.getMedian(0) * scale - awtPaintArea.getCenterX(); double yoff = refEnv.getMedian(1) * scale + awtPaintArea.getCenterY(); worldToScreen = new AffineTransform(scale, 0, 0, -scale, -xoff, yoff); try { screenToWorld = worldToScreen.createInverse(); } catch (NoninvertibleTransformException ex) { ex.printStackTrace(); } }
/** * Draw some graphics into an Graphics2D object. * * @param image the image to draw into * @throws NoninvertibleTransformException in transform errors. */ private void draw(Graphics2D gr) throws NoninvertibleTransformException { gr.setPaint(Color.WHITE); gr.fill(new Rectangle(0, 0, tileWidth, tileHeight)); // AffineTransform[[0.318755336305853, 0.0, 420.03106689453125], // [0.0, 0.318755336305853, 245.5029296875]] AffineTransform transform = new AffineTransform( 0.318755336305853, 0.0, 0.0, 0.318755336305853, 420.03106689453125, 245.5029296875); gr.setTransform(transform); Shape s = new Rectangle(0, 0, 96, 83); // create an enbedded graphics Graphics2D grr = (Graphics2D) gr.create(); // AffineTransform[[1.0, 0.0, -343.9285583496093], // [0.0, 1.0, -502.5158386230469]] grr.clip(s.getBounds()); transform = new AffineTransform(1.0, 0.0, 0.0, 1.0, -343.9285583496093, -502.5158386230469); grr.transform(transform); AffineTransform t = transform.createInverse(); s = t.createTransformedShape(s); assertTrue(s.getBounds().intersects(grr.getClip().getBounds2D())); grr.setPaint(Color.BLUE); grr.draw(s); grr.dispose(); gr.dispose(); }
/** * Constructor creates an instance to be used for fill operations. * * @param shading the shading type to be used * @param colorModel the color model to be used * @param xform transformation for user to device space * @param matrix the pattern matrix concatenated with that of the parent content stream * @param deviceBounds the bounds of the area to paint, in device units * @throws IOException if there is an error getting the color space or doing color conversion. */ public AxialShadingContext( PDShadingType2 shading, ColorModel colorModel, AffineTransform xform, Matrix matrix, Rectangle deviceBounds) throws IOException { super(shading, colorModel, xform, matrix); this.axialShadingType = shading; coords = shading.getCoords().toFloatArray(); // domain values if (shading.getDomain() != null) { domain = shading.getDomain().toFloatArray(); } else { // set default values domain = new float[] {0, 1}; } // extend values COSArray extendValues = shading.getExtend(); if (shading.getExtend() != null) { extend = new boolean[2]; extend[0] = ((COSBoolean) extendValues.get(0)).getValue(); extend[1] = ((COSBoolean) extendValues.get(1)).getValue(); } else { // set default values extend = new boolean[] {false, false}; } // calculate some constants to be used in getRaster x1x0 = coords[2] - coords[0]; y1y0 = coords[3] - coords[1]; d1d0 = domain[1] - domain[0]; denom = Math.pow(x1x0, 2) + Math.pow(y1y0, 2); try { // get inverse transform to be independent of current user / device space // when handling actual pixels in getRaster() rat = matrix.createAffineTransform().createInverse(); rat.concatenate(xform.createInverse()); } catch (NoninvertibleTransformException ex) { LOG.error(ex, ex); } // shading space -> device space AffineTransform shadingToDevice = (AffineTransform) xform.clone(); shadingToDevice.concatenate(matrix.createAffineTransform()); // worst case for the number of steps is opposite diagonal corners, so use that double dist = Math.sqrt( Math.pow(deviceBounds.getMaxX() - deviceBounds.getMinX(), 2) + Math.pow(deviceBounds.getMaxY() - deviceBounds.getMinY(), 2)); factor = (int) Math.ceil(dist); // build the color table for the given number of steps colorTable = calcColorTable(); }
public Frame(Point2D point, Vector2D vec1, Vector2D vec2) throws NoninvertibleTransformException { toStd_ = new AffineTransform( vec1.getX(), vec1.getY(), vec2.getX(), vec2.getY(), point.getX(), point.getY()); fromStd_ = toStd_.createInverse(); origin_ = (Point2D) point.clone(); xAxis_ = new Vector2D(vec1); yAxis_ = new Vector2D(vec2); }
/** * Performs a translation using the "Resample" operation. * * @param grid the {@link GridCoverage2D} to apply the translation on. * @throws NoninvertibleTransformException If a "grid to CRS" transform is not invertible. */ private void doTranslation(GridCoverage2D grid) throws NoninvertibleTransformException { final int transX = -253; final int transY = -456; final double scaleX = 0.04; final double scaleY = -0.04; final ParameterBlock block = new ParameterBlock() .addSource(grid.getRenderedImage()) .add((float) transX) .add((float) transY); RenderedImage image = JAI.create("Translate", block); assertEquals("Incorrect X translation", transX, image.getMinX()); assertEquals("Incorrect Y translation", transY, image.getMinY()); /* * Create a grid coverage from the translated image but with the same envelope. * Consequently, the 'gridToCoordinateSystem' should be translated by the same * amount, with the opposite sign. */ AffineTransform expected = getAffineTransform(grid); assertNotNull(expected); expected = new AffineTransform(expected); // Get a mutable instance. final GridCoverageFactory factory = CoverageFactoryFinder.getGridCoverageFactory(null); grid = factory.create( "Translated", image, grid.getEnvelope(), grid.getSampleDimensions(), new GridCoverage2D[] {grid}, grid.getProperties()); expected.translate(-transX, -transY); assertTransformEquals(expected, getAffineTransform(grid)); /* * Apply the "Resample" operation with a specific 'gridToCoordinateSystem' transform. * The envelope is left unchanged. The "Resample" operation should compute automatically * new image bounds. */ final AffineTransform at = AffineTransform.getScaleInstance(scaleX, scaleY); final MathTransform tr = ProjectiveTransform.create(at); // account for the half pixel correction between the two spaces since we are talking raster here // but the resample will talk model! final MathTransform correctedTransform = PixelTranslation.translate(tr, PixelInCell.CELL_CORNER, PixelInCell.CELL_CENTER); final GridGeometry2D geometry = new GridGeometry2D(null, correctedTransform, null); final GridCoverage2D newGrid = (GridCoverage2D) Operations.DEFAULT.resample(grid, grid.getCoordinateReferenceSystem(), geometry, null); assertEquals(correctedTransform, getAffineTransform(newGrid)); image = newGrid.getRenderedImage(); expected.preConcatenate(at.createInverse()); final Point point = new Point(transX, transY); assertSame(point, expected.transform(point, point)); // Round toward neareast integer }
public Frame() { toStd_ = new AffineTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0); try { fromStd_ = toStd_.createInverse(); } catch (NoninvertibleTransformException ntex) { throw new IllegalStateException(); } origin_ = new Point2D.Double(0.0, 0.0); xAxis_ = new Vector2D(1.0, 0.0); yAxis_ = new Vector2D(0.0, 1.0); }
/** @throws RuntimeException */ private void calculateAffineTransform() { if (extent == null) { return; } else if (image == null || getWidth() == 0 || getHeight() == 0) { return; } if (adjustExtent) { double escalaX = getWidth() / extent.getWidth(); double escalaY = getHeight() / extent.getHeight(); double xCenter = extent.getMinX() + extent.getWidth() / 2.0; double yCenter = extent.getMinY() + extent.getHeight() / 2.0; adjustedExtent = new Envelope(); double scale; if (escalaX < escalaY) { scale = escalaX; double newHeight = getHeight() / scale; double newX = xCenter - (extent.getWidth() / 2.0); double newY = yCenter - (newHeight / 2.0); adjustedExtent = new Envelope(newX, newX + extent.getWidth(), newY, newY + newHeight); } else { scale = escalaY; double newWidth = getWidth() / scale; double newX = xCenter - (newWidth / 2.0); double newY = yCenter - (extent.getHeight() / 2.0); adjustedExtent = new Envelope(newX, newX + newWidth, newY, newY + extent.getHeight()); } trans.setToIdentity(); trans.concatenate(AffineTransform.getScaleInstance(scale, -scale)); trans.concatenate( AffineTransform.getTranslateInstance( -adjustedExtent.getMinX(), -adjustedExtent.getMinY() - adjustedExtent.getHeight())); } else { adjustedExtent = new Envelope(extent); trans.setToIdentity(); double scaleX = getWidth() / extent.getWidth(); double scaleY = getHeight() / extent.getHeight(); /** Map Y axis grows downward but CRS grows upward => -1 */ trans.concatenate(AffineTransform.getScaleInstance(scaleX, -scaleY)); trans.concatenate( AffineTransform.getTranslateInstance( -extent.getMinX(), -extent.getMinY() - extent.getHeight())); } try { transInv = trans.createInverse(); } catch (NoninvertibleTransformException ex) { transInv = null; throw new RuntimeException(ex); } }
/** * Clears any existing transformation and sets the a new one. The default implementation calls * writeTransform using the inverted affine transform to calculate it. s * * * @param transform to be written */ protected void writeSetTransform(AffineTransform transform) throws IOException { try { AffineTransform deltaTransform = new AffineTransform(transform); deltaTransform.concatenate(oldTransform.createInverse()); writeTransform(deltaTransform); } catch (NoninvertibleTransformException e) { // ignored... System.err.println( "Warning: (ignored) Could not invert matrix: " //$NON-NLS-1$ + oldTransform); } }
public Frame(Point2D origin, Point2D ptX, Point2D ptY) throws NoninvertibleTransformException { toStd_ = new AffineTransform( ptX.getX() - origin.getX(), ptX.getY() - origin.getY(), ptY.getX() - origin.getX(), ptY.getY() - origin.getY(), origin.getX(), origin.getY()); fromStd_ = toStd_.createInverse(); origin_ = (Point2D) origin.clone(); xAxis_ = new Vector2D(origin, ptX).normalized(); yAxis_ = new Vector2D(origin, ptY).normalized(); }
/** * Constructs a raster reference with given resolutions, origin and rotations. The origin maps to * the pixel location given by location. * * @param location of the origin on the upper left pixel. * @param resolutionX the resolution of one pixel on the x axis in the raster * @param resolutionY the resolution of one pixel on the y axis in the raster * @param rotationX rotation about x-axis * @param rotationY rotation about y-axis * @param origin0 ordinate of the origin of the first axis defined in the world crs * @param origin1 ordinate of the origin of the second axis defined in the world crs * @param crs in which the origin is defined. */ public RasterGeoReference( OriginLocation location, double resolutionX, double resolutionY, double rotationX, double rotationY, double origin0, double origin1, ICRS crs) { this.crs = crs; if (crs != null) { transformer = new GeometryTransformer(crs); try { eastingAxis = crs.getEasting(); } catch (ReferenceResolvingException e) { transformer = null; LOG.debug("CRS could not be resolved: {}", e.getLocalizedMessage()); } } else { transformer = null; } // define a delta to which calculations will be correct. It is dependent on the highest // resolution. (smallest // value). delta = Math.min(Math.abs(resolutionX), Math.abs(resolutionY)) * 1E-6; this.resX = resolutionX; this.resY = resolutionY; this.rotX = rotationX; this.rotY = rotationY; transform = new AffineTransform( cos(rotationX) * resolutionX, sin(rotationY), -sin(rotationX), cos(rotationY) * resolutionY, origin0, origin1); try { invTransform = transform.createInverse(); } catch (NoninvertibleTransformException e) { LOG.debug("No inverse transform available, this means the supplies values are not valid.", e); throw new IllegalArgumentException( "Could not create Raster Geo reference, the given values do not specify an affine transform: " + e.getLocalizedMessage()); } this.location = location; }
public void undo() throws CannotUndoException { super.undo(); JEnvironment env = viewer.getEnvironment(); AffineTransform inv = null; try { inv = af.createInverse(); } catch (NoninvertibleTransformException e) { return; } env.addClip(target.getBounds()); for (int i = 0; i < segments.size(); i++) { segments.get(i).transform(inv); } target.updatePath(); env.addClip(target.getBounds()); }
/** Renders the GVT tree. */ protected void renderGVTTree() { Rectangle visRect = getRenderRect(); if (gvtRoot == null || visRect.width <= 0 || visRect.height <= 0) { return; } // Renderer setup. if (renderer == null || renderer.getTree() != gvtRoot) { renderer = createImageRenderer(); renderer.setTree(gvtRoot); } // Area of interest computation. AffineTransform inv; try { inv = renderingTransform.createInverse(); } catch (NoninvertibleTransformException e) { throw new IllegalStateException("NoninvertibleTransformEx:" + e.getMessage()); } Shape s = inv.createTransformedShape(visRect); // Rendering thread setup. gvtTreeRenderer = new GVTTreeRenderer( renderer, renderingTransform, doubleBufferedRendering, s, visRect.width, visRect.height); gvtTreeRenderer.setPriority(Thread.MIN_PRIORITY); Iterator it = gvtTreeRendererListeners.iterator(); while (it.hasNext()) { gvtTreeRenderer.addGVTTreeRendererListener((GVTTreeRendererListener) it.next()); } // Disable the dispatch during the rendering // to avoid concurrent access to the GVT tree. if (eventDispatcher != null) { eventDispatcher.setEventDispatchEnabled(false); } gvtTreeRenderer.start(); }
public void vec2FieldMagnitude(Field field, AffineTransform ftoi) { AffineTransform itof = null; try { itof = ftoi.createInverse(); } catch (NoninvertibleTransformException niv) { TDebug.println(0, "NoninvertibleTransformException: " + niv); } Vector3d v = new Vector3d(); Point2D.Double p = new Point2D.Double(); for (int j = 0, k = 0; j < height; ++j) for (int i = 0; i < width; ++i, ++k) { p.x = i; p.y = j; itof.transform(p, p); v = field.get(p.x, p.y, 0.0); f[k] = (float) Math.sqrt(v.x * v.x + v.y * v.y); } }
/** * Función de pintado del canvas. Pintamos un marco a la imagen para saber donde la movemos. * * <p>Para dibujar el marco alrededor del raster hacemos lo mismo que para pintar el raster * rotado. En realidad dibujamos un cuadrado y luego le aplicamos las transformaciones necesarias * para que se vea con la misma forma del raster al que representa. */ public void paintComponent(Graphics g) { if (isMoveable && lyr != null && ptoFin != null && ptoIni != null) { try { ViewPort vp = grBehavior.getMapControl().getMapContext().getViewPort(); AffineTransform at = (AffineTransform) lyr.getAffineTransform().clone(); at.preConcatenate(vp.getAffineTransform()); Extent ext = lyr.getFullRasterExtent(); Point2D pt = new Point2D.Double(ext.getULX(), ext.getULY()); vp.getAffineTransform().transform(pt, pt); at.inverseTransform(pt, pt); Point2D size = new Point2D.Double(ext.getLRX(), ext.getLRY()); vp.getAffineTransform().transform(size, size); at.inverseTransform(size, size); double distX = ptoFin.getX() - ptoIni.getX(); double distY = ptoFin.getY() - ptoIni.getY(); Point2D d = new Point2D.Double(ext.getULX() + distX, ext.getULY() + distY); vp.getAffineTransform().transform(d, d); at.inverseTransform(d, d); // Giramos el graphics se dibuja y se vuelve a dejar como estaba ((Graphics2D) g).transform(at); g.setColor(rectangleColor); AlphaComposite alpha = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f); ((Graphics2D) g).setComposite(alpha); g.fillRect( (int) pt.getX() + (int) d.getX(), (int) pt.getY() + (int) d.getY(), (int) size.getX(), (int) size.getY()); ((Graphics2D) g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f)); g.drawRect( (int) pt.getX() + (int) d.getX(), (int) pt.getY() + (int) d.getY(), (int) size.getX(), (int) size.getY()); ((Graphics2D) g).transform(at.createInverse()); } catch (NoninvertibleTransformException e1) { RasterToolsUtil.messageBoxError("error_transformacion1", this, e1); } } }
/** * Derives the "magic" transform that can transform source points to destination points. * * @param srcPoints Three points representing the source parallelogram. * @param destPoints Three points representing the destination parallelogram. * <p>Matrix is represent [m00 m01 m02] [m10 m11 m12] [ 0 0 1 ] * @return A transform as described above. */ public static AffineTransform deriveTransform(Point2D[] srcPoints, Point2D[] destPoints) throws NoninvertibleTransformException { if ((srcPoints == null) || (srcPoints.length != 3)) { throw new IllegalArgumentException("Source points must contain three points!"); } else if ((destPoints == null) || (destPoints.length != 3)) { throw new IllegalArgumentException("Destination points must contain three points!"); } AffineTransform returnTransform = null; // System.out.println(srcPoints[0]+","+srcPoints[1]+","+srcPoints[2]); final double m00 = srcPoints[1].getX() - srcPoints[0].getX(); final double m10 = srcPoints[1].getY() - srcPoints[0].getY(); final double m01 = srcPoints[2].getX() - srcPoints[0].getX(); final double m11 = srcPoints[2].getY() - srcPoints[0].getY(); final double m02 = srcPoints[0].getX(); final double m12 = srcPoints[0].getY(); final double n00 = destPoints[1].getX() - destPoints[0].getX(); final double n10 = destPoints[1].getY() - destPoints[0].getY(); final double n01 = destPoints[2].getX() - destPoints[0].getX(); final double n11 = destPoints[2].getY() - destPoints[0].getY(); final double n02 = destPoints[0].getX(); final double n12 = destPoints[0].getY(); // Build the transform based on the source points. final AffineTransform srcTransform = new AffineTransform(new double[] {m00, m10, m01, m11, m02, m12}); // System.out.println("src Tran "+srcTransform); final AffineTransform destTransform = new AffineTransform(new double[] {n00, n10, n01, n11, n02, n12}); // System.out.println("destTran "+destTransform); try { returnTransform = srcTransform.createInverse(); returnTransform.preConcatenate(destTransform); } catch (NoninvertibleTransformException e) { NaviLogger.logger.severe(e.getMessage()); } // System.out.println("retTran "+returnTransform); return returnTransform; }
public void vec2FieldZero(Field field, AffineTransform ftoi) { AffineTransform itof = null; try { itof = ftoi.createInverse(); } catch (NoninvertibleTransformException niv) { TDebug.println(0, "NoninvertibleTransformException: " + niv); } Vector3d v = new Vector3d(); Point2D.Double p = new Point2D.Double(); for (int j = 0, k = 0; j < height; ++j) for (int i = 0; i < width; ++i, ++k) { p.x = i; p.y = j; itof.transform(p, p); v = field.get(p.x, p.y, 0.0); if ((v.x == 0.0) && (v.y == 0.0)) f[k] = 1.0f; else f[k] = 0.0f; } }
public void setRenderingTransform(AffineTransform at, boolean performRedraw) { renderingTransform = new AffineTransform(at); suspendInteractions = true; if (eventDispatcher != null) { try { eventDispatcher.setBaseTransform(renderingTransform.createInverse()); } catch (NoninvertibleTransformException e) { handleException(e); } } if (jgvtListeners != null) { Iterator iter = jgvtListeners.iterator(); ComponentEvent ce = new ComponentEvent(this, JGVTComponentListener.COMPONENT_TRANSFORM_CHANGED); while (iter.hasNext()) { JGVTComponentListener l = (JGVTComponentListener) iter.next(); l.componentTransformChanged(ce); } } if (performRedraw) scheduleGVTRendering(); }
/** * Utility method for transforming a geometry ROI into the raster space, using the provided affine * transformation. * * @param roi a {@link Geometry} in model space. * @param mt2d an {@link AffineTransform} that maps from raster to model space. This is already * referred to the pixel corner. * @return a {@link ROI} suitable for using with JAI. * @throws ProcessException in case there are problems with ivnerting the provided {@link * AffineTransform}. Very unlikely to happen. */ public static ROI prepareROI(Geometry roi, AffineTransform mt2d) throws ProcessException { // transform the geometry to raster space so that we can use it as a ROI source Geometry rasterSpaceGeometry; try { rasterSpaceGeometry = JTS.transform(roi, new AffineTransform2D(mt2d.createInverse())); } catch (MismatchedDimensionException e) { throw new ProcessException(e); } catch (TransformException e) { throw new ProcessException(e); } catch (NoninvertibleTransformException e) { throw new ProcessException(e); } // System.out.println(rasterSpaceGeometry); // System.out.println(rasterSpaceGeometry.getEnvelopeInternal()); // simplify the geometry so that it's as precise as the coverage, excess coordinates // just make it slower to determine the point in polygon relationship Geometry simplifiedGeometry = DouglasPeuckerSimplifier.simplify(rasterSpaceGeometry, 1); // build a shape using a fast point in polygon wrapper return new ROIGeometry(simplifiedGeometry); }
/** * Applies the band select operation to a grid coverage. * * @param cropEnvelope the target envelope; always not null * @param cropROI the target ROI shape; nullable * @param roiTolerance; as read from op's params * @param sourceCoverage is the source {@link GridCoverage2D} that we want to crop. * @param hints A set of rendering hints, or {@code null} if none. * @param sourceGridToWorldTransform is the 2d grid-to-world transform for the source coverage. * @return The result as a grid coverage. */ private static GridCoverage2D buildResult( final GeneralEnvelope cropEnvelope, final Geometry cropROI, final double roiTolerance, final boolean forceMosaic, final Hints hints, final GridCoverage2D sourceCoverage, final AffineTransform sourceGridToWorldTransform) { // // Getting the source coverage and its child geolocation objects // final RenderedImage sourceImage = sourceCoverage.getRenderedImage(); final GridGeometry2D sourceGridGeometry = ((GridGeometry2D) sourceCoverage.getGridGeometry()); final GridEnvelope2D sourceGridRange = sourceGridGeometry.getGridRange2D(); // // Now we try to understand if we have a simple scale and translate or a // more elaborated grid-to-world transformation n which case a simple // crop could not be enough, but we may need a more elaborated chain of // operation in order to do a good job. As an instance if we // have a rotation which is not multiple of PI/2 we have to use // the mosaic with a ROI // final boolean isSimpleTransform = CoverageUtilities.isSimpleGridToWorldTransform(sourceGridToWorldTransform, EPS); // Do we need to explode the Palette to RGB(A)? // int actionTaken = 0; // // // // Layout // // // final RenderingHints targetHints = new RenderingHints(null); if (hints != null) targetHints.add(hints); final ImageLayout layout = initLayout(sourceImage, targetHints); targetHints.put(JAI.KEY_IMAGE_LAYOUT, layout); // // prepare the processor to use for this operation // final JAI processor = OperationJAI.getJAI(targetHints); final boolean useProvidedProcessor = !processor.equals(JAI.getDefaultInstance()); try { if (cropROI != null) { // replace the cropEnvelope with the envelope of the intersection // of the ROI and the cropEnvelope. // Remember that envelope(intersection(roi,cropEnvelope)) != intersection(cropEnvelope, // envelope(roi)) final Polygon modelSpaceROI = FeatureUtilities.getPolygon(cropEnvelope, GFACTORY); Geometry intersection = IntersectUtils.intersection(cropROI, modelSpaceROI); Envelope2D e2d = JTS.getEnvelope2D( intersection.getEnvelopeInternal(), cropEnvelope.getCoordinateReferenceSystem()); GeneralEnvelope ge = new GeneralEnvelope((org.opengis.geometry.Envelope) e2d); cropEnvelope.setEnvelope(ge); } // // // // Build the new range by keeping into // account translation of grid geometry constructor for respecting // OGC PIXEL-IS-CENTER ImageDatum assumption. // // // final AffineTransform sourceWorldToGridTransform = sourceGridToWorldTransform.createInverse(); // // // // finalRasterArea will hold the smallest rectangular integer raster area that contains the // floating point raster // area which we obtain when applying the world-to-grid transform to the cropEnvelope. Note // that we need to intersect // such an area with the area covered by the source coverage in order to be sure we do not try // to crop outside the // bounds of the source raster. // // // final Rectangle2D finalRasterAreaDouble = XAffineTransform.transform( sourceWorldToGridTransform, cropEnvelope.toRectangle2D(), null); final Rectangle finalRasterArea = finalRasterAreaDouble.getBounds(); // intersection with the original range in order to not try to crop outside the image bounds Rectangle.intersect(finalRasterArea, sourceGridRange, finalRasterArea); if (finalRasterArea.isEmpty()) throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP)); // // // // It is worth to point out that doing a crop the G2W transform // should not change while the envelope might change as // a consequence of the rounding of the underlying image datum // which uses integer factors or in case the G2W is very // complex. Note that we will always strive to // conserve the original grid-to-world transform. // // // // we do not have to crop in this case (should not really happen at // this time) if (finalRasterArea.equals(sourceGridRange) && isSimpleTransform && cropROI == null) return sourceCoverage; // // // // if I get here I have something to crop // using the world-to-grid transform for going from envelope to the // new grid range. // // // final double minX = finalRasterArea.getMinX(); final double minY = finalRasterArea.getMinY(); final double width = finalRasterArea.getWidth(); final double height = finalRasterArea.getHeight(); // // // // Check if we need to use mosaic or crop // // // final PlanarImage croppedImage; final ParameterBlock pbj = new ParameterBlock(); pbj.addSource(sourceImage); java.awt.Polygon rasterSpaceROI = null; String operatioName = null; if (!isSimpleTransform || cropROI != null) { // ///////////////////////////////////////////////////////////////////// // // We don't have a simple scale and translate transform, JAI // crop MAY NOT suffice. Let's decide whether or not we'll use // the Mosaic. // // ///////////////////////////////////////////////////////////////////// Polygon modelSpaceROI = FeatureUtilities.getPolygon(cropEnvelope, GFACTORY); // // // // Now convert this polygon back into a shape for the source // raster space. // // // final List<Point2D> points = new ArrayList<Point2D>(5); rasterSpaceROI = FeatureUtilities.convertPolygonToPointArray( modelSpaceROI, ProjectiveTransform.create(sourceWorldToGridTransform), points); if (rasterSpaceROI == null || rasterSpaceROI.getBounds().isEmpty()) if (finalRasterArea.isEmpty()) throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP)); final boolean doMosaic = forceMosaic ? true : decideJAIOperation(roiTolerance, rasterSpaceROI.getBounds2D(), points); if (doMosaic || cropROI != null) { // prepare the params for the mosaic final ROI[] roiarr; try { if (cropROI != null) { final LiteShape2 cropRoiLS2 = new LiteShape2( cropROI, ProjectiveTransform.create(sourceWorldToGridTransform), null, false); ROI cropRS = new ROIShape(cropRoiLS2); Rectangle2D rt = cropRoiLS2.getBounds2D(); if (!hasIntegerBounds(rt)) { // Approximate Geometry Geometry geo = (Geometry) cropRoiLS2.getGeometry().clone(); transformGeometry(geo); cropRS = new ROIShape(new LiteShape2(geo, null, null, false)); } roiarr = new ROI[] {cropRS}; } else { final ROIShape roi = new ROIShape(rasterSpaceROI); roiarr = new ROI[] {roi}; } } catch (FactoryException ex) { throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP), ex); } pbj.add(MosaicDescriptor.MOSAIC_TYPE_OVERLAY); pbj.add(null); pbj.add(roiarr); pbj.add(null); pbj.add(CoverageUtilities.getBackgroundValues(sourceCoverage)); // prepare the final layout final Rectangle bounds = rasterSpaceROI.getBounds2D().getBounds(); Rectangle.intersect(bounds, sourceGridRange, bounds); if (bounds.isEmpty()) throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP)); // we do not have to crop in this case (should not really happen at // this time) if (!doMosaic && bounds.getBounds().equals(sourceGridRange) && isSimpleTransform) return sourceCoverage; // nice trick, we use the layout to do the actual crop final Rectangle boundsInt = bounds.getBounds(); layout.setMinX(boundsInt.x); layout.setWidth(boundsInt.width); layout.setMinY(boundsInt.y); layout.setHeight(boundsInt.height); operatioName = "Mosaic"; } } // do we still have to set the operation name? If so that means we have to go for crop. if (operatioName == null) { // executing the crop pbj.add((float) minX); pbj.add((float) minY); pbj.add((float) width); pbj.add((float) height); operatioName = "GTCrop"; } // // // // Apply operation // // // if (!useProvidedProcessor) { croppedImage = JAI.create(operatioName, pbj, targetHints); } else { croppedImage = processor.createNS(operatioName, pbj, targetHints); } // conserve the input grid to world transformation Map sourceProperties = sourceCoverage.getProperties(); Map properties = null; if (sourceProperties != null && !sourceProperties.isEmpty()) { properties = new HashMap(sourceProperties); } if (rasterSpaceROI != null) { if (properties != null) { properties.put("GC_ROI", rasterSpaceROI); } else { properties = Collections.singletonMap("GC_ROI", rasterSpaceROI); } } return new GridCoverageFactory(hints) .create( sourceCoverage.getName(), croppedImage, new GridGeometry2D( new GridEnvelope2D(croppedImage.getBounds()), sourceGridGeometry.getGridToCRS2D(PixelOrientation.CENTER), sourceCoverage.getCoordinateReferenceSystem()), (GridSampleDimension[]) (actionTaken == 1 ? null : sourceCoverage.getSampleDimensions().clone()), new GridCoverage[] {sourceCoverage}, properties); } catch (TransformException e) { throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP), e); } catch (NoninvertibleTransformException e) { throw new CannotCropException(Errors.format(ErrorKeys.CANT_CROP), e); } }
private void setPaint(boolean invert, double xoffset, double yoffset, boolean fill) { if (paint instanceof Color) { Color color = (Color) paint; int alpha = color.getAlpha(); if (fill) { if (alpha != currentFillGState) { currentFillGState = alpha; PdfGState gs = fillGState[alpha]; if (gs == null) { gs = new PdfGState(); gs.setFillOpacity(alpha / 255f); fillGState[alpha] = gs; } cb.setGState(gs); } cb.setColorFill(color); } else { if (alpha != currentStrokeGState) { currentStrokeGState = alpha; PdfGState gs = strokeGState[alpha]; if (gs == null) { gs = new PdfGState(); gs.setStrokeOpacity(alpha / 255f); strokeGState[alpha] = gs; } cb.setGState(gs); } cb.setColorStroke(color); } } else if (paint instanceof GradientPaint) { GradientPaint gp = (GradientPaint) paint; Point2D p1 = gp.getPoint1(); transform.transform(p1, p1); Point2D p2 = gp.getPoint2(); transform.transform(p2, p2); Color c1 = gp.getColor1(); Color c2 = gp.getColor2(); PdfShading shading = PdfShading.simpleAxial( cb.getPdfWriter(), (float) p1.getX(), normalizeY((float) p1.getY()), (float) p2.getX(), normalizeY((float) p2.getY()), c1, c2); PdfShadingPattern pat = new PdfShadingPattern(shading); if (fill) cb.setShadingFill(pat); else cb.setShadingStroke(pat); } else if (paint instanceof TexturePaint) { try { TexturePaint tp = (TexturePaint) paint; BufferedImage img = tp.getImage(); Rectangle2D rect = tp.getAnchorRect(); com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(img, null); PdfPatternPainter pattern = cb.createPattern(image.getWidth(), image.getHeight()); AffineTransform inverse = this.normalizeMatrix(); inverse.translate(rect.getX(), rect.getY()); inverse.scale(rect.getWidth() / image.getWidth(), -rect.getHeight() / image.getHeight()); double[] mx = new double[6]; inverse.getMatrix(mx); pattern.setPatternMatrix( (float) mx[0], (float) mx[1], (float) mx[2], (float) mx[3], (float) mx[4], (float) mx[5]); image.setAbsolutePosition(0, 0); pattern.addImage(image); if (fill) cb.setPatternFill(pattern); else cb.setPatternStroke(pattern); } catch (Exception ex) { if (fill) cb.setColorFill(Color.gray); else cb.setColorStroke(Color.gray); } } else { try { BufferedImage img = null; int type = BufferedImage.TYPE_4BYTE_ABGR; if (paint.getTransparency() == Transparency.OPAQUE) { type = BufferedImage.TYPE_3BYTE_BGR; } img = new BufferedImage((int) width, (int) height, type); Graphics2D g = (Graphics2D) img.getGraphics(); g.transform(transform); AffineTransform inv = transform.createInverse(); Shape fillRect = new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight()); fillRect = inv.createTransformedShape(fillRect); g.setPaint(paint); g.fill(fillRect); if (invert) { AffineTransform tx = new AffineTransform(); tx.scale(1, -1); tx.translate(-xoffset, -yoffset); g.drawImage(img, tx, null); } g.dispose(); g = null; com.lowagie.text.Image image = com.lowagie.text.Image.getInstance(img, null); PdfPatternPainter pattern = cb.createPattern(width, height); image.setAbsolutePosition(0, 0); pattern.addImage(image); if (fill) cb.setPatternFill(pattern); else cb.setPatternStroke(pattern); } catch (Exception ex) { if (fill) cb.setColorFill(Color.gray); else cb.setColorStroke(Color.gray); } } }
/** * Slow filter. * * @param src the src. * @param dst the dst. * @return the int. */ private int slowFilter(Raster src, WritableRaster dst) { // TODO: make correct interpolation // TODO: what if there are different data types? Rectangle srcBounds = src.getBounds(); Rectangle dstBounds = dst.getBounds(); Rectangle normDstBounds = new Rectangle(0, 0, dstBounds.width, dstBounds.height); Rectangle bounds = getBounds2D(src).getBounds().intersection(normDstBounds); AffineTransform inv = null; try { inv = at.createInverse(); } catch (NoninvertibleTransformException e) { return -1; } double[] m = new double[6]; inv.getMatrix(m); int minSrcX = srcBounds.x; int minSrcY = srcBounds.y; int maxSrcX = srcBounds.x + srcBounds.width; int maxSrcY = srcBounds.y + srcBounds.height; int minX = bounds.x + dstBounds.x; int minY = bounds.y + dstBounds.y; int maxX = minX + bounds.width; int maxY = minY + bounds.height; int hx = (int) (m[0] * 256); int hy = (int) (m[1] * 256); int vx = (int) (m[2] * 256); int vy = (int) (m[3] * 256); int sx = (int) (m[4] * 256) + hx * bounds.x + vx * bounds.y + (srcBounds.x) * 256; int sy = (int) (m[5] * 256) + hy * bounds.x + vy * bounds.y + (srcBounds.y) * 256; vx -= hx * bounds.width; vy -= hy * bounds.width; if (src.getTransferType() == dst.getTransferType()) { for (int y = minY; y < maxY; y++) { for (int x = minX; x < maxX; x++) { int px = sx >> 8; int py = sy >> 8; if (px >= minSrcX && py >= minSrcY && px < maxSrcX && py < maxSrcY) { Object val = src.getDataElements(px, py, null); dst.setDataElements(x, y, val); } sx += hx; sy += hy; } sx += vx; sy += vy; } } else { float pixel[] = null; for (int y = minY; y < maxY; y++) { for (int x = minX; x < maxX; x++) { int px = sx >> 8; int py = sy >> 8; if (px >= minSrcX && py >= minSrcY && px < maxSrcX && py < maxSrcY) { pixel = src.getPixel(px, py, pixel); dst.setPixel(x, y, pixel); } sx += hx; sy += hy; } sx += vx; sy += vy; } } return 0; }
/** * Stop the generation of any previous page, and draw the new one. * * @param page the PDFPage to draw. */ public void showPage(PDFPage page) { // stop drawing the previous page if (currentPage != null && prevSize != null) { currentPage.stop(prevSize.width, prevSize.height, prevClip); } // set up the new page currentPage = page; if (page == null) { // no page currentImage = null; clip = null; currentXform = null; canvas.repaint(); } else { // Reset highlight highlight = null; boolean resize = false; int newW = Math.round(zoomFactor * page.getWidth()); int newH = Math.round(zoomFactor * page.getHeight()); // setSize(Math.round(zoomFactor*page.getWidth()), Math.round(zoomFactor*page.getHeight())); Point sz = getSize(); if (sz.x != newW || sz.y != newH) { sz.x = newW; sz.y = newH; resize = true; } if (sz.x + sz.y == 0) { // no image to draw. return; } // calculate the clipping rectangle in page space from the // desired clip in screen space. Rectangle2D useClip = clip; if (clip != null && currentXform != null) { useClip = currentXform.createTransformedShape(clip).getBounds2D(); } Dimension pageSize = page.getUnstretchedSize(sz.x, sz.y, useClip); ImageInfo info = new ImageInfo(pageSize.width, pageSize.height, useClip, null); currentImage = new RefImage(pageSize.width, pageSize.height, BufferedImage.TYPE_INT_ARGB); Rectangle rect = new Rectangle(0, 0, pageSize.width, pageSize.height); PDFRenderer r = new PDFRenderer( page, ((BufferedImage) currentImage).createGraphics(), rect, useClip, Color.WHITE); page.renderers.put(info, new WeakReference<PDFRenderer>(r)); // get the new image /*currentImage = page.getImage(pageSize.width, pageSize.height, useClip, this, true, false);*/ // calculate the transform from screen to page space currentXform = page.getInitialTransform(pageSize.width, pageSize.height, useClip); try { currentXform = currentXform.createInverse(); } catch (NoninvertibleTransformException nte) { System.out.println("Error inverting page transform!"); nte.printStackTrace(); } prevClip = useClip; prevSize = pageSize; r.go(true); if (r.getStatus() != Watchable.COMPLETED) return; if (resize) // Resize triggers repaint setSize( Math.round(zoomFactor * page.getWidth()), Math.round(zoomFactor * page.getHeight())); else { EventQueue.invokeLater( new Runnable() { @Override public void run() { // canvas.repaint(); } }); } } }
public void draw(java.awt.Graphics2D g, java.awt.geom.AffineTransform normal2Device) { if ((project == null) || !posWasCalc) return; // use world coordinates for position, but draw in screen coordinates // so that the symbols stay the same size AffineTransform world2Device = g.getTransform(); g.setTransform(normal2Device); // identity transform for screen coords // transform World to Normal coords: // world2Normal = pixelAT-1 * world2Device // cache for pick closest AffineTransform world2Normal; try { world2Normal = normal2Device.createInverse(); world2Normal.concatenate(world2Device); } catch (java.awt.geom.NoninvertibleTransformException e) { System.out.println(" RendSurfObs: NoninvertibleTransformException on " + normal2Device); return; } // we want aliasing; but save previous state to restore at end Object saveHint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING); // g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, // RenderingHints.VALUE_ANTIALIAS_ON); g.setStroke(new java.awt.BasicStroke(1.0f)); /* set up the grid Rectangle2D bbox = (Rectangle2D) g.getClip(); // clipping area in normal coords // clear the grid = "no stations are drawn" stationGrid.clear(); // set the grid size based on typical bounding box stationGrid.setGrid(bbox, typicalBB.getWidth(), typicalBB.getHeight()); // always draw selected if (selected != null) { selected.calcPos( world2Normal); stationGrid.markIfClear( selected.getBB(), selected); selected.draw(g); } */ g.setFont(textFont.getFont()); g.setColor(color); int count = 0; int npts = obsUIlist.size(); GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD, npts); for (int i = 0; i < npts; i++) { ObservationUI s = (ObservationUI) obsUIlist.get(i); s.calcPos(world2Normal); s.draw(g); if (Double.isNaN(s.screenPos.getX())) { System.out.println("screenPos=" + s.screenPos + " world = " + s.worldPos); continue; } if (count == 0) path.moveTo((float) s.screenPos.getX(), (float) s.screenPos.getY()); else path.lineTo((float) s.screenPos.getX(), (float) s.screenPos.getY()); count++; } g.setColor(color); g.draw(path); // draw selected if (selected != null) selected.draw(g); // restore g.setTransform(world2Device); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, saveHint); }
/** * Constructor for superclass. Does some initialization, but leaves most of the heavy-duty math * for calculateGradient(), so the subclass may do some other manipulation beforehand if * necessary. This is not possible if this computation is done in the superclass constructor which * always gets called first. */ public MultipleGradientPaintContext( ColorModel cm, Rectangle deviceBounds, Rectangle2D userBounds, AffineTransform t, RenderingHints hints, float[] fractions, Color[] colors, MultipleGradientPaint.CycleMethodEnum cycleMethod, MultipleGradientPaint.ColorSpaceEnum colorSpace) throws NoninvertibleTransformException { // We have to deal with the cases where the 1st gradient stop is not // equal to 0 and/or the last gradient stop is not equal to 1. // In both cases, create a new point and replicate the previous // extreme point's color. boolean fixFirst = false; boolean fixLast = false; int len = fractions.length; // if the first gradient stop is not equal to zero, fix this condition if (fractions[0] != 0f) { fixFirst = true; len++; } // if the last gradient stop is not equal to one, fix this condition if (fractions[fractions.length - 1] != 1f) { fixLast = true; len++; } for (int i = 0; i < fractions.length - 1; i++) if (fractions[i] == fractions[i + 1]) len--; this.fractions = new float[len]; Color[] loColors = new Color[len - 1]; Color[] hiColors = new Color[len - 1]; normalizedIntervals = new float[len - 1]; gradientUnderflow = colors[0].getRGB(); gradientOverflow = colors[colors.length - 1].getRGB(); int idx = 0; if (fixFirst) { this.fractions[0] = 0; loColors[0] = colors[0]; hiColors[0] = colors[0]; normalizedIntervals[0] = fractions[0]; idx++; } for (int i = 0; i < fractions.length - 1; i++) { if (fractions[i] == fractions[i + 1]) { // System.out.println("EQ Fracts"); if (!colors[i].equals(colors[i + 1])) { hasDiscontinuity = true; } continue; } this.fractions[idx] = fractions[i]; loColors[idx] = colors[i]; hiColors[idx] = colors[i + 1]; normalizedIntervals[idx] = fractions[i + 1] - fractions[i]; idx++; } this.fractions[idx] = fractions[fractions.length - 1]; if (fixLast) { loColors[idx] = hiColors[idx] = colors[colors.length - 1]; normalizedIntervals[idx] = 1 - fractions[fractions.length - 1]; idx++; this.fractions[idx] = 1; } // The inverse transform is needed to from device to user space. // Get all the components of the inverse transform matrix. AffineTransform tInv = t.createInverse(); double m[] = new double[6]; tInv.getMatrix(m); a00 = (float) m[0]; a10 = (float) m[1]; a01 = (float) m[2]; a11 = (float) m[3]; a02 = (float) m[4]; a12 = (float) m[5]; // copy some flags this.cycleMethod = cycleMethod; this.colorSpace = colorSpace; // PATCH Werner Randelshofer: ColorModel can be null! // Setup an example Model, we may refine it later. if (cm != null && cm.getColorSpace() == lrgbmodel_A.getColorSpace()) dataModel = lrgbmodel_A; else if (cm == null || cm.getColorSpace() == srgbmodel_A.getColorSpace()) dataModel = srgbmodel_A; else throw new IllegalArgumentException("Unsupported ColorSpace for interpolation"); calculateGradientFractions(loColors, hiColors); model = GraphicsUtil.coerceColorModel(dataModel, cm != null && cm.isAlphaPremultiplied()); }
private Point getWorldPoint(Point point) throws NoninvertibleTransformException { AffineTransform invVTM; invVTM = currentAT.createInverse(); Point2D temp = invVTM.transform(point, null); return new java.awt.Point((int) temp.getX(), (int) temp.getY()); }
protected void renderImageXform( SunGraphics2D sg, Image img, AffineTransform tx, int interpType, int sx1, int sy1, int sx2, int sy2, Color bgColor) { Region clip = sg.getCompClip(); SurfaceData dstData = sg.surfaceData; SurfaceData srcData = dstData.getSourceSurfaceData(img, sg.TRANSFORM_GENERIC, sg.imageComp, bgColor); if (srcData == null) { img = getBufferedImage(img); srcData = dstData.getSourceSurfaceData(img, sg.TRANSFORM_GENERIC, sg.imageComp, bgColor); if (srcData == null) { // REMIND: Is this correct? Can this happen? return; } } if (isBgOperation(srcData, bgColor)) { // We cannot perform bg operations during transform so make // an opaque temp image with the appropriate background // and work from there. img = makeBufferedImage(img, bgColor, BufferedImage.TYPE_INT_RGB, sx1, sy1, sx2, sy2); // Temp image has appropriate subimage at 0,0 now. sx2 -= sx1; sy2 -= sy1; sx1 = sy1 = 0; srcData = dstData.getSourceSurfaceData(img, sg.TRANSFORM_GENERIC, sg.imageComp, bgColor); } SurfaceType srcType = srcData.getSurfaceType(); TransformHelper helper = TransformHelper.getFromCache(srcType); if (helper == null) { /* We have no helper for this source image type. * But we know that we do have helpers for both RGB and ARGB, * so convert to one of those types depending on transparency. * ARGB_PRE might be a better choice if the source image has * alpha, but it may cause some recursion here since we only * tend to have converters that convert to ARGB. */ int type = ((srcData.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB); img = makeBufferedImage(img, null, type, sx1, sy1, sx2, sy2); // Temp image has appropriate subimage at 0,0 now. sx2 -= sx1; sy2 -= sy1; sx1 = sy1 = 0; srcData = dstData.getSourceSurfaceData(img, sg.TRANSFORM_GENERIC, sg.imageComp, null); srcType = srcData.getSurfaceType(); helper = TransformHelper.getFromCache(srcType); // assert(helper != null); } AffineTransform itx; try { itx = tx.createInverse(); } catch (NoninvertibleTransformException e) { // Non-invertible transform means no output return; } /* * Find the maximum bounds on the destination that will be * affected by the transformed source. First, transform all * four corners of the source and then min and max the resulting * destination coordinates of the transformed corners. * Note that tx already has the offset to sx1,sy1 accounted * for so we use the box (0, 0, sx2-sx1, sy2-sy1) as the * source coordinates. */ double coords[] = new double[8]; /* corner: UL UR LL LR */ /* index: 0 1 2 3 4 5 6 7 */ /* coord: (0, 0), (w, 0), (0, h), (w, h) */ coords[2] = coords[6] = sx2 - sx1; coords[5] = coords[7] = sy2 - sy1; tx.transform(coords, 0, coords, 0, 4); double ddx1, ddy1, ddx2, ddy2; ddx1 = ddx2 = coords[0]; ddy1 = ddy2 = coords[1]; for (int i = 2; i < coords.length; i += 2) { double d = coords[i]; if (ddx1 > d) ddx1 = d; else if (ddx2 < d) ddx2 = d; d = coords[i + 1]; if (ddy1 > d) ddy1 = d; else if (ddy2 < d) ddy2 = d; } int dx1 = (int) Math.floor(ddx1); int dy1 = (int) Math.floor(ddy1); int dx2 = (int) Math.ceil(ddx2); int dy2 = (int) Math.ceil(ddy2); SurfaceType dstType = dstData.getSurfaceType(); MaskBlit maskblit; Blit blit; if (sg.compositeState <= sg.COMP_ALPHA) { /* NOTE: We either have, or we can make, * a MaskBlit for any alpha composite type */ maskblit = MaskBlit.getFromCache(SurfaceType.IntArgbPre, sg.imageComp, dstType); /* NOTE: We can only use the native TransformHelper * func to go directly to the dest if both the helper * and the MaskBlit are native. * All helpers are native at this point, but some MaskBlit * objects are implemented in Java, so we need to check. */ if (maskblit.getNativePrim() != 0) { // We can render directly. helper.Transform( maskblit, srcData, dstData, sg.composite, clip, itx, interpType, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2, null, 0, 0); return; } blit = null; } else { /* NOTE: We either have, or we can make, * a Blit for any composite type, even Custom */ maskblit = null; blit = Blit.getFromCache(SurfaceType.IntArgbPre, sg.imageComp, dstType); } // We need to transform to a temp image and then copy // just the pieces that are valid data to the dest. BufferedImage tmpimg = new BufferedImage(dx2 - dx1, dy2 - dy1, BufferedImage.TYPE_INT_ARGB); SurfaceData tmpData = SurfaceData.getPrimarySurfaceData(tmpimg); SurfaceType tmpType = tmpData.getSurfaceType(); MaskBlit tmpmaskblit = MaskBlit.getFromCache(SurfaceType.IntArgbPre, CompositeType.SrcNoEa, tmpType); /* * The helper function fills a temporary edges buffer * for us with the bounding coordinates of each scanline * in the following format: * * edges[0, 1] = [top y, bottom y) * edges[2, 3] = [left x, right x) of top row * ... * edges[h*2, h*2+1] = [left x, right x) of bottom row * * all coordinates in the edges array will be relative to dx1, dy1 * * edges thus has to be h*2+2 in length */ int edges[] = new int[(dy2 - dy1) * 2 + 2]; // It is important that edges[0]=edges[1]=0 when we call // Transform in case it must return early and we would // not want to render anything on an error condition. helper.Transform( tmpmaskblit, srcData, tmpData, AlphaComposite.Src, null, itx, interpType, sx1, sy1, sx2, sy2, 0, 0, dx2 - dx1, dy2 - dy1, edges, dx1, dy1); /* * Now copy the results, scanline by scanline, into the dest. * The edges array helps us minimize the work. */ int index = 2; for (int y = edges[0]; y < edges[1]; y++) { int relx1 = edges[index++]; int relx2 = edges[index++]; if (relx1 >= relx2) { continue; } if (maskblit != null) { maskblit.MaskBlit( tmpData, dstData, sg.composite, clip, relx1, y, dx1 + relx1, dy1 + y, relx2 - relx1, 1, null, 0, 0); } else { blit.Blit( tmpData, dstData, sg.composite, clip, relx1, y, dx1 + relx1, dy1 + y, relx2 - relx1, 1); } } }
/* */ protected MultipleGradientPaintContext( MultipleGradientPaint paramMultipleGradientPaint, ColorModel paramColorModel, Rectangle paramRectangle, Rectangle2D paramRectangle2D, AffineTransform paramAffineTransform, RenderingHints paramRenderingHints, float[] paramArrayOfFloat, Color[] paramArrayOfColor, MultipleGradientPaint.CycleMethod paramCycleMethod, MultipleGradientPaint.ColorSpaceType paramColorSpaceType) /* */ { /* 159 */ if (paramRectangle == null) { /* 160 */ throw new NullPointerException("Device bounds cannot be null"); /* */ } /* */ /* 163 */ if (paramRectangle2D == null) { /* 164 */ throw new NullPointerException("User bounds cannot be null"); /* */ } /* */ /* 167 */ if (paramAffineTransform == null) { /* 168 */ throw new NullPointerException("Transform cannot be null"); /* */ } /* */ /* */ AffineTransform localAffineTransform; /* */ try /* */ { /* 177 */ localAffineTransform = paramAffineTransform.createInverse(); /* */ } /* */ catch (NoninvertibleTransformException localNoninvertibleTransformException) /* */ { /* 181 */ localAffineTransform = new AffineTransform(); /* */ } /* 183 */ double[] arrayOfDouble = new double[6]; /* 184 */ localAffineTransform.getMatrix(arrayOfDouble); /* 185 */ this.a00 = ((float) arrayOfDouble[0]); /* 186 */ this.a10 = ((float) arrayOfDouble[1]); /* 187 */ this.a01 = ((float) arrayOfDouble[2]); /* 188 */ this.a11 = ((float) arrayOfDouble[3]); /* 189 */ this.a02 = ((float) arrayOfDouble[4]); /* 190 */ this.a12 = ((float) arrayOfDouble[5]); /* */ /* 193 */ this.cycleMethod = paramCycleMethod; /* 194 */ this.colorSpace = paramColorSpaceType; /* */ /* 197 */ this.fractions = paramArrayOfFloat; /* */ /* 202 */ this.gradient = (paramMultipleGradientPaint.gradient != null ? (int[]) paramMultipleGradientPaint.gradient.get() : null); /* */ /* 204 */ this.gradients = (paramMultipleGradientPaint.gradients != null ? (int[][]) paramMultipleGradientPaint.gradients.get() : (int[][]) null); /* */ /* 207 */ if ((this.gradient == null) && (this.gradients == null)) /* */ { /* 209 */ calculateLookupData(paramArrayOfColor); /* */ /* 213 */ paramMultipleGradientPaint.model = this.model; /* 214 */ paramMultipleGradientPaint.normalizedIntervals = this.normalizedIntervals; /* 215 */ paramMultipleGradientPaint.isSimpleLookup = this.isSimpleLookup; /* 216 */ if (this.isSimpleLookup) /* */ { /* 218 */ paramMultipleGradientPaint.fastGradientArraySize = this.fastGradientArraySize; /* 219 */ paramMultipleGradientPaint.gradient = new SoftReference(this.gradient); /* */ } /* */ else { /* 222 */ paramMultipleGradientPaint.gradients = new SoftReference(this.gradients); /* */ } /* */ } /* */ else { /* 226 */ this.model = paramMultipleGradientPaint.model; /* 227 */ this.normalizedIntervals = paramMultipleGradientPaint.normalizedIntervals; /* 228 */ this.isSimpleLookup = paramMultipleGradientPaint.isSimpleLookup; /* 229 */ this.fastGradientArraySize = paramMultipleGradientPaint.fastGradientArraySize; /* */ } /* */ }