Git Product home page Git Product logo

watermarkjs's Introduction

watermark.js Build Status

A functional library for watermarking images in the browser. Written with ES6, and made available to current browsers via Babel. Supports urls, file inputs, blobs, and on-page images.

Note: For anyone that is interested: I ported this to a ClojureScript library called Dandy Roll.

Tested Browsers

Any browser supporting File and FileReader should work. The following browsers have been tested and work:

  • IE10 (Windows 7)
  • Chrome 42 (OS X 10.10.3)
  • Firefox 38 (OS X 10.10.3)
  • Safari 8.0.6 (OS X 10.10.3)
  • Opera 29.0 (OS X 10.10.3)

Please feel free to update this list or submit a fix for a particular browser via a pull request.

Installing

watermark.js is available via npm and bower:

# install via npm
$ npm install watermarkjs

# install via bower
$ bower install watermarkjs

Usage

// watermark by local path
watermark(['img/photo.jpg', 'img/logo.png'])
  .image(watermark.image.lowerRight(0.5))
  .then(img => document.getElementById('container').appendChild(img));

// load a url and file object
const upload = document.querySelector('input[type=file]').files[0];
watermark([upload, 'img/logo.png'])
  .image(watermark.image.lowerLeft(0.5))
  .then(img => document.getElementById('container').appendChild(img));

// watermark from remote source
const options = {
  init(img) {
    img.crossOrigin = 'anonymous'
  }
};
watermark(['http://host.com/photo.jpg', 'http://host.com/logo.png'], options)
  .image(watermark.image.lowerRight(0.5))
  .then(img => document.getElementById('container').appendChild(img));

Building

Before building or testing, install all the deps:

npm i

There is an npm script you can run to build:

npm run build

Or to kick off the file watcher and build as you make changes, run the start task:

$ npm start

Testing

There is an npm script for that too!:

$ npm test

This library uses the Jest testing framework. Due to some current issues with Jest, Node 0.10.x is required to run the tests.

Examples

You can view examples and documentation by running the sync task via npm:

$ npm run sync

The examples demonstrate using watermark images and text, as well as a demonstration of uploading a watermarked image to Amazon S3. It is the same content hosted at http://brianium.github.io/watermarkjs/.

Development

Running npm run dev will start a browser and start watching source files for changes.

Motivation

  • Not every server has image libraries (shared hosting anyone?)
  • Not every server has reliable concurrency libs for efficient uploading (shared hosting anyone?)
  • JavaScript is fun and cool - more so with ES6

Clearly watermarking on the client has some limitations when watermarking urls and on-page elements. The curious can find urls for non-watermarked images, but it is likely that most average users won't go down this path - keeping this soft barrier useful. However!...

watermark.js has the ability to accept file inputs as a source for watermarking. This makes it easy to preview, watermark, and upload without the non-watermarked image ever becoming public. Check out the uploading demo to see this in action.

This tool certainly shines in admin or CMS environments where you want to generate watermarks and upload them asynchronously where it would not be possible or preferable on the server. One less thing the server has to do can be a good thing :)

Suggestions? Improvements?

Please open issues or pull requests if you have bugs/improvements.

watermarkjs's People

Contributors

brianium avatar skliffmueller avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

watermarkjs's Issues

Upload image with hard coded watermark?

I would like to use the same watermark for all uploaded images. Using the code from the upload example, how can I go about removing the select watermark field and upon uploading an image, populate the preview container with the uploaded image and hard coded watermark?

When use other web's image get error

Uncaught (in promise) DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

I am using with facebook profile picture but i got error

How to rotate the watermark text?

Its not an issue actually but just want to know if i can rotate the text like slanting or about like this ' / '. Hoping for your response. Thank you for the help.

examples are not working at all for me

hi
i have xampp installation on windows
i have downloaded watermark and when i go to examples/text.html nothing happens in my browser...
is it necesary some kind of configuration or installation?

what i want to do is not put the watermark on picture.
i need to have a watermak on the browser.

thanks very much for your help.

Apply watermark as a tile: multiple consequtive watermarks

