Sat, Nov 30, 8:54 AM CST

Renderosity Forums / Poser Python Scripting



Welcome to the Poser Python Scripting Forum

Forum Moderators: Staff

Poser Python Scripting F.A.Q (Last Updated: 2024 Sep 18 2:50 am)

We now have a ProPack Section in the Poser FreeStuff.
Check out the new Poser Python Wish List thread. If you have an idea for a script, jot it down and maybe someone can write it. If you're looking to write a script, check out this thread for useful suggestions.

Also, check out the official Python site for interpreters, sample code, applications, cool links and debuggers. This is THE central site for Python.

You can now attach text files to your posts to pass around scripts. Just attach the script as a txt file like you would a jpg or gif. Since the forum will use a random name for the file in the link, you should give instructions on what the file name should be and where to install it. Its a good idea to usually put that info right in the script file as well.

Checkout the Renderosity MarketPlace - Your source for digital art content!



Subject: How to call ImageMagick from PoserPython


HartyBart ( ) posted Tue, 03 August 2021 at 9:38 PM · edited Sat, 30 November 2024 at 8:50 AM

Is there a way to call ImageMagick from a PoserPython script, without using subprocess.call in the script to launch the main EXE and then feed the EXE some script (it seems that may be possible)? Or to call a Windows BAT file and have that do the work with ImageMagick?

Example: let's say you wanted to have your script call ImageMagick to shrink and optimize a GIF file, that Poser has just rendered and written to a folder. In a command line to invoke ImageMagick, that would apparently be done thus:

magick mogrify -layers 'optimize' -fuzz 7% poser.gif



Learn the Secrets of Poser 11 and Line-art Filters.


HartyBart ( ) posted Tue, 03 August 2021 at 9:47 PM

Edit: Or [without having] to call a Windows BAT file...



Learn the Secrets of Poser 11 and Line-art Filters.


HartyBart ( ) posted Tue, 03 August 2021 at 10:31 PM · edited Tue, 03 August 2021 at 10:35 PM

Ah, it appears that it's actually possible to run a Windows command line from within a PoserPython script, using shell=True and import subprocess. It appears it should look something like this?

cmd = "magick mogrify -layers 'optimize' -fuzz 7% poser.gif" 
run_cmd = subprocess.call(cmd, shell=True)

Although I'm not sure if that would work on its own for Poser 11 and Python 2.7. I have another example that suggests square brackets are needed for 2.7:

subprocess.call(["ls", "-l"])



Learn the Secrets of Poser 11 and Line-art Filters.


HartyBart ( ) posted Wed, 04 August 2021 at 2:46 PM · edited Wed, 04 August 2021 at 2:49 PM

I've now had time to start to make some actual tests. This simplest-possible script works in having Poser run a command-line. Windows Notepad opens, the file is not present so is created, and on a save Notepad offers to save it into Poser 11's exe directory.

import poser
import subprocess

cmd = "notepad myfile2.txt"
run_cmd = subprocess.call(cmd, shell=True)

I could be wrong, but I get the feeling that the square brackets and commas are only needed in Python 2.7 and Poser 11 if dealing with file paths?



Learn the Secrets of Poser 11 and Line-art Filters.


HartyBart ( ) posted Wed, 04 August 2021 at 3:32 PM · edited Wed, 04 August 2021 at 3:33 PM

To answer my own starting question on this thread, after more research it appears that os.system and os.popen once did the job, but are now depreciated for the safer subprocess.call. Though the latest Python 3.5 or higher is said to prefer the subprocess.run command.

However, it appears that shell=False is somewhat 'safer' to use after with subprocess.call - and my further test with the above script shows it also works with Poser 11. Any reason then to prefer shell=True with Poser 11 scripts?

