"Inspiration is Beauty"
The Watermark Conundrum
April 30, 2015         (updated on April 20th, 2017)

For this blog post I’m going to step into the quagmire that is watermarking. This is something I’ve toiled over, trying to figure out the best solution for me and my business. If you’re reading this you may be in the middle of your own internal conflict. Considering how difficult a task it was for me to figure out, and the limited amount of information I could gather, I thought it might be useful to share my own trials and tribulations.

a nice image no obstructions.

A nice image no obstructions but not informative either.

Whoa.. What's all that's gibberish!!! This just ruins the image.

Whoa.. What’s all that gibberish!!!
This just ruins the image.

The opposing forces I struggled with were maximizing the quality of my prized images vs. protection and branding. You work really hard to create inspiring and beautiful pictures. The last thing you want to do is smear a giant hot mess of legalese and advertising all over it. On the other hand most of us photographers post images to further our business and attract clients. How do you implement a solution that satisfies both opposing needs. UGH!!!!

After far too much research, taking too many notes, going in too many circles, and way too much tequila. I finally came to the conclusion that the main reason for posting images to the internet is to promote my business. So I can be profitable and stay in the business of making more beautiful pictures! This was a huge euphony for me, coming to that conclusion removed a lot of noise that was distracting.

Coming to the understanding that my images speak for my business, I needed to figure out what and how to brand them. Every marketing/branding book and blog post I’ve ever read, reiterated the same mantra: “To have an effective branding campaign you must be consistent and everything should tie together” Okay, got it!, putting that at the top of my list of requirements.

At this point I know I should brand my images and it needs to be consistent. But what information is important enough to warrant the possible distraction to my beautiful pictures?

My business name seemed the most obvious, but to be honest, I don’t think a business name is unique enough in the current flat world 1 we are living in today. To make sure a potential client or customer finds me and not some other Martin business, I decided my website address would be the most precise target I could provide.

I’d rather start a conversation with someone who’s asking about permissions rather than having one that starts with a DRM take down notice.

Second on my list was a copyright notice. Let’s face it, once you post an image to the internet it’s out of your control and there will be people who use it without your permission. You will have to accept a certain amount of this, the best you can hope for is it to minimize it. It’s too expensive and draining to track down every misappropriated image. So why not be proactive from the very beginning!

Even with the risk of unauthorized use I still think the copyright notice is of great value. Number one, it shows due diligence on my part as the owner to protect my work. Number two, it clears up any confusion to as to whether the image is owned or public domain. Which I think helps people looking for imagery on the internet understand an picture’s provenance.

So adding the copyright notice makes a lot of sense to me. I’d rather start a conversation with someone who’s asking about permissions rather than one that starts with a DRM take down notice.

The copyright message and the website address were the two bits of information I thought were valuable enough to append to my images. The next question is how do I do that without completely ruining the beauty and message of my pictures. For this I looked to the art industry.

All the art museums I’ve been to usually have a small unassuming note next to the art pieces stating things like: the title, artists name, and other interesting facts. Why can’t I do that to my photographs?

Well first off there’s no way I can make sure there’s a little note following my images throughout their travels on the internet. However sometimes that little note is attached to the bottom of the frame. If my information is small enough I could append it to the bottom of my works of art!

This is not a bad solution. People are already accustomed to viewing art and subliminally ignoring frames. Adding something to the bottom of an image would not be much different. My information would be apart the image and minimally obtrusive.

A normal everyday nice pretty image.

A normal everyday nice pretty image.

Same image signed and information appended. I don't think it's very obtrusive.

Same image signed and information appended.
I don’t think it’s very obtrusive.

Now I know what you’re thinking, yea but anyone with simple photo editing software can clip the bar off the bottom. I thought that same thing and this brought me to my next step.

I saw a video produced by Aaron Nace at Phlearn about how to make a signature or logo and embed it into an image. I thought “WOW!” Most of the world’s famous painters sign their work, why not carry on that same tradition.

