You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
3.9 KiB
99 lines
3.9 KiB
14 years ago
|
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 * heigth * 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), aptqparently.
|
||
|
|
||
|
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);
|