[gtkmm] Improved Gdk::Pixbuf pixel interface
- From: Ole Laursen <olau hardworking dk>
- To: gtkmm-list gnome org
- Subject: [gtkmm] Improved Gdk::Pixbuf pixel interface
- Date: 22 Jan 2003 22:57:23 +0100
Hi,
Currently, the interface for manipulating pixel data in a Gdk::Pixbuf
consists of:
int get_n_channels () const
bool get_has_alpha () const
int get_bits_per_sample () const
guint8* get_pixels () const
int get_width () const
int get_height () const
int get_rowstride () const
This is a very inconvient interface since it requires manual
computations to actually locate a pixel. I been thinking about this,
and I think a better one would be:
PixelIterator begin();
PixelIterator end();
PixelPosition get_position(int x, int y);
PixelIterator is then a bidirectional STL-like iterator which simply
iterates over the pixels (row by row), returning a Pixel if
dereferenced. The interface of PixelPosition is:
Pixel pixel();
// move a number of positions, returning *this
PixelPosition &left(int n = 1);
PixelPosition &right(int n = 1);
PixelPosition &up(int n = 1);
PixelPosition &down(int n = 1);
Pixel is then a simple proxy class for the pixel array index with the
interface:
unsigned char &red();
unsigned char &green();
unsigned char &blue();
unsigned char &alpha(); // undefined if pixbuf doesn't have alpha
With this, you can do stuff like this:
void scale_alpha(const Glib::RefPtr<Gdk::Pixbuf> &pixbuf, int scale)
{
for (PixelIterator i = pixbuf.begin(), e = pixbuf.end(); i != e; ++i)
i->alpha() = i->alpha() * scale / 256;
}
Or like this (visits all even rows):
int width = p.get_width(), height = p.get_height();
for (int y = 0; y < height; y += 2) {
PixelPosition ppos = p.get_position(0, y);
for (int x = 0; x < width; ++x, ppos.right()) {
Pixel pixel = ppos.pixel();
pixel.red() = somevalue;
pixel.green() = someothervalue;
pixel.blue() = athirdvalue;
pixel.alpha() = thealphavalue;
}
}
Or to simply colour a single pixel:
Pixel pixel = p.get_position(x, y).pixel();
pixel.red() = 74;
pixel.green() = 174;
pixel.blue() = 34;
The reason for having PixelPosition with its movements methods is that
the multiplication required for converting a (x, y) point to the
correct array index is expensive compared to just adding a fixed
amount to a precomputed index. On the order of 3-5 times slower it
seems.
I've already implemented the interfaces - you can have a look here:
http://www.cs.auc.dk/~olau/misc/pixbuf-drawing.hpp - the interfaces
http://www.cs.auc.dk/~olau/misc/test.cpp - timing tests
Comments?
With the iterator interface, manually setting the pixel colours:
for (PixelIterator i = p.begin(), e = p.end(); i != e; ++i) {
Pixel pixel = *i;
pixel.red() = 0;
pixel.green() = 0;
pixel.blue() = 0;
pixel.alpha() = 0;
}
is just as fast as using the dedicated, wrapped C function:
p->fill(0);
--
Ole Laursen
http://www.cs.auc.dk/~olau/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]