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