A nice stylized signature embedded in the image is much more difficult to remove. Not impossible mind you, just more difficult. The added difficulty of removing the signature brings with it an obvious attempt by someone to misappropriate an image. If I ever do end up in court I should have a stronger case that it was deliberate and malicious.

By and large I’m a fairly easy going person and would rather settle any disputes in a normal business negotiation fashion. However, if for whatever reason someone forces me into court, I want the deck stacked in my favor as much as possible. Hopefully by clearly signing and copyrighting my images I’m doing just that.

At this point I think I have met all my requirements: identified my work, labeled the work as copyrighted, how I can be reached, minimized infringements, and maintain the artistic quality of the image.

There is just one last little thing that needs to be addressed. Previously I mentioned that branding needed to be consistent and relative. For me to manually implement all the above modifications on every images I post would prove very time consuming (a.k.a. costly) and wouldn’t be very consistent.

Software automation is the key to solving the consistency and time issue. I know Lightroom has a watermark tool and it works well but it doesn’t address all the features I have identified for myself. For me, a custom Photoshop script was be the best solution.

Being a programmer in a former life, it didn’t take me much to the cobble something together. Realizing a lot of my photography friends are facing this exact same issue, but do not possess the programming skills I do, I decided I would share my work. It may not be exactly what you want, but by providing commented and working code gives everyone an advanced starting position.

/* Adobe Photoshop JavaScript action to append a copyright string
   and signature/logo watermark to an image for publication to the
   internet.  
   
  This script is really designed for automation and consistency
  as such it doesn't have much in the way of a user interface.
  The values in the user array (below) can be customized in any text 
  editor to fit your needs. 
  (SEE NOTES AT THE BOTTOM OF THIS FILE FOR MORE INFORMATION!)
  
   Copyright 2015 TR.Martin Designs LLC.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. 
*/


//Global Variables
var user = {                                                // Object for values the user can customize.
         copyright:  "© %y [COMPANY NAME]     [OWNER URL]",      // Copyright string ('%y' will be replaced w/ current 4 digit year)
        CopyrightHeight: 20,                                    // Height of copyright message at bottom of image (in pixels)         
        JpgQuality: 8,                                          // Quality of JPEG image to output. (0-12)        
        SignatureUri:  "",                                      // Path to signature image (Adobe syntax, (See Footnote B @ bottom of file.)
        RelativeSigSize: .05,                                   // Relative size of signature image to the master image (percentage)       
        SigYMargin: .01,                                        // Margin between signature & edge of image (percentage)
        SigXMargin: .05,                                        // Margin between signature & bottom of image (percentage)
        SigOpacity: 60,                                         // Opacity of the signature image overlay. (0-100) 
        Debug: 0                                                // Debug script(0=off,1-on) Saving & auto closing are disabled. 
};

var Thefiles = null;                                            // Selected files, default to no files
var Filter = "Files:*.jpg,All Files:*.*"                        // Filter for the file picker.
var SigFilter = "Files:*.png";                                  // Filter for the file picker.
var OnePxRes = 72;                                              // Container for ugly 1px workaround, default 72ppi
var ImageCount = 0;                                             // Counter of images we signed.
var Help = "This script will append a copyright string & Signature overlay to the bottom of selected image(s)\
for use to on the Internet such as social networking\n\n Would you like to continue?";

/* Simple debug routine that honors the user debug flag. 
   Input: string to put in dialog box.
   Output: dialog box w/ message
*/
function squirt(s){
    if(user.Debug){alert(s);}
}

/* Set the application to a known default state before we begin.
   The foreground & Background colors may not be @ their default values,
   make sure to set them. Otherwise the background will be wrong!
   All our calculations are done in pixels so make sure that's the
   measurement unit.
   Input: nothing
   Output: value set and other goodness
*/
function SetDefaults(){

    var origianlRulerUnits = app.preferences.rulerUnits;    // we will be working in pixels 
    app.preferences.rulerUnits = Units.PIXELS;

    var black = new SolidColor();                           // create some new color objects
    var white = new SolidColor();    
    black.rgb.red = 0;                                      // set the Black values
    black.rgb.blue = 0;
    black.rgb.green = 0;
    white.rgb.red = 255;                                    // set the White values
    white.rgb.blue = 255;
    white.rgb.green = 255;    
    
    app.foregroundColor = black;                            // Load new colors into the brush palette 
    app.backgroundColor = white;                            // foreground = black , background = white
}

