Creating watermarks can be fun

Create invisible digital watermarks with android WM, a lightweight Android library

Yizheng Huang
© Shutterstock / HomeArt  

Time to introduce the creation of this bright young developer. Meet android WM, a lightweight Android image watermark library that supports invisible digital watermarks. In this article, Yizheng Huang walks us through his project and how we can use android WM to create invisible digital watermarks.

I like to use my mobile phone to read news and jokes in my spare time, and I can notice that in many mobile apps, news images and user-uploaded images are watermarked. In the current era of privacy and copyright, watermarking pictures is a very good means of protecting individual rights. Until now, this job (watermarking images) was usually done by the developers themselves, so I start wondering if I can build a library to help them finish this work.

I am a third-year undergraduate student at EECS and I like doing some contributions in open source projects after class. So after learning about how to implement a watermark function, I started my project: android WM, which is a lightweight Android image watermark library that supports invisible digital watermarks.

The first step in building this framework is to write the code that can add a text watermark to the background image. In order to give users a good experience and flexible interface, I applied the factory mode that can be very helpful in this project. Since the watermark text has lots of attributes that need to be set before drawing, like the watermark position, the watermark size, etc. the factory mode can avoid using lots of Java constructors and make the attribute setting be more comfortable and clear.

So if you want to use android WM to draw a visible watermark, you can add this library to your own Android project using Gradle:

implementation 'com.huangyz0918:androidwm:0.1.9'

After the preparation is complete, you need a WatermarkBuilder to create a watermark image. You can get an instance from ‘create method of WatermarkBuilder’, and you need to put a Bitmap or an int Drawable as the background image first.

            .create(context, backgroundBitmap)

You can create an image watermark in the same way, since it’s very easy to use.

Drawing the visible watermarks in the background image is not a difficult task, both the text watermarks and the image watermarks are drawn to the background image using Canvas. I sealed the drawing methods and then provided the developers with an easy-to-call interface to the package, so the first version of the open source library is ready. But I don’t want to stop here. After all, there are a lot of people who like to infringe copyright by destroying watermarks, we need to draw the invisible watermarks in some special cases. I want to create the best watermark library in Android, so this part cannot be ignored.

But drawing the invisible digital watermarks is not an easy task, common implementation methods currently in the field of information hiding are:

  1. Drawing an LSB watermark on the spatial domain.
  2. Drawing a hidden watermark on the frequency domain.

android WM has perfected the methods of drawing the LSB watermarks but the ways to draw the watermarks into the frequency domain is still in developing progress.

The full name of the LSB is Least Significant Bits, which stores our hidden information (watermarks) through some of the least significant bits in the picture. The LSB method is the simplest way to embed the watermarks. In fact, any picture has a certain degree of noise tolerance. This is reflected in the fact that the Least Significant Bit (LSB) of the pixel data has little visual impact on the human eye. The human eye can hardly distinguish the subtle changes in the last digit of the RGB color in each pixel. So that the secret information can be hidden in the lowest or lower order of each pixel, which makes the watermark seem like it disappeared.

SEE ALSO: Airbnb open sources MvRx, its Kotlin-first, Kotlin-only Android framework

To implement our invisible LSB watermark, android WM  extracts all the pixels of the background image, each of which can be decomposed into an ARGB (alpha, red, green, blue) four-bit integer and each element in ARGB is represented by an integer number from 0 to 255. Like the human eye, the small change of the last bit gradation cannot be observed at all. So we can encode the text (or an image) information of the watermark into a string of binary characters A.fter the encoding, we cleared the last bit of each ARGB value and replaced them with the binary characters, which achieves the use of the last bit gradation to store our hidden watermarks.

To detect the invisible LSB watermarks, we just need to read the messages in the last bit of each ARGB value and put them together. The principle of the LSB can be explained by the following picture:

Now, you can try the invisible LSB watermark by android WM, like the normal watermarks, you need a WatermarkBuilder first, can call the method: .setInvisibleWMListener to draw the watermarked image:

            .create(this, backgroundBitmap)
            .setInvisibleWMListener(true, new BuildFinishListener<Bitmap>() {
                public void onSuccess(Bitmap object) {
                     // do something...

                public void onFailure(String message) {
                   // do something...

In the actual project,  android WM will add non-binary suffixes to identify the watermark binary information. At the same time, in order to make the whole picture covered by the watermark, our algorithm will cyclically mark the watermark information. Laid in the background image, it can be successfully detected as long as the image contains a valid watermark information.

If you want to detect the LSB watermarks, you can use a WatermarkDetector, for specific usage, you can check out the documentation I wrote on Github. The demo of LSB invisible watermark looks like:

















For LSB spatial domain digital watermarking, it has the following advantages:

  • A large amount of watermark information is supported.
  • Little influence on the original image.
  • Simple algorithm.

But it also has huge drawbacks that cannot be ignored:

  • Draw a digital watermark on the spatial domain, the watermark will destroy as the image changes.
  • Poor robustness, not resistant to cropping, scaling, and jpg compression.

So in the next step, I’d like to refactor the code using C++, which can greatly speed up the drawing and detection speed of the invisible watermarks and try to implement the invisible watermarks in the frequency domain, which has a better robustness than the LSB watermark.


Yizheng Huang

Yizheng Huang is in his junior year at EECS bachelor program in ShanDong University, China. He has some successful Web and Android application developments and also made contributions to some open source communities. Now, his research interests are Cryptography and Software Testing.

Inline Feedbacks
View all comments