This is an example of how to implement an ImageOperation that converts image to grayscale using a direct access to ImageBuffer.
#include "BWconversion_direct.hpp"
template <ValueType::Enum PixelFormat>
void  BWconversion::convert(MipMap* srcMipMap, MipMap* destMipMap, vector<UpdateInfo>& ROIlist, const long stamp) {
    for (typename std::vector<UpdateInfo>::iterator ROI = ROIlist.begin(); ROI != ROIlist.end(); ++ROI) {
        const int level = ROI->ROI->mipmapLevel;
        ImageBuffer<PixelFormat>* src = static_cast<ImageBuffer<PixelFormat>*>((*srcMipMap)[level]);
        ImageBuffer<PixelFormat>* dest = static_cast<ImageBuffer<PixelFormat>*>((*destMipMap)[level]);
        unsigned int startTileVert = ROI->ROI->y / src->getTileExtent();
        unsigned int endTileVert = startTileVert + (ROI->ROI->sizeY - 1) / src->getTileExtent();
        unsigned int startTileHoriz = ROI->ROI->x / src->getTileExtent();
        unsigned int endTileHoriz = startTileHoriz + (ROI->ROI->sizeX - 1) / src->getTileExtent();
        for (unsigned int tileVert = startTileVert; tileVert <= endTileVert; tileVert++) {
            for (unsigned int tileHoriz = startTileHoriz; tileHoriz <= endTileHoriz; tileHoriz++) {
                Tile<PixelFormat>* destTile = dest->getTile(tileHoriz, tileVert);
                if (destTile->getStamp() != stamp) {
                    typename Tile<PixelFormat>::Iterator srcIt = src->getTile(tileHoriz, tileVert)->upperLeft();
                    typename Tile<PixelFormat>::Iterator srcLr = src->getTile(tileHoriz, tileVert)->lowerRight();
                    typename Tile<PixelFormat>::Iterator destIt = destTile->upperLeft();
                    unsigned int bands = dest->getPixelData().numOfBands();
                    for (; srcIt != srcLr; ++srcIt, ++destIt) {
                        for (unsigned int i = 0; i < bands; i++) {
                            destIt[i] = srcIt[0];
                        }
                    }
                    destTile->setStamp(stamp);
                }
            }
        }
    }
}
    switch(sources[0]->getPixelData().format()) {
        #define FORMAT_DO_STH(T,U) convert<T>(sources[0], dest[0], ROI, stamp);
        case_ANY;
        #undef FORMAT_DO_STH
    }
}