/* Ugly work around for bug in Photoshop JavaScript API. If someone has set the 
   image resolution to 1 pixel, the artlayer.translate() method gets confused &
   will not move the layer properly. The work around is to check for this condition, 
   if present change image resolution to 72ppi do our work then set it back to the 
   original 1ppi.
   Input: Document Object reference, and Resolution container
   Output: Resolution either set to value stored in container 
           Return old resolution
*/
function OnePxFixUp(docRef,res){
    var OldRes = docRef.resolution;
    docRef.resizeImage(docRef.width,docRef.height,res,ResampleMethod.BICUBIC);
    return(OldRes);
}

/* Get the aspect ratio of the signature image to keep things consistent when scaling it down. 
   Input: Adobe bounding box tuple 
   output: Aspect Ratio of box. (should be less than 1)
*/   
function GetAspectRatio(bounds){
    var w = (bounds[2]-bounds[0]);
    var h = (bounds[3]-bounds[1]);
    var ar = (w/h);
    if(w > h){                    // if width is larger swap the dividend/denominator
        ar=(h/w);
    }
    return(ar);
}

/*verify the signature file is present and accessible 
  Input: object with user values.
  Output: boolean True = file reachable false= file not found 
*/  
function VerifySigFile(sig){
    var sigfile = new File(sig);
    if(sigfile.exists){
        return true;
    }else{        
        alert("Can't find signature file!");
        return false;
   }
}

/* Build the name we will use for saving the new watermark'd/signed file.
   Start with the fileObj path ... add a trailing separator "/"
   split the file name from it's extension using regular expression split function at the period.
   append "_sd" to the root filename for "_SigneD" ... put the period separator back
   and finally append the extension.
   Input: <filename.ext> 
   output: <filename_SD.ext>
*/   
function getOutputFileName(fileObj){

    var str = fileObj.path +"/"
    var nameExt = fileObj.name.split(/\./);
    str = str + nameExt[0] + "_SD." + nameExt[1];
    return (str);
}

/* Save the newly signed image.
   Input: Output File object (not the name, a File object)
          the JPEG quality value to use when saving.
   Output: File saved next to input file with '_SD' appendage
*/
function saveImage(fo, Quality){

    jpgSaveOptions = new JPEGSaveOptions();                                 // Tell Photoshop how to 
    jpgSaveOptions.embedColorProfile = true;                                //   save the new .JPG
    jpgSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;          //   image to file.
    jpgSaveOptions.matte = MatteType.NONE;                                  //
    jpgSaveOptions.quality = Quality;                                       //
    
    app.activeDocument.saveAs(fo, jpgSaveOptions, true,Extension.LOWERCASE);// Save the signed image.
}


/* Create a layer for the background and fill it with the foreground
   brush color. In this case the default black.
   Input: document object
   output: background layer created & painted
*/  
function DoBackground(docRef){

    var layerRef = docRef.artLayers.add();        
    layerRef.name = "Background";        
    layerRef.move(docRef.artLayers[docRef.artLayers.length-1],ElementPlacement.PLACEAFTER);
    docRef.activeLayer = docRef.artLayers.getByName("Background");              
    docRef.selection.fill(app.foregroundColor)
}

