Skip to main content
Participant
March 22, 2010
Answered

Exporting Layers as Files with RGB & Coordinate Info?

  • March 22, 2010
  • 4 replies
  • 5634 views

Using CS4. Trying to figure out a way to export layers in a PSD as individual files WITH coordinate & RGB values in the file name..... I know the "Export Layers as Files" script already exists... but can't figure out how to apply the coordinate and RGB info to the file name... without renaming each layer manually...

Is there a way to create an action that appends the layer name with coordinates? Same question with RGB values...

Then I could run those scripts/actions, and then export as individual files....

Thoughts??

This topic has been closed for replies.
Correct answer Michael_L_Hale

I guess I'd just want the layer name to look something like:

Home Button x75 y32

Speed isn't a HUGE deal... as we don't expect to be doing this hundreds of

times... though we'd probably want it to go faster than renaming the layers

manually

The naming format doesn't have to look that way either if there's an easier

way. As long as you can decipher the coordinates from the end file name of

the layer.


How is this?

appendCoords( app.activeDocument )
function appendCoords( theParent ) {
     for ( var m = theParent.layers.length - 1; m >= 0; m-- ) {
          var theLayer = theParent.layers[ m ];
          if ( theLayer.typename != "LayerSet" ) {
               if( !theLayer.isBackgroundLayer ){
                    app.activeDocument.activelayer = theLayer;
                    var bounds = app.activeDocument.activelayer.bounds;
                    var x = bounds[0].as('px');
                    var y = bounds[1].as('px');
                    app.activeDocument.activelayer.name = app.activeDocument.activelayer.name+' X'+x+' Y'+y;
               }
          }else {
               findTextLayers( theLayer );
          }
     }
}

4 replies

March 27, 2011

Hi Michael,

I've been using the script and it's been very helpful! I incorporated your fix above so that X and Y are reported correctly (and not reversed). Can't quite figure how to incorporate the offset bit though. I have almost zero knowledge of scripting but I've tried placing the code you posted throughout the script and it has no effect. I'm guessing it needs a little more to fit in than that?

Thanks,

Alex

Inspiring
March 27, 2011

