Displaying Base64 Image as Node Icon in Graph Browser

I’m currently working with the Graph Browser in Siren Investigate, and I’d like to use Base64-encoded images as node icons.

Here’s what I’ve done so far:

  • I’ve converted images (JPEG/PNG) to Base64 format.
  • The Base64 string is stored in a field (e.g., payload.image_base64).i inserted in elasticsearch
  • In the Graph Browser settings, I tried using the “URL”, “Image Proxy URL”, and “Local Image” options to display these images as node icons.

However, the images are not rendering in any of these nodes.

I also attempted the following JEXL expression under the “URL” icon option:

payload.image_base64 != null ? ‘data:image/jpeg;base64,’ + payload.image_base64 : null

Unfortunately, this doesn’t seem to work — the nodes remain blank or the icons do not load.

Could you please confirm:

  • Does Siren Investigate currently support Base64 data:image/... URIs in node icons?
  • Is there a size limit or proxy restriction I should be aware of?
  • Should I consider using an external image server instead?

Any guidance or recommended workaround would be greatly appreciated.

Hi James,
Base64 images are supported in the graph browser in the following ways:

  • Advanced lens: you can configure a base64 image selecting URL and configuring the expression like this: 'data:image/png;base64,' + payload["image_field"]

  • You can set it directly in the datamodel. Go to your entity page and set up a scripted image with the following expression data:image/png;base64,@doc[_source][image_field]@

In general, I would consider using an external image server (or the built-in image proxy to access available images on other domains). Having base64 images stored as part of the documents will increase the data stored as part of the saved graph. If you were to retrieve images dynamically via a URL, you would end up with lighter saved graphs.

Hope this helps you
Regards,
Fabio

Thank you for your response.

I have stored my images on a separate server, and the image URLs (along with other related data) are saved in a separate Elasticsearch index.

I created an entity table and defined entity identifiers for relations . When I load the graph, the table and nodes(Entity Identifiers) are displayed correctly. However, I want to display the images on the entity identifiers in the graph nodes by referencing the image URL field using something like:
payload[‘image’]
But it’s not working as expected. How can I correctly configure this so that the image appears on the Entity identifier? when i specifiy path in url it displays icons on entity identifier to on node images but when i render from Elasticsearch payload[“image”] it doesnot display @FabioTacchelli

Thank you for your response.

I have stored my images on a separate server, and the image URLs (along with other related data) are saved in a separate Elasticsearch index.

I created an entity table and defined entity identifiers. When I load the graph, the table and nodes are displayed correctly. However, I want to display the images on the entity identifiers in the graph nodes by referencing the image URL field using something like:


payload['image']

because i m using aggregated relations using entity identifiers

But it’s not working as expected. How can I correctly configure this so that the image appears on the node identifier?

Entity identifiers are pure values that may come from multiple documents.

To display a custom image coming from one of the connected documents, you would need to create a custom lens that gets the image URL from a connected node and adds it to the EID node.

Alternatively, you would have to query the index to retrieve the image URL of the connected documents

I’ve developed a new script intended to function as a custom lens for displaying entity-related images on the graph. However, I’m currently unable to get new lens script within the ‘Lens’ options in the graph browser. I’m actively troubleshooting why it’s not appearing in the available selections

Hello James,
you’ll need to add your script to the graph browser configuration. You can go there by clicking edit on the top right of the dashboard and then the pencil on the graph browser visualization.

After doing this, your script will be available from the graph browser dropdown selector

@FabioTacchelli can you provide me script to display image in entity identifier .. data is comming from elasticsearch payload[“image”]

this is my script is used for entity identifier i used index name also i.e people
var _parameters = {
entityId: ‘$$ALL$’,
entityIdSet: new Set(),
condition: ‘’,
expression: ‘’,
imageMode: ‘url’,
modelProperty: ‘’,
when: ‘always’,
selection: ,
methods: {}
};