/* Write the copyright string to the image in the correct location, font, color, etc.
   Input: User values object
          Reference object to document
   Ouput: Copyright string written to it's own layer          
*/
function WriteCopyrightString(docRef, Sig){

    // create font color object.
    var textColor = new SolidColor();
    textColor.rgb.red = 255;
    textColor.rgb.blue = 255; 
    textColor.rgb.green = 255; 
    
    // create the new text layer
    var textlayer = docRef.artLayers.add();
    textlayer.name = "Copyright";
    textlayer.kind = LayerKind.TEXT;
    
    // write to the new text layer
    var textItemRef = docRef.artLayers["Copyright"].textItem  
    textItemRef.font = "Verdana";                                               // See Footnote A @ bottom of file.   
    textItemRef.justification = Justification.CENTER;
    textItemRef.color = textColor;
    var date = new Date();
    var year = date.getFullYear();
    textItemRef.contents = Sig.copyright.replace(/%y/,year);       
       
    // MATHY MATH MATH....    
    // 72pts = one inch and res = pixels per inch of image.
    // to calculate the size of the font, use the following math:
    // 90% height of the copyright box x points per inch (72) / the resolution of the image = size of font in points.
    textItemRef.size = ((72*(Sig.CopyrightHeight*0.9))/docRef.resolution);                    
   
    //the text base line needs to be calculated to account for the decent
    // the x coordinate is simple, centered in the middle of the image.
    // the y coordinate is a little more tricky, the font baseline does not account for the font decent
    //       so I'm setting the base point to 25% of the copyright box height from the bottom of the image.
    //       it's not perfect but it's good enough to handle 72-300ppi & heights of 20px to 80px.
    textItemRef.position =[(docRef.width/2),(docRef.height-(Sig.CopyrightHeight/4))];                                                                                     
} 

/* find the most frequent color in the list.
   Input: array with SolidColor Ojects
   Output: SolidColor Object of most freq color found.
*/   
function MostFreq(colors){ 
    var popular = colors[0];
    var PopularCount = 1;
    var temp = 0;
    var tempCount;    
    
    for(var i = 0; i < (colors.length - 1); i++){               // test current color w/ current winner 
        temp = colors[i];
        tempCount = 0;
        for (var j = 1; j < colors.length; j++){                // Get freq of current color
            if (temp.rgb.hexValue == colors[j].rgb.hexValue)    // test the actual color value.
            tempCount++;
        }
        if (tempCount > PopularCount){                          // if current color >freq than current
            popular = temp;                                     // winner, unseat winner
            PopularCount = tempCount;
        }
  }
  return popular;       
}

/* Overlaying the signature is not as easy as just pasting to into a layer.
   It must be legible, for this we must take luminescence, contrast, & temp into account. 
   I think cool images look best with White signatures & warm with Black .
   To achieve this we will use an averaging and frequency test of the background 
   with in the bounds of signature 'box' where the image will be overlayed.  
   Input: Document Object reference
          bounding box tuple.
   Output: signature recommendation 1 = black, 0 = white
*/
function BlackSignature(DocRef, box){
    var BLACK = 1;                              // Names for return value
    var WHITE = 0;
    var WARM2DARK = 55;                         // Avg. warm background too dark swith to white
    var COOL2LITE = 21;                         // Avg. cool background too lite switch to black
    var GRAY_POINT = 47;                        // Test point for B/W image Range: White(0...100)BLACK 
    var WARMMINANGLE = 74;                      // use HSV/HSB Hue angle to determine cool temp 
    var WARMMAXANGLE = 350;                     //   range
    var xit = (((box[2]-box[0])*10)/100);       // Sample size ~100 pixels of box for avg.
    var yit = (((box[3]-box[1])*10)/100);       //
    var colors = new Array()                    // List of sampled colors in box
    var sampler;                                // Handle for Photoshop color smapler/picker 
    var grays=0;                                // Container for grayscale values
    var popular;                                // Container for most freq color in box
    var shade;                                  // Avg grayscale color in box
    var Decision;                               // Container for result to send to caller
    
    for(x=box[0]; x < box[2]; x+=xit){                  // read sampled background colors in box
        for(y=box[1]; y < box[3]; y+=yit){              //   & grays for popular and avarage 
            sampler = docRef.colorSamplers.add([x,y]);  //   values.
            colors.push(sampler.color);
            grays += sampler.color.gray.gray;              
            sampler.remove();                           // Clear picker so we can use it again.
        }
    }
    popular = MostFreq(colors);                 
    shade = (grays/colors.length);                      // calculate avarage grey color of box  
    squirt("Shade= " + shade + "\npopular= " + popular.rgb.hexValue + "\nHue= " + popular.hsb.hue );

    // Decide what color of signature we are going to use (Black or White)
    Decision =BLACK;                                    // default to Black and see if we need to change it.
    if(popular.hsb.saturation < 10){                    // if saturation is low it's probably a B/W image
        if(shade > GRAY_POINT){ 
            squirt("image greyscale, using white " + shade);
            Decision = WHITE;
        }
    }else{                                              // not a B/W image use color temp to decide.
        if((popular.hsb.hue > WARMMINANGLE)&&(popular.hsb.hue < WARMMAXANGLE)){      //cool color
            squirt("image cool using white " + shade);         
            if(shade > COOL2LITE){                      // is cool image too light?
                squirt("Cool image ok" );
                Decision = WHITE;
            }
        }else{                                          // image is warm
            squirt("image warm using black " + shade); 
            if(shade > WARM2DARK){                      // Is warm image too dark ?
                squirt("Override Warm image too dark!" );         
                Decision = WHITE;                                      
            }
        }
    }
    return Decision;
}

