Skip to main content
chrisell99
Known Participant
November 18, 2009
Answered

Copying and pasting channels - how to?

  • November 18, 2009
  • 2 replies
  • 3083 views

So I've got myself wrapped around the axle here trying to understand channels. I can't get my head around the fact that you can duplicate, add and remove, but you can't copy and paste channel contents? I'm working in JS in CS3. Or trying to.

I'm trying to take a gray image with three channels, and reduce it to two. Copy channel 2 into channel 1, copy channel 3 into 2, then delete channel 3 and save the file.

Why doesn't this work? I can copy and paste from artlayers so the method exists, but for whatever reason I can't get it to accept this method for channels:

// copy Alpha 1 and paste it into Gray
app.activeDocument.channel[2].copy();
app.activeDocument.channel[1].paste();

// copy Alpha 2 and paste it into Alpha 1
app.activeDocument.channel[3].copy();
app.activeDocument.channel[2].paste();

// Delete old Alpha 2 channel
app.activeDocument.channel[3].remove();

I tried another way - setting the active channel then copying and pasting, but I couldn't even get it to set the active channel without an error:


app.activeDocument.activeChannels = app.activeDocument.channel[2];

Very stuck and in need of help. Thanks.

This topic has been closed for replies.
Correct answer Michael_L_Hale

It's not working for lots of reasons. Channels, and almost everything else start with 0. To use an index you have to use Channels. The Channel class does not have a copy method. And finally activeChannels expects an array.

So it's easy fixes for everything except the copy method. For that we need to use scriptlistner to make an applyImage function. When you apply a image in normal mode it's the same as copy without going through the clipboard.

// assumes grayscale mode with two alpha channels
// make gray channel active
app.activeDocument.activeChannels = [app.activeDocument.channels[0]];
// copy first alpha contents to gray
applyChannelByName( app.activeDocument.channels[1].name );
// make first alpha channel active
app.activeDocument.activeChannels = [app.activeDocument.channels[1]];
// copy second alpha content to frist alpha
applyChannelByName( app.activeDocument.channels[2].name );
// remove the second alpha
app.activeDocument.channels[2].remove();
// make gray channel active
app.activeDocument.activeChannels = [app.activeDocument.channels[0]];

function applyChannelByName( name ) {
    var desc = new ActionDescriptor();
        var applyDesc = new ActionDescriptor();
            var ref = new ActionReference();
            ref.putName( charIDToTypeID('Chnl'), name);
        applyDesc.putReference( charIDToTypeID('T   '), ref );
        applyDesc.putBoolean( charIDToTypeID('PrsT'), true );
    desc.putObject( charIDToTypeID('With'), charIDToTypeID('Clcl'), applyDesc );
    executeAction( charIDToTypeID('AppI'), desc, DialogModes.NO );
}

2 replies

Paul Riggott
Inspiring
November 18, 2009

Is this what you are trying to do?

if(activeDocument.mode == DocumentMode.RGB){
selectChannel('green');
activeDocument.selection.selectAll();
activeDocument.selection.copy();
selectChannel('red');
activeDocument.paste();
selectChannel('blue');
activeDocument.selection.selectAll();
activeDocument.selection.copy();
selectChannel('green');
activeDocument.paste();
activeDocument.selection.deselect();
selectChannel('RGB');
//If you remove the blue channel you will be left with a multichannel not RGB file
// You will have Cyan and Magenta channels
//activeDocument.activeChannels[2].remove();
}
function selectChannel (colour){
    var desc = new ActionDescriptor();
        var ref = new ActionReference();
        ref.putEnumerated( charIDToTypeID('Chnl'), charIDToTypeID('Chnl'), stringIDToTypeID(colour) );
    desc.putReference( charIDToTypeID('null'), ref );
    executeAction( charIDToTypeID('slct'), desc, DialogModes.NO );
};

Edit: Mike was much faster than me and a better solution.

Inspiring
November 18, 2009

Thanks Paul, but you bring up a good point. I should have a test for mode and number of channels to avoid throwing errors. I just tried my code on an RGB image to see what would happen and the apply image function doesn't work in that mode. Even if it did, removing a component channel is not something you would want to do without a very good reason.

Muppet_Mark-QAl63s
Inspiring
November 19, 2009

if (activeDocument.mode == DocumentMode.GRAYSCALE && activeDocument.channels.length == 3) {

app.activeDocument.activeChannels = [app.activeDocument.channels[0]];

app.activeDocument.channels[0].remove();

// Now Multi channel Doc

app.activeDocument.changeMode(ChangeMode.GRAYSCALE);

// Alpha 1 has become composite Gray

app.activeDocument.channels[1].name = 'Alpha 1';

}

Just my option…

Michael_L_HaleCorrect answer
Inspiring
November 18, 2009

It's not working for lots of reasons. Channels, and almost everything else start with 0. To use an index you have to use Channels. The Channel class does not have a copy method. And finally activeChannels expects an array.

So it's easy fixes for everything except the copy method. For that we need to use scriptlistner to make an applyImage function. When you apply a image in normal mode it's the same as copy without going through the clipboard.

// assumes grayscale mode with two alpha channels
// make gray channel active
app.activeDocument.activeChannels = [app.activeDocument.channels[0]];
// copy first alpha contents to gray
applyChannelByName( app.activeDocument.channels[1].name );
// make first alpha channel active
app.activeDocument.activeChannels = [app.activeDocument.channels[1]];
// copy second alpha content to frist alpha
applyChannelByName( app.activeDocument.channels[2].name );
// remove the second alpha
app.activeDocument.channels[2].remove();
// make gray channel active
app.activeDocument.activeChannels = [app.activeDocument.channels[0]];

function applyChannelByName( name ) {
    var desc = new ActionDescriptor();
        var applyDesc = new ActionDescriptor();
            var ref = new ActionReference();
            ref.putName( charIDToTypeID('Chnl'), name);
        applyDesc.putReference( charIDToTypeID('T   '), ref );
        applyDesc.putBoolean( charIDToTypeID('PrsT'), true );
    desc.putObject( charIDToTypeID('With'), charIDToTypeID('Clcl'), applyDesc );
    executeAction( charIDToTypeID('AppI'), desc, DialogModes.NO );
}

chrisell99
Known Participant
November 18, 2009

Mike - good answer. It's solved my issue and I've been able to carry on with the rest of the script function. Thanks for that. I've learned a little more about PS scripting today.