Skip navigation
ChrisRJ
Currently Being Moderated

How to create an action to insert hundreds of different numbers for limited edition prints?

Mar 7, 2013 8:24 PM

Tags: #action #signature #numbers

Hi,

I sell limited edition prints of a run of between 350 and 500.

I am trying to get it set up so that my signature and the print number is included as part of the print. Here is an example:

 

 

You'll see at bottom left there is my signature and underneath is is the print number e.g. 110/350 (this is legible when printed at 18x12" size).

Inserting the signature and the "/350" is easy since it only needs to be done once per image.

The difficulty comes with inserting the actual print number e.g. "110"

 

At the moment I have 0 to 9 written out and scanned in as separate numbers. So to make "110" I use the "1" digit twice, plus the "0" digit. I.e. I haven't written out 1 to 500 and scanned them in all as separate numbers, I've just done the 10 digits and use those 10 digits to make all the different numbers I need.

 

Is there a way to create an action that will create say 350 JPEG copies of the original file, each one with its own unique print number inserted? (And ideally automatically saved with the print number as its file name!)

 

Many thanks in advance

 
Replies
  • Currently Being Moderated
    Mar 7, 2013 11:05 PM   in reply to ChrisRJ

    Please ask for help over at

    http://forums.adobe.com/community/photoshop/photoshop_scripting

     

    Maybe you could also check out »Creating data-driven graphics« in the Reference, but I would recommend a custom Scripting solution.

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 7, 2013 11:18 PM   in reply to ChrisRJ

    At the moment I have 0 to 9 written out and scanned in as separate numbers. So to make "110" I use the "1" digit twice, plus the "0" digit.

    One problem with this might be spacing of the numbers.

    When you consider how badly even professional fonts »fail« at times with numbers like 2011 (I mean the distance between the 1s compared to the distance between 2 and 0) it might take some finagling to get the numbers-layers to fit properly and aesthetically pleasingly without controlling them all individually.

     
    |
    Mark as:
  • JJMack
    5,995 posts
    Jan 9, 2006
    Currently Being Moderated
    Mar 8, 2013 6:52 AM   in reply to c.pfaffenbichler

    I don't think that numbers and fonts spacing would be a problem for Actions and Scripts for there is no problem aligning a text layer.

     

    An Action would be hard to create though to add a serial number for you would need to have a step for each serial number of so many. You would need a save step  to go with the text step to name the file.  Scripting it is a much better solution.

     

    A script  would have no problem at all.  It would have a dialog that has a input file selection and output folder selection and field for number of print file.  Additional labeling fields can also be in the dialog  for thing like title, date etc. The output file names would be File-Name-serial.ext The script would simply open the source Image file then for number of prints Dupe the  doc add the needed border and a text layers top left image area with Title, with the date and with the series print number and of number of prints in the series.  These text layer would then be aligned to the border left, center or right. then save the print file. The addition of the border could be moved out of the loop and only need be done once.

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 8, 2013 6:55 AM   in reply to JJMack

    I don't think that numbers and fonts spacing would be a problem for Actions and Scripts for there is no problem aligning a text layer.

    But alignment bears keeping in mind when creating the Layers.

    With Screen Layers with the text in white on larger black backgrounds for example the edges would naturally affect the alignment.

    In any case running a couple of tests with various combinations of numbers might be a good idea.

     
    |
    Mark as:
  • JJMack
    5,995 posts
    Jan 9, 2006
    Currently Being Moderated
    Mar 8, 2013 7:20 AM   in reply to c.pfaffenbichler

    The Image size and resolution need to be taken into account.  You do not want to add to big of a border.  Once you know the number the pixels height of the bottom border you can set the document DPI resolution to 72dpi and set a good font size for that height when adding the text layers.  Once the text is added and aligned Left, Center, Right the Image Resolution can be restored so it prints correctly.  The Border and some labeling can be done outside the look only the sequence number need be done in the loop.  The border can be added to the source doc resolution changed to 72dpi font size set and some labeling done.  Inside the loop the serial added and aligned thn document resolution restored and print file saved. When the loop end the original document is just closed no save.

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 8, 2013 7:24 AM   in reply to JJMack

    If I understood the OP correctkly the numbers are not supposed to be created as type layer/s but combined from scanned hand written numbers.

     
    |
    Mark as:
  • JJMack
    5,995 posts
    Jan 9, 2006
    Currently Being Moderated
    Mar 8, 2013 7:57 AM   in reply to c.pfaffenbichler

    Yes scanning is harder from his image  where the bounds of the serial overlay part of the signature makes it even harder.  I see no reason though to use scanned numbers it just to make the job harder then need be. There are so may good script fonts available why use scanned numbers that make aligning the serial numbers themselves hard and it will not scale well for it will be a pixel layer not text layer.  You can get the bounds of a placed scaned Signature png then scale and move it to the lower left.  You can also gets the bounds of a text layer and scale it and align it to an selection that has a top right corner within the bounds of the sized and position scanned signature.

     

     

    The signature and serial is going to be part of the print not hand written with white ink after all.

     
    |
    Mark as:
  • JJMack
    5,995 posts
    Jan 9, 2006
    Currently Being Moderated
    Mar 9, 2013 3:28 PM   in reply to ChrisRJ

    Many Fonts are proportional they are design to space correctly and the spacing can be tweaked. Adobe was in the font business before there was a Photoshop. Adobe started in 1982 developing Postscript which they marketed in 1984  Photoshop first release was 1989.

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 10, 2013 4:06 AM   in reply to ChrisRJ

    This Script might be able to do some of what you wanted (the startNumber and endNumber would have to be set in the Script).

    It needs a Layer Group named »numbers« to contain layers for the numbers named »0«, »1«, …

    numbersScr.jpgnumbersScr2.jpg

    (script edited)

    // this script saves jpg copies with numbers created from number-layers in a layer group;
    // use it at your own risk;
    #target photoshop;
    if (app.documents.length > 0) {
    // define the numbers to create;
    var startNumber = 290;
    var endNumber = 310;
    // set to pixels;
    var originalRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.PIXELS;
    // get doc;
    var myDocument = app.activeDocument;
    // getting the name and location;
    var docName = myDocument.name;
    var baseName = docName.match(/(.*)\.[^\.]+$/)[1];
    //getting the location;
    var docPath = myDocument.path;
    // duplicate the image;
    var thecopy = myDocument.duplicate (thecopy, false);
    // jpg options;
    var jpgopts = new JPEGSaveOptions();
    jpgopts.embedProfile = true;
    jpgopts.formatOptions = FormatOptions.STANDARDBASELINE;
    jpgopts.matte = MatteType.NONE;
    jpgopts.quality = 9;
    // get number layers;
    var numberSet = thecopy.layers.getByName("numbers");
    // collect in an array;
    var theNumbers = [numberSet.layers.getByName("0"), numberSet.layers.getByName("1"), numberSet.layers.getByName("2"),
    numberSet.layers.getByName("3"), numberSet.layers.getByName("4"), numberSet.layers.getByName("5"),
    numberSet.layers.getByName("6"), numberSet.layers.getByName("7"), numberSet.layers.getByName("8"), numberSet.layers.getByName("9")];
    numberSet.visible = true;
    // proceed if all numbers have been found;
    if (theNumbers.length == 10) {
    // hide layers;
    for (var n = 0; n < numberSet.layers.length; n++) {
    numberSet.layers[n].visible = false
    };
    var theState = thecopy.activeHistoryState;
    ////////////////////////////////////
    // process the numbers;
    for (var m = startNumber; m < endNumber + 1; m++) {
    // the position;
    var theHor = 500;
    // create an array for the new numbers;
    var theArray = new Array;
    // the number;
    var thisString = String(m);
    // duplicate layers to create the numbers;
    for (var o = 0; o < thisString.length; o++) {
    var theNumberLayer = theNumbers[Number(thisString[o])];
    // create copy;
    var theLayer = duplicateMoveRotateScale (theNumberLayer, theHor - Number(theNumberLayer.bounds[0]), 0, 100, 100, 0);
    theNumberLayer.visible = false;
    //alert (m+"_"+o+"\n"+theNumberLayer+"\n"+theLayer);
    // set the hor to edge of the new layer;
    var theHor = theLayer.bounds[2];
    theArray.push(theLayer);
    };
    // get the number for the file name;
    var theNumber = bufferNumberWithZeros(m, String(endNumber).length);
    //save jpg;
    thecopy.saveAs((new File(docPath+"/"+baseName+"_"+theNumber+".jpg")),jpgopts,true);
    // remove copied layers;
    //for (var p = theArray.length - 1; p >= 0; p--) {theArray[p].remove()};
    thecopy.activeHistoryState = theState;
    };
    };
    // close copy;
    thecopy.close(SaveOptions.DONOTSAVECHANGES);
    // reset ruler;
    app.preferences.rulerUnits = originalRulerUnits
    };
    //that’s it; thanks to xbytor;
    ////// buffer number with zeros //////
    function bufferNumberWithZeros (number, places) {
              var theNumberString = String(number);
              for (var o = 0; o < (places - String(number).length); o++) {
                        theNumberString = String("0" + theNumberString)
                        };
              return theNumberString
              };
    ////// duplicate layer and move, rotate and scale it //////
    function duplicateMoveRotateScale (theLayer, theX, theY, theScaleX, theScaleY, theRotation) {
    app.activeDocument.activeLayer = theLayer;
    try{
    // =======================================================
    var idTrnf = charIDToTypeID( "Trnf" );
        var desc10 = new ActionDescriptor();
        var idnull = charIDToTypeID( "null" );
            var ref6 = new ActionReference();
            var idLyr = charIDToTypeID( "Lyr " );
            var idOrdn = charIDToTypeID( "Ordn" );
            var idTrgt = charIDToTypeID( "Trgt" );
            ref6.putEnumerated( idLyr, idOrdn, idTrgt );
        desc10.putReference( idnull, ref6 );
        var idFTcs = charIDToTypeID( "FTcs" );
        var idQCSt = charIDToTypeID( "QCSt" );
        var idQcsa = charIDToTypeID( "Qcsa" );
        desc10.putEnumerated( idFTcs, idQCSt, idQcsa );
        var idOfst = charIDToTypeID( "Ofst" );
            var desc11 = new ActionDescriptor();
            var idHrzn = charIDToTypeID( "Hrzn" );
            var idPxl = charIDToTypeID( "#Pxl" );
            desc11.putUnitDouble( idHrzn, idPxl, theX );
            var idVrtc = charIDToTypeID( "Vrtc" );
            var idPxl = charIDToTypeID( "#Pxl" );
            desc11.putUnitDouble( idVrtc, idPxl, theY );
        var idOfst = charIDToTypeID( "Ofst" );
        desc10.putObject( idOfst, idOfst, desc11 );
        var idWdth = charIDToTypeID( "Wdth" );
        var idPrc = charIDToTypeID( "#Prc" );
        desc10.putUnitDouble( idWdth, idPrc, theScaleX );
        var idHght = charIDToTypeID( "Hght" );
        var idPrc = charIDToTypeID( "#Prc" );
        desc10.putUnitDouble( idHght, idPrc, theScaleY );
        var idAngl = charIDToTypeID( "Angl" );
        var idAng = charIDToTypeID( "#Ang" );
        desc10.putUnitDouble( idAngl, idAng, theRotation );
        var idIntr = charIDToTypeID( "Intr" );
        var idIntp = charIDToTypeID( "Intp" );
        var idbicubicAutomatic = stringIDToTypeID( "bicubicAutomatic" );
        desc10.putEnumerated( idIntr, idIntp, idbicubicAutomatic );
        var idCpy = charIDToTypeID( "Cpy " );
        desc10.putBoolean( idCpy, true );
    executeAction( idTrnf, desc10, DialogModes.NO );
    return app.activeDocument.activeLayer
    } catch (e) {}
    };
    

     

    Edit: This Script just uses the layers’ horizontal bounds for orientation, so it does not address the issue I referred to earlier reagrding aesthetically pleasing spacing of the elements.

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 10, 2013 11:24 AM   in reply to ChrisRJ

    Chris,

    did you ever use the variables? (Menu Image) It's just the right thing for your task.

    You can use a font of your choice and export all the images with some simple mouse clicks.

    Each will have its individual number. The number range ist your choice too.

    Search for dynamic data in the Photoshop help.

    My knowledge of English is not good enough for translating.

     

    miss_marple

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 10, 2013 5:00 PM   in reply to ChrisRJ

    i was curious about this as well,  i will stay tuned for solutions

     
    |
    Mark as:
  • Currently Being Moderated
    Mar 11, 2013 12:24 AM   in reply to ChrisRJ

    The Script was intended for images of numbers, if you are willing to go type the issue is easier.

    With a text layer selected you could try this:

    // this script saves jpg copies with numbers created from selected type layer;
    // 2013, use it at your own risk;
    #target photoshop;
    if (app.documents.length > 0) {
    if (app.activeDocument.activeLayer.kind == LayerKind.TEXT) {
    // define the numbers to create;
    var startNumber = 95;
    var endNumber = 120;
    // get doc;
    var myDocument = app.activeDocument;
    // getting the name and location;
    var docName = myDocument.name;
    var baseName = docName.match(/(.*)\.[^\.]+$/)[1];
    //getting the location;
    var docPath = myDocument.path;
    // duplicate the image;
    var thecopy = myDocument.duplicate (thecopy, false);
    // the type layer;
    var typeLayer = thecopy.activeLayer;
    // jpg options;
    var jpgopts = new JPEGSaveOptions();
    jpgopts.embedProfile = true;
    jpgopts.formatOptions = FormatOptions.STANDARDBASELINE;
    jpgopts.matte = MatteType.NONE;
    jpgopts.quality = 9;
    ////////////////////////////////////
    // process the numbers;
    for (var m = startNumber; m <= endNumber; m++) {
    // the number;
    var thisString = String(m);
    // change text;
    typeLayer.textItem.contents = m;
    // get the number for the file name;
    var theNumber = bufferNumberWithZeros(m, String(endNumber).length);
    //save jpg;
    thecopy.saveAs((new File(docPath+"/"+baseName+"_"+theNumber+".jpg")),jpgopts,true);
    };
    // close copy;
    thecopy.close(SaveOptions.DONOTSAVECHANGES);
    }
    };
    //that’s it; thanks to xbytor;
    ////// buffer number with zeros //////
    function bufferNumberWithZeros (number, places) {
              var theNumberString = String(number);
              for (var o = 0; o < (places - String(number).length); o++) {
                        theNumberString = String("0" + theNumberString)
                        };
              return theNumberString
              };
    
     
    |
    Mark as:
  • Currently Being Moderated
    Mar 25, 2013 3:20 AM   in reply to ChrisRJ

    What do you need transparency for?

    If you put the type Layer in the montage you can save the jpgs off of that straight away.

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (1)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points