PixelIop
========

  The PixelIop class provides a more specialised version of Iop which provides certain boilerplate code, given certain assumptions.
  PixelIop is intended for ops that are not spatial in any way - that each pixel in the output depends upon the pixel at the
  same coordinates in the input, and no other pixels.  Examples of Ops that might be implemented as PixelIops could include Gain
  or Desaturate.

  PixelIop varies from Iop by having two new pure virtual calls, that the plugin must implement.  These are:

  .. code-block:: c

       virtual void in_channels(int input, ChannelSet& mask) const = 0;
       virtual void pixel_engine(const Row &in, int y, int x, int r, ChannelMask, Row &);
   
  in_channels is called by the PixelIop's definition of _request, for each input.  It passes the input number as /input/ and
  a reference to a ChannelSet as /mask/.  This ChannelSet is initialised with the channels that have been requested 
  - in_channels should fill in any other channels that are needed (or remove those that are unnecessary) on the given input.
  For example, a simple Desaturate would implement in_channels like so:

  .. code-block:: c

    virtual void in_channels(int input, ChannelSet& mask) const 
    {
      if (mask.contains(Mask_RGB))
        mask += Mask_RGB;
    }

  That is, if any of the Red, Green or Blue channels have been requested, it needs to request all of them from its input.

  The pixel_engine function is called with the row from the input already fetched with the correct channels from in_channels
  Generally the output row and the input row are actually the same Row, but this should not be relied upon.  A simple 
  implementation of pixel_engine that merely multiples all the pixels by 0.5 is as follows:

  .. code-block:: c

    virtual void pixel_engine(const Row &in, int y, int l, int r, ChannelMask channels, Row& out)
    {
      foreach(z, channels) {
        const float* inptr = in[z];
        float* outptr = out.writable(z);
        for (int x = l; x < r; x++) {
          outptr[x] = inptr[x] * 0.5;
        }
      }
    }
