High-level pixel access methods

Boudewijn Rempt boud at calcifer.valdyas.org
Sun Feb 15 13:25:17 CET 2004


On Sunday 15 February 2004 10:16, Patrick Julien wrote:
>
> Single pixel access from methods is always going to be slow, no matter when
> they reside.
>

But perhaps not as slow as they're now -- I think it's something that's really 
needed. The tile system should be hidden as much as possible from the rest of 
the system. And time and again, one needs to get a pixel, set a pixel -- it's
 what painting apps is all about.

>
> So, you basically want a way to access pixels on a line basis without
> having to think about tiles?

Yes -- and without having to allocate temporary memory buffers to copy 
the image data into before accessing it. Two examples:


In KisPainter::computeDab, I take the alpha mask from a brush (but it would be 
the same with the QImage of a brush) and create a temporary layer that I can 
composite with any of the implemented composite ops onto the target layer. 
This is what I do:

        m_dab = new KisLayer(mask -> width(),
                             mask -> height(),
                             m_device -> typeWithAlpha(),
                             "dab");
        m_dab -> setOpacity(OPACITY_TRANSPARENT);
        for (int y = 0; y < mask -> height(); y++) {
                for (int x = 0; x < mask -> width(); x++) {
                        m_dab -> setPixel(x, y, m_paintColor, mask -> 
alphaAt(x, y));
                }
        }

I guess I could create a KisPixelDataSP structure, allocate a buffer for the 
data,
and push the pixels directly into that buffer, but I'd really like that kind 
of
code to be hidden.

In KisPaintDevice::transform, I use a QWMatrix to perform what I guess are 
affine
transforms on a layer. Apart from all the matrix code, what I have, or would
like to have, is this:

	... matrix stuff ...

        KisTileMgrSP oldData = data();
        KisTileMgrSP newData = new KisTileMgr(oldData -> depth(), wd, hd);
        KisPainter gc;
        // Now we already set the tilemanager of this paint device to the new 
tiles
        data(newData);
        // And resize it
        width(wd);
        height(hd);
        // Clean it out
        gc.begin(this);
        gc.eraseRect(0, 0, wd, hd);
        gc.end();

	... matrix stuff ...

        //For each target line of pixels
        KoColor c;
        QUANTUM opacity = OPACITY_TRANSPARENT;
        Q_INT32 tmp;

        for (Q_INT32 y = 0; y < dHeight; y++) {
                trigx = m21ydx;
                trigy = m22ydy;
                // For each target pixel
                for (Q_INT32 x = 0; x < dWidth; x++) {
                        if ( trigx < maxws && trigy < maxhs ) {
                                oldData.pixel(trigx, trigy, c, opacity);
				newData.setPixel(x, y, c, opacity);
                        }
                        trigx += m11;
                        trigy += m12;
                }
                m21ydx += m21;
                m22ydy += m22;
        }

I could more closely copy the original Qt code, and use pointers to loop 
through the image data:


    for ( int y=0; y<dHeight; y++ ) {           // for each target scanline
        trigx = m21ydx;
        trigy = m22ydy;
        uchar *maxp = dptr + dbpl;
        if ( depth != 1 ) {
            switch ( depth ) {
                case 8:                         // 8 bpp transform
                while ( dptr < maxp ) {
                    if ( trigx < maxws && trigy < maxhs )
                        *dptr = *(sptr+sbpl*(trigy>>16)+(trigx>>16));
                    trigx += m11;
                    trigy += m12;
                    dptr++;
                }
                break;

                case 16:                        // 16 bpp transform
                while (

	etc.

In short, when I'm not coding inside KisPainter (and even if I am), I'd like 
the tiles 
to be hidden as much as possible, just as I would prefer to never have to 
construct a
KisPixelData by hand like we do in the ColorStrategies.


> > I would like something like:
> >
> > in KisTileMgr:
> >
> > KisPixelDataSP getPixel(Q_UINT32 x, Q_UINT32 y);
> > void setPixel(KisPixelDataSP pixel, x, y);
>
> This would be just has slow, not only, but using KisTileMgr directly is
> discouraged.  The only reason why data() isn't private in KisPaintDevice is
> due to lack of features in KSharedPtr.
>

Okay... So KisPaintDevice::pixel() and setPixel() are the correct interface; I 
do
hope there are ways of making those methods more efficient.

> Hmm, yes an interator that takes care of position in tiles would be quite
> possible...

And useful.

>
> Well, at least for input, I need to think about this for random access...
>

I meant for reading existing data, not using it for writing, so that should 
work out.


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


More information about the kimageshop mailing list