diff --git a/msi.gama.core/src/msi/gama/outputs/display/AWTDisplayGraphics.java b/msi.gama.core/src/msi/gama/outputs/display/AWTDisplayGraphics.java index 5f9e738345..0a716c4904 100644 --- a/msi.gama.core/src/msi/gama/outputs/display/AWTDisplayGraphics.java +++ b/msi.gama.core/src/msi/gama/outputs/display/AWTDisplayGraphics.java @@ -41,11 +41,7 @@ import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.ImageObserver; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; import org.locationtech.jts.awt.PointTransformation; import org.locationtech.jts.awt.ShapeWriter; @@ -55,10 +51,6 @@ import org.locationtech.jts.geom.Lineal; import org.locationtech.jts.geom.Puntal; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; - import msi.gama.common.geometry.AxisAngle; import msi.gama.common.geometry.GeometryUtils; import msi.gama.common.interfaces.IAsset; @@ -246,37 +238,22 @@ public Rectangle2D drawImage(final BufferedImage img, final DrawingAttributes at curY = yFromModelUnitsToPixels(attributes.getLocation().getY()); } imageTransform.translate(curX, curY); - double curWidth, curHeight; + int curWidth, curHeight; if (attributes.getSize() == null) { curWidth = getLayerWidth(); curHeight = getLayerHeight(); } else { - curWidth = wFromModelUnitsToPixels(attributes.getSize().getX()); - curHeight = hFromModelUnitsToPixels(attributes.getSize().getY()); + curWidth = (int) wFromModelUnitsToPixels(attributes.getSize().getX()); + curHeight = (int) hFromModelUnitsToPixels(attributes.getSize().getY()); } - if (attributes.getAngle() != null) { imageTransform.rotate(Maths.toRad * attributes.getAngle(), curWidth / 2d, curHeight / 2d); - // currentRenderer.rotate(Maths.toRad * attributes.getAngle(), curX + curWidth / 2d, curY + curHeight / 2d); } - - BufferedImage after = img; - Point2D.Double point = new Point2D.Double(curWidth, curHeight); - try { - Map sizes = cache.get(img); - if (sizes.containsKey(point)) { - after = sizes.get(point); - } else { - after = resize(img, (int) Math.round(curWidth), (int) Math.round(curHeight)); - } - } catch (ExecutionException e) {} - - // imageTransform.scale(curWidth / img.getWidth(), curHeight / img.getHeight()); - currentRenderer.drawImage(after, imageTransform, null); - // currentRenderer.drawImage(img, (int) FastMath.round(curX), (int) FastMath.round(curY), (int) curWidth, - // (int) curHeight, null); + if (curWidth != img.getWidth() || curHeight != img.getHeight()) { + imageTransform.scale((double) curWidth / img.getWidth(), (double) curHeight / img.getHeight()); + } + currentRenderer.drawImage(img, imageTransform, null); if (attributes.getBorder() != null) { drawGridLine(img, attributes.getBorder()); } - // currentRenderer.setTransform(saved); rect.setRect(curX, curY, curWidth, curHeight); if (highlight) { highlightRectangleInPixels(rect); } return rect.getBounds2D(); @@ -303,21 +280,6 @@ public static BufferedImage resize(final BufferedImage img, final int newW, fina return dimg; } - /** The cache. */ - @SuppressWarnings ({ "unchecked", - "unused" }) static LoadingCache> cache = - CacheBuilder.> newBuilder() - .expireAfterAccess(30, TimeUnit.SECONDS).removalListener(notif -> { - Map map = (Map) notif.getValue(); - map.forEach((a, b) -> { b.flush(); }); - }).build(new CacheLoader<>() { - - @Override - public Map load(final BufferedImage arg0) throws Exception { - return new HashMap<>(); - } - }); - /** * Method drawString. * diff --git a/msi.gama.core/src/msi/gaml/statements/draw/DrawStatement.java b/msi.gama.core/src/msi/gaml/statements/draw/DrawStatement.java index a44d152a1b..d8557b4a72 100644 --- a/msi.gama.core/src/msi/gaml/statements/draw/DrawStatement.java +++ b/msi.gama.core/src/msi/gaml/statements/draw/DrawStatement.java @@ -60,6 +60,7 @@ import msi.gaml.statements.draw.DrawStatement.DrawValidator; import msi.gaml.types.IType; import msi.gaml.types.Types; +import ummisco.gama.dev.utils.DEBUG; // A command that is used to draw shapes, figures, text on the display @@ -404,7 +405,7 @@ private Rectangle2D privateExecuteIn(final IGraphicsScope scope) throws GamaRunt } catch (final GamaRuntimeException e) { throw e; } catch (final Throwable e) { - java.lang.System.err.println("Error when drawing in a display : " + e.getMessage()); + DEBUG.ERR("Error when drawing in a display : " + e.getMessage()); e.printStackTrace(); } return null; diff --git a/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/GamaImage.java b/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/GamaImage.java index 6f5a91338d..0822a8ce88 100644 --- a/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/GamaImage.java +++ b/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/GamaImage.java @@ -21,12 +21,14 @@ import msi.gama.common.interfaces.IAsset; import msi.gama.common.interfaces.IImageProvider; import msi.gama.common.interfaces.IKeyword; +import msi.gama.common.interfaces.IValue; import msi.gama.metamodel.topology.grid.GamaSpatialMatrix; import msi.gama.precompiler.GamlAnnotations.doc; import msi.gama.precompiler.GamlAnnotations.getter; import msi.gama.precompiler.GamlAnnotations.variable; import msi.gama.precompiler.GamlAnnotations.vars; import msi.gama.runtime.IScope; +import msi.gama.runtime.exceptions.GamaRuntimeException; import msi.gama.util.IList; import msi.gama.util.file.IFieldMatrixProvider; import msi.gama.util.matrix.GamaField; @@ -53,10 +55,10 @@ name = IKeyword.WIDTH, type = IType.INT, doc = { @doc ("Returns the width (in pixels) of this image") }) }) -public class GamaImage extends BufferedImage implements IImageProvider, IAsset, IFieldMatrixProvider { +public class GamaImage extends BufferedImage implements IImageProvider, IAsset, IFieldMatrixProvider, IValue { /** The id. */ - final String id; + String id; /** * Gets the id. @@ -351,4 +353,22 @@ public static GamaImage from(final ColorModel cm, final WritableRaster raster, f return new GamaImage(cm, raster, b, "raster" + System.currentTimeMillis()); } + /** + * Sets the id. + * + * @param string + * the new id + */ + public void setId(final String string) { id = string; } + + @Override + public String stringValue(final IScope scope) throws GamaRuntimeException { + return id; + } + + @Override + public GamaImage copy(final IScope scope) throws GamaRuntimeException { + return from(this, this.getAlpha(scope)); + } + } diff --git a/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/ImageConstants.java b/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/ImageConstants.java index e8ffc462da..26415c6aa5 100644 --- a/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/ImageConstants.java +++ b/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/ImageConstants.java @@ -15,6 +15,7 @@ import java.awt.Toolkit; import java.awt.color.ColorSpace; import java.awt.datatransfer.Clipboard; +import java.awt.image.BufferedImageOp; import java.awt.image.ColorConvertOp; import java.awt.image.ConvolveOp; import java.awt.image.Kernel; @@ -73,4 +74,8 @@ public interface ImageConstants { */ ColorConvertOp OP_GRAYSCALE = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null); + /** The descriptions. */ + Map DESCRIPTIONS = Map.of(OP_DARKER, "darker", OP_ANTIALIAS, "antialiased", OP_BRIGHTER, + "brighter", OP_SHARPEN, "sharpened", OP_BLUR, "blurred", OP_GRAYSCALE, "grayscaled"); + } diff --git a/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/ImageHelper.java b/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/ImageHelper.java index 7424e59890..1655c741e0 100644 --- a/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/ImageHelper.java +++ b/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/ImageHelper.java @@ -50,6 +50,7 @@ static GamaImage apply(GamaImage src, final BufferedImageOp op) { GamaImage result = GamaImage.bestFor(src, (int) Math.round(bounds.getWidth()), (int) Math.round(bounds.getHeight())); op.filter(src, result); + result.setId(src.getId() + DESCRIPTIONS.get(op)); return result; } @@ -71,6 +72,7 @@ protected static GamaImage copyToOptimalImage(final Image src) { GamaImage result = GamaImage.ofDimensions(src.getWidth(null), src.getHeight(null), type); Graphics g = result.getGraphics(); g.drawImage(src, 0, 0, null); + result.setId((src instanceof GamaImage gi ? gi.getId() : "image") + "optimized"); g.dispose(); return result; } @@ -123,6 +125,7 @@ static GamaImage rotate(final GamaImage src, final int typeOfRotation) g2d.setRenderingHints(HINTS); g2d.drawImage(src, tx, null); g2d.dispose(); + result.setId(src.getId() + "rotated" + typeOfRotation); return result; } @@ -185,6 +188,7 @@ static GamaImage resize(final GamaImage src, final Mode resizeMode, int targetWi } else { result = ImageHelper.scaleImageIncrementally(src, targetWidth, targetHeight); } + result.setId(src.getId() + "resized" + targetWidth + "|" + targetHeight); return result; } @@ -226,7 +230,7 @@ static GamaImage scaleImageIncrementally(GamaImage src, final int targetWidth, f src = incrementalImage; hasReassignedSrc = true; } while (currentWidth != targetWidth || currentHeight != targetHeight); - + src.setId(src.getId() + "resized" + targetWidth + "|" + targetHeight); return src; } @@ -247,7 +251,7 @@ static GamaImage scaleImageIncrementally(GamaImage src, final int targetWidth, f public static GamaImage scaleImage(final Image bufferedImage, final int targetWidth, final int targetHeight) { GamaImage result = GamaImage.bestFor(bufferedImage, targetWidth, targetHeight); Graphics2D resultGraphics = result.createGraphics(); - resultGraphics.setRenderingHints(ImageHelper.HINTS); + resultGraphics.setRenderingHints(ImageConstants.HINTS); resultGraphics.drawImage(bufferedImage, 0, 0, targetWidth, targetHeight, null); resultGraphics.dispose(); return result; diff --git a/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/ImageOperators.java b/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/ImageOperators.java index e4eb09c5f1..4dbafb5f61 100644 --- a/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/ImageOperators.java +++ b/ummisco.gaml.extensions.image/src/ummisco/gaml/extensions/image/ImageOperators.java @@ -401,6 +401,7 @@ public static GamaImage rotated(final IScope scope, final GamaImage image, final g2.rotate(rads, w / 2, h / 2); g2.drawImage(image, 0, 0, null); g2.dispose(); + rotated.setId(image.getId() + "rotated" + angleInDegrees); return rotated; } @@ -419,18 +420,18 @@ public static GamaImage rotated(final IScope scope, final GamaImage image, final @doc ("Returns the image tinted using the color passed in parameter. This effectively multiplies the colors of the image by it. The original image is left untouched") @no_test public static GamaImage tint(final IScope scope, final GamaImage image, final GamaColor color) { - GamaImage tintedSprite = GamaImage.ofDimensions(image.getWidth(), image.getHeight(), Transparency.TRANSLUCENT); - Graphics2D graphics = tintedSprite.createGraphics(); + GamaImage result = GamaImage.ofDimensions(image.getWidth(), image.getHeight(), Transparency.TRANSLUCENT); + Graphics2D graphics = result.createGraphics(); graphics.drawImage(image, 0, 0, null); graphics.dispose(); - ColorModel cm = tintedSprite.getColorModel(); - WritableRaster raster = tintedSprite.getRaster(); + ColorModel cm = result.getColorModel(); + WritableRaster raster = result.getRaster(); float r = color.getRed() / 255f; float g = color.getGreen() / 255f; float b = color.getBlue() / 255f; float a = color.getAlpha() / 255f; - for (int i = 0; i < tintedSprite.getWidth(); i++) { - for (int j = 0; j < tintedSprite.getHeight(); j++) { + for (int i = 0; i < result.getWidth(); i++) { + for (int j = 0; j < result.getHeight(); j++) { int ax = cm.getAlpha(raster.getDataElements(i, j, null)); int rx = cm.getRed(raster.getDataElements(i, j, null)); int gx = cm.getGreen(raster.getDataElements(i, j, null)); @@ -439,10 +440,11 @@ public static GamaImage tint(final IScope scope, final GamaImage image, final Ga gx *= g; bx *= b; ax *= a; - tintedSprite.setRGB(i, j, ax << 24 | rx << 16 | gx << 8 | bx); + result.setRGB(i, j, ax << 24 | rx << 16 | gx << 8 | bx); } } - return tintedSprite; + result.setId(image.getId() + "tinted" + color.getRGB()); + return result; } /** @@ -476,30 +478,17 @@ public static GamaImage tint(final IScope scope, final GamaImage image, final Ga public static GamaImage tint(final IScope scope, final GamaImage image, final GamaColor color, final double ratio) { int w = image.getWidth(); int h = image.getHeight(); - GamaImage dyed = GamaImage.ofDimensions(w, h, BufferedImage.TYPE_INT_ARGB); - Graphics2D g = dyed.createGraphics(); + GamaImage result = GamaImage.ofDimensions(w, h, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = result.createGraphics(); g.drawImage(image, 0, 0, null); g.setComposite(AlphaComposite.SrcAtop.derive(Math.min(1f, Math.max((float) ratio, 0f)))); g.setColor(color); g.fillRect(0, 0, w, h); g.dispose(); - return dyed; + result.setId(image.getId() + "tinted" + color + "|" + ratio); + return result; } - /** - * Blend. - * - * @param scope - * the scope - * @param image - * the image - * @param overlay - * the overlay - * @param ratio - * the ratio - * @return the gama image - */ - /** * Blend. * @@ -526,14 +515,15 @@ public static GamaImage tint(final IScope scope, final GamaImage image, final Ga @no_test public static GamaImage blend(final IScope scope, final GamaImage image, final GamaImage overlay, final double ratio) { - GamaImage composed = ImageHelper.copyToOptimalImage(image); - Graphics2D g2d = composed.createGraphics(); + GamaImage result = ImageHelper.copyToOptimalImage(image); + Graphics2D g2d = result.createGraphics(); g2d.setComposite(AlphaComposite.SrcOver.derive(Math.min(1f, Math.max((float) ratio, 0f)))); - int x = (composed.getWidth() - overlay.getWidth()) / 2; - int y = (composed.getHeight() - overlay.getHeight()) / 2; + int x = (result.getWidth() - overlay.getWidth()) / 2; + int y = (result.getHeight() - overlay.getHeight()) / 2; g2d.drawImage(overlay, x, y, null); g2d.dispose(); - return composed; + result.setId(image.getId() + "|" + overlay.getId()); + return result; } /** @@ -605,6 +595,7 @@ public static GamaImage cropped(final IScope scope, final GamaImage image, final Graphics g = result.getGraphics(); g.drawImage(image, 0, 0, width, height, x, y, x + width, y + height, null); g.dispose(); + result.setId(image.getId() + "crop" + ox + "|" + oy + "|" + ow + "|" + oh); return result; }