But.... now I'm learning that there's also a sh command - "sh is a full-fledged subprocess replacement that allows you to call any program as if it were a function" and is for 2.6 - 3.8. So that also helps answer my starting question. Difficult to find working examples that look like PoserPython rather than admin server scripts, though. Also difficult to fathom by looking at it, and it appears to be using a lot of shorthand switches. Seems to be a thing for server admins?



Learn the Secrets of Poser 11 and Line-art Filters.


HartyBart ( ) posted Wed, 04 August 2021 at 7:11 PM · edited Wed, 04 August 2021 at 7:13 PM

Well, this is as far as I've got so far. I can see why people don't want to work with ImageMagick - it seems so difficult to get the arguments accepted and encapsulated correctly in the Python. This still isn't working, but I think it's the closest I've come yet. I just don't know how to get past this...

import subprocess
path = [r'C:|Program Files|ImageMagick|mogrify.exe']
args = ['mogrify -layers "optimize" -fuzz 7% test.gif']
cmd = path + args
run_cmd = subprocess.call(cmd, shell=True)



Learn the Secrets of Poser 11 and Line-art Filters.


adp001 ( ) posted Wed, 04 August 2021 at 7:24 PM · edited Wed, 04 August 2021 at 7:29 PM

"sh" is a lib made with Unix/Linux in mind. There is no benefit in combination with Posers Python implementation.

Use subprocess. It's save and without side effects.

Regarding ImageMagic: https://stackoverflow.com/questions/33973250/python-imagemagick-and-subprocess-call

This is about "shell==True": https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess




HartyBart ( ) posted Wed, 04 August 2021 at 7:36 PM

I have to give up on ImageMagic and Python and Windows. Error after error after error... Even with the simplest possible script, that apparently works perfectly for others...

import subprocess
subprocess.call([r'C:|Program Files|ImageMagick|convert.exe image.jpg -resize 350x350 export.jpg'])



Learn the Secrets of Poser 11 and Line-art Filters.


adp001 ( ) posted Wed, 04 August 2021 at 9:35 PM

Beside of your trouble with subprocess and Windows: Do you need ImageMagic just to convert images? If so, why don't you use PIL? It's a standard Python lib (included in Poser Python since ever), really fast and easy to use.




adp001 ( ) posted Wed, 04 August 2021 at 9:42 PM · edited Wed, 04 August 2021 at 9:45 PM

Here is an example from PILs docs:

from PIL import Image
import glob, os

size = 128, 128

for infile in glob.glob("*.jpg"):
    file, ext = os.path.splitext(infile)
    with Image.open(infile) as im:
        im.thumbnail(size)
        im.save(file + ".thumbnail", "JPEG")

The docs are here:

https://pillow.readthedocs.io/en/stable/index.html




adp001 ( ) posted Wed, 04 August 2021 at 10:10 PM

HartyBart posted at 10:06PM Wed, 04 August 2021 - #4424562

Well, this is as far as I've got so far. I can see why people don't want to work with ImageMagick - it seems so difficult to get the arguments accepted and encapsulated correctly in the Python. This still isn't working, but I think it's the closest I've come yet. I just don't know how to get past this...

import subprocess
path = [r'C:|Program Files|ImageMagick|mogrify.exe']
args = ['mogrify -layers "optimize" -fuzz 7% test.gif']
cmd = path + args
run_cmd = subprocess.call(cmd, shell=True)

Not tested in Windows, but maybe you want to give this a try:

import subprocess

command = ["ls", "-l"]
try:
    output = subprocess.check_output(command, stderr=subprocess.STDOUT).decode()
    success = True 
except subprocess.CalledProcessError as e:
    output = e.output.decode()
    success = False

print(output)

The commandstring above has two parts. The command itself ("ls") and an argument ("-l"). Change it to a command you want to try.




adp001 ( ) posted Wed, 04 August 2021 at 10:22 PM

You can give the command as many parameters as you like. As strings in an array (first element in the list is the program to call, anything that follows is parameters).

E.g:

command=[r'C:\Program Files\ImageMagick\convert.exe', 'image.jpg', '-resize 350x350', 'export.jpg']

