Image::Base(3pm)

πŸ“¦
version 2+~1.17+~1.13+~1.11 Β· 7 versions
, in ubuntu resolute, ubuntu stonking

🌸 Image::Base πŸ’… β€” the Image::Base(3pm) page, bestie edition

okay so. This is the Perl User Contributed docs for Image::Base, and yes it's a base class, meaning it's the mom friend of the image module family. She doesn't do the work herself. She sets the vibe and everyone else inherits it. πŸ‘‘


✨ NAME ✨

Image::Base β€” the base class for loading, manipulating and saving images. It's giving "template", it's giving "blueprint", it's giving "the group chat rules everyone else follows."


πŸŽ€ SYNOPSIS πŸŽ€

# base class only
package My::Image::Class;
use base 'Image::Base';

literally that's it. that's the whole vibe check. πŸ¦‹


πŸ’– DESCRIPTION πŸ’–

So this is a base class for images, which means bestie… you do not use it directly. It's not for you to touch, it's for you to inherit from. The known inheritors are Image::Xbm and Image::Xpm, plus the ones hanging out in "SEE ALSO" down below. πŸ‘‡

use Image::Xpm ;

my $i = Image::Xpm->new( -file => 'test.xpm' ) ;
$i->line( 1, 1, 3, 7, 'red' ) ;
$i->ellipse( 3, 3, 6, 7, '#ff00cc' ) ;
$i->rectangle( 4, 2, 9, 8, 'blue' ) ;

Subclasses like Image::Xpm and Image::Xbm are stand-alone Perl code implementations of their respective formats. They're the ones you want when you're drawing and manipulating image files and you want to keep the code and the dependencies modest, like a cute little carry-on bag. 🧳✨

Other inheritors like Image::Base::GD are front-ends to big image libraries. These are highkey useful when you want to point generic Image::Base-style code at whichever module (and whichever supported file formats) you feel like that day. And some inheritors β€” shoutout Image::Base::X11::Protocol::Drawable β€” even go all the way to a window or whatever for direct display. main character energy fr fr. πŸͺŸπŸ’…

🌈 More Methods 🌈

If you want to invent your own algorithms to manipulate images in terms of (x,y,colour), you can extend this class without changing the file, like this:

# 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.

Now here's the slay part: if you require mylibrary.pl after you've used Image::Xpm or any other Image::Base-inheriting class, then all of those classes will inherit your mytransform() method. One file, everyone gets the upgrade. obsessed. 🫢


πŸ”₯ FUNCTIONS πŸ”₯

⭐ new_from_image() ⭐

my $bitmap = Image::Xbm->new( -file => 'bitmap.xbm' ) ;
my $pixmap = $bitmap->new_from_image( 'Image::Xpm', -cpp => 1 ) ;
$pixmap->save( 'pixmap.xpm' ) ;

ngl, the above only works if you've actually installed Image::Xbm and Image::Xpm β€” but it'll work correctly for any image object that inherits from Image::Base and respects its API. no cap.

You can use this method to transform an image into another image of the same type but with some different characteristics, e.g.

my $p = Image::Xpm->new( -file => 'test1.xpm' ) ;
my $q = $p->new_from_image( ref $p, -cpp => 2, -file => 'test2.xpm' ) ;
$q->save ;

✏️ line() ✏️

$i->line( $x0, $y0, $x1, $y1, $colour ) ;

Draw a line from point ($x0,$y0) to point ($x1,$y1) in colour $colour. simple as that, bestie.

                ***
           *****
       ****
    ***

πŸ₯š ellipse() πŸ₯š

$i->ellipse( $x0, $y0, $x1, $y1, $colour ) ;
$i->ellipse( $x0, $y0, $x1, $y1, $colour, $fill ) ;

Draw an oval enclosed by the rectangle whose top left is ($x0,$y0) and bottom right is ($x1,$y1), using a line colour of $colour. If the optional argument $fill is true then the ellipse gets filled in. πŸ“

     *********
   **         **
  *             *
   **         **
     *********

🟦 rectangle() 🟦

$i->rectangle( $x0, $y0, $x1, $y1, $colour ) ;
$i->rectangle( $x0, $y0, $x1, $y1, $colour, $fill ) ;

Draw a rectangle whose top left is ($x0,$y0) and bottom right is ($x1,$y1), using a line colour of $colour. If $fill is true then the rectangle will be filled. the most straightforward shape, we love her. πŸ’™

***************
*             *
*             *
*             *
***************

πŸ’Ž diamond() πŸ’Ž

$i->diamond( $x0, $y0, $x1, $y1, $colour ) ;
$i->diamond( $x0, $y0, $x1, $y1, $colour, $fill ) ;

Draw a diamond shape inside the rectangle with top left ($x0,$y0) and bottom right ($x1,$y1), using a $colour. If the optional argument $fill is true then the diamond gets filled. For example:

       ***
   ****   ****
***           ***
   ****   ****
       ***

πŸ†• new() πŸ†•

Virtual β€” must be overridden. she's abstract, she's mysterious, she will not do the thing herself. πŸ™ˆ

Recommend that it at least supports -file (filename), -width and -height.


πŸ“¦ new_from_serialised() πŸ“¦

Not implemented. Recommended for inheritors. Should accept a string serialised using serialise() and return an object (reference). yes this is basically the unboxing video. 🎁


🧡 serialise() 🧡

Not implemented. Recommended for inheritors. Should return a string representation (ideally compressed).


πŸ‘€ get() πŸ‘€

my $width = $i->get( -width ) ;
my( $hotx, $hoty ) = $i->get( -hotx, -hoty ) ;

Get any of the object's attributes. Multiple attributes may be requested in a single call, so efficient of her. ⭐