if( app.documents.length > 0 ){
     var ref = new ActionReference();
     ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
     var xOffset = executeActionGet(ref).getInteger(stringIDToTypeID('rulerOriginH'))/65536;
     var yOffset = executeActionGet(ref).getInteger(stringIDToTypeID('rulerOriginV'))/65536;
     app.activeDocument.suspendHistory('Add XY postition to layer names','addXYposToSelectedLayersNames()');
}
function addXYposToSelectedLayersNames(){
     var selectedLayers = getSelectedLayersIdx();
     for( var l = 0;l < selectedLayers.length; l++){
           if( isLayerSet( selectedLayers[ l ] ) ) continue;// comment out to include layersets
          var oldName =  getLayerNameByIndex( selectedLayers[ l ] );
            var bounds = getBoundsByIndex(selectedLayers[ l ]);
            var x = bounds[0];
           var y = bounds[1];
          var newName = oldName+' X'+x+' Y'+y;
          makeActiveByIndex( selectedLayers[ l ], false );
          putLayerNameByIndex( selectedLayers[ l ], newName )
     }
     makeActiveByIndex( selectedLayers, false );
};
function getLayerNameByIndex( idx ) {
    var ref = new ActionReference();
    ref.putProperty( charIDToTypeID('Prpr') , charIDToTypeID( 'Nm  ' ));
    ref.putIndex( charIDToTypeID( 'Lyr ' ), idx );
    return executeActionGet(ref).getString(charIDToTypeID( 'Nm  ' ));
};
function putLayerNameByIndex( idx, name ) {
     if( idx == 0 ) return;
    var desc = new ActionDescriptor();
        var ref = new ActionReference();
        ref.putIndex( charIDToTypeID( 'Lyr ' ), idx );
    desc.putReference( charIDToTypeID('null'), ref );
        var nameDesc = new ActionDescriptor();
        nameDesc.putString( charIDToTypeID('Nm  '), name );
    desc.putObject( charIDToTypeID('T   '), charIDToTypeID('Lyr '), nameDesc );
    executeAction( charIDToTypeID('setd'), desc, DialogModes.NO );
};
function isValidActiveLayer( idx ) {
     var propName = stringIDToTypeID( 'layerSection' );
     var ref = new ActionReference();
     ref.putProperty( 1349677170 , propName);
     ref.putIndex( 1283027488, idx );
     var desc =  executeActionGet( ref );
     var type = desc.getEnumerationValue( propName );
     var res = typeIDToStringID( type );
     return res == 'layerSectionEnd' ? false:true;
};
function isLayerSet( idx ) {
     var propName = stringIDToTypeID( 'layerSection' );
     var ref = new ActionReference();
     ref.putProperty( 1349677170 , propName);
     ref.putIndex( 1283027488, idx );
     var desc =  executeActionGet( ref );
     var type = desc.getEnumerationValue( propName );
     var res = typeIDToStringID( type );
     return res == 'layerSectionStart' ? true:false;
};
function getSelectedLayersIdx(){
     var selectedLayers = new Array;
     var ref = new ActionReference();
     ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
     var desc = executeActionGet(ref);
     if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ){
          desc = desc.getList( stringIDToTypeID( 'targetLayers' ));
          var c = desc.count
          var selectedLayers = new Array();
               for(var i=0;i<c;i++){
                    try{
                         activeDocument.backgroundLayer;
                         selectedLayers.push(  desc.getReference( i ).getIndex() );
                    }catch(e){
                         selectedLayers.push(  desc.getReference( i ).getIndex()+1 );
                    }
               }
          }else{
               var ref = new ActionReference();
               ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID( "ItmI" ));
               ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
               try{
                    activeDocument.backgroundLayer;
                    selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" ))-1);
               }catch(e){
                    selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" )));
               }
     }
     return selectedLayers;
};
function makeActiveByIndex( idx, visible ){
     if( idx.constructor != Array ) idx = [ idx ];
     for( var i = 0; i < idx.length; i++ ){
          var desc = new ActionDescriptor();
          var ref = new ActionReference();
          ref.putIndex(charIDToTypeID( 'Lyr ' ), idx)
          desc.putReference( charIDToTypeID( 'null' ), ref );
          if( i > 0 ) {
               var idselectionModifier = stringIDToTypeID( 'selectionModifier' );
               var idselectionModifierType = stringIDToTypeID( 'selectionModifierType' );
               var idaddToSelection = stringIDToTypeID( 'addToSelection' );
               desc.putEnumerated( idselectionModifier, idselectionModifierType, idaddToSelection );
          }
          desc.putBoolean( charIDToTypeID( 'MkVs' ), visible );
          executeAction( charIDToTypeID( 'slct' ), desc, DialogModes.NO );
     }    
};
function getBoundsByIndex(idx) {
    var ref = new ActionReference();
    ref.putProperty( charIDToTypeID("Prpr") , stringIDToTypeID('bounds'));
    ref.putIndex( charIDToTypeID( 'Lyr ' ), idx );
    desc = executeActionGet(ref).getObjectValue(stringIDToTypeID('bounds'));
    var res = new Array;
     res.push(desc.getDouble(charIDToTypeID("Left"))-xOffset);
    res.push(desc.getDouble(charIDToTypeID("Top "))-yOffset);
     res.push(desc.getDouble(charIDToTypeID("Rght"))-xOffset);    
    res.push(desc.getDouble(charIDToTypeID("Btom"))-yOffset);
    return res;
};

March 28, 2011

Great! Works perfectly :-)

I get around the problem of miscalculating vector objects by either rasterising them or making them smart objects.

All the best,

Alex

March 15, 2011

Hi Michael,

I spoke to soon.

The script won't run with the last layer selected.

But even weirder, if I run the script on layers 1-5, it writes co-ordinates to 0-4:

Something weird going on with that last layer!

Thanks,

Alex

Inspiring
March 15, 2011