should work for your call to ImageMagic.




adp001 ( ) posted Thu, 05 August 2021 at 9:07 AM

Using just "call" from subprocess starts a new standalone thread in the background running the named program – without any connection to it. That only makes sens in special cases and is not what a normal Windows user wants. The lib subprocess has a lot other goodies, more useful if you want to get any results back :)

As you said before: Some times ago subprocess replaced "popen" (popen returns a pipe to a started program running in a seperate thread in the best case, just like subprocess.call does). subprocess has splitted the complex popen command into several more easy to use parts.

In German, I could tell you much more and give you more precise answers. Nevertheless, I hope that what I have written makes sense.




HartyBart ( ) posted Thu, 05 August 2021 at 2:51 PM · edited Thu, 05 August 2021 at 2:55 PM

Thanks for the tip on PIL, adp001. In all my searching it didn't come up once, though I heard about PythonMagick and Wand. Apparently PIL is now called 'Pillow' for Python 3, and thus for Poser 12. It appears the old PIL had a lot of trouble compiling animated GIFs. (Search: "Python Imaging Library (PIL) and Animated GIFs") and was otherwise a bit clunky. But possibly Pillow on Python 3 and Poser 12 will allow more.

Thanks also for your test script and expanded example. But I just cannot get it working, errors every time from both Poser 11 and MS Visual Studio. I read that there's what is effectively a long-unfixed bug on Windows. If the full path is specified in Python, and then the Windows exe is fed arguments, Windows cannot then find the path. This problem runs across all versions and remains unfixed. (Search: "Subprocess does not find executable on Windows if it is PATH with quotes"). Perhaps that's what's happening here?

Though I should add that I know that if you use PoserPython subprocess.call to feed the called exe its own script type (e.g. you feed Blender a script), then the exe will load that perfectly. It also works if you just invoke an already installed software simply by its cmd name, e.g. notepad or similar.

Given all this, I've tried invoking a good old Windows Bat file. This works fine and does it in four very obvious lines of code. Basic one-line call in PoserPython:

subprocess.call([r'C:|Users|YOUR_NAME|do_something.bat'], shell=False)

Then in the called BAT file:

@echo off
cd c:|software_folder|
software.exe output.gif input.gif arg1 arg2 arg3 arg4

(Backslashes replaced with | for the forum, which does not allow backslashes)



Learn the Secrets of Poser 11 and Line-art Filters.


adp001 ( ) posted Thu, 05 August 2021 at 3:26 PM

Pil is Pillow even in Poser 11.




HartyBart ( ) posted Thu, 05 August 2021 at 3:46 PM

Oh, that's interesting, thanks. So I should look more into Pillow, and what it can do on Poser 11. Maybe that will mean the bat file can be avoided.



Learn the Secrets of Poser 11 and Line-art Filters.


adp001 ( ) posted Thu, 05 August 2021 at 3:58 PM

Sorry, but I can not help with Windows problems. I use Windows only to start Poser and DAZ Studio. My Windows runs in a protected VM on my LAN Server, reachable only via RDP over local network. Even all data files used by the Windows applications are provided and managed by the underlying Linux that runs the VM. And if something goes wrong while I use Windows, I just reset the VM to the last saved state. So, no need here to fight with Windows internals.

For anything else I use Linux (I'm a happy Linux user since over 20 years) :).




adp001 ( ) posted Thu, 05 August 2021 at 4:05 PM

Even with the most current version you have to import Pillow as "PIL". That is while most users don't call it Pillow. PIL means: Python Image Library. So nothing's wrong if Pillow is called PIL (hardly anyone remembers the old version anyway) :)




adp001 ( ) posted Thu, 05 August 2021 at 4:07 PM

HartyBart posted at 4:05PM Thu, 05 August 2021 - #4424630

It appears the old PIL had a lot of trouble compiling animated GIFs.

