DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Google Cloud Document AI Basics
  • Thumbnail Generator Microservice for PDF in Spring Boot
  • Designing a Blog Application Using Document Databases
  • How to Split PDF Files into Separate Documents Using Java

Trending

  • Blue Skies Ahead: An AI Case Study on LLM Use for a Graph Theory Related Application
  • How Clojure Shapes Teams and Products
  • Java's Quiet Revolution: Thriving in the Serverless Kubernetes Era
  • Scalability 101: How to Build, Measure, and Improve It
  1. DZone
  2. Data Engineering
  3. Databases
  4. Dynamic Watermarking of Bitmaps in Databases

Dynamic Watermarking of Bitmaps in Databases

Learn how to make the bitmaps in your database traceable, without changing your database or your applications.

By 
Max Tardiveau user avatar
Max Tardiveau
·
May. 20, 24 · Tutorial
Likes (9)
Comment
Save
Tweet
Share
3.6K Views

Join the DZone community and get the full member experience.

Join For Free

Synopsis

Many databases contain bitmaps stored as blobs or files: photos, document scans, medical images, etc. When these bitmaps are retrieved by various database clients and applications, it is sometimes desirable to uniquely watermark them as they are being retrieved, so that they can be identified later. In some cases, you may even want to make this watermark invisible.

This kind of dynamic bitmap manipulation can easily be done by a programmable database proxy, without changing the persisted bitmaps.

This approach has the following benefits:

  • The watermark can be customized for each retrieval and can contain information about the date, time, user identity, IP address, etc.
  • The image processing is done by the proxy, which puts no extra load on the database.
  • This requires no changes to the database or to the database clients.

The End Result

Given a bitmap stored in a database, such as:

A bitmap stored in a database

a programmable database proxy can modify the bitmap on its way to the client to include a watermark containing any desired information, such as:

Bitmap with watermark

How This Works

The architecture is simple: instead of the normal connection between database clients and servers:

Architecture: normal connection between database clients and servers

the clients connect to the proxy, and the proxy connects to the server:

Architecture where clients connect to the proxy, and the proxy connects to the server

The proxy can then manipulate the bitmaps as needed when they are retrieved. For instance, it can watermark only some bitmaps, or it can use different styles of watermarks, depending on the circumstances.

The bitmaps stored in the database are completely unaffected: they are modified on the fly as they are forwarded to the clients.

Advantages

  • The clients and the database are blissfully unaware - this is completely transparent to them.
  • Each image can be watermarked uniquely when it is retrieved (e.g., date/time, user name, IP address of client, etc.).
  • No additional load is put on the database server(s).

Disadvantages

  • The system is more complex with the addition of the proxy.
  • There will be (typically modest) an increase in latency, depending mostly on the size of the images, but this should be compared to the alternatives.

Example

Using a proxy, we can create a simple filter to add a watermark to certain bitmaps.

If we assume that our database contains a table called images, with a column called bitmap of type blob or varbinary (depending on your database), we can create a result set filter in the proxy with the following parameter:

Query pattern: regex:select.*from.*images.*


and a bit of JavaScript code (which also uses the underlying Java engine):

JavaScript
 
// Get the value of the bitmap column as a byte stream
let stream = context.packet.getJavaStream("bitmap");
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();

// Read the bitmap
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("sans-serif", Font.BOLD, 16));

// Draw the text at the bottom of the bitmap
let textRect = textFont.getStringBounds(watermark, g.getFontRenderContext());
g.drawString(watermark, (img.getWidth() / 2) - (textRect.getWidth() / 2),
                img.getHeight() - (textRect.getHeight() / 2));

// Write the bitmap to the column value
const ByteArrayOutputStream = Java.type("java.io.ByteArrayOutputStream");
let outStream = new ByteArrayOutputStream();
ImageIO.write(img, "png", outStream);
context.packet.bitmap = outStream.toByteArray();


With this filter in place, bitmaps retrieved from this table will include a watermark containing the name of the database user, and a timestamp.

The database is never affected: the bitmaps stored in the database are completely unchanged. They are modified on the fly as they are delivered to the client.

Obviously, we can watermark bitmaps selectively, we can change the text of the watermark depending on any relevant factors, and we can play with fonts, colors, positioning, transparency, etc. See this example for details. 

Secret Watermarks

In some cases, it might be desirable to mark the bitmaps in a way that is not visible to the naked eye. One trivial way to do this would be to edit the image's metadata, but if we need something more subtle, we can use steganography to distribute a secret message among the bitmap in a way that makes it difficult to detect.

The example above can be modified to use the Adumbra library:

// Get the value of the bitmap column as a byte stream
let inStream = context.packet.getJavaStream("bitmap");
if (inStream === null) {
    return;
}

// The hidden message
const now = new Date();
const message = "Retrieved by " + context.connectionContext.userName + 
    " on " + now.getFullYear() + "/" + (now.getMonth()+1) + "/" + now.getDate();
const messageBytes = context.utils.getUTF8BytesForString(message);
const keyBytes = context.utils.getUTF8BytesForString("This is my secret key");

// Hide the message in the bitmap
const Encoder = Java.type("com.galliumdata.adumbra.Encoder");
const ByteArrayOutputStream = Java.type("java.io.ByteArrayOutputStream");
let outStream = new ByteArrayOutputStream();
let encoder = new Encoder(1);
encoder.encode(inStream, outStream, "png", messageBytes, keyBytes);
context.packet.bitmap = outStream.toByteArray();


With this in place, the modified bitmaps served to the clients will contain a secret watermark that will be difficult to detect, and almost impossible to extract without the secret key.

What Else Can You Do With This?

This watermarking technique can also be applied to documents other than bitmaps:

  • Documents such as PDF and MS Word can be given some extra metadata on the fly, or they can be given a visible or invisible watermark - see this example for PDF documents.
  • All text documents can be subtly marked using techniques such as altering spacing, spelling, layout, fonts and colors, zero-width characters, etc.
  • All digital documents that can sustain minor changes without losing any significant meaning, such as bitmaps, audio files, and sample sets, can be altered in a similar way.
  • In fact, entire data sets can be watermarked by subtly modifying some non-critical aspects of the data, making it possible to identify these datasets later on and know exactly their origin. This is beyond the scope of this article, but there are many ways to make data traceable back to its origin.

Conclusion

When you need to have a custom watermark for every retrieval of some bitmaps or documents from a database, the technique shown here is a solid approach that avoids any additional load on the database and requires no changes to the clients or servers.

Bitmap Database Database server Document PDF

Opinions expressed by DZone contributors are their own.

Related

  • Google Cloud Document AI Basics
  • Thumbnail Generator Microservice for PDF in Spring Boot
  • Designing a Blog Application Using Document Databases
  • How to Split PDF Files into Separate Documents Using Java

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!