function getLensDefinition(graphId, graphModel, selection, precomputed) {
var html = ‘Entity Type’;
let entities = ;
html += f.buildSelectEntityMenu(graphModel, precomputed, entities);

html += ‘If …’;
html += ‘
always’;
html += ‘
’;
html += ‘only for the {{ params.selection.length }} selected elements.’;
html += ‘’;
html += ‘ ’;
html += ‘’;
html += ‘
’;
html += ‘only if the condition is true’;
html += ‘<expression-editor entity-id-set=“data.entityIdSet” required-field=“params.when === 'conditional'”’;
html += ’ ng-hide=“params.when !== 'conditional'” ‘;
html += ’ type=“params.entityId” expression=“params.condition” error-message=“data.errorMessages.condition”>’;
html += ‘’;
html += ‘
Set this property’;
html += ‘’;
html += ‘’;
html += ‘Url ’;
html += ‘’;
html += ‘Image Proxy Url ’;
html += ‘’;
html += ‘Local image’;
html += ‘’;

_parameters.selection = selection;
_parameters.methods = {
imageModeChanged: function () {
if (this.params.imageMode === ‘urlDirect’) {
this.params.expression = ‘'https://cdn4.iconfinder.com/data/icons/fugue/icon_shadowless/dummy.png\’‘;
} else if (this.params.imageMode === ‘urlProxy’) {
this.params.expression = ‘'https://siren.io/wp-content/uploads/Siren-small_V1.1.png\’’;
} else {
this.params.expression = ‘'set1/bank.png'’;
}
},
propertyChanged: function (prop) {
if (prop.name === ‘pathIcon’) {
this.params.imageMode = ‘url’;
}
this.params.expression = prop.default;
},
showSelection: function () {
this.loadItems({ selection: this.params.selection });
},
isPathIcon: function () {
var prop = this.params.modelProperty;
return prop.name === ‘pathIcon’;
},
updateSelection: function () {
this.params.selection = _.filter(this.getSelection(), function (id) {
return id.split(‘/’).length === 3;
});
}
};

return Promise.resolve({
displayName: ‘Entity Icon with Image’,
type: ‘Advanced’,
template: html,
params: _parameters,
data: {
entityIdSet: precomputed.entityIdSet,
currentSelection: selection,
entities: entities
}
});
}

function setParams(params) {
_parameters = params;
}

function onGraphUpdate(graphId, graphModel, oldModel, precomputed) {
const entityId = _parameters.entityId;
const prop = _parameters.modelProperty;
const imageMode = _parameters.imageMode;
const expression = _parameters.expression.replace(/\n\r?/g, ’ ');
const selection = _parameters.selection;
const when = _parameters.when;

return f.getEntityAndDescendantsIds(entityId).then(function (entityIds) {
const proms = ;

function getImageUrlFromDoc(node) {
  const query = {
    size: 1,
    query: {
    match_all:{}
    },
    _source: ["image"]
  };

  return f.executeEsSearch("people", null, query).then(function (res) {
    const hit = res.hits.hits[0];
    if (hit && hit._source && hit._source.image_url) {
      let img = hit._source.image_url;
      if (prop.name === "pathIcon") {
        if (imageMode === "urlDirect") {
          node[prop.name] = img;
        } else if (imageMode === "urlProxy") {
          node[prop.name] = "/image_proxy?url=" + encodeURIComponent(img);
        }
      }
    }
  });
}

_.each(graphModel.nodes, function (node) {
  if (prop && prop.name === 'pathIcon') {
    if (node.isEntityIdentifier) {
      proms.push(getImageUrlFromDoc(node));
    } else {
      let nodeExpr = '\'\' + ' + expression;
      proms.push(jexl.eval(nodeExpr, node).then(function (img) {
        if (imageMode === 'urlDirect') {
          node[prop.name] = img;
        } else if (imageMode === 'urlProxy') {
          node[prop.name] = '/image_proxy?url=' + encodeURIComponent(img);
        }
      }).catch(() => {}));
    }
  }
});

return Promise.all(proms).then(() => graphModel);

});
}
not working for me

@FabioTacchelli can you check this