See "xy" to get/set colours of the image itself.


πŸ› οΈ set() πŸ› οΈ

Virtual β€” must be overridden.

Set any of the object's attributes. Multiple attributes may be set in a single call; some attributes are read-only (so hands off those ones bestie πŸ’€).

See "xy" to get/set colours of the image itself.


🎨 xy() 🎨

Virtual β€” must be overridden. Expected to provide the following functionality:

$i->xy( 4, 11, '#123454' ) ;    # Set the colour at point 4,11
my $colour = $i->xy( 9, 17 ) ;  # Get the colour at point 9,17

Get/set colours using x, y coordinates; coordinates start at 0. (yes, zero-indexed, we live in a society. 🌍)

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.

$colour = xy( $x, $y ) ;  # e.g. #123456
xy( $x, $y, $colour ) ;   # Return value is class specific

We don't normally pick up the return value when setting the colour. like, we're not checking receipts on that one. πŸ§ΎπŸ™ˆ


πŸ“‚ load() πŸ“‚

Virtual β€” must be overridden. Expected to provide the following functionality:

$i->load ;
$i->load( 'test.xpm' ) ;

Load the image from the -file attribute filename. Or, if a filename parameter is given, then set -file to that name and load it. either way she's getting loaded. ✨


πŸ’Ύ save() πŸ’Ύ

Virtual β€” must be overridden. Expected to provide the following functionality:

$i->save ;
$i->save( 'test.xpm' ) ;

Save the image to the -file attribute filename. Or, if a filename parameter is given, then set -file to that name and save to there. πŸŽ€

The save format depends on the Image::Base subclass. Some implement a -file_format attribute if multiple formats can be saved.


🌈 add_colours() 🌈

Add colours to the image palette, if applicable.

$i->add_colours( $name, $name, ...)

The drawing functions add colours as necessary, so this is just a way to pre-load the palette. like pre-gaming but for colours. 🎨

add_colours() does nothing for images which don't have a palette or can't take advantage of pre-loading colour names. The base code in Image::Base is a no-op. (she's literally just standing there, menacingly. πŸ’€)


πŸ‘‘ ATTRIBUTES πŸ‘‘

The attributes for new(), get() and set() are up to the subclasses, but the common settings β€” when available β€” include:

  • -width (integers)
  • -height β€” The size of the image. These might be create-only, with new() taking a size which is then fixed. If the image can be resized then set() of -width and/or -height does a resize.
  • -file (string) β€” Set by new() reading a file, or by load() or save() if passed a filename, or just by set() ready for a future load() or save(). she's patient like that. 🫢
  • -file_format (string) β€” The name of the file format loaded or to save as. This is generally an abbreviation like "XPM", set by load() or set() and then used by save().
  • -hotx (integers, or maybe -1 or maybe "undef")
  • -hoty β€” The coordinates of the "hotspot" 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 XPM and CUR (cursor form of ICO) formats have hotspot positions. πŸ–±οΈ
  • -zlib_compression (integer -1 to 9, or "undef") β€” The compression level for images which use Zlib, such as PNG. 0 is no compression, 9 is maximum compression. -1 is the Zlib compiled-in default (usually 6). "undef" means no setting, to use an image library default if it has one, or the Zlib default.

For reference, PNG format doesn't record the compression level used in the file, so for it -zlib_compression can be set() to control a save(), but generally won't read back from a load(). πŸ’…

  • -quality_percent (integer 0 to 100, or "undef") β€” The quality level for saving lossy image formats such as JPEG. 0 is the worst quality, 100 is the best. Lower quality should mean a smaller file, but fuzzier. "undef" means no setting, which gives some image library default.

🧠 ALGORITHMS 🧠

πŸ“ 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. consistency queen. πŸ‘‘

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 "wide" lines, but for implementation-dependent "thin" lines it's only encouraged, not required.

πŸ₯š 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).

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 "discriminator" 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. (iykyk 😭)

πŸ’Ž 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 of height, or vice versa) is biased towards making the pointier vertices narrower. That tends to look better, especially when the diamond is small. ✨

πŸ–ΌοΈ Image Libraries πŸ–ΌοΈ

The subclasses like GD or PNGwriter which are front-ends to other drawing libraries don't necessarily use these base algorithms, but can be expected to do 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. πŸ’€)

πŸ’– SEE ALSO πŸ’–

okay bestie, here's the whole friendship group β€” every module that plays nice with Image::Base:

  • 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

and the GUI girlies ✨:

  • 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
  • Image::Base::Prima::Drawable, Image::Base::Prima::Image
  • Image::Base::Tk::Canvas, Image::Base::Tk::Photo
  • Image::Base::Wx::Bitmap, Image::Base::Wx::DC, Image::Base::Wx::Image
  • Image::Base::X11::Protocol::Drawable, Image::Base::X11::Protocol::Pixmap, Image::Base::X11::Protocol::Window

and the link, in quotes, exactly like this:

"http://user42.tuxfamily.org/image-base/index.html"

πŸ‘‘ AUTHOR πŸ‘‘

Mark Summerfield. you can reach him at <summer@perlpress.com> β€” and bestie, please put the word imagebase in the subject line, he's asking nicely 🫢


Copyright (c) Mark Summerfield 2000. All Rights Reserved.

Copyright (c) Kevin Ryde 2010, 2011, 2012.

This module may be used/distributed/modified under the LGPL.


and that's the whole page, bestie, no cap πŸ’… this was Image::Base(3pm) from perl v5.40.1, dated 2024-11-11 β€” go make something iconic with it, you ate πŸŽ€πŸ’–βœ¨

πŸ“¦ where this page comes from