NAME
Gimp::PixelRgn - Operate on raw pixels in powerful, efficient way.
SYNOPSIS
use Gimp;
use PDL; # to do sensible things with the pixels
my $i = Gimp::Image->new(10,10,RGB);
my $l = $i->layer_new(10,10,RGBA_IMAGE,"new layer",100,LAYER_MODE_HSV_VALUE_LEGACY);
$i->insert_layer($l,0,0);
my $gd = $l->get;
my $region = $gd->pixel_rgn(0,0,10,10,0,0);
my $piddle = $region->get_pixel($x,$y);
print $piddle."\n"; # stringified piddle is readable
DESCRIPTION
Perl interface to GIMP's low-level pixel-access functions. In Gimp-Perl (mirroring how GIMP does it), to access these functions you must get a Gimp::GimpDrawable
from a Gimp::Drawable
. You can then get either a Gimp::Tile
or Gimp::PixelRgn
object, and work with that. Since the tile interface is very low-level, it is not further documented here. The Gimp::PixelRgn
methods take and return PDL objects to handle the data, with a few exceptions.
COLOURS
It is vital to note that while GIMP uses the GimpRGB
format (each colour a floating point number from 0 to 1.0) to pass colours around as parameters, the pixel functions all work on bytes, integers with values from 0 to 255. Depending on the type of layer/image colour mode (e.g. RGB vs indexed), the meaning of the integers' values may also vary.
Gimp::GimpDrawable
In GIMP, drawables (also known as PARAM_DRAWABLE or Gimp::Drawable) are things you can draw on: layers or channels. While in GIMP most functions named gimp_drawable_something
operate on drawable_ID
s, some functions (notably the ones operating on raw pixel data!) need a GimpDrawable
instead. In Gimp-Perl, this distinction is made explicit in that every function that operates on a GimpDrawable
is no longer called gimp_drawable_something
but gimp_gdrawable_something
.
Every drawable has a corresponding GimpDrawable
, you can get it with the gimp_drawable_get
function:
my $gdrawable = $drawable->get;
When the $gdrawable
is destroyed, it is automatically flushed & detached, so you don't need to do this yourself. Do not call this method more than once; each time it is called, GIMP makes a new internal list of tiles, which will cause mayhem if done more than once.
Gimp::PixelRgn
GIMP's PixelRgn
s are rectangular parts of a drawable. You can access single pixels, rows, columns and rectangles within these regions.
To create a pixel region, you first get a GimpDrawable structure as above. Then you can create a Gimp::PixelRgn
structure:
$region = $gdrawable->pixel_rgn(0,0,50,30,0,0); # read-only
$region = $gdrawable->pixel_rgn(0,0,50,30,1,1); # read-write
$region = $gdrawable->pixel_rgn(0,0,50,30,1,0); # means undo won't work!
The last two parameters are respectively dirty
and shadow
. Be warned that if you set shadow
to be true, the "shadow" tile(s) start out as all-zero. If you only set some, e.g. with set_pixel
, then once you have called $drawable->merge_shadow($undo)
, nearly all the drawable's contents will be zeros.
The main "use case" for this functionality is to have a read-only "source" region, and a writable "destination" region:
$gdrawable = $drawable->get;
$src = $gdrawable->pixel_rgn(0,0,50,30,0,0); # read-only
$dst = $gdrawable->pixel_rgn(0,0,50,30,1,1); # read-write
my ($x,$y,$w,$h)=($dst->x,$dst->y,$dst->w,$dst->h);
my $pdl = $src->get_rect($x,$y,$w,$h);
$pdl += 7; # trivial operation
$dst->set_rect($pdl, $x, $y);
$drawable->merge_shadow(1);
However, it is possible to use dirty=1, shadow=0; see the "setpixel" example below. The GIMP API document says that it "could prevent the Undo-System from working as expected".
The following functions return pixel data in PDL objects:
$piddle = $region->get_pixel(45,60); # return the pixel at (45|60)
$piddle = $region->get_row(45,60,10); # return ten horizontal pixels
$piddle = $region->get_col(45,60,10); # same but vertically
$piddle = $region->get_rect(45,60,10,12); # a 10x12 rectangle
And the corresponding set-functions:
$region->set_pixel($piddle,45,60); # set pixel at (45|60)
$region->set_row($piddle,45,60); # set a row
$region->set_col($piddle,45,60); # set a column
$region->set_rect($piddle,45,60); # set a whole rectangle
Please note that (unlike the C functions they call), the size arguments (width and/or height) are omitted; they are calculated from the piddle.
The dimensions of the piddle are, for a rectangle (due to how GIMP stores the data):
($bytesperpixel, $width, $height) = $r->get_rect($l->bounds)->dims;
For a row or column:
($bytesperpixel, $width) = $r->get_row(0, 0, $width)->dims;
($bytesperpixel, $height) = $r->get_col(0, 0, $height)->dims;
EXAMPLES
Functions demonstrating getting and setting the colour of a pixel on an RGB layer:
use PDL;
sub setpixel {
my ($i, $l, $x, $y, $colour) = @_;
my @bounds = $l->bounds;
my $region = $l->get->pixel_rgn(@bounds,1,0); # warning! see above
my $piddle = pdl [ @{$colour}[0..2] ]; # remove any alpha
$piddle *= 255; # so it's bytes, not floats
$region->set_pixel($piddle, $x, $y);
$l->update(@bounds);
}
sub getpixel {
my ($i, $l, $x, $y) = @_;
my $region = $l->get->pixel_rgn($l->bounds,0,0);
my $piddle = $region->get_pixel($x,$y);
return unpdl $piddle;
}
ITERATORS
GIMP uses "tiles" as a way of breaking drawables into smaller chunks. This allows a potentially very large image to be process in manageable pieces. To use this, GIMP (and therefore Gimp-Perl) provides an "iterator" functionality to process each part of the image. This is best explained with a simple working example:
sub iterate {
my ($i, $l, $inc) = @_;
my @bounds = $l->bounds;
{
# in block so $src/$dst go out of scope before merge
my $src = Gimp::PixelRgn->new($l,@bounds,0,0);
my $dst = Gimp::PixelRgn->new($l,@bounds,1,1);
my $iter = Gimp->pixel_rgns_register($dst);
do {
my ($x,$y,$w,$h)=($dst->x,$dst->y,$dst->w,$dst->h);
my $pdl = $src->get_rect($x,$y,$w,$h);
$pdl += $inc;
$dst->data($pdl);
} while (Gimp->pixel_rgns_process($iter));
}
$l->merge_shadow(1);
$l->update(@bounds);
}
The key points are:
- Iterator registration and processing
-
Done respectively with
$iter = Gimp->pixel_rgns_register($dst)
anddo { ... } while (Gimp->pixel_rgns_process($iter))
. - Block scope
-
The source and destination
Gimp::PixelRgn
s are in a block so their lexical variables go out of scope at the end, and therefore the objects get destroyed, and they get flushed and detached. - Merge shadow tiles
-
Once the operation is complete and the shadow tiles have all been set with the right data,
$drawable->merge_shadow($undo)
is called.$undo
is a boolean telling GIMP "whether to add an undo step for the operation". - data method only valid for iterators
-
The
$region->data
method is only valid for use within an iterator.
NON-PDL METHODS
These functions take/return not PDL objects, but Perl scalars:
gimp_gdrawable_get_tile2
gimp_pixel_rgn_get_col2
gimp_pixel_rgn_get_rect2
gimp_pixel_rgn_set_rect2
gimp_pixel_rgn_get_row2
AUTHOR
Ed J, based on Gimp::Pixel.pod
by Marc Lehmann <pcg@goof.com>
SEE ALSO
perl(1), Gimp(1), PDL.
These GIMP API docs are also relevant:
http://developer.gimp.org/api/2.0/libgimp/libgimp-gimppixelrgn.html http://developer.gimp.org/api/2.0/libgimp/libgimp-gimpdrawable.html