/* Change the size of the signature image so it's what the user wants in respect to size 
   of the master image and put it in the lower right corner. 
   Input: width & height of master image
         reference to the signature layer object
         reference to the user values  
   Output: Signature image resized and located.
*/   
function ResizeSignature(ImgX, ImgY, siglayer, Sig){

    var YMargin = (ImgY * Sig.SigYMargin);
    var XMargin = (ImgX * Sig.SigXMargin );
    var SmallerSigWidth = 0;
    var SmallerSigHeight = 0;
    var AspectRatio = GetAspectRatio(siglayer.bounds);         // Get aspect ratio of the signature to reduce it evenly

    // Calculate the reduced size of the long edge of the signature image.
    //   The math we use is a percentage of the image volume to determine the volume of the signature image.
    //   Then we convert that reduced volume value to a linear value for the long edge. 
    var LongEdge = Math.sqrt((ImgX * ImgY) * Sig.RelativeSigSize * AspectRatio);
    
    SmallerSigWidth = LongEdge;                                 // Width is the long edge so it gets the full X value.
    SmallerSigHeight = (LongEdge * AspectRatio);                // and height is a fraction of the X value.
    if((siglayer.bounds[3]-siglayer.bounds[1])> (siglayer.bounds[2]-siglayer.bounds[0])){
        SmallerSigHeight = LongEdge;                            // Height is the long edge so it gets the full X value
        SmallerSigWidth = (LongEdge * AspectRatio);             // and the width is a fraction of the X value.       
    }
    
    // resize the signature image; the Adobe resize function wants a % of the original
    siglayer.resize(((SmallerSigWidth / (siglayer.bounds[2]-siglayer.bounds[0])) * 100), 
                    ((SmallerSigHeight / (siglayer.bounds[3]-siglayer.bounds[1])) * 100), 
                      AnchorPosition.TOPLEFT);   

    // move sig to lower right corner. 
    siglayer.translate((ImgX - (siglayer.bounds[0] + SmallerSigWidth + XMargin)), 
                       (ImgY - (siglayer.bounds[1] + SmallerSigHeight + YMargin + Sig.CopyrightHeight))); 
}

