Example: watermarking bitmaps

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.

Step 1: set up

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.*

Step 2: filter code

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();

Step 3: test

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:

Step 4: experiment

You can change a lot of things in the watermark:

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.