Pixel operations and colorspaces

Boudewijn Rempt boud at valdyas.org
Mon Aug 15 20:06:28 CEST 2005


I'm getting bogged down when trying to work with the colormodel classes -- 
they are getting too big, and I'm not succeeding in making it possible to
warn users when they try a filter or another operation that isn't natively
supported. Besides, adding a new operation is a lot of work and means adding
code all over the place.

I think the following design will help us achieve more flexibility, smaller
classes and a clearer and safer user interface.

I want to define a class KisPixelOp which is the abstraction of the idea of
 messing with one or more pixels as  expressed by an array of Q_UINT8's. 

A given colorstrategy can provide a given pixelop natively, or return a 
default implementation; a default implementation implements the same 
algorithm, but may have to downscale or upscale the pixel data or convert it 
to a colorspace that may have a smaller gamut.

If a filter or a plugin or even a core part of Krita needs to mess with some 
pixels, it will ask the colormodel of the current paint device for an 
implementation; it then needs to downcast the implementation to the needed 
subclass. For instance:


// The cast is necessary because we need to be able to call the
// specialized process method which may have any amount and type of
// parameters. No need for genericity here, because we _know_ what we
// want :-).

KisApplyAdjustmentOp * adjustop = 
dynamic_cast<KisApplyAdjustmentOp*>(dev->colorStrategy()->getOp("applyAdjustment");

    if (!adjustop) {
	KMessageBox::error(0, i18n("Brightness/contrast adjustment is not possible 
with this image type.");        
    }

    if (!adjustop->isNative()) {
        KMessageBox::questionYesNo(0, i18n("Brightness/contrast adjustment may 
cause information loss when used with this image type. Do you want to 
continue?"));
    }

    KisBrightnessContrastFilterConfiguration* configBC = 
(KisBrightnessContrastFilterConfiguration*) config;

    KisColorAdjustment *adj = 
src->colorStrategy()->createBrightnessContrastAdjustment(configBC->transfer);
        
    KisRectIteratorPixel dstIt = dst->createRectIterator(rect.x(), rect.y(), 
rect.width(), rect.height(), true );
    KisRectIteratorPixel srcIt = src->createRectIterator(rect.x(), rect.y(), 
rect.width(), rect.height(), false);

    setProgressTotalSteps(rect.width() * rect.height());
    Q_INT32 pixelsProcessed = 0;

    while( ! srcIt.isDone()  && !cancelRequested())
    {
        Q_UINT32 npix;
        npix = srcIt.nConseqPixels();
        
        // change the brightness and contrast
        adjustOp->applyAdjustment(srcIt.oldRawData(), dstIt.rawData(), adj, 
npix);
                    
        srcIt+=npix;
        dstIt+=npix;

        pixelsProcessed++;
        setProgress(pixelsProcessed);
    }

If a plugin wants to add a new pixelop, it can create one or more 
implementations for one or more colormodels and register them with the 
colormodels. You can also implement a generic op that converts pixel data 
using toQColor and nativeColor, for instance, or through XYZ, applies the 
operation and then converts it back.

As an API for registring pixelops I think it'd work to add something like this 
to KisColorSpaceRegistry:


/**
 * Add a new pixelop to the specified colorspace. If default is
 * true, then this pixelop will be used whenever any colorspace doesn't
 * have a specific implementation. If that is the case, the pixelop needs
 * to take care of all conversions between colormodels, so it isn't any old
 * pixel op that can handle the responsibilty.
 */
addPixelOp(KisID colorspace, KisPixelOp * op);

/** 
 * Retrieve a default pixel op. This is called by the colormodels, not by
 * filters or other clients
 */
getPixelOp(KisID * id);

No doubt I'll encounter some hitches with this scheme, so if anyone can point 
them out beforehand, that'd be helpful. But I think that, all things 
considered, this is a pretty sound scheme.


-- 
Boudewijn Rempt 
http://www.valdyas.org/fading/index.cgi


More information about the kimageshop mailing list