/* Entry point to putting the signature image into the collateral image.
   #1 place image on its own layer within the main image
   #2 resize the image.
   #3 reposition the image.
   #4 determine if image is best black or white. 
   an we're done!
   Input: width & height of master image 
          Sig object with user values
   Output: Signature placed in image
*/   
function PlaceSignature(width, height, Sig){
    var lumosity = 0;

    var fileObj = new File(Sig.SignatureUri);
    app.load(fileObj);                                          //load it into a document
    TempSigFile= app.activeDocument;                            //prepare your image layer as active document
    TempSigFile.selection.selectAll();
    TempSigFile.selection.copy();                               //copy image into clipboard
    TempSigFile.close(SaveOptions.DONOTSAVECHANGES);            //close image without saving changes
    // create the new text layer
    var siglayer = app.activeDocument.artLayers.add();
    siglayer.name = "Signature";
    siglayer.kind = LayerKind.NORMAL;
    app.activeDocument.paste();                                 //paste selection into your document
    
    ResizeSignature(width, height,siglayer, Sig);
    siglayer.blendMode = BlendMode.LINEARLIGHT;                 // change blending mode.
    siglayer.opacity = 0;                                       // temp disable sig so we can sample the base image    
    if(BlackSignature(docRef,siglayer.bounds)){                 // Check to see what signature we use black or White.
       siglayer.invert();
    }
    siglayer.opacity = Sig.SigOpacity;                          // Return signature opacity to user value    
}



/******************************************************************************/
/***************************  Script Entry Point  *****************************/
/******************************************************************************/
SetDefaults();                                                          // make sure the app in the state we need.

if(confirm(Help)){                                                      // Give user an out if accidently started script.

    Thefiles = File.openDialog("Select files to Watermark",Filter,1);   // Bring up OS file picker so user can pick files
}

if(user.SignatureUri.length == 0){                                      // If no predefined signature file, ask user for one.
    user.SignatureUri = File.openDialog("Select Signature File",SigFilter,0);    
}

if((Thefiles != null) && VerifySigFile(user.SignatureUri)){             // Make sure the user picked at least 1 file & 
                                                                        //    we can read the sig file before we begin.
    for(var i=0;i<Thefiles.length;i++){
        
        var fileIn = new File(Thefiles[i].fsName);                      // Create file OBJ for Open()
        var fileOut = new File(getOutputFileName(Thefiles[i]));         // Create file OBJ for save()
        
        // NOTE: we only work with .JPGs, no need to set open options. 
        var docRef = app.open(fileIn);                                  // Open the requested image document.
        app.activeDocument = docRef;                                    // Belt & Suspenders, make sure opened doc is active doc.
        
        // 1 Pixel workaround 
        if(docRef.resolution == 1){ OnePxRes = OnePxFixUp(docRef,OnePxRes); }
        
        // Massage the original background layer for editing. 
        docRef.backgroundLayer.isBackgroundLayer = false;               // Make JPG default background layer editable.
        var newname = "image (" + (ImageCount+1) + "-" + Thefiles.length + ")";
        docRef.artLayers[0].name = newname;                             // Rename the old background layer "image x of n" 
        
        // Make room for the copyright string at the bottom of the image.        
        docRef.resizeCanvas(docRef.width,(docRef.height + user.CopyrightHeight),AnchorPosition.TOPCENTER)         
                
        // Create layer & paint background
         DoBackground(docRef);                
        
        // Write the copyright string in the new space at the bottom of the image.
        WriteCopyrightString(docRef, user );          
       
      
        // Open signature image in a new layer, scale it, move to lower right corner, change blend mode. 
        PlaceSignature(docRef.width,docRef.height,user);
      
        // 1 Pixel workaround
        if(OnePxRes == 1){ OnePxRes = OnePxFixUp(docRef, OnePxRes); }

        if(!user.Debug){        
            saveImage(fileOut,user.JpgQuality);                             // Save new image & Exit.
            docRef.close(SaveOptions.DONOTSAVECHANGES);                
        }
        ImageCount++;
    }
    var plural = ImageCount > 1 ? "s" : "";
    alert(ImageCount + " Image" + plural + " Signed!.... We're Done!    "); // Let the user know we've reached completion.
}


/*
FOOTNOTE A:
  So originally I tried to use a mixture of get font by name and some regex 
  but it was problematic. The postscript names in the 'textItem' I was 
  looking for were extremely obscure. 
  (e.g. "Arial" the universal font is "ArialMT")
  If this becomes a problem I can look into expanding this function, but for 
  now just use "verdana" or manually put the font name in.
  
FOOTNOTE B:
  Adobe uses an abstracted syntax for their pathes. This abstracted 
  path will be converted to an OS dependent string before it's passed on. 
  See the 'Adobe JavaScript Tools guide' chapter 3: File system access.
  from the SDK.
  WINDOWS - /C/PATH/TO/FILE/FILE.PNG      
  MAC OS  - /VOLUME/PATH/TO/FILE/FILE.PNG
*/  
  

