Skip to content

Instantly share code, notes, and snippets.

@PatD
Created July 2, 2020 20:13
Show Gist options
  • Save PatD/ab96e09ca1255929f5ce8ae5d4ad69cd to your computer and use it in GitHub Desktop.
Save PatD/ab96e09ca1255929f5ce8ae5d4ad69cd to your computer and use it in GitHub Desktop.
Add logo watermark to SharePoint (classic) image-renditioned photos in a Picture library.
<style>
/* We're inside an iframe */
#waterMarkedImage{
background:url('/_layouts/images/gears_an.gif') top left no-repeat;
min-height:300px;
}
</style>
<!-- Rendition choices are injected here -->
<select id="renditionPicker" style="margin-bottom:20px;">
<option>Select your size</option>
<option>Full Size [Takes a minute]</option>
</select>
<a style="float:right;" download="filename.png" href id="downloadImageLink">Download Image</a>
<br/>
<div id="waterMarkedImage"></div>
<br/>
<br /><br />
<script src="axios.min.js"></script>
<!-- https://github.com/brianium/watermarkjs -->
<script src="watermarking.min.js"></script>
<script>
// Expects to be run on a classic SharePoint DispForm.aspx page, in an iframe
// Expects axios.js for REST calls and watermarking.js plugin to apply the Logo
// Expects site collection to have at least two image renditions defined
// Plugin expects you've created a few different sized logos to watermark the image with
// Updates download link href attribute with image data, and forces-download
var downloadImageLink = document.getElementById('downloadImageLink');
function addDownloadLink(imgdata){
downloadImageLink.innerHTML= "Download " + imageFileName + ".png"
downloadImageLink.setAttribute('download',imageFileName + '.png')
downloadImageLink.setAttribute('href',imgdata)
}
// Converts loaded XML to JSON
// from https://davidwalsh.name/convert-xml-json
function xmlToJson(xml) {
// Create the return object
var obj = {};
if (xml.nodeType == 1) { // element
// do attributes
if (xml.attributes.length > 0) {
obj["@attributes"] = {};
for (var j = 0; j < xml.attributes.length; j++) {
var attribute = xml.attributes.item(j);
obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
}
}
} else if (xml.nodeType == 3) { // text
obj = xml.nodeValue;
}
// do children
if (xml.hasChildNodes()) {
for(var i = 0; i < xml.childNodes.length; i++) {
var item = xml.childNodes.item(i);
var nodeName = item.nodeName;
if (typeof(obj[nodeName]) == "undefined") {
obj[nodeName] = xmlToJson(item);
} else {
if (typeof(obj[nodeName].push) == "undefined") {
var old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push(old);
}
obj[nodeName].push(xmlToJson(item));
}
}
}
return obj;
};
// Adds <options> to select box with axios-loaded rendition data:
function buildDropdowns(loadedRenditions){
// Dropdown box is:
var renditionPicker = document.getElementById('renditionPicker');
var _drops = loadedRenditions.Renditions.ImageRendition;
_drops.forEach(function(_dropdownChoice){
// fix weird URLs in SharePoint
var _name = JSON.stringify(_dropdownChoice.Name).replace('{"#text":"','').replace('"}','')
var _height = JSON.stringify(_dropdownChoice.Height).replace('{"#text":"','').replace('"}','');
var _width = JSON.stringify(_dropdownChoice.Width).replace('{"#text":"','').replace('"}','');
var _rendition = JSON.stringify(_dropdownChoice.Id).replace('{"#text":"','').replace('"}','');
var _option = document.createElement("option");
_option.setAttribute('data-width',_width);
_option.setAttribute('data-height',_height);
_option.value = _rendition;
_option.text = _name + " - ["+ _width + " x " + _height + "]";
renditionPicker.appendChild(_option);
})
// Include full size image too? Maybe you don't want to do that.
/*
var _option = document.createElement("option");
_option.setAttribute('data-width',0);
_option.setAttribute('data-height',0);
_option.value = 'fullsize';
_option.text = "Image full size - Takes a while";
renditionPicker.appendChild(_option);
*/
};
// Axios-loads SharePoint image rendition data.
function getRenditions(){
var _renditionPath = '/_catalogs/masterpage/PublishingImageRenditions.xml';
axios.get(_renditionPath)
.then(response => {
var oParser = new DOMParser();
var oDOM = oParser.parseFromString(response.data, "application/xml");
buildDropdowns(xmlToJson(oDOM.documentElement))
})
};
// Size of our currently displayed image:
// And the default rendition number on page load
var selectedRendition = {
_rend: 20, // Number next to a nicely sized rendition choice.
_height:450,
_width:745
}
// Holds the path of the right logo size
var waterMarkLogo;
// The generated image lives here:
var waterMarkedImage = document.getElementById('waterMarkedImage')
// On page load, Locate our image path from the page
var imageToTagTag = parent.document.getElementById('webImgShrinked');
var imageToTagHref = imageToTagTag.getAttribute('src')
//var imageToTagHref = imageToTagHref.replace('/_w/','/').replace('_jpg.jpg','.jpg')
// File name for download:
var imageFileName = imageToTagHref.replace("/Pictures/_w/","").replace("_jpg.jpg","");
// Path to image:
var imageToTagHref = imageToTagHref.replace('.jpg','.jpg?RenditionId=' + selectedRendition._rend)
var imageNeedingWatermarking = imageToTagHref;
// Takes our image and watermarks it.
function waterMarkThisImage(rendURL, waterMarkLogo,imgHeight){
downloadImageLink.removeAttribute('href')
// selects the right watermark for the job
if(imgHeight < 400){
var waterMarkLogo = '80_logo.png'
} else if(imgHeight >= 400 && imgHeight <700){
var waterMarkLogo = '100_logo.png'
} else if(imgHeight >= 700 && imgHeight <1000){
// etc
} else if(imgHeight >= 1000 ){
// etc
} else if (imgHeight === undefined){
// etc
} else{
var waterMarkLogo = '80_logo.png'
}
// Clears out an existing image first
waterMarkedImage.innerHTML = "";
// Runs the watermark plugin on the page's image, using the right logo size
watermark([rendURL, waterMarkLogo])
.image(watermark.image.lowerRight(1))
.then(function (img) {
waterMarkedImage.appendChild(img);
addDownloadLink(img.attributes.src.nodeValue)
});
};
// Update watermarked image with different renditionPicker selection
document.getElementById('renditionPicker').addEventListener('change', function() {
selectedRendition._rend = this.value;
selectedRendition._height = this.options[this.selectedIndex].getAttribute('data-height');
selectedRendition._width = this.options[this.selectedIndex].getAttribute('data-width');
// Update path
var imageToTagTag = parent.document.getElementById('webImgShrinked'); // sharepoint-generated ID
var imageToTagHref = imageToTagTag.getAttribute('src')
var imageToTagHref = imageToTagHref.replace('/_w/','/').replace('_jpg.jpg','.jpg')
var imageToTagHref = imageToTagHref.replace('.jpg','.jpg?RenditionId=' + selectedRendition._rend)
var imageNeedingWatermarking = imageToTagHref
// Pass the source image, the logo to use, and the rendition height:
waterMarkThisImage(imageNeedingWatermarking,waterMarkLogo,selectedRendition._height)
});
// Init for the interface.
getRenditions();
// On load, watermarks the preview image rendition
waterMarkThisImage(imageNeedingWatermarking,waterMarkLogo, 399)
</script>
@PatD
Copy link
Author

PatD commented Sep 18, 2020

Some additional notes about how this works:

  • First, this code assumes your SharePoint site has Image Renditions enabled. If you only have one size image you need to watermark, you'll have to update the code to remove it.

  • Has to be in a Classic Picture library, use the Gear icon to edit DispForm.aspx. Then, copy and paste the code into a new Script Editor Web Part on that DispForm.aspx page.  The watermarking occurs on that page.

  • You'll need to include references to script tags on line 24 and 26 to these JS libraries:
    https://github.com/axios/axios
    https://github.com/brianium/watermarkjs

    I put mine in a Site Assets library. 

  • The Picture Library will need at least one image in for this to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment