Calvin Williamson wrote:
You arent stepping on any toes. Its fine to think about everything
you have been raising on the list so far. And this is the right
place to hash out all the details of architecture that we can.
ok good :-)
Current envisioned class list
<interface>
*class*
-abstract_class-
Some iterfaces. A GeglCacheable object can be moved between caches
by a cache manager
<GeglCacheable>
ImageProducers are Nodes that have outputs
<GeglImageProducer>
ImageConsumers are nodes that have inputs.
<GeglImageConsumer>
Cacheable would make a fine interface, agreed.
What are some of the methods you would put on an ImageProducer and Image
Consumer interface, and why do you need these?
The producer and consumer interface would have GeglNode as a
prerequisite. An image producer is something that has images as output.
An image consumer is something that has images as input. This might
be better constructed as a GeglDataProducer and GeglDataConsumer
subclass. This would allow us to do things like check that the proper
consumer/producer is attached to an appropriate op of the opposite type.
Also the consumer/producer interface might provide methods to
interator of its list of inputs for the partiular relevant type. What I
really belive is that there is value to declaring that an object just
produces images (has outputs) just consumes images (has just inputs) or
does both. It also lets me make the GeglNode class look cleaner (I
think anyway).
This is an abstraction I have seen in several data flow-oriented api's
including BeOS's sound api, and Java's sound (and image, I think) api.
I think it is clean and does away with the GeglNoInput subclass, which I
think is awkward.
This represents some area of memory (not the same as the Current
GeglStorage) Also, here, GeglTile is just a portion of a two-dimential
block of memory. GeglBuffer is actually a continuous portion of memory.
-GeglStorage- implements <GeglCacheable>
*GeglTile*
*GeglBuffer*
I dont see why both Tile and Buffer are here. I envision the Tile has a
swappable Buffer.
I envision a Tile as a two dimensional object (in sample space) that is
a sub set of a larger, two dimensional set of samples. I think a Tile
should know about the exsistence of it's neighbors (up, down, left, and
right). A GeglBuffer would be complete on it's own. There is also no
reason why loner buffers could not be swapped (say for example, a
convolution kernel, or a large array of scalars that represents a
histogram).
-GeglData-
(GeglChannel behaves like a continuous block (through a good *non
existant* api :-) It's backed by tiles.)
*GeglChannel*
*GeglScalar*
*GeglPixel*
-GeglDataContainer-
*GeglImage* (this is because Images can be
seen as a set of channels or set of pixels)
*GeglScalarArray*
*GeglPixelArray*
This is based on the current GeglData hierarchy, correct?
If so, this is sort of the right idea, at least for the Data hierarchy.
Except I think you are confused what GeglChannelData is. The current
GeglChannelData is similar to a scalar, except it is restricted to the
channel data space. eg 0-255, 0.0-1.0, 0-65535, etc. If you are
going to pass an array of these things you would probably pass
that as a grayscale Image with that channel data type.
Yes, this is based on the current GeglData hierarchy. Except I don't
like the GeglImage and GeglImageData distinction; mostly 'cause I don't
see why it must exist. I think you said that to read an image, you
subclass GeglImage, but shouldn't an image reading function be a node in
the execution graph? And if so, doesn't that mean that our real image
objects are the GeglImageData which are passed around by the nodes? So
I did away with GeglImage and dropped data out of the class name of all
the subclasses of GeglData (since they are data by being a subclass, so
I feel the longer name didn't contribute much to it's description).
I see GeglChannel as a container of Samples. A sample is a measurement
that is mapped to the 1.0-0.0 interval when converted to a float (one
can argue that even when we do the math with integers, we do it such
that the result is the same as it would have been if it was done on the
1.0-0.0 interval, and then mapped backed to the integers). Scalars, on
the other hand, can have any value, and are converted to the same value
(possibly with rounding) when converted to a float. But you are right.
I didn't see a need for a seperate GeglSample class, but you could
add GeglSample above, and add GeglChannel under GeglDataContainer (as a
container for Samples).
This is similar to the exsisting setup, but makes use of the cleaner
(I think anyway) interfaces defined above.
-GeglNode-
*GeglGraph*
-GeglImageSource- Implements <GeglImageProducer>
-GeglReadImageFile-
*GeglReadPNG*
-GeglReadImageSequence-
*GeglReadMpeg*
*GeglSingleColorImage*
*GeglPatternedImage*
-GeglImageSink- Implements <GeglImageConsumer>
*GeglXViewer*
-GeglWriteImage-
*GeglWritePNG*
-GeglWriteImageSequence-
*GeglWriteMpeg*
-GeglPipe-
*GeglPrint*
-GeglFilter- Implements <GeglImageProducer> and <GeglImageConsumer>
-GeglPointOp-
-GeglUnary-
-GeglBinary-
-GeglComp-
*GeglConvolve*
*GeglBlur*
But you need something abstract above ImageSource, ImageSink, and Filter,
since you will have Ops that have nothing to do with images, and they
will still have process, inputs and outputs, just they arent image
inputs or outputs necessarily, etc.
Ah, ok. Then I'll stick a GeglImageOp in the approiate place above.
--
Dan