Skip to content

Commit

Permalink
add an operator to send a GAMAimage to websocket using base64
Browse files Browse the repository at this point in the history
  • Loading branch information
ptaillandier committed Oct 29, 2024
1 parent 808c9b7 commit 242a137
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 1 deletion.
6 changes: 5 additions & 1 deletion gama.core/src/gama/core/kernel/root/PlatformAgent.java
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,10 @@ public Object sendMessageThroughServer(final IScope scope) {
* @date 3 nov. 2023
*/
public void sendMessage(final IScope scope, final Object message) {
sendMessage(scope,GamaServerMessage.Type.SimulationOutput);

Check warning on line 537 in gama.core/src/gama/core/kernel/root/PlatformAgent.java

View workflow job for this annotation

GitHub Actions / SpotBugs

IL_INFINITE_RECURSIVE_LOOP

There is an apparent infinite recursive loop in gama.core.kernel.root.PlatformAgent.sendMessage(IScope, Object)
Raw output
This method unconditionally invokes itself. This would seem to indicate an infinite recursive loop that will result in a stack overflow.
}

public void sendMessage(final IScope scope, final Object message, final gama.core.runtime.server.GamaServerMessage.Type type) {
try {
var socket = scope.getServerConfiguration().socket();
// try to get the socket in platformAgent if the request is too soon before agent.schedule()
Expand All @@ -543,7 +547,7 @@ public void sendMessage(final IScope scope, final Object message) {
+ message);
return;
}
socket.send(jsonEncoder.valueOf(new GamaServerMessage(GamaServerMessage.Type.SimulationOutput, message,
socket.send(jsonEncoder.valueOf(new GamaServerMessage(type, message,
scope.getServerConfiguration().expId())).toString());
} catch (Exception ex) {
ex.printStackTrace();
Expand Down
5 changes: 5 additions & 0 deletions gama.core/src/gama/core/runtime/server/GamaServerMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ public enum Type {
*/
SimulationOutput,

/**
* Used to send a image of a display of a running simulation
*/
SimulationImage,

/**
* Used to describe the content printed using the debug statement in a running simulation
*/
Expand Down
39 changes: 39 additions & 0 deletions gama.extension.image/src/gama/extension/image/ImageOperators.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@
import java.awt.image.ColorModel;
import java.awt.image.RescaleOp;
import java.awt.image.WritableRaster;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Base64;

import javax.imageio.ImageIO;

import gama.annotations.precompiler.GamlAnnotations.doc;
import gama.annotations.precompiler.GamlAnnotations.example;
Expand All @@ -33,11 +40,14 @@
import gama.core.common.interfaces.IDisplaySurface;
import gama.core.common.interfaces.IKeyword;
import gama.core.kernel.experiment.ITopLevelAgent;
import gama.core.kernel.root.PlatformAgent;
import gama.core.metamodel.agent.IAgent;
import gama.core.metamodel.shape.GamaPoint;
import gama.core.outputs.IOutput;
import gama.core.outputs.LayeredDisplayOutput;
import gama.core.runtime.GAMA;
import gama.core.runtime.IScope;
import gama.core.runtime.server.GamaServerMessage;
import gama.core.util.GamaColor;
import gama.core.util.matrix.GamaIntMatrix;
import gama.core.util.matrix.IMatrix;
Expand Down Expand Up @@ -157,6 +167,35 @@ public static GamaImage snapshot(final IScope scope, final IAgent exp, final Str
IDisplaySurface surface = ldo.getSurface();
return SnapshotMaker.getInstance().captureImage(surface, customDimensions);
}

public static String imgToBase64String(final GamaImage img, final String formatName)
{
final ByteArrayOutputStream os = new ByteArrayOutputStream();

try
{
ImageIO.write(img, formatName, os);
return Base64.getEncoder().encodeToString(os.toByteArray());
}
catch (final IOException ioe)
{
throw new UncheckedIOException(ioe);
}
}

@operator (
value = "send_image_to_websocket",
can_be_const = false)
@doc ("Takes a snapshot of the display whose name is passed in parameter and returns the image. "
+ "The search for the display begins in the agent passed in parameter and, if not found, its experiment. A custom size (a point representing width x height) can be given "
+ "Returns nil if no display can be found or the snapshot cannot be taken.")
@no_test
public static GamaImage sendImageWebsocket(final IScope scope, final GamaImage image) {
PlatformAgent pa = GAMA.getPlatformAgent();

pa.sendMessage(scope, imgToBase64String(image, "png"), GamaServerMessage.Type.SimulationImage);
return image;
}

/**
* Grayscale.
Expand Down

0 comments on commit 242a137

Please sign in to comment.