|
|
|
THIS DOCUMENT IS OBSOLETED BY THE AUTOLAYERS MERGE
|
|
|
|
|
|
|
|
* Paint devices and painters
|
|
|
|
|
|
|
|
Chalk's core consists of paint devices and painters:
|
|
|
|
|
|
|
|
KisPaintDevice
|
|
|
|
KisPainter
|
|
|
|
|
|
|
|
These classes are (very) loosely modelled on QPaintDevice and
|
|
|
|
QPainter. KisPaintDevice also takes up some of the roles of QImage,
|
|
|
|
but isn't all that efficient at it.
|
|
|
|
|
|
|
|
This is a write-up of my (Boudewijn's) understanding at this point;
|
|
|
|
|
|
|
|
* Getting pixel data in and out of a KisPaintDevice.
|
|
|
|
|
|
|
|
Chalk stores all image data in tiles; the tiles are managed by the
|
|
|
|
aptly named KisTileMgr. Inside the tiles, we have a KisPixelData
|
|
|
|
structure, which is basically a wrapper that packs together a pointer
|
|
|
|
to a memory area that contains the pixel data (QUANTUM's) and some
|
|
|
|
more information.
|
|
|
|
|
|
|
|
Ordinarily, you will change the data inside a KisPaintDevice through
|
|
|
|
the KisPainter. Using KisPainter has the advantage that your changes
|
|
|
|
will be undoable and that the tile manager is hidden. That's
|
|
|
|
especially nice, since you generally don't want to work directly with
|
|
|
|
tiles, not before having bought shares in an aspirin producer.
|
|
|
|
|
|
|
|
The other way of messing with the pixels inside a KisPaintDevice is
|
|
|
|
through the pixel() and and setPixel() methods in KisPaintDevice.
|
|
|
|
These methods retrieve and set the specified pixel data using the
|
|
|
|
tiles, but are not undoable. They are also rather ineffcient and slow.
|
|
|
|
|
|
|
|
KisPainter and KisPaintDevice do the job of hiding the actual image
|
|
|
|
data from the chalk hacker, but sometimes it's not enough, sometimes
|
|
|
|
you need to loop over all the pixels in an image, do
|
|
|
|
something, and write the pixels back to this or another image (or
|
|
|
|
sections of images).
|
|
|
|
|
|
|
|
In the near future, we will offer an iterator over the pixels, for now
|
|
|
|
you will have to ask the tile manager to copy all the bytes of the
|
|
|
|
image data in a buffer for you to read. Likewise, in the future we
|
|
|
|
will hopefully have something clever to feed pixel data to the tile
|
|
|
|
manager. For now, you will have to fill a memory buffer with the
|
|
|
|
desired data and feed that to the tile manager.
|
|
|
|
|
|
|
|
** Getting pixel data into your buffer
|
|
|
|
|
|
|
|
Define a pointer to a memory buffer with QUANTUMS
|
|
|
|
|
|
|
|
QUANTUM *buf;
|
|
|
|
|
|
|
|
Create the buffer. Note that you cannot assume that there is one byte
|
|
|
|
per channel; QUANTUM can be bigger.
|
|
|
|
|
|
|
|
buf = new QUANTUM[width * height * depth * sizeof(QUANTUM)];
|
|
|
|
|
|
|
|
Fill the buf with the data. x1, y1, x2, y2 are the top left and bottom
|
|
|
|
right corner of the section you want. stride is the width of the
|
|
|
|
section in bytes, i.e. (x2 - x1 + 1) * depth. Note that stride does
|
|
|
|
not need to be pre-multiplied with sizeof(QUANTUM), apparently.
|
|
|
|
|
|
|
|
tilemgr -> readPixelData(x1, y1, x2, y2, buf, stride);
|
|
|
|
|
|
|
|
Now all the pixels in the tile manager are copied into 'buf' -- the
|
|
|
|
operative word is 'copy', which means slow, and takes a lot of memory
|
|
|
|
is the section is big.
|
|
|
|
|
|
|
|
If you can stand computing with tiles, you can copy each tile into the
|
|
|
|
buffer, which takes a lot less memory, but you have to take care when
|
|
|
|
the image isn't exactly a multiple of the tilesize. See
|
|
|
|
kis_image_magick_converter.cpp for an example.
|
|
|
|
|
|
|
|
** Getting your data into a KisPaintDevice without using KisPainter
|
|
|
|
|
|
|
|
Although in the future we might offer a bitBlt that takes a simple
|
|
|
|
memory buffer and blits that onto the paint device, for now, you will
|
|
|
|
have to access the tile manager directly, using writePixelData.
|
|
|
|
|
|
|
|
|
|
|
|
First create a buffer, just as above:
|
|
|
|
|
|
|
|
QUANTUM * newData = new QUANTUM[width * height * depth * sizeof(QUANTUM)];
|
|
|
|
|
|
|
|
But unless you are sure you are going to fill absolutely every pixel,
|
|
|
|
you might want to initialize the buffer with memset. Chalk, in
|
|
|
|
contrast with ImageMagick, uses 0 as the value for transparent
|
|
|
|
opacity, so that's nice:
|
|
|
|
|
|
|
|
memset(newData, width * height * depth * sizeof(QUANTUM), 0);
|
|
|
|
|
|
|
|
Then create a new tilemanager, or reuse the old one if the size is
|
|
|
|
still correct. Stride is again width * depth, not width * depth *
|
|
|
|
sizeof(QUANTUM)
|
|
|
|
|
|
|
|
KisTileMgrSP tm = new KisTileMgr(depth, width, height);
|
|
|
|
tm -> writePixelData(x1, y1, x2, y2, newData, stride);
|