Consider the use case if I need to cover all the space of the source image with watermark. So use watermark as a tile: an example of what I want to achieve - tiled watermark image

For now I see the solution only in combing multiple atPos from the docs calls, depending on the size

Something like this:

// getX, getY - functions
let intermediate;
let counter = 0
const nextStep = () => {
  counter++;
  if counter < NEEDED_AMOUNT {
    applySingleWatermark(intermediate || '/img/my_source_image.png')
  }
}
const applySingleWatermark = (source) => {
 watermark([source, '/img/my_watermark.png'])
    .image(watermark.image.atPos(getX, getY, 0.6)).
    .then(data => {
      intermediate= data
      nextStep()
   )
}

Is there a better way?

If not, do you see a value in creating such functionality and submitting an MR ?

Convert this to a backend plugin

Convert this into a backend plugin so that with nodejs we can watermark the image before download time.

Ideally this would become a part of a grunt or gulp task automation tool.

EXIF implementation brainstorming

In reference to #34 and #42

With the previous issues arising around retaining EXIF data, would provide added convenience in specific situations. But the implementation has some potential issues, which I'd like to address here for further discussion.

The first issue is EXIF orientation of jpg images. The current effect is when you are referencing a jpg that requires to be rotated based on EXIF data, the image is not being rotated within the library. If the EXIF data were to be merged into the new image, you would then have a problem with the text/overlays/watermarks being in the wrong orientation, now that they have been embedded into the image. Example
The solution to this would be to perform rotation of the images on initial load. But then the EXIF orientation data would be incorrect on the new image as the raw image has been rotated. This field would need to be updated if we expect to retain the EXIF data.

The next issue I can see is a situation where you include multiple images with EXIF data. What takes priority? Just the first image? Is there a way to store multiple EXIF records on one image? Or would an option to force user defined EXIF data be better?

Another consideration on a performance standpoint, would there be a way to copy the EXIF headers as one big binary chunk, and attach it to the new image. Instead of having to parse and recompile the data? And in reference to the rotation data, It might be easier to just pull the specific value from this chunk, instead of parsing the entire binary.
This stack overflow topic does provide such a script in Base64 image data where it's just copying the EXIF chunk and merging it into a new image
https://stackoverflow.com/questions/18297120/html5-resize-image-and-keep-exif-in-resized-image

//Based on MinifyJpeg
//http://elicon.blog57.fc2.com/blog-entry-206.html

var ExifRestorer = (function()
{
   
	var ExifRestorer = {};
	 
    ExifRestorer.KEY_STR = "ABCDEFGHIJKLMNOP" +
                         "QRSTUVWXYZabcdef" +
                         "ghijklmnopqrstuv" +
                         "wxyz0123456789+/" +
                         "=";

    ExifRestorer.encode64 = function(input)
    {
        var output = "",
            chr1, chr2, chr3 = "",
            enc1, enc2, enc3, enc4 = "",
            i = 0;

        do {
            chr1 = input[i++];
            chr2 = input[i++];
            chr3 = input[i++];

            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;

            if (isNaN(chr2)) {
               enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
               enc4 = 64;
            }

            output = output +
               this.KEY_STR.charAt(enc1) +
               this.KEY_STR.charAt(enc2) +
               this.KEY_STR.charAt(enc3) +
               this.KEY_STR.charAt(enc4);
            chr1 = chr2 = chr3 = "";
            enc1 = enc2 = enc3 = enc4 = "";
        } while (i < input.length);

        return output;
    };
    
    ExifRestorer.restore = function(origFileBase64, resizedFileBase64)
    {    	
        if (!origFileBase64.match("data:image/jpeg;base64,"))
        {
        	return resizedFileBase64;
        }       
        
        var rawImage = this.decode64(origFileBase64.replace("data:image/jpeg;base64,", ""));
        var segments = this.slice2Segments(rawImage);
                
        var image = this.exifManipulation(resizedFileBase64, segments);
        
        return this.encode64(image);
        
    };


    ExifRestorer.exifManipulation = function(resizedFileBase64, segments)
    {
            var exifArray = this.getExifArray(segments),
                newImageArray = this.insertExif(resizedFileBase64, exifArray),
                aBuffer = new Uint8Array(newImageArray);

            return aBuffer;
    };


    ExifRestorer.getExifArray = function(segments)
    {
            var seg;
            for (var x = 0; x < segments.length; x++)
            {
                seg = segments[x];
                if (seg[0] == 255 & seg[1] == 225) //(ff e1)
                {
                    return seg;
                }
            }
            return [];
    };


    ExifRestorer.insertExif = function(resizedFileBase64, exifArray)
    {
            var imageData = resizedFileBase64.replace("data:image/jpeg;base64,", ""),
                buf = this.decode64(imageData),
                separatePoint = buf.indexOf(255,3),
                mae = buf.slice(0, separatePoint),
                ato = buf.slice(separatePoint),
                array = mae;

            array = array.concat(exifArray);
            array = array.concat(ato);
           return array;
    };


    
    ExifRestorer.slice2Segments = function(rawImageArray)
    {
        var head = 0,
            segments = [];

        while (1)
        {
            if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 218){break;}
            if (rawImageArray[head] == 255 & rawImageArray[head + 1] == 216)
            {
                head += 2;
            }
            else
            {
                var length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3],
                    endPoint = head + length + 2,
                    seg = rawImageArray.slice(head, endPoint);
                segments.push(seg);
                head = endPoint;
            }
            if (head > rawImageArray.length){break;}
        }

        return segments;
    };


    
    ExifRestorer.decode64 = function(input) 
    {
        var output = "",
            chr1, chr2, chr3 = "",
            enc1, enc2, enc3, enc4 = "",
            i = 0,
            buf = [];

        // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
        var base64test = /[^A-Za-z0-9\+\/\=]/g;
        if (base64test.exec(input)) {
            alert("There were invalid base64 characters in the input text.\n" +
                  "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
                  "Expect errors in decoding.");
        }
        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

        do {
            enc1 = this.KEY_STR.indexOf(input.charAt(i++));
            enc2 = this.KEY_STR.indexOf(input.charAt(i++));
            enc3 = this.KEY_STR.indexOf(input.charAt(i++));
            enc4 = this.KEY_STR.indexOf(input.charAt(i++));

            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;

            buf.push(chr1);

            if (enc3 != 64) {
               buf.push(chr2);
            }
            if (enc4 != 64) {
               buf.push(chr3);
            }

            chr1 = chr2 = chr3 = "";
            enc1 = enc2 = enc3 = enc4 = "";

        } while (i < input.length);

        return buf;
    };

    
    return ExifRestorer;
})();

