Copy link to clipboard
Copied
Hi!
I'm trying to get next things:
1) layers hierarchy
2) layers bounds rect
3) save every layer to PNG file
--
Currently I can only get list of layers:
auto &layerInfo = globals->exportParamBlock->documentInfo->layersDescriptor;
for (int i = 0; i < layerN; ++i)
{
std::u16string utfStr = layerInfo->unicodeName;
layerInfo = layerInfo->next;
}
Help me, please!
In the SDK take a look at
X:\.....\AdobeCSY_SDK\samplecode\automation\listner\
X:\.....\AdobeCSY_SDK\samplecode\automation\getter\
Compile the plugins in debug mode and place them in photoshop plugin folder.
Listner creates C++ function for every action that you do in Photoshop (select layer, save file, copy, paste, make new doc etc.)
C++ functions are in listner.log That is text file and ... Listner is magician
His partner is getter you call it ftom meny in photoshop I think file>automate>getter
Tak
...Copy link to clipboard
Copied
Within automation plugin we are traversing layer accessing them using index.
however to decide whether a layer is a real layer or just layer set start or stop we use following routine:
SPErr AMAutoPlugin::GetLayerSetInfo(int index, int * result)
{
SPErr error = kSPNoError;
char layertype[1024]="";
char cdata1[1024]="";
char cdata2[1024]="";
DescriptorTypeID runtimeKeyID;
uint32 data1;
uint32 data2;
error = sPSActionControl->StringIDToTypeID("layerSection", &runtimeKeyID);
if (error) goto returnError;
error = PIUGetInfoByIndex(index, classLayer,runtimeKeyID, &data1, &data2);
if (error) goto returnError;
error = sPSActionControl->TypeIDToStringID(data1,cdata1,255);
if (error) goto returnError;
error = sPSActionControl->TypeIDToStringID(data2,cdata2,255);
if (error) goto returnError;
if (strcmp(cdata1, "layerSectionStart")==0)*result=2;
else if (strcmp(cdata1, "layerSectionEnd")==0)*result=1;
else if (strcmp(cdata1, "layerSectionContent")==0)*result=0;
else *result =-1;
returnError:
return error;
}
It is old and not to safe but i think you will get the picture.
To get layer bounds use something like (Part of the saving routine):
AUTO_ERROR AMAutoPlugin::SaveClipFromLayer(int LayerCounter, char* path_buffer, string &sErrorString )
{
.......
DescriptorTypeID runtimeKeyID;
DescriptorTypeID runtimeClassID;
DescriptorClassID descClass;
PIActionDescriptor descLayer = NULL;
PIActionDescriptor descPosition = NULL;
double top= 0;
double left= 0;
double bottom= 0;
double right= 0;
AUTO_ERROR autoError =AUTO_OK;
SPErr error =kSPNoError;
........
error = sPSActionDescriptor->Make(&descLayer);
if (error) goto returnAutoError;
error = sPSActionDescriptor->Make(&descPosition);
if (error) goto returnAutoError;
error =SelectLayerByIndex( LayerCounter);
if (error!=-1 && error!=0){
autoError=ERR_SELECT_LAYER_BYINDEX;
goto returnAutoError;
}
//
// GET LAYER BOUNDS
//
error = PIUGetInfoByIndex(LayerCounter,classLayer,0,&descLayer,NULL);
if (error) goto returnAutoError;
error = sPSActionControl->StringIDToTypeID("bounds", &runtimeKeyID);
if (error) goto returnAutoError;
error = sPSActionControl->StringIDToTypeID("classRectangle", &runtimeClassID);
if (error) goto returnAutoError;
error = PIUGetSingleItemFromDescriptor(descLayer,runtimeKeyID,&descPosition,&descClass);
if (error) goto returnAutoError;
error = sPSActionDescriptor->GetFloat(descPosition, keyTop, &top);
if (error) goto returnAutoError;
error = sPSActionDescriptor->GetFloat(descPosition, keyLeft, &left);
if (error) goto returnAutoError;
error = sPSActionDescriptor->GetFloat(descPosition, keyBottom, &bottom);
if (error) goto returnAutoError;
error = sPSActionDescriptor->GetFloat(descPosition, keyRight, &right);
if (error) goto returnAutoError;
......
returnAutoError:
// do error handling in this case we are calling our AddErrorDescription function
// clean something ...
if (descLayer != NULL) sPSActionDescriptor->Free(descLayer);
if (descPosition != NULL) sPSActionDescriptor->Free(descPosition);
autoError=AddErrorDescription(sErrorString, autoError,LayerCounter, 2);
return autoError;
...
}
Saving PNG (made from listner plugin)
SPErr AMAutoPlugin::SavePNGALPHA(char *FullPath, bool SaveAlpha)
{
SPErr error = kSPNoError;
PIActionDescriptor result = NULL;
PIActionDescriptor FileDesc = NULL;
PIActionDescriptor FileTypeDesc = NULL;
Handle aliasValue = NULL;
error = sPSActionDescriptor->Make(&FileDesc);
if (error) goto returnError;
error = sPSActionDescriptor->Make(&FileTypeDesc);
if (error) goto returnError;
error = sPSActionDescriptor->PutEnumerated(FileTypeDesc, keyPNGInterlaceType, typePNGInterlaceType, enumPNGInterlaceNone);
if (error) goto returnError;
error = sPSActionDescriptor->PutEnumerated(FileTypeDesc, keyPNGFilter, typePNGFilter, enumPNGFilterAdaptive);
if (error) goto returnError;
error = sPSActionDescriptor->PutObject(FileDesc, keyAs, classPNGFormat, FileTypeDesc);
if (error) goto returnError;
FullPathToAlias(FullPath, aliasValue);
error = sPSActionDescriptor->PutAlias(FileDesc, keyIn, aliasValue);
if (error) goto returnError;
error = sPSActionDescriptor->PutBoolean(FileDesc, keyCopy, true);
if (error) goto returnError;
error = sPSActionDescriptor->PutBoolean(FileDesc, keyLowerCase, true);
if (error) goto returnError;
error = sPSActionDescriptor->PutBoolean(FileDesc, keyAlphaChannels, SaveAlpha);
if (error) goto returnError;
error = sPSActionControl->Play(&result, eventSave, FileDesc, plugInDialogSilent);
if (error) goto returnError;
returnError:
if (result != NULL) sPSActionDescriptor->Free(result);
if (FileDesc != NULL) sPSActionDescriptor->Free(FileDesc);
if (FileTypeDesc != NULL) sPSActionDescriptor->Free(FileTypeDesc);
if (aliasValue != NULL) sPSHandle->Dispose(aliasValue);
return error;
}
Use getter plugin (its source is in SDK examples automation section) to se how PS stores info about everything in it
(ok not everything but close), it saves data in getter.log
buy the way it should be called putter because ... you will se from log file
Use listner (also automation plugin in SDK examples) to make you a code for the command that you have
performed in PS
Hope this help.
Regards,
Momir Zecevic
Copy link to clipboard
Copied
thanks a lot!
But I want this functionality in export plugin, not automation one.
Is that possible?
Copy link to clipboard
Copied
12 years ago when written my first plugin it was impossible.
Fie format plugins (import/export) was ment to import export single file.
I also needed to export each layer into separate file and thus ended in automation plugin.
From that time maybe something has changed i file format plugins i dont know.
Regards,
Momir
Copy link to clipboard
Copied
Ok. I don't understand how do you create such code, this is some magic..
SelectLayerByIndex is missing. Can you tell me how to do that?
And also, how I can get Layer's name (utf16) and how much layers is in document?
Copy link to clipboard
Copied
In the SDK take a look at
X:\.....\AdobeCSY_SDK\samplecode\automation\listner\
X:\.....\AdobeCSY_SDK\samplecode\automation\getter\
Compile the plugins in debug mode and place them in photoshop plugin folder.
Listner creates C++ function for every action that you do in Photoshop (select layer, save file, copy, paste, make new doc etc.)
C++ functions are in listner.log That is text file and ... Listner is magician
His partner is getter you call it ftom meny in photoshop I think file>automate>getter
Take a look at getter.log
Modify the code to suite you.
Regards,
Momir
PS
SPErr AMAutoPlugin::SelectLayerByIndex( uint32 value)
{
SPErr error = kSPNoError;
DescriptorClassID desiredClass=classLayer;
error = PIUSelectByIndex(desiredClass, value);
if (error) goto returnError;
returnError:
return error;
}
Modified minorely from listner.log
By the way if you debug listner it self you will se underlying mechanisms
of getting subscibed to events, how thw events are handled etc.
Debuging getter is priceles since you will se that there are many ways to get info from PS.
Copy link to clipboard
Copied
HI
Is there any way we can save the document image as png or in binary format if the color mode is cmyk.
I would really appreciate any thoughts/suggestions on the matter.