/*
There are some assumptions this script makes:

  You're familiar with installing scripts in Photoshop. If not,
  basically you need to copy this script to the presets\scripts
  folder and restart Photoshop. The root file name becomes the 
  menu option under file\scripts. If you need more info you'll
  need to do some internet research. A detailed explanation is
  too much for me to describe here.
  
  Your signature file is a Portable Network Graphics (PNG) file.
  The image is white with a transparent background. The code 
  will determine if a black signature or white signature looks
  best for the image. For best result make sure the image is large,
  approximately 2000 x 3000 pixels. the script will scale it to fit 
  the image you're signing.

Here is some more information on using the script:
  
  If you manually fill in the 'SignatureUri' in the user object
  at the top of this file it will assume that file is the one to 
  use and not bring up the file picker dialog box and ask you to 
  select a signature file. a time saving feature for automation.
  
  If the copyright string is wider than the image to be signed
  it will clip the string. I may fix this later but for now I've 
  only had this problem with images less than 400px wide. 
  
  When you're using the script to sign multiple files you can keep
  track of the progress by looking at the image layer name. It will
  say something like 'image (3-32)' meaning it's working on image #3
  of the 32 images you selected.
     
  If you watch the script execute you will notice what appears to be a 
  pause, this is normal. The script is sampling the image and it takes a
  while. It should not last more than 5 seconds or so depending on the
  speed of your system. For performance make sure the move tool is the 
  active tool in the tool bar, for some reason if certain tools like the
  brush tool are active the sampling slows down.
         
  There is a debug flag that will stop the script from automatically
  closing the image when it's done. This is helpful if you want to tweak the
  user values or the code. It will also pop up dialog boxes with internal 
  values it's calculated. 
   
  This script is not 100% perfect, there are some conditions where averaging
  and frequency analysis do not choose the best overlay color (black or white).
  Usually it's where the colors under the overlay are high contrast or very
  complex. These cases are pretty infrequent, however it's recommended to 
  review the signed images once the script is complete.
 
  Feel free to use this script 'as is' or modify it to meet your needs.
  I have taken extra steps in the architecture of the code to make it
  easier for modification. If you're uncomfortable with programming 
  or JavaScript, any skilled programmer should be able to help you out.
  Other than some tricky math this script is pretty simple to read. 
  the Adobe 'Photoshop-CS?-Javascript-Ref.pdf' contains all the application
  object descriptions and is very helpful. 
*/ 

If you want a copy of the script all you need to do is highlight all the code in the window, then copy and paste it into a text editor 2. Once it’s copied to your system you can save it using any name you want with the .JSX extension. If you don’t use the .JSX extension Photoshop will not recognize it as a script. Then it’s a simple matter of putting the file in the presets/scripts folder in your Photoshop install 3.

This delivery method is a little odd, but considering how dangerous it is to download stuff from the internet. I thought a safer solution would be to publish the source code and let users just cut and paste it, eliminating the worry of viruses and other unsavory things.

watermark2

That’s pretty much my solution to this sticky mess. My images are my businesses calling card, people know they’re managed, potential clients can find me on the internet, the images are aesthetically whole, and finally automate everything so it’s consistent and quick.

I know my solution is not perfect for everyone, but I thought by sharing what I learned, my thought process, and my implementation. I might be able to ease the burden and help you to a quicker resolution. Good luck and best wishes.



Enjoy,
Todd

Notes:

  1. I’m referring to Thomas Friedman’s book ‘The World Is flat’
  2. You can use notepad on Windows or TextEdit on a Mac
  3. You can find more information about scripts at Adobe here.
 

0 Responses to The Watermark Conundrum

Add Your Thoughts

Your email address will not be published. Required fields are marked *

COPYRIGHT 2024 TR. MARTIN DESIGNS