Some other problems with using action manager is there is vary little official info on it's use and then AM layer index changes depending on if there is a background layer or not in the document. It looks like I used some old code that does not adjust for background layer correctly and I didn't catch it in my limited testing of this script.

I will see if I can sort it out and will post a new version when I have it working correctly. I don't think it is a layerset or last layer issue per se. It is just not handling the layer indexes correctly.

Inspiring
March 15, 2011

I was using an old function that doesn't work correctly. The script below does seem to work correctly and skips layersets. The AM bounds for layersets is the same as the document bounds so is not that useful. It still works on selected layers only but it is easy enough to select all layers with a keyboard shortcut.

if( app.documents.length > 0 ){
app.activeDocument.suspendHistory('Add XY postition to layer names','addXYposToSelectedLayersNames()');
}
function addXYposToSelectedLayersNames(){
     var selectedLayers = getSelectedLayersIdx();
     for( var l = 0;l < selectedLayers.length; l++){
           if( isLayerSet( selectedLayers[ l ] ) ) continue;// comment out to include layersets
          var oldName =  getLayerNameByIndex( selectedLayers[ l ] );
            var bounds = getBoundsByIndex(selectedLayers[ l ]);
            var x = bounds[0];
           var y = bounds[1];
          var newName = oldName+' X'+x+' Y'+y;
          makeActiveByIndex( selectedLayers[ l ], false );
          putLayerNameByIndex( selectedLayers[ l ], newName )
     }
     makeActiveByIndex( selectedLayers, false );
};
function getLayerNameByIndex( idx ) {
    var ref = new ActionReference();
    ref.putProperty( charIDToTypeID('Prpr') , charIDToTypeID( 'Nm  ' ));
    ref.putIndex( charIDToTypeID( 'Lyr ' ), idx );
    return executeActionGet(ref).getString(charIDToTypeID( 'Nm  ' ));
};
function putLayerNameByIndex( idx, name ) {
     if( idx == 0 ) return;
    var desc = new ActionDescriptor();
        var ref = new ActionReference();
        ref.putIndex( charIDToTypeID( 'Lyr ' ), idx );
    desc.putReference( charIDToTypeID('null'), ref );
        var nameDesc = new ActionDescriptor();
        nameDesc.putString( charIDToTypeID('Nm  '), name );
    desc.putObject( charIDToTypeID('T   '), charIDToTypeID('Lyr '), nameDesc );
    executeAction( charIDToTypeID('setd'), desc, DialogModes.NO );
};
function isValidActiveLayer( idx ) {
     var propName = stringIDToTypeID( 'layerSection' );
     var ref = new ActionReference();
     ref.putProperty( 1349677170 , propName);
     ref.putIndex( 1283027488, idx );
     var desc =  executeActionGet( ref );
     var type = desc.getEnumerationValue( propName );
     var res = typeIDToStringID( type );
     return res == 'layerSectionEnd' ? false:true;
};
function isLayerSet( idx ) {
     var propName = stringIDToTypeID( 'layerSection' );
     var ref = new ActionReference();
     ref.putProperty( 1349677170 , propName);
     ref.putIndex( 1283027488, idx );
     var desc =  executeActionGet( ref );
     var type = desc.getEnumerationValue( propName );
     var res = typeIDToStringID( type );
     return res == 'layerSectionStart' ? true:false;
};
function getSelectedLayersIdx(){
     var selectedLayers = new Array;
     var ref = new ActionReference();
     ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
     var desc = executeActionGet(ref);
     if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ){
          desc = desc.getList( stringIDToTypeID( 'targetLayers' ));
          var c = desc.count
          var selectedLayers = new Array();
               for(var i=0;i<c;i++){
                    try{
                         activeDocument.backgroundLayer;
                         selectedLayers.push(  desc.getReference( i ).getIndex() );
                    }catch(e){
                         selectedLayers.push(  desc.getReference( i ).getIndex()+1 );
                    }
               }
          }else{
               var ref = new ActionReference();
               ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID( "ItmI" ));
               ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
               try{
                    activeDocument.backgroundLayer;
                    selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" ))-1);
               }catch(e){
                    selectedLayers.push( executeActionGet(ref).getInteger(charIDToTypeID( "ItmI" )));
               }
     }
     return selectedLayers;
};
function makeActiveByIndex( idx, visible ){
     if( idx.constructor != Array ) idx = [ idx ];
     for( var i = 0; i < idx.length; i++ ){
          var desc = new ActionDescriptor();
          var ref = new ActionReference();
          ref.putIndex(charIDToTypeID( 'Lyr ' ), idx)
          desc.putReference( charIDToTypeID( 'null' ), ref );
          if( i > 0 ) {
               var idselectionModifier = stringIDToTypeID( 'selectionModifier' );
               var idselectionModifierType = stringIDToTypeID( 'selectionModifierType' );
               var idaddToSelection = stringIDToTypeID( 'addToSelection' );
               desc.putEnumerated( idselectionModifier, idselectionModifierType, idaddToSelection );
          }
          desc.putBoolean( charIDToTypeID( 'MkVs' ), visible );
          executeAction( charIDToTypeID( 'slct' ), desc, DialogModes.NO );
     }    
};
function getBoundsByIndex(idx) {
    var ref = new ActionReference();
    ref.putProperty( charIDToTypeID("Prpr") , stringIDToTypeID('bounds'));
    ref.putIndex( charIDToTypeID( 'Lyr ' ), idx );
    desc = executeActionGet(ref).getObjectValue(stringIDToTypeID('bounds'));
    var res = new Array;
    res.push(desc.getDouble(charIDToTypeID("Top ")));
    res.push(desc.getDouble(charIDToTypeID("Left")));
    res.push(desc.getDouble(charIDToTypeID("Btom")));
    res.push(desc.getDouble(charIDToTypeID("Rght")));
    return res;
};

