A lot of databases contain images stored as blobs: document scans, medical images, photos, etc...
When these images are retrieved by various database clients and applications, it is sometimes desirable to watermark them as they are being retrieved, so that they can be identified. This example shows how to do that.
This example works for SQL Server, but could be adapted with minimal effort for other databases.
We assume that there is a table called gallium_demo.images with a column named image of type VARBINARY.
We also assume that this table contains some data, with the image column containing bitmap data (e.g. PNG, JPEG, TIFF, ...)
Create a result set filter for SQL Server, name it e.g. "Modify images"
Set the parameters for this new filter so that it gets invoked for the table, e.g.:
Query pattern = regex:select.*from.*images.*
The code for the filter is:
// Get the value of the image column as a byte stream
let stream = context.packet.getJavaStream("image");
if (stream === null) {
return;
}
// The text to use as watermark
const now = new Date();
const watermark = "Retrieved by " + context.connectionContext.userName +
" on " + now.getFullYear() + "/" + (now.getMonth()+1) + "/" + now.getDate();
// We need to do this, otherwise it may fail on headless servers
const System = Java.type("java.lang.System");
System.setProperty("java.awt.headless", "true");
// Read the image
const ImageIO = Java.type("javax.imageio.ImageIO");
let img = ImageIO.read(stream);
// Create the Graphics to draw the text
let g = img.createGraphics();
const Color = Java.type("java.awt.Color");
g.setColor(new Color(255, 255, 0, 150));
const Font = Java.type("java.awt.Font");
g.setFont(new Font("serif", Font.BOLD, 16));
// Draw the text at the bottom of the image
let rect = textFont.getStringBounds(watermark, g.getFontRenderContext());
g.drawString(watermark, (img.getWidth() / 2) - (rect.getWidth() / 2),
img.getHeight() - (rect.getHeight() / 2));
// Write the image back to the database row
const ByteArrayOutputStream = Java.type("java.io.ByteArrayOutputStream");
let outStream = new ByteArrayOutputStream();
ImageIO.write(img, "png", outStream);
context.packet.image = outStream.toByteArray();
When you retrieve bitmaps from the database, using a query that triggers your new filter, you will see that a watermark has been added to the bitmap.
For instance, if the bitmap stored in the database is:
then the bitmap retrieved by the client will be something like:
You can change a lot of things in the watermark:
font, font size: let textFont = new Font("sans-serif", Font.ITALIC, 18);
color and transparency: g.setColor(new Color(255, 0, 0, 255));
Rotation: right before g.drawString, you can add: g.rotate(-0.6);
Position: g.drawString(watermark, (img.getWidth() / 2) - (rect.getWidth() / 2), 20);
See the documentation for Font and Graphics2D for many more possibilities.
A list of all available fonts can be found in the Gallium Data app, under Server -> Scripting, at the bottom of the page.