emcconville / wand

The ctypes-based simple ImageMagick binding for Python
http://docs.wand-py.org/
Other
1.4k stars 197 forks source link

ImageMagick CLI to Wand compilator #100

Open honzajavorek opened 11 years ago

honzajavorek commented 11 years ago

Just an idea, maybe silly, feel free to close this. Dive into the world of dreams and imagine following tool...

I have standard CLI command for ImageMagick:

convert test.jpg ( -clone 0 -fill '#00ff00' -colorize 100% ) ( -clone 0 -colorspace gray ) -compose blend -define compose:args=0,100 -composite test.jpg

I can do this:

from wand import cli_compiler

cmd = '''
    convert {filename}
    ( -clone 0 -fill {color} -colorize 100% )
    ( -clone 0 -colorspace gray )
    -compose blend -define compose:args=0,100
    -composite
    {filename}
'''
processor = cli_compiler(cmd)   # pre-compiles the command
processor(filename='test.jpg', color='#00ff00')  # does the job

cli_compiler would translate the command into Python code calling MagickWand API. It would also support parameters, as shown above. It returns callable, which does the job.

Is this science-fiction? I think it could be done by PLY or something, though the parser would have to be probably very complex. I don't know IM's "parameter language" so well so I could judge it from such point of view right now.


Use cases:

lqez commented 11 years ago

:+1:

dahlia commented 11 years ago

It’s really a brilliant idea for me, though it seems hard to be completely implemented, because there are still a lot of lacking features for Wand when it compares to ImageMagick.

Plus, I think the compiler should be possible to generate actual Python codes. It help users who don’t want to maintain command strings (which cannot be easily composed) to migrate their code to pure Wand API calls.

suminb commented 11 years ago

:+1:

honzajavorek commented 11 years ago

Well I wrote a simple compiler (in PLY) of custom query language into SQL (code to code) and later on I changed it so it constructs directly an object of dynamic select clause from SQLAlchemy (code to complex set of objects). It was not harder to write one or another, so I assume this to be just an implementation detail. I agree that for purposes of Wand, generation of code would be probably more helpful, it makes sense to me.

So the only stopper here is that Wand does not have complete API support? Well, we could implement what is already available and just raise NotImplementedErrors for the rest. When feature is added, it could be then (usually easily) added also to compiler. Most of people just rotate/resample images anyway...

dahlia commented 11 years ago

I think it would be released in 0.4.0 if we start working on this.

honzajavorek commented 11 years ago

I could help with writing the compiler. But first I suggest to start from designing the API of such feature. If it's supposed to be code generator, it could be available as standalone script, a tool for developers.

dahlia commented 11 years ago

It could consist of two primitives and rest facades:

  1. Parser which takes an iterable of strings. (We don’t have to write a lexer for it by ourselves because shlex would be able to do it for us.) It returns a tree.
  2. Compiler which takes a tree. As like typical compilers generate IR, bytecode, or assembly, this would generate a Python code string, or ast object. We can also learn things from Jinja about this. See this talk.
  3. Facades like a shortcut interface that combines lexer and parser, interpreter interface that compiles convert command string and then immediately executes the result, migration utility that finds convert command strings in a source tree and then automatically substitutes them into Wand codes, and so on. We can imagine a lot of examples.
honzajavorek commented 11 years ago

:+1:

Although I do not know Python ast objects (I know what generally AST is) or convert, it sounds like fun :-) I was always curious how Armin made Jinja without PLY, pyparsing or something like that.

dahlia commented 11 years ago

Oh convert command string I said means our input string like this:

'''
    convert {filename}
    ( -clone 0 -fill {color} -colorize 100% )
    ( -clone 0 -colorspace gray )
    -compose blend -define compose:args=0,100
    -composite
    {filename}
'''
dahlia commented 11 years ago

I think the reason why Armin made Jinja without any parser generators/combinators is that he want to make the syntax customizable. For example, you can use <% or [$ instead of {% token.

emcconville commented 9 years ago

Rebooting this effort. This enhancement may be growing in complexity. It's ideal to build out a lexical analyzer, but hints of ImageMagick 7 may suggest changes in the upstream CLI parser. Also, some IM operators have different context between utility (e.g. the -format & -frame alter between identify and convert.) Building a compiler may be a really large effort.

If the original request is just to take raw CLI commands, and optional bind parameters feature, then MagickCommandGenesis could offer a straight solution. Each ImageMagick utility has it's own CLI parser, which we can "hand-off" user commands to. I'm experimenting with this method, and it seems like a valid proposal.

from wand.cli import Parser

cmd = '''
    convert {filename}
    ( -clone 0 -fill {color} -colorize 100% )
    ( -clone 0 -colorspace gray )
    -compose blend -define compose:args=0,100
    -composite
    {filename}
'''
processor = Parser(cmd)
processor(filename='test.jpg', color='#00ff00') 

Pros: Easy to implement & support Cons: ImageMagick hijacks I/O, like stdout & stderr. (although that might be desired behavior)

dahlia commented 9 years ago

There would be two purposes as @honzajavorek said:

  • I have old code with subprocessing ImageMagick. Having such compiler, I can immediately migrate to Wand.
  • I have no further knowledge of ImageMagick and I find a tutorial on the internet how to perform what I need - of course using CLI params and convert command. I could just copy-paste it and use such compiler. Job done in 3 minutes!

The solution proposed by @emcconville seems to solve only the former one. Although it does not mean I disagree with @emcconville. If the latter purpose does not that matter it could be a valid solution.

honzajavorek commented 9 years ago

I do not do much with ImageMagick these days, but from those two use cases I see the second as more "important" nice-to-have feature, because:

From my POV enabling convert tutorial to Python masses via Wand would be awesome.