10 Replies Latest reply on Oct 26, 2011 10:31 AM by Paul Riggott

    Creating catalogues automatically using image metadata

    durannarud Level 1

      Hi,

       

      I've been looking all over for this and I have found various bits and pieces of information, but nothing comprehensive enough for a beginner. Perhaps I am researching it wrong... Could you please point me to a complete and easy to understand source, or give me some tips and details regarding the process?

       

      I don't know if this makes a difference, but basically I'd like to be able to select a folder(s) full of images and place those images in a pre-made document automatically and group them by the category they are in (which it will also list automatically), while also displaying any other relevant metadata info in various fileds (when applicable). How would I go about doing this?

       

      Thank you in advance.

        • 1. Re: Creating catalogues automatically using image metadata
          Paul Riggott Level 6

          To get started, a bit of information would be helpful.

           

          What version of Photoshop?

          What file formats input/output?

          Where is the group information?

          If the group information is held in the metadata, which field?

          What groups are they?

          What format/ is there an example template of where the flies are to be placed?

          Are the groups to be placed into seperate documents?

          The metadata you want displaying, what fields and where do they want to be placed?

          • 2. Re: Creating catalogues automatically using image metadata
            durannarud Level 1

            Hi,

             

            Thanks for answering. I hope the following clarifies my situation a bit better:

             

            What version of Photoshop?

            CS5.5

             

            What file formats input/output?

            JPG input, output PDF.

             

            Where is the group information?

            In the folder name, in theory, although I wouldn't mind adding another field specifically for that instead, if it's easier.

             

            What format/ is there an example template of where the flies are to be placed?

            I'm not sure how to go about this in Photoshop (I guess Indesign would be more appropriate), but basically let's say it would be a page with one big picture and three smaller pictures. Same item in each picture, just from different angeles. The page would also display the name of the item, the category and perhaps other metadata information, depending on which item it is.

             

            Are the groups to be placed into seperate documents?

            Ideally no, just on different pages of the same document.

             

            The metadata you want displaying, what fields and where do they want to be placed?

            Top of page for category and name for instance, but under the pictures for any other information.

            • 3. Re: Creating catalogues automatically using image metadata
              Paul Riggott Level 6

              Ok, there still isn't enough information to get started.

              Is it required to selected a top level folder, find all subfolders (these being the different groups?)

              In each of these folders are there only four jpgs? if more, how do you select the groups of four? is there a naming convention?

              How is the big picture named?

              The template, what size and ppi?

              Where on the template would they have to be placed? A small jpg with areas marked would help.

              Are the pictures landscape/portrait?

              • 4. Re: Creating catalogues automatically using image metadata
                durannarud Level 1

                Sorry, I'm not 100% sure on everything. Hope this further clarifies:

                 

                Is it required to selected a top level folder, find all subfolders (these being the different groups?)

                It would be practical, yes. Unless there's a better option for grouping... in which case I'm open to trying something else.

                 

                In each of these folders are there only four jpgs? if more, how do you select the groups of four? is there a naming convention?

                Only four JPGs. I think the naming convention should be 1, 2, 3, 4 (which is to establish the order in which they appear on the document).

                 

                How is the big picture named?

                I would name it "1".

                 

                The template, what size and ppi?

                The template would be 11*8.5 (at 300dpi), but I may have to change it for esthetic reasons.

                 

                Where on the template would they have to be placed? A small jpg with areas marked would help.

                Here's a quick sketch of what I was thinking: http://imgur.com/fcf9a

                 

                Are the pictures landscape/portrait?

                I think I will batch-treat them prior to this in order to make them square.

                • 5. Re: Creating catalogues automatically using image metadata
                  Paul Riggott Level 6

                  Here is a start, could you please set up a few folders to do a test with this script.

                   

                  It prompts for a top level folder

                  It then processes each folder in turn, it expects that there exists 1.jpg, 2.jpg,3.jpg and 4.jpg in each folder.

                  The template is then created and the files resized to fit in thier respective masks.

                  The PSD is then saved to the relevant folder with a the folder name as the filename.

                   

                  Note the Categary is entered as the Folder name, I don't know what you want for the name or the other details but that can be worked out later.

                   

                   

                  main();
                  function main(){
                  var folderList=[];
                  topLevelFolder = Folder.selectDialog("Please select the source folder");
                  folderList = findAllFolders( topLevelFolder, folderList);
                  for(var z in folderList){
                  var file1 = File(folderList[z] +"/1.jpg");
                  var file2 = File(folderList[z] +"/2.jpg");
                  var file3 = File(folderList[z] +"/3.jpg");
                  var file4 = File(folderList[z] +"/4.jpg");
                  if(!file1.exists) continue;
                  if(!file2.exists) continue;
                  if(!file3.exists) continue;
                  if(!file4.exists) continue;
                  createTemplate(decodeURI(folderList[z].name),"MyName");
                  fillMask("Big", file1);
                  fillMask("topSquare", file2);
                  fillMask("middleSquare", file3);
                  fillMask("bottomSquare", file4);
                  var saveFile= File(folderList[z] +"/"+ decodeURI(folderList[z].name) + ".psd");
                  SavePSD(saveFile);
                  app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                  }
                  }
                  function fillMask(layerToSelect, sFile){
                  var FillColor = new SolidColor;
                  FillColor.rgb.hexValue = 'ff00f0'; 
                  var docRef=activeDocument;
                  var strtRulerUnits = app.preferences.rulerUnits;
                  var strtTypeUnits = app.preferences.typeUnits;
                  app.preferences.rulerUnits = Units.PIXELS;
                  app.preferences.typeUnits = TypeUnits.PIXELS;
                  docRef.activeLayer = app.activeDocument.activeLayer;
                  var layerName = app.activeDocument.activeLayer.name;
                  app.activeDocument = docRef;  
                  selectLayerMask(layerToSelect); 
                  unSelectMask();
                  docRef.selection.selectAll();
                  docRef.selection.fill(FillColor);
                  docRef.selection.deselect();
                  waitForRedraw();
                  selectLayerMask(layerToSelect); 
                  var LB = activeDocument.activeLayer.bounds;
                  var res = activeDocument.resolution;
                  var width = LB[2]-LB[0];
                  var height = LB[3]-LB[1];
                  open(File(sFile));
                  var layerFullName = decodeURI(activeDocument.fullName);
                  var dwidth = activeDocument.width.value; 
                  var dheight = activeDocument.height.value;   
                  var ratio = height/width; 
                  var dratio = dheight/dwidth; 
                  if (dratio > ratio) {  height = undefined; } else { width = undefined; } 
                  activeDocument.resizeImage(width, height, res, ResampleMethod.BICUBICSHARPER);
                  activeDocument.flatten();
                  activeDocument.selection.selectAll();
                  activeDocument.selection.copy();
                  app.activeDocument.close(SaveOptions.DONOTSAVECHANGES); 
                  activeDocument = docRef;
                  selArea();
                  docRef.paste(true);
                  linkLayer();
                  activeDocument.activeLayer.name=decodeURI(sFile.name);
                  selectLayerMask (layerToSelect);
                  activeDocument.activeLayer.remove();
                  $.gc();
                  app.preferences.rulerUnits = strtRulerUnits;
                  app.preferences.typeUnits = strtTypeUnits;
                  }
                  function createTemplate(Category,cName){
                  var strtRulerUnits = app.preferences.rulerUnits;       
                  var strtTypeUnits = app.preferences.typeUnits;       
                  app.preferences.rulerUnits = Units.PIXELS;       
                  app.preferences.typeUnits = TypeUnits.PIXELS;
                  var doc = app.documents.add(3300, 2550, 300, "Template", NewDocumentMode.RGB, DocumentFill.WHITE);
                  var LB=[176,451,1928,2202];
                  MakeLayerMask("Big",LB[0],LB[1],LB[2],LB[3],0);
                  LB=[1968,451,2528,1009];
                  MakeLayerMask("topSquare",LB[0],LB[1],LB[2],LB[3],0);
                  LB=[1968,1049,2528,1607];
                  MakeLayerMask("middleSquare",LB[0],LB[1],LB[2],LB[3],0);
                  LB=[1968,1642,2528,2202];
                  MakeLayerMask("bottomSquare",LB[0],LB[1],LB[2],LB[3],0);
                  addTextLayer("Cat",Category,178,220);
                  addTextLayer("Name",cName,178,308);
                  addTextLayer("Other","Other Fields",178,2334);
                  app.preferences.rulerUnits = strtRulerUnits;  
                  app.preferences.typeUnits = strtTypeUnits;
                  }
                  function MakeLayerMask(LayerName,Left,Top,Right,Bottom,Feather){
                   var Colour = new SolidColor;
                   Colour.rgb.hexValue = 'CACACA'; 
                      activeDocument.selection.select([[Left,Top],[Right,Top],[Right,Bottom],[Left,Bottom]], SelectionType.REPLACE,Feather, false); 
                    activeDocument.artLayers.add();
                   activeDocument.selection.fill(Colour);
                      addMask();
                   activeDocument.activeLayer.name = LayerName;
                  }
                  function addMask(){
                      var desc = new ActionDescriptor();
                      desc.putClass( charIDToTypeID('Nw  '), charIDToTypeID('Chnl') );
                          var ref = new ActionReference();
                          ref.putEnumerated( charIDToTypeID('Chnl'), charIDToTypeID('Chnl'), charIDToTypeID('Msk ') );
                      desc.putReference( charIDToTypeID('At  '), ref );
                      desc.putEnumerated( charIDToTypeID('Usng'), charIDToTypeID('UsrM'), charIDToTypeID('RvlS') );
                      executeAction( charIDToTypeID('Mk  '), desc, DialogModes.NO );
                  }
                  function addTextLayer(layerName,newText,X,Y) { 
                        var thisLayer = activeDocument.artLayers.add(); 
                        thisLayer.kind = LayerKind.TEXT; 
                        thisLayer.name = layerName; 
                        var textProperty = thisLayer.textItem; 
                        textProperty.size = 16; 
                        textProperty.font = "Georgia"; 
                        var newColor = new SolidColor(); 
                        newColor.rgb.red = 0; 
                        newColor.rgb.green = 0; 
                        newColor.rgb.blue = 0; 
                        textProperty.color = newColor; 
                        textProperty.position = new Array( X,Y); 
                        thisLayer.blendMode = BlendMode.NORMAL; 
                        thisLayer.opacity = 100; 
                        textProperty.contents = newText; 
                  };
                  function selectLayerMask (LayerName) { 
                  var desc = new ActionDescriptor();
                  var ref = new ActionReference(); 
                  ref.putEnumerated( charIDToTypeID( "Chnl" ), charIDToTypeID( "Chnl" ), charIDToTypeID( "Msk " ) ); 
                  ref.putName( charIDToTypeID( "Lyr " ), LayerName ); 
                  desc.putReference( charIDToTypeID( "null" ), ref ); 
                  desc.putBoolean( charIDToTypeID( "MkVs" ), false ); 
                  executeAction( charIDToTypeID( "slct" ), desc, DialogModes.NO ); 
                  };
                  function selArea(){
                  var desc467 = new ActionDescriptor();
                          var ref331 = new ActionReference();
                          ref331.putProperty( charIDToTypeID('Chnl'), charIDToTypeID('fsel') );
                      desc467.putReference( charIDToTypeID('null'), ref331 );
                          var ref332 = new ActionReference();
                          ref332.putEnumerated( charIDToTypeID('Chnl'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
                      desc467.putReference( charIDToTypeID('T   '), ref332 );
                      executeAction( charIDToTypeID('setd'), desc467, DialogModes.NO );
                  };
                  function linkLayer(){
                     var desc460 = new ActionDescriptor();
                          var ref42 = new ActionReference();
                          ref42.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
                      desc460.putReference( charIDToTypeID('null'), ref42 );
                          var desc461 = new ActionDescriptor();
                          desc461.putBoolean( charIDToTypeID('Usrs'), true );
                      desc460.putObject( charIDToTypeID('T   '), charIDToTypeID('Lyr '), desc461 );
                      executeAction( charIDToTypeID('setd'), desc460, DialogModes.NO );
                  };
                  function unSelectMask() {
                      var desc28 = new ActionDescriptor();
                          var ref14 = new ActionReference();
                          ref14.putEnumerated( charIDToTypeID('Chnl'), charIDToTypeID('Chnl'), charIDToTypeID('RGB ') );
                      desc28.putReference( charIDToTypeID('null'), ref14 );
                      desc28.putBoolean( charIDToTypeID('MkVs'), false );
                      executeAction( charIDToTypeID('slct'), desc28, DialogModes.NO );
                  };
                  function waitForRedraw() {
                    var desc = new ActionDescriptor();
                    desc.putEnumerated(charIDToTypeID("Stte"), charIDToTypeID("Stte"), charIDToTypeID("RdCm"));
                    executeAction(charIDToTypeID("Wait"), desc, DialogModes.NO);
                  };
                  function findAllFolders( srcFolderStr, destArray) {
                   var fileFolderArray = Folder( srcFolderStr ).getFiles();
                   for ( var i = 0; i < fileFolderArray.length; i++ ) {
                    var fileFoldObj = fileFolderArray[i];
                    if ( fileFoldObj instanceof File ) {   
                    } else {
                           destArray.push( Folder(fileFoldObj) );
                    findAllFolders( fileFoldObj.toString(), destArray );
                    }
                   }
                   return destArray;
                  };
                  function SavePSD(saveFile){ 
                  psdSaveOptions = new PhotoshopSaveOptions(); 
                  psdSaveOptions.embedColorProfile = true; 
                  psdSaveOptions.alphaChannels = true;  
                  activeDocument.saveAs(saveFile, psdSaveOptions, true, Extension.LOWERCASE); 
                  }
                  
                  
                  • 6. Re: Creating catalogues automatically using image metadata
                    durannarud Level 1

                    Wow, thanks! That's great.

                     

                    I have a few questions:

                     

                    - How long did it take you to do this??? Did you code it from scratch or do you have templates you add to?

                    - Is this script applicable to Indesign too (provided it has some modifications, naturally)? I'd love to be able to automatically put all the generated pages into one big document.

                    - Can borders be added to those masks, if necessary?

                    - For this line: addTextLayer("Other","Other Fields",178,2334); - How is this applicable to the metadata in the images?

                     

                    And, if you don't mind, what do you do for a living?

                     

                    Thanks again!

                    • 7. Re: Creating catalogues automatically using image metadata
                      Bob Stucky Adobe Employee

                      Contact sheet for InDesign

                       

                      www.creativescripting.net

                      • 8. Re: Creating catalogues automatically using image metadata
                        Paul Riggott Level 6

                        It took a couple of hours whilst watching the television. Yes it was written from scratch but there are certain functions that can be used in many scripts.

                        Layer Effects can be added to any of the masks.

                        Sorry this is just Photoshop only.

                        the "Other Fields" is only there as I don't know what metadata you want extracting to be put into this field.

                        I am a retired Telephone technician, being retired eleven years now, so do as I want (well what the wife tells me to do).

                         

                        I see Bob is suggesting Contact sheet for Indesign, I have never used InDesign but Bob is the expert and it would be worth seeing what it can do.

                        • 9. Re: Creating catalogues automatically using image metadata
                          durannarud Level 1

                          Wow, then you must really know your stuff... I can code simple-ish things in HTML or CSS, but I dont think I could do it while watching TV or somethign distracting like that.

                           

                          I checked out Bob's suggestion and it seems to fit pretty well. I'm definitely gonna look it up further, but I'd still like to understand this script better:

                           

                          - How do I tell it which metadata field to extract? What needs to be modified in this line for instance: addTextLayer("Other","Other Fields",178,2334);?

                          - How are layer effects added to the script? Is there a guide for the most commonly used ones or something along those lines?

                           

                          Thanks!

                          • 10. Re: Creating catalogues automatically using image metadata
                            Paul Riggott Level 6

                            The metadata is what you want to extract from the document, IE: Description, Headline Etc. it just depends on what data you have entered into the documents and where and what you want to be extracted to be displayed on the finished document.

                            Once you have decided what data is to be extracted there will be a fair amount of code to be added to the script to get the data from the fields so that it can be inserted into the "Other Fields" text area

                            It might be a good idea just to add the metadata to the largest picture of the group as it would speed up the process.

                             

                             

                            Layer effects have to use ScriptListener code (this is a plug-in that is supplied with Photoshop), You would apply the effects you require and look at the code generated in the ScriptingListenerJS.log that is created on the desktop. This code would then be appiled to each masked layer.

                             

                            The effects have to be applied all in one go, IE: if you add a stoke then add a dropshadow, the stoke is removed. So if you want a stoke and dropshadow that is what needs to be done to generate the code.

                             

                            Or if you tell me what you would like adding I will put something together.