File: //usr/local/share/man/man3/Image::Base.3pm
.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
. ds C`
. ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\"
.\" If the F register is >0, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{\
. if \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. if !\nF==2 \{\
. nr % 0
. nr F 2
. \}
. \}
.\}
.rr rF
.\" ========================================================================
.\"
.IX Title "Image::Base 3"
.TH Image::Base 3 "2012-08-01" "perl v5.26.3" "User Contributed Perl Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
Image::Base \- base class for loading, manipulating and saving images.
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
.Vb 3
\& # base class only
\& package My::Image::Class;
\& use base \*(AqImage::Base\*(Aq;
.Ve
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
This is a base class for image. It shouldn't be used directly. Known
inheritors are \f(CW\*(C`Image::Xbm\*(C'\fR and \f(CW\*(C`Image::Xpm\*(C'\fR and in see \*(L"\s-1SEE ALSO\*(R"\s0
below.
.PP
.Vb 1
\& use Image::Xpm ;
\&
\& my $i = Image::Xpm\->new( \-file => \*(Aqtest.xpm\*(Aq ) ;
\& $i\->line( 1, 1, 3, 7, \*(Aqred\*(Aq ) ;
\& $i\->ellipse( 3, 3, 6, 7, \*(Aq#ff00cc\*(Aq ) ;
\& $i\->rectangle( 4, 2, 9, 8, \*(Aqblue\*(Aq ) ;
.Ve
.PP
Subclasses like \f(CW\*(C`Image::Xpm\*(C'\fR and \f(CW\*(C`Image::Xbm\*(C'\fR are stand-alone Perl code
implementations of the respective formats. They're good for drawing and
manipulating image files with a modest amount of code and dependencies.
.PP
Other inheritors like \f(CW\*(C`Image::Base::GD\*(C'\fR are front-ends to big image
libraries. They can be handy for pointing generic \f(CW\*(C`Image::Base\*(C'\fR style code
at a choice of modules and supported file formats. Some inheritors like
\&\f(CW\*(C`Image::Base::X11::Protocol::Drawable\*(C'\fR even go to a window etc for direct
display.
.SS "More Methods"
.IX Subsection "More Methods"
If you want to create your own algorithms to manipulate images in terms of
(x,y,colour) then you could extend this class (without changing the file),
like this:
.PP
.Vb 2
\& # Filename: mylibrary.pl
\& package Image::Base ; # Switch to this class to build on it.
\&
\& sub mytransform {
\& my $self = shift ;
\& my $class = ref( $self ) || $self ;
\&
\& # Perform your transformation here; might be drawing a line or filling
\& # a rectangle or whatever... getting/setting pixels using $self\->xy().
\& }
\&
\& package main ; # Switch back to the default package.
.Ve
.PP
Now if you \f(CW\*(C`require\*(C'\fR mylibrary.pl after you've \f(CW\*(C`use\*(C'\fRd Image::Xpm or any
other Image::Base inheriting classes then all these classes will inherit your
\&\f(CW\*(C`mytransform()\*(C'\fR method.
.SH "FUNCTIONS"
.IX Header "FUNCTIONS"
.SS "\fBnew_from_image()\fP"
.IX Subsection "new_from_image()"
.Vb 3
\& my $bitmap = Image::Xbm\->new( \-file => \*(Aqbitmap.xbm\*(Aq ) ;
\& my $pixmap = $bitmap\->new_from_image( \*(AqImage::Xpm\*(Aq, \-cpp => 1 ) ;
\& $pixmap\->save( \*(Aqpixmap.xpm\*(Aq ) ;
.Ve
.PP
Note that the above will only work if you've installed Image::Xbm and
Image::Xpm, but will work correctly for any image object that inherits from
Image::Base and respects its \s-1API.\s0
.PP
You can use this method to transform an image to another image of the same
type but with some different characteristics, e.g.
.PP
.Vb 3
\& my $p = Image::Xpm\->new( \-file => \*(Aqtest1.xpm\*(Aq ) ;
\& my $q = $p\->new_from_image( ref $p, \-cpp => 2, \-file => \*(Aqtest2.xpm\*(Aq ) ;
\& $q\->save ;
.Ve
.SS "\fBline()\fP"
.IX Subsection "line()"
.Vb 1
\& $i\->line( $x0, $y0, $x1, $y1, $colour ) ;
.Ve
.PP
Draw a line from point ($x0,$y0) to point ($x1,$y1) in colour \f(CW$colour\fR.
.PP
.Vb 4
\& ***
\& *****
\& ****
\& ***
.Ve
.SS "\fBellipse()\fP"
.IX Subsection "ellipse()"
.Vb 2
\& $i\->ellipse( $x0, $y0, $x1, $y1, $colour ) ;
\& $i\->ellipse( $x0, $y0, $x1, $y1, $colour, $fill ) ;
.Ve
.PP
Draw an oval enclosed by the rectangle whose top left is ($x0,$y0) and bottom
right is ($x1,$y1) using a line colour of \f(CW$colour\fR. If optional argument
\&\f(CW$fill\fR is true then the ellipse is filled.
.PP
.Vb 5
\& *********
\& ** **
\& * *
\& ** **
\& *********
.Ve
.SS "\fBrectangle()\fP"
.IX Subsection "rectangle()"
.Vb 2
\& $i\->rectangle( $x0, $y0, $x1, $y1, $colour ) ;
\& $i\->rectangle( $x0, $y0, $x1, $y1, $colour, $fill ) ;
.Ve
.PP
Draw a rectangle whose top left is ($x0,$y0) and bottom right is ($x1,$y1)
using a line colour of \f(CW$colour\fR. If \f(CW$fill\fR is true then the rectangle will be
filled.
.PP
.Vb 5
\& ***************
\& * *
\& * *
\& * *
\& ***************
.Ve
.SS "\fBdiamond()\fP"
.IX Subsection "diamond()"
.Vb 2
\& $i\->diamond( $x0, $y0, $x1, $y1, $colour ) ;
\& $i\->diamond( $x0, $y0, $x1, $y1, $colour, $fill ) ;
.Ve
.PP
Draw a diamond shape within the rectangle top left ($x0,$y0) and bottom
right ($x1,$y1) using a \f(CW$colour\fR. If optional argument \f(CW$fill\fR is true
then the diamond is filled. For example
.PP
.Vb 5
\& ***
\& **** ****
\& *** ***
\& **** ****
\& ***
.Ve
.SS "\fBnew()\fP"
.IX Subsection "new()"
Virtual \- must be overridden.
.PP
Recommend that it at least supports \f(CW\*(C`\-file\*(C'\fR (filename), \f(CW\*(C`\-width\*(C'\fR and
\&\f(CW\*(C`\-height\*(C'\fR.
.SS "\fBnew_from_serialised()\fP"
.IX Subsection "new_from_serialised()"
Not implemented. Recommended for inheritors. Should accept a string serialised
using \fBserialise()\fR and return an object (reference).
.SS "\fBserialise()\fP"
.IX Subsection "serialise()"
Not implemented. Recommended for inheritors. Should return a string
representation (ideally compressed).
.SS "\fBget()\fP"
.IX Subsection "get()"
.Vb 2
\& my $width = $i\->get( \-width ) ;
\& my( $hotx, $hoty ) = $i\->get( \-hotx, \-hoty ) ;
.Ve
.PP
Get any of the object's attributes. Multiple attributes may be requested in a
single call.
.PP
See \f(CW\*(C`xy\*(C'\fR get/set colours of the image itself.
.SS "\fBset()\fP"
.IX Subsection "set()"
Virtual \- must be overridden.
.PP
Set any of the object's attributes. Multiple attributes may be set in a single
call; some attributes are read-only.
.PP
See \f(CW\*(C`xy\*(C'\fR get/set colours of the image itself.
.SS "\fBxy()\fP"
.IX Subsection "xy()"
Virtual \- must be overridden. Expected to provide the following functionality:
.PP
.Vb 2
\& $i\->xy( 4, 11, \*(Aq#123454\*(Aq ) ; # Set the colour at point 4,11
\& my $colour = $i\->xy( 9, 17 ) ; # Get the colour at point 9,17
.Ve
.PP
Get/set colours using x, y coordinates; coordinates start at 0.
.PP
When called to set the colour the value returned is class specific; when
called to get the colour the value returned is the colour name, e.g. 'blue' or
\&'#f0f0f0', etc, e.g.
.PP
.Vb 2
\& $colour = xy( $x, $y ) ; # e.g. #123456
\& xy( $x, $y, $colour ) ; # Return value is class specific
.Ve
.PP
We don't normally pick up the return value when setting the colour.
.SS "\fBload()\fP"
.IX Subsection "load()"
Virtual \- must be overridden. Expected to provide the following functionality:
.PP
.Vb 2
\& $i\->load ;
\& $i\->load( \*(Aqtest.xpm\*(Aq ) ;
.Ve
.PP
Load the image from the \f(CW\*(C`\-file\*(C'\fR attribute filename. Or if a filename
parameter is given then set \f(CW\*(C`\-file\*(C'\fR to that name and load it.
.SS "\fBsave()\fP"
.IX Subsection "save()"
Virtual \- must be overridden. Expected to provide the following functionality:
.PP
.Vb 2
\& $i\->save ;
\& $i\->save( \*(Aqtest.xpm\*(Aq ) ;
.Ve
.PP
Save the image to the \f(CW\*(C`\-file\*(C'\fR attribute filename. Or if a filename
parameter is given then set \f(CW\*(C`\-file\*(C'\fR to that name and save to there.
.PP
The save format depends on the \f(CW\*(C`Image::Base\*(C'\fR subclass. Some implement a
\&\f(CW\*(C`\-file_format\*(C'\fR attribute if multiple formats can be saved.
.SS "\fBadd_colours()\fP"
.IX Subsection "add_colours()"
Add colours to the image palette, if applicable.
.PP
.Vb 1
\& $i\->add_colours( $name, $name, ...)
.Ve
.PP
The drawing functions add colours as necessary, so this is just a way to
pre-load the palette.
.PP
\&\f(CW\*(C`add_colours()\*(C'\fR does nothing for images which don't have a palette or can't
take advantage of pre-loading colour names. The base code in \f(CW\*(C`Image::Base\*(C'\fR
is a no-op.
.SH "ATTRIBUTES"
.IX Header "ATTRIBUTES"
The attributes for \f(CW\*(C`new()\*(C'\fR, \f(CW\*(C`get()\*(C'\fR and \f(CW\*(C`set()\*(C'\fR are up to the subclasses,
but the common settings, when available, include
.ie n .IP """\-width"" (integers)" 4
.el .IP "\f(CW\-width\fR (integers)" 4
.IX Item "-width (integers)"
.PD 0
.ie n .IP """\-height""" 4
.el .IP "\f(CW\-height\fR" 4
.IX Item "-height"
.PD
The size of the image. These might be create-only with \f(CW\*(C`new()\*(C'\fR taking a
size which is then fixed. If the image can be resized then \f(CW\*(C`set()\*(C'\fR of
\&\f(CW\*(C`\-width\*(C'\fR and/or \f(CW\*(C`\-height\*(C'\fR does a resize.
.ie n .IP """\-file"" (string)" 4
.el .IP "\f(CW\-file\fR (string)" 4
.IX Item "-file (string)"
Set by \f(CW\*(C`new()\*(C'\fR reading a file, or \f(CW\*(C`load()\*(C'\fR or \f(CW\*(C`save()\*(C'\fR if passed a
filename, or just by \f(CW\*(C`set()\*(C'\fR ready for a future \f(CW\*(C`load()\*(C'\fR or \f(CW\*(C`save()\*(C'\fR.
.ie n .IP """\-file_format"" (string)" 4
.el .IP "\f(CW\-file_format\fR (string)" 4
.IX Item "-file_format (string)"
The name of the file format loaded or to save as. This is generally an
abbreviation like \*(L"\s-1XPM\*(R",\s0 set by \f(CW\*(C`load()\*(C'\fR or \f(CW\*(C`set()\*(C'\fR and then used by
\&\f(CW\*(C`save()\*(C'\fR.
.ie n .IP """\-hotx"" (integers, or maybe \-1 or maybe ""undef"")" 4
.el .IP "\f(CW\-hotx\fR (integers, or maybe \-1 or maybe \f(CWundef\fR)" 4
.IX Item "-hotx (integers, or maybe -1 or maybe undef)"
.PD 0
.ie n .IP """\-hoty""" 4
.el .IP "\f(CW\-hoty\fR" 4
.IX Item "-hoty"
.PD
The coordinates of the \*(L"hotspot\*(R" position. Images which can be a mouse
cursor or similar have a position within the image which is the active pixel
for clicking etc. For example \s-1XPM\s0 and \s-1CUR\s0 (cursor form of \s-1ICO\s0) formats have
hotspot positions.
.ie n .IP """\-zlib_compression"" (integer \-1 to 9, or ""undef"")" 4
.el .IP "\f(CW\-zlib_compression\fR (integer \-1 to 9, or \f(CWundef\fR)" 4
.IX Item "-zlib_compression (integer -1 to 9, or undef)"
The compression level for images which use Zlib, such as \s-1PNG.\s0 0 is no
compression, 9 is maximum compression. \-1 is the Zlib compiled-in default
(usually 6). \f(CW\*(C`undef\*(C'\fR means no setting to use an image library default if
it has one, or the Zlib default.
.Sp
For reference, \s-1PNG\s0 format doesn't record the compression level used in the
file, so for it \f(CW\*(C`\-zlib_compression\*(C'\fR can be \f(CW\*(C`set()\*(C'\fR to control a \f(CW\*(C`save()\*(C'\fR,
but generally won't read back from a \f(CW\*(C`load()\*(C'\fR.
.ie n .IP """\-quality_percent"" (integer 0 to 100, or ""undef"")" 4
.el .IP "\f(CW\-quality_percent\fR (integer 0 to 100, or \f(CWundef\fR)" 4
.IX Item "-quality_percent (integer 0 to 100, or undef)"
The quality level for saving lossy image formats such as \s-1JPEG.\s0 0 is the
worst quality, 100 is the best. Lower quality should mean a smaller file,
but fuzzier. \f(CW\*(C`undef\*(C'\fR means no setting which gives some image library
default.
.SH "ALGORITHMS"
.IX Header "ALGORITHMS"
.SS "Lines"
.IX Subsection "Lines"
Sloping lines are drawn by a basic Bressenham line drawing algorithm with
integer-only calculations. It ends up drawing the same set of pixels no
matter which way around the two endpoints are passed.
.PP
Would there be merit in rounding odd numbers of pixels according to which
way around line ends are given? Eg. a line 0,0 to 4,1 might do 2 pixels on
y=0 and 3 on y=1, but 4,1 to 0,0 the other way around. Or better to have
consistency either way around? For reference, in the X11 drawing model the
order of the ends doesn't matter for \*(L"wide\*(R" lines, but for
implementation-dependent \*(L"thin\*(R" lines it's only encouraged, not required.
.SS "Ellipses"
.IX Subsection "Ellipses"
Ellipses are drawn with the midpoint ellipse algorithm. This algorithm
chooses between points x,y or x,y\-1 according to whether the position
x,y\-0.5 is inside or outside the ellipse (and similarly x+0.5,y on the
vertical parts).
.PP
The current ellipse code ends up with 0.5's in the values, which means
floating point, but is still exact since binary fractions like 0.5 are
exactly representable. Some rearrangement and factors of 2 could make it
all-integer. The \*(L"discriminator\*(R" in the calculation may exceed 53\-bits of
float mantissa at around 160,000 pixels wide or high. That might affect the
accuracy of the pixels chosen, but should be no worse than that.
.SS "Diamond"
.IX Subsection "Diamond"
The current code draws a diamond with the Bressenham line algorithm along
each side. Just one line is calculated and is then replicated to the four
sides, which ensures the result is symmetric. Rounding in the line (when
width not a multiple or height, or vice versa) is biased towards making the
pointier vertices narrower. That tends to look better, especially when the
diamond is small.
.SS "Image Libraries"
.IX Subsection "Image Libraries"
The subclasses like \s-1GD\s0 or PNGwriter which are front-ends to other drawing
libraries don't necessarily use these base algorithms, but can be expected
to something sensible within the given line endpoints or ellipse bounding
box. (Among the image libraries it's surprising how variable the quality of
the ellipse drawing is.)
.SH "SEE ALSO"
.IX Header "SEE ALSO"
Image::Xpm,
Image::Xbm,
Image::Pbm,
Image::Base::GD,
Image::Base::Imager,
Image::Base::Imlib2,
Image::Base::Magick,
Image::Base::PNGwriter,
Image::Base::SVG,
Image::Base::SVGout,
Image::Base::Text,
Image::Base::Multiplex
.PP
Image::Base::Gtk2::Gdk::Drawable,
Image::Base::Gtk2::Gdk::Image,
Image::Base::Gtk2::Gdk::Pixbuf,
Image::Base::Gtk2::Gdk::Pixmap,
Image::Base::Gtk2::Gdk::Window
.PP
Image::Base::Prima::Drawable,
Image::Base::Prima::Image
.PP
Image::Base::Tk::Canvas,
Image::Base::Tk::Photo
.PP
Image::Base::Wx::Bitmap,
Image::Base::Wx::DC,
Image::Base::Wx::Image
.PP
Image::Base::X11::Protocol::Drawable,
Image::Base::X11::Protocol::Pixmap,
Image::Base::X11::Protocol::Window
.PP
\&\f(CW\*(C`http://user42.tuxfamily.org/image\-base/index.html\*(C'\fR
.SH "AUTHOR"
.IX Header "AUTHOR"
Mark Summerfield. I can be contacted as <summer@perlpress.com> \-
please include the word 'imagebase' in the subject line.
.SH "COPYRIGHT"
.IX Header "COPYRIGHT"
Copyright (c) Mark Summerfield 2000. All Rights Reserved.
.PP
Copyright (c) Kevin Ryde 2010, 2011, 2012.
.PP
This module may be used/distributed/modified under the \s-1LGPL.\s0