Learn from the Past
I was on a Google hunt for a picture of Peter Weinberger (the 'W' in awk) on a water tower and I ran across a book I had seen once many years earlier called "Beyond Photography - The Digital Darkroom". This book is available online in a series of PDF files. In the book it describes the image processing and a little language that can be used for image processing.
There are a number of elements that are built into the language that are fantastic. It has the ability to describe a set of transformations that map pixel values from one or more source images to a destination image as well as to manipulate the image data on the way through.
Transformations can be done in Cartesian or polar coordinates or both.
The language itself has implicit looping, so you never need to worry about that.
In essence, your job is to use the language to write an expression that will be evaluated for each pixel in the image and it does the rest.
There are a number of things in the base implementation that are, well, quaint by today's standards. For example, the image dimensions are compiled into the application and default to 248x248, which is tiny. The language has a hard-coded recursive-descent parser, which is based on a spelled-out grammar. In fact, the chapter which describes the language is an excellent tutorial on how to write a parser.
The program has the facility for JIT compilation to boost performance, and is extensible to include display support.
There are a lot of nice goodies in there including recipes for image processing.
Translating this to .NET wouldn't be too hard - even easier if you used dotImage to do the image reading and writing. I would make an abstract descendant of ImageCommand that includes a method for performing the image processing. The use the expression parser to JIT compile it to CLI and instantiate a new command. This is not trivial work, but it is straightforward. It's actually not that different from the DotImage UserTransform command that lets you do any coordinate transform from one space to another, using a delegate.