Automating Photoshop via 3DSMax with DotNet and Com Interop

Hello peeps,

Just posted a new article on my site detailing how to control Photoshop via 3dsMax using a dotnet assembly and COM interop. Hope someone finds it useful.

Awesome stuff - useful subject matter, and a detailed and well-written tutorial to match. Thanks! :slight_smile:

I have robot website envy.

I’m new to the whole COM stuff so it’s very nice to see it so well explained. I’m gonna dive into this at a later stage, but i already know this will teach me tons of cool stuff.

Thanks.


VALIUM REHAB FORUMS

Very nice indeed

Hi chaps,

thanks for your replies, i’m glad you found the article useful. I’m pretty much learning as i go on the COM stuff myself, but I was blown away at the potential of what you could do with this. I’m hoping i can post a few more updates to this as the wrapper class library, with some work could mirror most of the photoshop operations.

I’m trying to figure out how the COM stuff works with the 3dsMax dot net bridge in order to be able to instantiate the interop assembly without the wrapper. But as you can see from the article, Without casting in max the object type is not what i would hope. Im thinking it’s a late binding issue in max - maybe by taking the system.type method i can use invokemember to call the COM properties directly from the interop assembly within max. It’s a little outside my confort zone to be honest, but I’ll see if it’s possible. I did some other Dotnet research on extracting the 3ds file thumbnail so i’d love to adapt that so I can get that without an extra assembly besides the interop.

Hello All,

Just posted an update to the PhotoShop control library. It now contains the following methods -

article is as before, at http://www.lonerobot.net

LoneRobot First i wanna thank you for this post :D:, im still pretty new to the hole programming thing but could understand and put in pratice your exemplo(in some way cause im doing it in C# so i had to change some syntax).

but i have 2 questions.

first and the most annoying one is this. i have something like this

       private Photoshop.Application PSDapp;
public void New(string imagePath)
     {
         PSDapp = new Photoshop.Application();
         Action(imagePath);
     }
private void Action(string imagePath)
     {
         string stringPath = imagePath;
         PSDapp.Load(stringPath);
         PSDapp.ActiveDocument = PSDapp.Documents[1];
         PSDapp.ActiveDocument.ArtLayers[1].Invert();
         PhotoshopSaveOptions psdSaveOptions = new PhotoshopSaveOptions();
            PSDapp.ActiveDocument.SaveAs("D:\
ew.psd", psdSaveOptions, true, "");
        }

my problem is here

PSDapp.ActiveDocument.SaveAs("D:\
ew.psd", psdSaveOptions, true, "");

i tryed to load those arguments in many ways and couldnt get it to work (the 4th arg i can´t set it right).
found that exemple:
activeDocument.saveAs( sFile, tiffSaveOptions, false, Extension.LOWERCASE);
but the Extension.LOWERCASE dosent exist here in C# (or at least i cant find a similar option).
I couldn´t type the function with just the path string dosent work either.

the second question is more abstract, u know someway i can from maxscript script the photoshop actions so its easier to test and create any solution?
(maybe reference all the photoshop actions in the main class?! :?::?:slight_smile:

thks in advance

Hi,

Extension type is an enum. From the reflector:

public enum PsExtensionType
{
    psLowercase = 2,
    psUppercase = 3
}

Light

[QUOTE=Light;3329]Hi,

Extension type is an enum. From the reflector:

public enum PsExtensionType
{
    psLowercase = 2,
    psUppercase = 3
}

Light[/QUOTE]
Wow… that was quick. thanks that worked .(sorry but how i can find the reflector?).

Hi RedCrab!

Yes, Light is correct, there are many constants set up as enums for you to use. Reflector is a tool to expose assemblies and their methods. Google it to find out. it’s very helpful.

If my conversion went okay, a saveas method in C# would be something like -

to save a progressive JPG at medium quality -

 {
     JPEGSaveOptions oJpg = new JPEGSaveOptions();
     oJpg.Quality = 6;
     oJpg.FormatOptions = PsFormatOptionsType.psProgressive;
   
    PSapplication.ActiveDocument.SaveAs("c:\	est.jpg", oJpg, true,PsExtensionType.psLowercase);
}

I think the last three arguments could be optional too, in your case, if you want to use saveas to another psd, you could run with the first string argument only.

the whole method is -

 
SaveAs
SaveIn - type String
[Options] - type pssavedocumenttype constant enum
[AsCopy] - type boolean
[ExtensionType] - type PsExtensionType constant enum

the extension type is just if it is saved in lower or uppercase extension.

To your other question, That was my primary aim also, although I haven’t beena ble to figure out whether it is possible. My porblem at the moment is that max is not returning the correct class objects when I probe it via the interop assembly. I can get so far, and then max reports a “system._COMobject”. You cant get at artlayers or documents so it’s pretty useless. I don’t understand it enough myself to get around it. You got any thoughts on this Light? - havent seen you on CGtalk for a while, how long you been at bioware?

At the moment I will be adding SaveAs as a method within my wrapper. In the next few days I will hope to expose all of the photoshop library to a dotnet assembly. For now that’s the best I can suggest. I have had this problem as I mentioned before with COM interop and Max.

nice thks Light and LR , fixed my problem.
btw searching around in the net found that in C# for some how i must put the optional args , u can use System.Type.Missing in case you dont want to use it. but you cant skip them.

Hey Pete, yeah I am mostly in read only mode (: It’s has been 2.5 years at BW.

As for using PS COM or any other .NET assembly directly in Max, it’s not worth it, unless the assembly is specifically designed for Max. So you can’t chain things together, like:

uvMesh.Polygons[0].Vertices[0]

Because as soon as you run uvMesh.Polygons, max converts it to an array and then subsequent calls fail.

But you can still use methods like Add on uvMesh.Polygons and add separately created Vertex objects, etc. I did similar things, not the best but working is better than neat.

To be fair, PS API is one of the worst ones I have ever seen. It could have been million times better.

Also redcrab, with C# 4.0 you can avoid typing the missing value.

Light

Hey Light!

Heh heh, I agree it’s not the most transparent in terms of useablility. The example of using the selection method is a classic one - passing an array of system objects, each being an object array of integers, each representing a single axis of a coordinate position in an anti-clockwise direction. duh! took a fair bit of guess work there on my part. I think my overloaded SelectMarquee method of passing a gdi rectangle or x,y,width,height is a bit easier to use, as my assembly handles all the weird stuff.

Yeah right on. But it’s also very dumb and is completely tied to the UI. I hate PS API. (:

Light

I’d noticed that - you can hide the PS UI but it needs to open the program before you can do it. It would be like max having to open up the UI on other machines for a distributed render! :laugh:

Hello Again,

Just posted another update to the PhotoShop control library. It now contains classes to access various image types in order to automate saving a compositon to other filetypes -

article is as before, at http://www.lonerobot.net

Another Update! -

I have integrated a function encapsulating the Action Descriptor - this means I can now set up pretty much anything into the assembly. I’ve added a hatload of new filters and a few more methods. This upgrade now paves the way to integrate whatever custom function you wanted, easilly called from 3dsmax.

If you’ve not seen the new blog layout, take a look, I think it’s much better now with the increased number of articles.

I have been using hacky work arounds for sending things to Photoshop for too long. You have just saved me a lot of headaches with this thorough explanation.

You’re welcome,

Been a while since I have updated this project, but I hope to add a few things in the next week or so.

I am still using CS3 but I hope to upgrade to CS5 shortly so that I can test it with the latest release. that’s certainly been overdue!