Participant
October 18, 2010

Noob here, would it be possible to do this with slices instead of layers in CS3?

Slightly annoying you can't append the X/Y directly by editing the output options

March 14, 2011

Hi,

This is almost exactly what I'm looking for... I'm designing a set top box interface and I need to provide the XY positioning for every asset. Some of my documents contain hundreds of layers, in many groups and sub-groups. Unfortunately the script provided above does not work with groups.

I would be most grateful if someone could update the script for me? I do not have any knowledge of scripting.

Thanks,

Alex

Inspiring
March 14, 2011

There is a copy/paste/edit mistake in the script above( I am good at those ). The script below should now work with layersets.

appendCoords( app.activeDocument )
function appendCoords( theParent ) {
     for ( var m = theParent.layers.length - 1; m >= 0; m-- ) {
          var theLayer = theParent.layers[ m ];
          if ( theLayer.typename != "LayerSet" ) {
               if( !theLayer.isBackgroundLayer ){
                    app.activeDocument.activelayer = theLayer;
                    var bounds = app.activeDocument.activelayer.bounds;
                    var x = bounds[0].as('px');
                    var y = bounds[1].as('px');
                    app.activeDocument.activelayer.name = app.activeDocument.activelayer.name+' X'+x+' Y'+y;
               }
          }else {
               appendCoords( theLayer );
          }
     }
};

Inspiring
March 22, 2010

The layer coordinates are somewhat easy to add. You can use layer bounds to get the coordinates. But bounds can be effected by layer styles.

Not sure what you mean by RGB values. Are the layers one color?

Participant
March 22, 2010

Well...I'm trying to figure this out for a friend, and told him that the

layer would have to be a solid color to have a chance at exporting the file

with any RGB values... the coordinates are probably the most important part

of this.

When you say the layer bounds can be affected by the styles, do you mean

something like a stroke or drop shadow that extend beyond the layer itself?

Inspiring
March 23, 2010

From the layer bounds you can get the top left X,Y position and the width and height. And yes styles like stroke, dropshadow, and outer glow can effect the bounds even if it doesn't extend beyond the document bounds. That may or not matter depending what what you want to do the the coordinates. I just thought I would make you aware that you may need to turn off the layer effects to get the correct bounds.