wand icon indicating copy to clipboard operation
wand copied to clipboard

ImageMagick CLI to Wand compilator

Open honzajavorek opened this issue 11 years ago • 13 comments

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:

  • 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!

honzajavorek avatar Mar 14 '13 09:03 honzajavorek

:+1:

lqez avatar Mar 14 '13 13:03 lqez

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.

dahlia avatar Mar 14 '13 23:03 dahlia

:+1:

suminb avatar Mar 15 '13 00:03 suminb

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...

honzajavorek avatar Mar 15 '13 07:03 honzajavorek

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

dahlia avatar Mar 15 '13 10:03 dahlia

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.

honzajavorek avatar Mar 15 '13 10:03 honzajavorek

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.

dahlia avatar Mar 15 '13 11:03 dahlia

:+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.

honzajavorek avatar Mar 15 '13 11:03 honzajavorek

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 avatar Mar 15 '13 12:03 dahlia

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.

dahlia avatar Mar 15 '13 12:03 dahlia

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)

emcconville avatar Apr 03 '15 15:04 emcconville

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.

dahlia avatar Apr 04 '15 02:04 dahlia

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:

  • Having old code which works isn't such a burden. Why would I want to reimplement it in Wand? For convenience? For optimization? Every case is special and needs more efforts.
  • The Internet is full of ImageMagick tutorials. You can even make yourself your very own little Instagram.

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

honzajavorek avatar Apr 07 '15 07:04 honzajavorek