You are still using GIFs? Interesting...




adp001 ( ) posted Thu, 05 August 2021 at 4:14 PM

Tip: wxPython can also handle images. To crop, scale and or copy images to other common formats it is quite sufficient. GIFs should be handled by wxPython as well. I haven't tried it myself, but I assume that it can.




HartyBart ( ) posted Fri, 06 August 2021 at 12:08 AM · edited Fri, 06 August 2021 at 12:09 AM

Thanks. No, I'm not targeting GIF any more. Am now basing the testing around calling an exe to optimise a PNG. For that optimisation, using a Bat file to call a dedicated PNG optimizer is best. Maybe ImageMagick can rival those dedicated optimizers, maybe not. But it seems it can't work via subprocess.call Python on Windows due to the above problems.

Somewhat related, here is another (tested and working) way of calling subprocess.call and feeding an exe a known file:

# Python 2.7 - load a known Poser PNG render, dropped by the script onto a user's unknown Desktop.
import os
import subprocess

from os.path import expanduser
home = expanduser("~")
fulldesk = os.path.join(home,"Desktop|output.png")
subprocess.call([r"C:|Program Files|IrfanView|i_view64.exe",fulldesk])

| = backslash



Learn the Secrets of Poser 11 and Line-art Filters.


HartyBart ( ) posted Sun, 08 August 2021 at 5:18 PM · edited Sun, 08 August 2021 at 5:19 PM

After a little digging I now see that a Pillow (PIL) optimize command is available for PNG, at least according the Handbook. A simple convert using optimize then works when run from Poser 11:

import poser
from PIL import Image

im = Image.open(r"C:|Users|NAME|input.png")

im.save(r"C:|Users|NAME|output.png",optimize=True)

However, with optimize=True set, the output file is actually slightly larger. Which is obviously no use.

The user might also add a line between these to quantize the PNG to shrink it - by reducing the palette size. There appear to be two ways to do this, old and new:

im = im.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=256)

or

im = im.quantize(method=2)

But both fail under Poser 11. Either "quantize is not found", or the PNG "has the wrong mode". There appears to be no way to "import qualitize", at least under Python 2.7, which I thought might be something that was needed. Either method - when it works - apparently has major problems with maintaining background transparency, though there appear to be highly complex pixel sampling workarounds for this.

So the idea of using PIL (to bypass having to call an EXE file via subprocess.call) does not appear viable for automatically optimizing Poser 11's PNG image output.



Learn the Secrets of Poser 11 and Line-art Filters.


HartyBart ( ) posted Mon, 09 August 2021 at 1:38 AM · edited Mon, 09 August 2021 at 1:38 AM

On Windows, I've found a freeware BAT To EXE Converter that works and does what it says. The resulting EXE can be used to feed arguments to other EXEs and read/write files, without having to set up the arguments in Python. All that is needed in the actual Python is then:

subprocess.call([r"C:my_bat_as_an.exe"])

But how is this superior to using a plain old BAT, you ask? Well, in one important way.

It bypasses the need to have the Poser 11 user launch Poser in Administrator mode. With Poser running normally, a Python script will fail at the point of calling a Windows BAT file. But.... if the BAT is inside an EXE and called from subprocess.call, then Admin mode does not appear to be needed. The script maker is then relieved of having to tell users to 'run Poser in Admin mode' to run his script.

I know this still doesn't make the Python cross-platform. As it might if PIL could be used to do things like optimisation. Or if arguments/switches could be passed to an EXE via Python on Windows (they can't, it seems). But it is a step forward for Windows-only scripts.



Learn the Secrets of Poser 11 and Line-art Filters.


Privacy Notice

This site uses cookies to deliver the best experience. Our own cookies make user accounts and other features possible. Third-party cookies are used to display relevant ads and to analyze how Renderosity is used. By using our site, you acknowledge that you have read and understood our Terms of Service, including our Cookie Policy and our Privacy Policy.