finalizing the Iterator API

Boudewijn Rempt boud at
Wed Jul 7 09:14:23 CEST 2004

On Wednesday 07 July 2004 00:15, Casper Boemann wrote:

> > As for the ".h", here is my opinion :
> > * I don't see the difference between KisPixelIterator and
> > KisPixelRectIterator.
> Well KisPixelIterator is just a super class (oh I forgot that in the class
> definition didn't I)
> Other subclasses besides Rect could be Path or Line, or Extent
> They only visits some pixels. The superclass doesn't really do anything - I
> think it should be abstract.
> And as Boudewijn said up,down.left,right might be nice functions, however
> they don't make sense for a PathIterator. I have had this idea myself, but
> on reflection: when would they really be used.

Edge detection, for instance.

> Another Iterator I just tought of is an affine transformation, used to
> scale, rotate and shear images.

I have a hard time visualizing that, so I'd like to see it... Currently we use
affine transform code I ported from Qt, debugged by Bart, for all this, but we 
really need bicubic interpolation scaling, as the current scaling is really 

> The prime requirements when defining our pixel representation are:
> 1) it should store only the actual channel data. No configuration data -
> since that would cost too much memory when storing several millions of
> pixels.

:-(. It's a pity, since it would make programming so much easier. But in the 
end, I think we have no choice.

> 2) it should allow any combination of int8, int12, int32, float,double,
> bits 

Fortunately, the colour strategies already have the rudiments of a pixel 
description in the ChannelInfo structure. This needs to be extended and 
formalized -- here I really put my foot down. I don't want to have to check 
the depth of the image every time I consult the ChannelInfo :-).

> 3) copyable without knowing interpretation 


> 4) it should either be
>    a) truly universal, but that requires configuration info clashing with
> requirement 1
>    b) dynamic down-castable to specific imagetypes but that also clashes
> with 1
>    c) static down-castable which is what my proposal does.

> Anyway , the GOF (p 91 bottom paragraph) 

My offer to provide a copy to people not having that book still stands: 
however, not having the paper version handy, can you give the pattern you 
refer to?

> discusses a similar problem, and 
> doesn't refer to a usable pattern. It actually alludes that there are none
> except the same solution I propose. Note our problem is even worse because
> we have even more requirements.

Yep. In image manipulation land there are a few solutions that are frequently 

* Manual code duplication -- this is what Photoshop does, I believe (because 
their 16-bit channel images cannot be manipulated like the 8-bit, but every 
release gets a bit better.
* Code generation from a description -- this is gegl. Generate C code for 
every image type from a common description.
* Templating -- this is what Vigra does to an amazing extent, and what CImg_ 
does to a lesser extent.
* Using the maximum precision representation internally, and convert down on
saving. This is what Vips does.
* Using classes and interfaces to abstract everything into polymorphism. This 
is what Java2D does, and what OpenEXR seems to do. (Note: ImageJ is a public
domain Java image manipulation app that's plenty fast enough, and it uses 
Java2D and some home-grown things. It can be made to work, but perhaps not in 
C++. Java is more efficient when it comes down to polymorphism).

So, having overseen the possible solutions, I think we will go with passing a 
pointer to bytes (Q_UINT8) to the colour strategies. The colour strategies 
can construct, on demand, pixel, colour or channel objects for algorithms to 
manipulate. Or algorithms that don't care about how the pixel is laid out 
(copy, affine transforms) can copy the Q_UINT8 data directly.

We can then get ultimately rid of QUANTUM, which is an inheritance from the 
days Krita used ImageMagick as its core. Howevere, that is another 
refactoring step, one which we don't have to take now.

We need the iterators now, so I can continue with selections, and we need to 
port the plugins and the affine transform code to use image-type independent 

> We could change my proposal to a pointer to an entirely empty class, but
> that is only name calling, and we would still have to static downcast to
> specific subclasses in the colorstrategies.
> The problem with an empty class is that calling sizeof() would be wrong
> (can sizeof be overloaded to give a compile error?). Also an empty class
> that actually contains something seems wrong to me conceptually. For
> example you cannot have an array of these empty classes. The byte array
> seems more correct.
> The benefit of an empty class is that the iterators return a pointer to a
> Pixel class, which may seem more descriptive to the programmer.
> Anyway I'm willing to use an empty class, if the rest of you insist. I do
> however think it gives more complicated and errorprone code, but it is
> definitely doable.

I feel convinced. Although -- see the pseudo-code I mailed in response to 
Cyrille's concerns. It seems a bit silly to have to manually ask the colour 
strategy to parse the data into a pixel. Maybe we can provide a PixelIterator 
that returns the parsed data, for those algorithms that need it that way, and
a PixelDataIterator that returns the pointer, for the algorithms that leave
all the real work to the colour strategy anyway.

> yes it is because of the dynamic layersize I'm working on. It may be
> possible to encode the row,col as a single number but that would just be
> yet another calculation to do for no real benefit. Row and col of a tile
> remain the same when the size of the device changes. tilenum does not as it
> depends on the number of columns (which obviously will  no longer be
> constant)

That's your party: if you need it this way for dynamic layersize, it's 
something that must get in. It doesn't affect the users of the iterators.

Boudewijn Rempt |

More information about the kimageshop mailing list