result image is bad work

Hi pro,
I have bug about
Watermarker([originSrc], options) .image(watermarkImage).render().image(watermarkText).then(function (img) { console.log(image.src) // sometime = data, }
On firefox all version, Thanks

Multiple Image Issue

I have multiple product images in a "c:forEach" statement on the site and each product has its own row and product image div but the code appears to be taking the image out of the product image div and merging all the images in one div causing all the images to flow right below each other and not in their respective div's. Just wondering if you have ever seen this or if i may be forgetting something. Thank You!
capture

Replace old image

I have a button to generate the image with random text, so far so good, but if I click again, it adds the new image to the side, I wanted the previous one to be replaced by the current one. How could he do that?

watermark(["img/bg.jpg"]) .image(ur(naoSei, "48px Josefin Slab", "#fff", 0, 48)) .then(function(img) { var kk = document.getElementById("upper-right").appendChild(img); var aff = document.getElementById("upper-right").src=img; var inocencia = document.getElementById("upper-right").innerHTML; kk.classList.add("img-responsive") is_img(kk); });

Browserify - can't find module

I'm having an issue where when adding watermarkjs via Browserify that it can't find the ./lib/images, ./lib/functions etc modules in node_modules/watermarkjs/dist.

I'm just using watermark = require('watermarkjs')

Any thoughts?

Each loop

Hi!
I have same issue with foreach loop. I'm trying to replace several images but it doesn't work.
var images = document.getElementsByClassName('watermark');
for(var i=0; i<images.length; i++){
watermark([images[i].src, logo])
.image(watermark.image.lowerRight(1))
.then(function(img){
images[i].src = img.src; // Undefined images[i] here
});
}

Repeat watermark

Nice lib!
Is there a way to repeat the watermark printing it in many places?
Something like a grid of the same watermark...

Thank you!

EXIF rotation data is lost

The EXIF data is lost.

If you use an image generated by a mobile device, after adding a watermark, you'll get a watermarked image with a different orientation.

Are you accepting pull requests for this?

get original image

Hi,
As long as watermark printed by js, is it possible for a user to get original images by Inspector or any other tool?

cross origin not working

I already use the init function for cross origin, but still have error like this:
Image from origin 'https://xxx' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access.

Support Cordova ?

In app android system was used? In my test app which can not be used. Requesting for help. Thank you

How to make watermark cover 100% width?

My users will be uploading different size images. Is there a way to make sure either we resize the uploaded image OR make the watermark cover 100% width?

Unable to build

my config:

node 10.14.2
npm 6.4.1

To build, I tried running
npm i
npm run build

I am getting below error

ERROR in ./index.js
Module not found: Error: Cannot resolve module 'babel' in /home/ajay/watermarkjs

 @ ./index.js 2:17-39

Could you please let me know how to build it?

for each

Hi,
I am having trouble to use your plugin on several images where I loop through with a $('element').each(function...

If I try to append the img to $(this) it doesnt work, but if I write the class hardcoded it works.
For me it looks like the this part .then(function(img){ $(this).append(img); }); doesn't work because "this" is not defined anymore...

Am I doing something wrong here?

generic load

the watermark factory should be able to take files and urls:

watermark(['url1', fileObj]);

Issue - document.getElementById('lower-left').appendChild(img) is NULL

Integrated this plugin with angularjs as below

myApp.directive('waterMark', function($timeout) {
    return {
        restrict: 'EA',
        link: function($scope, $element) {
            //$element.on('load', function(){

                $scope.videoSnapshotPath = 'img/watermark.png';
                $scope.watermarkLogoPath = 'img/logo.jpg';

                //$timeout(function() {
                    watermark([$scope.videoSnapshotPath, $scope.watermarkLogoPath])
                        .image(watermark.image.lowerRight(0.5))
                        .then(function (img) {
                            document.getElementById('lower-left').appendChild(img);
                        })
                //}, 2);
            //})
        }
    }
});

Throws below exception

TypeError: document.getElementById(...) is null
document.getElementById('lower-left').appendChild(img);

Data URI

How would I watermark an image I can only parse as a base 64 string?

Change Position options from Radio Button to Dropdown selection and Image Size

Integrated this plugin with our Angular app but I need to do the following changes

Select option

<select ng-model="data.selectedPosition" ng-options="position.name for position in data.waterMarkImgPosition track by position.id" id="mySelect" name="mySelect" class="form-control ng-pristine ng-valid ng-not-empty ng-touched" style=""><option label="Lower Right" value="1" selected="selected">Lower Right</option><option label="Lower Left" value="2">Lower Left</option><option label="Upper Right" value="3">Upper Right</option><option label="Upper left" value="4">Upper left</option><option label="Center" value="5">Center</option></select>

  1. How to set Image size for both Select the image to watermark & watermark image ?
  2. How to apply position using select options rather than radio button ?
  3. Any other angular plugin for the watermarking ?

Also it gives error in console at upload.js (line 176, col 7)

TypeError: document.getElementById(...) is null
document.getElementById(id).addEventListener('keyup', function () {

Tried changing upload.js from radio button to select option like below but not working

position = document.querySelector('input[type=radio]:checked').value;
position = document.querySelector('option:checked').value;

Please guide and help!
Thanks.

Return watermarked image as JPEG

Kind of related to #34, the watermarked image is returned as a PNG image object even though the original object was a JPEG. Is there a way to return the watermarked image as a JPEG so EXIF data can be written to it?

lightGallery + watermakjs

Hello guys,

I opened this question in "lightGallery", I received an orientation almost 1 year ago ... but I was not able to implement it.

sachinchoolur/lightGallery#726

Today my clients are charged me the use of the watermark.

Looking at this question, can anyone help me?

how to config outputWidth outputHeight

` setTimeout(function () { //ensure font faces are loaded
// lower right positioning
var text = watermark.text;

  watermark(['img/shepherd.jpg'])
    .image(text.lowerRight('watermark.js', '48px Josefin Slab', '#fff', 0.5))
    .then(function (img) {
      var pre = document.querySelector('#lower-right');
      pre.parentNode.insertBefore(img, pre);
    });
	    }, 1000);`

canvas caching/pooling

We use watermarkjs in an application have found that canvases to not get garbage collected in IE. For other places in the system that are using canvases, we implemented a pooling system to reuse canvases.

Would like to know how to get watermarkjs to either do its own canvas pooling or how to add what we are doing and have one shared canvas pool.

browser testing

test different browsers, maybe get one of those fancy saucelabs badges

Image is not defined

I have a nodejs project that i want use this module.
when i run this project i will get this problem:
ReferenceError: Image is not defined

CanvasPool can grow unbounded

The canvas pool will reuse available canvas elements, but if there are a lot of watermarks being generated quickly, then the canvas pool can grow quite large.

The pool implementation could probably benefit from some enhancements to make this a little more robust.

See #41

Text Align center of box

Hi.
i Have this:
.image(watermark.text.atPos(xSerial,ySerial,'1272359468', '48px Myriad Pro', 'black'))
i want that text will be center of a box in my image at that position.
What sholud i do?

in angularjs

` var text = watermark.text;

  watermark(['img/shepherd.jpg'])
    .image(text.lowerRight('watermark.js', '48px Josefin Slab', '#fff', 0.5))
    .then(function (img) {
      var pre = document.querySelector('#lower-right');
      pre.parentNode.insertBefore(img, pre);
    });`

ReferenceError: watermark is not defined at b.$scope.initPhoto (http://localhost:8080/html/app/employeeFile/employeeFileCtrl.js:405:32) at fn (eval at compile (http://localhost:8080/js/frame/lib/angular-1.4.6/angular.min.js:212:283), <anonymous>:4:218) at b.$eval (http://localhost:8080/js/frame/lib/angular-1.4.6/angular.min.js:132:452) at pre (http://localhost:8080/js/frame/lib/angular-1.4.6/angular.min.js:256:49) at $ (http://localhost:8080/js/frame/lib/angular-1.4.6/angular.min.js:73:89) at K (http://localhost:8080/js/frame/lib/angular-1.4.6/angular.min.js:61:354) at h (http://localhost:8080/js/frame/lib/angular-1.4.6/angular.min.js:54:410) at h (http://localhost:8080/js/frame/lib/angular-1.4.6/angular.min.js:54:433) at h (http://localhost:8080/js/frame/lib/angular-1.4.6/angular.min.js:54:433) at h (http://localhost:8080/js/frame/lib/angular-1.4.6/angular.min.js:54:433)

功能问题

可以有直接生成指定水印的功能嘛 就是有个需求让在项目中所有页面加水印 但是ie pionter event不支持

Watermark on the front side, can't protect images

The curious can find urls for non-watermarked images, but it is likely that most average users won't go down this path - keeping this soft barrier useful. However!...

Mostly the watermark should protect the images and avoid unwarranted use, but if web crawlers can down non-watermarked images, then the images are leaked to everyone...

Watermarking on list of images eats up CPU

I am using your library to watermark a series of images for a slideshow in a website. I have noticed however that the image() function hogs the CPU on my computer. To help the problem, I am initially loading the page and then setting timeouts reasonably apart to separate the writing to the canvas (which I believe is the source of the issue?). When I am writing the watermarks the page gets pretty laggy because it's eating up all the CPU.

Do you have any suggestion for how to implement your library on a list of images?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.