The Film Gimp Architecture Plan (FGAP)
Film Gimp is evolving. A team of developers,
about twenty at last count, is contributing to that, with each
member individually effecting what Film Gimp becomes. Sometimes
I'm asked if leading a cooperative open source project isn't impossible
because nobody can be ordered to do anything. From my experience
with corporate and research university projects I've learned that
leadership always requires persuasion. As my department chair
used to say when I was a lecturer and research scientist at the
Naval Postgraduate School, "Managing programmers is like
herding cats". In writing down a plan for Film Gimp my goal
is to define a vision, not to tell anyone what to do or limit
our options.
What is Film Gimp?
Film Gimp is a paint and image retouching
program that today is mainly used for dustbusting, that is, manually
cleaning dust off 35mm film scans. The architecture of Film Gimp
is a core program, a library of service routines, a procedural
database (PDB) with a wire interface, and program resources. Resources
include brushes, gradients, palettes, patterns, plug-ins, and
scripts. There are rc settings control files for core, gtk, menus,
and plug-ins. Fundamental to the core of Film Gimp is the frame
buffer, and for scalability that is operated upon as tiles. Film
Gimp has its own tile cache.
Film Gimp does not currently support motion
picture editing, compositing, morphing, rotoscoping, or blue screen
mattes. However, there are ideas in that direction.
Film Gimp seeks to support all popular
operating systems including Linux, Macintosh, and Windows.
The Frame Manager
Film Gimp has features and controls comparable
to Adobe Photoshop. A significant innovation in the workflow of
Film Gimp is the frame manager. The frame manager considers a
directory of numbered images to be a movie, and offers the typical
movie controls including a Play button and a Next Frame button.
That enables users to quickly advance frame-by-frame through a
movie made up of scanned high resolution frames, to rapidly retouch
frames using the clone tool to copy a region from an adjacent
frame to cover an imperfection. Defects being retouched include
dust and scratches, wire rig removal (e.g., flying actors), continuity
(e.g., removing power lines and overhead aircraft from historicals),
and animation errors (e.g., popped seams in NURBS).
Pixels
Pixels in Film Gimp are RGBA at 8-bit,
16-bit integer, and 16-bit float per channel bit depths internally.
Although able to read logarithmic Cineon files, Film Gimp converts
them internally. Formats such as Radiance HDR (which we can read
but writing is missing) could be more efficiently manipulated
in native form. Should Film Gimp be able to manipulate using any
pixel layout internally without conversions?
Because supporting multiple formats internally
is cumbersome in C (using "switch" statements), it is
tempting to convert to 32-bit RGBA throughout. However, there
can be an efficiency hit to doing that, and there can be truncation
of data with log formats. A single-pixel approach also fails to
address other color spaces such as CMYK and RGBAZ (laser-ranged
Z-map). A more sophisticated approach is C++ templates combined
with simple pixel object operators that can implicitly act in
any algorithm to perform upon any format in its native form. That
is the more desirable and flexible approach, but may be challenging
to implement.
C++ Code
Before using C++ templates or other object-oriented
design features, Film Gimp must first convert from C to C++. That
change is scheduled for February 2003. Conversion to C++ may not
be as trivial as some expect because C++ is more strict in interpretation
of rules than C, not simply a language superset.
Will future Film Gimp design become more
baroque after the C++ conversion? Will programmers inexperienced
with C++ go overboard? In C++ there may be ten ways to do the
same thing, and some programmers will try to use all ten ways
-- missing the point that flexibility enables choosing the best
way. Students especially are prone to want to prove they can use
every C++ feature available, like a new chef gone wild with every
spice in the kitchen spice rack. That result isn't very palatable.
For simplicity and efficiency, C++ features need to be employed
intelligently and sparingly.
Features of C++ that can improve program
clarity without cost include classes (encapsulation), function
overloading, and bool. Caution is necessary with inheritance,
operator overloading, and templates. Those can impact efficiency,
size, and even comprehension of what the code does. RTTI, namespaces,
and exceptions should be avoided. RTTI and namespaces are rarely
needed, add complexity, and can cause compiler portability problems.
Exceptions can be a religious debate. It depends upon whether
you believe in termination.
There are three fundamental approaches
to handling errors in C++ programs: hope, termination, and limping.
The hope system, which unfortunately many programmers became comfortable
with in school, is to use no error checking at all. The program
crashes or is erratic. Exceptions can prevent that by triggering
a condition that must handled. Exceptions are based on the termination
theory of program control, that any unexpected error must stop
the program. A program that throws an exception can abort. If
a second exception occurs as a side-effect of handling the first,
the program immediately exits.
Would you embed an abort() call in your
code? For academic research programs or batch programs yes you
may be happy to do that. However, for professional grade GUI programs
to abort isn't very nice. A GUI program such as Film Gimp should
limp, that is, disable what's gone wrong and keep going. The user
should keep control of when the program exits. This approach demands
greater care from programmers. Every error condition needs to
be accounted for, every return value checked.
The C++ language has an underservedly
bad reputation for executable size compared to C. Avoiding poorly
optimized C++ libraries is part of a strategy of preventing program
size ballooning when converting to C++ from C. The standard template
library (STL) needs to be avoided because of the code size risks
inherent to the casual use of templates. There is also a significant
learning curve for the STL that we don't want to inflict on every
programmer. Another standard library to be avoided is iostream.
That may seem shocking with it being the most popular C++ library
and commonly used everywhere as a replacement for stdio. Replacing
stdio seems very desirable because iostream is typesafe. That
avoids difficult to trace stack fault bugs that programmers using
printf can too easily create. However, iostream isn't particularly
efficient, and it is redundant to carry around both iostream and
stdio, which would be inevitable with legacy C code. I'm creating
an iostream-like wrapper for stdio that I'm calling iostdio. Including
that instead of iostream will grant programmers the most popular
subset of the iostream interface but will actually route faked
iostream calls into the highly optimized stdio library instead.
Plug-ins
The plug-in architecture in Film Gimp
is changing. Traditionally that has used fork/spawn to launch
a separate process, with communication between core and plug-in
via pipes. This has the advantage that a crash or abort in a plug-in
can't crash Film Gimp, but is very inefficient. Using dynamic
link libraries is the new architecture -- thus far only in the
prototype Windows version of Film Gimp. Using dlls means that
many core functions, for instance handling the XCF file format,
can become plug-ins. The plug-in architecture change makes Film
Gimp a less monolithic design, and the core may over time be pared
to just the frame buffer with the rest as plug-ins.
Wire Protocol
Plug-ins communicate with the core using
the wire protocol. This is a marshalling protocol that swizzles
data to make it travel over a pipe. The marshalling data tells
the receiver how to unpack the data into a struct. In the new
architecture pipes are dispensed with, and the protocol is read
directly from common memory. With dlls, everything is shared common
memory and there is no need to use system shared memory. That
will help the Mac OS X version of Film Gimp. Inter-process shared
memory doesn't work on that platform because Apple didn't implement
it. Film Gimp uses system shared memory optionally now to try
to improve performance in frame buffer operations. In converting
to dlls we will eliminate system shared memory calls.
Procedural Database
At the other end of the wire interface
in the core is the PDB. The procedural database exports functions
from the core or other plug-ins so that commands coming down the
wire will do something. Many exports are missing from the PDB,
such as access to the frame manager. Consequently, you can't presently
write a plug-in that will handle manipulating a frame sequence.
When that is fixed it will be feasible to write a plug-in that
manages any other plug-in over a sequence. A user will be able
to do an operation to the first frame and last frame of a sequence,
and the sequence plug-in could smoothly interpolate that operation
across the frames in between.
GUI Design
Film Gimp operations require too many
clicks. Film Gimp branched from GIMP 1.0.4 in 1998 and inherited
that questionable interface. Pulldown menus differ Film Gimp from
GIMP, but It is generally conceded that the interface of Adobe
Photoshop is still better. However, there are many complaints
about Photoshop also. Aping the Photoshop user interface is not
the answer. We have to be better than Photoshop.
Layers and channels are a critical problem.
It is way too hard to get at the alpha channel. After finishing
the Windows port of Film Gimp (which is now overdue as I write
this on February 7, 2003) that is my next burning issue. The new
design will employ a "layer of layers" approach to manipulate
channels. This architecture will make it easy write on the alpha
channel and make channels generally as powerful as layers. Channels
will become sub-layers named r, g, b, and a. Layer locking will
bring together channels to be one layer again. This design should
enable any set of layers to be locked together to act as one.
***More to come, back to Windows porting
.
Questions to rower@movieeditor.com
Created February 7, 2003; updated
February 7, 2003