NAME
Graphics::Framebuffer - A Simple Framebuffer Graphics Library
SYNOPSIS
Direct drawing for 32/24/16 bit framebuffers (others would be supported if asked for)
use Graphics::Framebuffer;
our $fb = Graphics::Framebuffer->new();
Drawing is this simple
$fb->cls('OFF'); # Clear screen and turn off the console cursor
$fb->set_color({'red' => 255, 'green' => 255, 'blue' => 255, 'alpha' => 255});
$fb->plot({'x' => 28, 'y' => 79,'pixel_size' => 1});
$fb->drawto({'x' => 405,'y' => 681,'pixel_size' => 1});
$fb->circle({'x' => 200, 'y' => 200, 'radius' => 100, 'filled' => 1});
$fb->polygon({'coordinates' => [20,20, 53,3, 233,620], 'pixel_size' => 5});
$fb->box({'x' => 95, 'y' => 100, 'xx' => 400, 'yy' => 600, 'filled' => 1});
# ... and many many more
$fb->cls('ON'); # Clear screen and turn on the console cursor
Methods requiring parameters require a hash (or anonymous hash) reference passed to the method. All parameters have easy to understand english names, all lower case, to understand exactly what the method is doing.
DESCRIPTION
A (mostly) Perl graphics library for exclusive use in a Linux/FreeBSD/Unix console framebuffer environment. It is written for simplicity, without the need for complex API's and drivers with "surfaces" and such.
Back in the old days, computers drew graphics this way, and it was simple and easy to do. I was writing a console based media playing program, and was not satisfied with the limited abilities offered by the nCurses library, and I did not want the overhead of the X-Windows environment to get in the way. My intention was to create a mobile media server. In case you are wondering, that project has been quite successful, and I am still making improvements to it. I may even include it in the "examples" directory on future versions.
There are places where Perl just won't cut it. So I use the Imager library to take up the slack, or my own C code. Imager is just used to load images,, save images, merge, rotate, and draw TrueType/Type1 text. I am also incorporating compiled C to further assist with speed. That is being implemented step by step, but "acceleration" will always be optional, and pure Perl routines always available for those systems without a C compiler or "Inline:C" available.
I cannot guarantee this will work on your video card, but I have successfully tested it on NVidia GeForce, AMD Radeon, Matrox, Raspberry PI, Odroid XU3/XU4, and VirtualBox displays. However, you MUST remember, your video driver MUST be framebuffer based. The proprietary Nvidia and AMD drivers (with DRM) will NOT work with this module. You must use the open source video drivers, such as Nouveau, to be able to use this library (with output to see). Also, it is not going to work from within X-Windows, so don't even try it, it will either crash X, or make a mess on the screen. This is a console only graphics library.
I highly recommend that you use a 32/24 bit graphics mode instead of 16 bit. Normally one might think that 16 bits are less and should be faster... WRONG. This module uses the Imager module to do complex tasks and this module only works in 32/24 bit modes. This means in order to do things on a 16 bit framebuffer, GFB must run a conversion to 16 bit on EVERY complex operation, slowing things down. Also, CPUs today hate 16 bit accessing and prefer 32 bit, hence faster. If you have no choice but to use 16 bit mode, then now you know it can be slower.
NOTE:
If a framebuffer is not available, the module will go into emulation mode and open a pseudo-screen in the object's hash variable 'SCREEN'
You can write this to a file, whatever. It defaults to a 640x480x32 RGB graphics 'buffer'. However, you can change that by passing parameters to the 'new' method.
You will not be able to see the output directly when in emulation mode. I mainly created this mode so that you could install this module (on systems without a framebuffer) and test code you may be writing to be used on other devices that have accessible framebuffer devices. Nevertheless, I have learned that people use emulation mode as an offscreen drawing surface, and blit from one to the other. Which is pretty clever.
Make sure you have read/write access to the framebuffer device. Usually this just means adding your account to the "video" group (make sure you log out and log in again after doing that). Alternately, you can just run your script as root. Although I don't recommend it.
INSTALLATION
Read the file "installing/INSTALL" and follow its instructions.
When you install this module, please do it within a console, not a console window in X-Windows, but the actual Linux/FreeBSD console outside of X-Windows.
If you are in X-Windows, and don't know how to get to a console, then just hit CTRL-ALT-F1 (actually CTRL-ALT-F1 through CTRL-ALT-F6 works) and it should show you a console. ALT-F7 or ALT-F8 will get you back to X-Windows.
OPERATIONAL THEORY
How many Perl modules actually tell you how they work? Well, I will tell you how this one works.
The framebuffer is simply a special file that is mapped to the screen. How the driver does this can be different. Some may actually directly map the display memory to this file, and some install a second copy of the display to normal memory and copy it to the display on every vertical blank, usually with a fast DMA transfer.
This module maps that file to a string, and that ends up making the string exactly the same size as the physical display. Plotting is simply a matter of calculating where in the string that pixel is and modifying it, via "substr" (never using "=" directly). It's that simple.
Drawing lines etc. requires some algorithmic magic though, but they all call the plot routine to do their eventual magic.
Originally everything was done in Perl, and the module's speed was mostly acceptable, unless you had a really slow system. It still can run in pure Perl, if you turn off the acceleration feature, although I do not recommend it, if you want speed.
SPECIAL VARIABLES
The following are hash keys to the main object variable. For example, if you use the variable $fb as the object variable, then the following are $fb->{VARIABLE_NAME}
* FONTS
List of system fonts
Contains a hash of every font found in the system in the format:
# 'FaceName' => { # 'path' => 'Path To Font', # 'font' => 'File Name of Font' # }, # ...
* Imager-Has-TrueType
If your installation of Imager has TrueType font capability, then this will be 1
* Imager-Has-Type1
If your installation of Imager has Adobe Type 1 font capability, then this will be 1
* Imager-Has-Freetype2
If your installation of Imager has the FreeType2 library rendering capability, then this will be 1
* Imager-Image-Types
An anonymous array of supported image file types.
* HATCHES
An anomyous array of hatch names for hatch fills.
This is also exported as @HATCHES
* X_CLIP
The top left-hand corner X location of the clipping region
* Y_CLIP
The top left-hand corner Y location of the clipping region
* XX_CLIP
The bottom right-hand corner X location of the clipping region
* YY_CLIP
The bottom right-hand corner Y location of the clipping region.
* CLIPPED
If this is true, then the clipping region is smaller than the full screen
If false, then the clipping region is the screen dimensions.
* DRAW_MODE
The current drawing mode. This is a numeric value corresponding to the constants described in the method 'draw_mode'
* RAW_FOREGROUND_COLOR
The current foreground color encoded as a string.
* RAW_BACKGROUND_COLOR
The current background color encoded as a string.
* ACCELERATED
Indicates if C code or hardware acceleration is being used.
- Possible Values
-
0 = Perl code only 1 = Some functions accelerated by compiled code (Default) 2 = All of #1 plus additional functions accelerated by hardware (currently not supported, and likely never will)
Many of the parameters you pass to the "new" method are also special variables.
CONSTANTS
The following constants can be used in the various methods. Each method example will have the possible constants to use for that method.
The value of the constant is in parenthesis:
CONSTANT (value)
Boolean constants
* TRUE ( 1 )
* FALSE ( 0 )
Draw mode constants
* NORMAL_MODE ( 0 )
* XOR_MODE ( 1 )
* OR_MODE ( 2 )
* AND_MODE ( 3 )
* MASK_MODE ( 4 )
* UNMASK_MODE ( 5 )
* ALPHA_MODE ( 6 )
* ADD_MODE ( 7 )
* SUBTRACT_MODE ( 8 )
* MULTIPLY_MODE ( 9 )
* DIVIDE_MODE ( 10 )
Draw Arc constants
* ARC ( 0 )
* PIE ( 1 )
* POLY_ARC ( 2 )
Virtual framebuffer color mode constants
* RGB ( 0 )
* RBG ( 1 )
* BGR ( 2 )
* BRG ( 3 )
* GBR ( 4 )
* GRB ( 5 )
Text rendering centering constants
* CENTER_NONE ( 0 )
* CENTER_X ( 1 )
* CENTER_Y ( 2 )
* CENTER_XY ( 3 )
Acceleration method constants
* PERL ( 0 )
* SOFTWARE ( 1 )
* HARDWARE ( 2 )
METHODS
With the exception of "new" and some other methods that only expect one parameter, the methods expect a single hash reference to be passed. This may seem unusual, but it was chosen for speed, and speed is important in a Perl graphics module.
new
This instantiates the framebuffer object
my $fb = Graphics::Framebuffer->new(parameter => value);
PARAMETERS
* FB_DEVICE
Framebuffer device name. If this is not defined, then it tries the following devices in the following order:
* /dev/fb0 - 31
* /dev/graphics/fb0 - 31
If none of these work, then the module goes into emulation mode.
You really only need to define this if there is more than one framebuffer device in your system, and you want a specific one (else it always chooses the first it finds). If you have only one framebuffer device, then you likely do not need to define this.
Use "EMULATED" instead of an actual framebuffer device, and it will open a memory only or "emulated" framebuffer. You can use this mode to have multiple "layers" for loading and manipulating images, but a single main framebuffer for displaying them.
* FOREGROUND
Sets the default (global) foreground color for when 'attribute_reset' is called. It is in the same format as "set_color" expects:
{ # This is the default value
'red' => 255,
'green' => 255,
'blue' => 255,
'alpha' => 255
}
* Do not use this to change colors, as "set_color" is intended for that. Use this to set the DEFAULT foreground color for when "attribute_reset" is called.
* BACKGROUND
Sets the default (global) background color for when 'attribute_reset' is called. It is in the same format as "set_b_color" expects:
{ # This is the default value
'red' => 0,
'green' => 0,
'blue' => 0,
'alpha' => 0
}
* Do not use this to change background colors, as "set_b_color" is intended for that. Use this to set the DEFAULT background color for when "attribute_reset" is called.
* SPLASH
The splash screen is or is not displayed
A value other than zero turns on the splash screen, and the value is the wait time to show it (default 2 seconds) A zero value turns it off
* IGNORE_X_WINDOWS
Bypasses the X-Windows check and loads anyway (dangerous). Set to 1 to disable X-Windows check. Default is 0.
* FONT_PATH
Overrides the default font path for TrueType/Type1 fonts
If 'ttf_print' is not displaying any text, then this may need to be overridden.
* FONT_FACE
Overrides the default font filename for TrueType/Type 1 fonts.
If 'ttf_print' is not displaying any text, then this may need to be overridden.
* SHOW_ERRORS
Normally this module is completely silent and does not display errors or warnings (to the best of its ability). This is to prevent corruption of the graphics. However, you can enable error reporting by setting this to 1.
This is helpful for troubleshooting.
* DIAGNOSTICS
If true, it shows images as they load, and displays benchmark informtion in the loading process.
* RESET [0 or 1 (default)]
When the object is created, it automatically creates a simple signal handler for INT and QUIT to run exec('reset') as a clean way of exiting your script and restoring the screen to defaults.
Also, when the object is destroyed, it is assumed you are exiting your script. This causes Graphics::Framebuffer to execute "exec('reset')" as its method of exiting instead of having you use "exit".
You can disable this behavior by setting this to 0.
EMULATION MODE OPTIONS
The options here only apply to emulation mode.
Emulation mode can be used as a secondary off-screen drawing surface, if you are clever.
* FB_DEVICE => 'EMULATED'
Sets this object to be in emulation mode.
Emulation mode special variables for "new" method:
* VXRES
Width of the emulation framebuffer in pixels. Default is 640.
* VYRES
Height of the emulation framebuffer in pixels. Default is 480.
* BITS
Number of bits per pixel in the emulation framebuffer. Default is 32.
* BYTES
Number of bytes per pixel in the emulation framebuffer. It's best to keep it BITS/8. Default is 4.
* COLOR_ORDER
Defines the colorspace for the graphics routines to draw in. The possible (and only accepted) string values are:
'RGB' for Red-Green-Blue (the default)
'RBG' for Red-Blue-Green
'GRB' for Green-Red-Blue
'GBR' for Green-Blue-Red
'BRG' for Blue-Red-Green
'BGR' for Blue-Green-Red (Many video cards are this)
Why do many video cards use the BGR color order? Simple, their GPUs operate with the high to low byte order for long words. To the video card, it is RGB, but to a CPU that stores bytes in low to high byte order.
text_mode
Sets the TTY into text mode, where text can interfere with the display
graphics_mode
Sets the TTY in exclusive graphics mode, where text and cursor cannot interfere with the display. Please remember, you must call text_mode before exiting, else your console will not show any text!
screen_dimensions
When called in an array/list context:
Returns the size and nature of the framebuffer in X,Y pixel values.
It also returns the bits per pixel.
my ($width,$height,$bits_per_pixel) = $fb->screen_dimensions();
When called in a scalar context, it returns a hash reference:
{
'width' => pixel width of physical screen,
'height' => pixel height of physical screen,
'bits_per_pixel' => bits per pixel (16, 24, or 32),
'bytes_per_line' => Number of bytes per scan line,
'top_clip' => top edge of clipping rectangle (Y),
'left_clip' => left edge of clipping rectangle (X),
'bottom_clip' => bottom edge of clipping rectangle (YY),
'right_clip' => right edge of clipping rectangle (XX),
'width_clip' => width of clipping rectangle,
'height_clip' => height of clipping rectangle,
'color_order' => RGB, BGR, etc,
}
splash
Displays the Splash screen. It automatically scales and positions to the clipping region.
This is automatically displayed when this module is initialized, and the variable 'SPLASH' is true (which is the default).
$fb->splash();
get_font_list
Returns an anonymous hash containing the font face names as keys and another anonymous hash assigned as the values for each key. This second hash contains the path to the font and the font's file name.
'face name' => {
'path' => 'path to font',
'font' => 'file name of font'
},
... The rest of the system fonts here
You may also pass in a face name and it will return that face's information:
my $font_info = $fb->get_font_list('DejaVuSerif');
Would return something like:
{
'font' => 'dejavuserif.ttf',
'path' => '/usr/share/fonts/truetype/'
}
When passing a name, it will return a hash reference (if only one match), or an array reference of hashes of fonts matching that name. Passing in "Arial" would return the font information for "Arial Black", "Arial Narrow", and "Arial Rounded" (if they are installed on your system).
draw_mode
Sets or returns the drawing mode, depending on how it is called.
my $draw_mode = $fb->draw_mode(); # Returns the current
# Drawing mode.
# Modes explained. These settings are global
# When you draw it...
$fb->draw_mode(NORMAL_MODE); # Replaces the screen pixel
# with the new pixel. Imager
# assisted drawing (acceleration)
# only works in this mode.
$fb->draw_mode(XOR_MODE); # Does a bitwise XOR with
# the new pixel and screen
# pixel.
$fb->draw_mode(OR_MODE); # Does a bitwise OR with
# the new pixel and screen
# pixel.
$fb->draw_mode(AND_MODE); # Does a bitwise AND with
# the new pixel and screen
# pixel.
$fb->draw_mode(MASK_MODE); # If pixels in the source
# are equal to the global
# background color, then they
# are not drawn (transparent).
$fb->draw_mode(UNMASK_MODE); # Draws the new pixel on
# screen areas only equal to
# the background color.
$fb->draw_mode(ALPHA_MODE); # Draws the new pixel on the screen
# using the alpha channel value as
# a transparency value. This means
# the new pixel will not be
# opague.
$fb->draw_mode(ADD_MODE); # Draws the new pixel on the screen
# by mathematically adding its pixel
# value to the existing pixel value
$fb->draw_mode(SUBTRACT_MODE); # Draws the new pixel on the screen
# by mathematically subtracting the
# the new pixel value from the existing
# value
$fb->draw_mode(MULTIPLY_MODE); # Draws the new pixel on the screen
# by mathematically multiplying it with
# the existing pixel value (usually not
# too useful, but here for completeness)
$fb->draw_mode(DIVIDE_MODE); # Draws the new pixel on the screen
# by mathematically dividing it with the
# existing pixel value (usually not too
# useful, but here for completeness)
normal_mode
This is an alias to draw_mode(NORMAL_MODE)
$fb->normal_mode();
xor_mode
This is an alias to draw_mode(XOR_MODE)
$fb->xor_mode();
or_mode
This is an alias to draw_mode(OR_MODE)
$fb->or_mode();
alpha_mode
This is an alias to draw_mode(ALPHA_MODE)
$fb->alpha_mode();
and_mode
This is an alias to draw_mode(AND_MODE)
$fb->and_mode();
mask_mode
This is an alias to draw_mode(MASK_MODE)
$fb->mask_mode();
unmask_mode
This is an alias to draw_mode(UNMASK_MODE)
$fb->unmask_mode();
add_mode
This is an alias to draw_mode(ADD_MODE)
$fb->add_mode();
subtract_mode
This is an alias to draw_mode(SUBTRACT_MODE)
$fb->subtract_mode();
multiply_mode
This is an alias to draw_mode(MULTIPLY_MODE)
$fb->multiply_mode();
divide_mode
This is an alias to draw_mode(DIVIDE_MODE)
$fb->divide_mode();
clear_screen
Fills the entire screen with the background color
You can add an optional parameter to turn the console cursor on or off too.
$fb->clear_screen(); # Leave cursor as is.
$fb->clear_screen('OFF'); # Turn cursor OFF (Does nothing with emulated framebuffer mode).
$fb->clear_screen('ON'); # Turn cursor ON (Does nothing with emulated framebuffer mode).
cls
This is an alias to 'clear_screen'
attribute_reset
Resets the plot point at 0,0. Resets clipping to the current screen size. Resets the global color to whatever 'FOREGROUND' is set to, and the global background color to whatever 'BACKGROUND' is set to, and resets the drawing mode to NORMAL.
$fb->attribute_reset();
plot
Set a single pixel in the set foreground color at position x,y with the given pixel size (or default). Clipping applies.
With 'pixel_size', if a positive number greater than 1, is drawn with square pixels. If it's a negative number, then it's drawn with round pixels. Square pixels are much faster.
$fb->plot(
{
'x' => 20,
'y' => 30,
'pixel_size' => 3
}
);
setpixel
An alias to plot.
set_pixel
An alias to plot.
pixel
Returns the color of the pixel at coordinate x,y, if it lies within the clipping region. It returns undefined if outside of the clipping region.
my $pixel = $fb->pixel({'x' => 20,'y' => 25});
$pixel is a hash reference in the form:
{
'red' => integer value, # 0 - 255
'green' => integer value, # 0 - 255
'blue' => integer value, # 0 - 255
'alpha' => integer value, # 0 - 255
'hex' => hexadecimal string of the values from 00000000 to FFFFFFFF
'raw' => 16/24/32bit encoded string (depending on screen mode)
}
getpixel
Alias for 'pixel'.
get_pixel
Alias for 'pixel'.
last_plot
Returns the last plotted position
my $last_plot = $fb->last_plot();
This returns an anonymous hash reference in the form:
{
'x' => x position,
'y' => y position
}
Or, if you want a simple array returned:
my ($x,$y) = $fb->last_plot();
This returns the position as a two element array:
( x position, y position )
line
Draws a line, in the foreground color, from point x,y to point xx,yy. Clipping applies.
$fb->line({
'x' => 50,
'y' => 60,
'xx' => 100,
'yy' => 332
'pixel_size' => 1,
'antialiased' => TRUE
});
angle_line
Draws a line, in the global foreground color, from point x,y at an angle of 'angle', of length 'radius'. Clipping applies.
$fb->angle_line({
'x' => 50,
'y' => 60,
'radius' => 50,
'angle' => 30.3, # Compass coordinates (0-360)
'pixel_size' => 3,
'antialiased' => FALSE
});
* This is not affected by the Acceleration setting
drawto
Draws a line, in the foreground color, from the last plotted position to the position x,y. Clipping applies.
$fb->drawto({
'x' => 50,
'y' => 60,
'pixel_size' => 2,
'antialiased' => TRUE
});
* Antialiased lines are not accelerated
bezier
Draws a Bezier curve, based on a list of control points.
$fb->bezier(
{
'coordinates' => [
x0,y0,
x1,y1,
... # As many as needed
],
'points' => 100, # Number of total points plotted for curve
# The higher the number, the smoother the curve.
'pixel_size' => 2, # optional
'closed' => 1, # optional, close it and make it a full shape.
'filled' => 1 # Results may vary, optional
'gradient' => {
'direction' => 'horizontal', # or vertical
'colors' => { # 2 to any number of transitions allowed
'red' => [255,255,0], # Red to yellow to cyan
'green' => [0,255,255],
'blue' => [0,0,255]
}
}
}
);
* This is not affected by the Acceleration setting
cubic_bezier
DISCONTINUED, use 'bezier' instead (now just an alias to 'bezier')
draw_arc
Draws an arc/pie/poly arc of a circle at point x,y.
x = x of center of circle
y = y of center of circle
radius = radius of circle
start_degrees = starting point, in degrees, of arc
end_degrees = ending point, in degrees, of arc
granularity = This is used for accuracy in drawing
the arc. The smaller the number, the
more accurate the arc is drawn, but it
is also slower. Values between 0.1
and 0.01 are usually good. Valid values
are any positive floating point number
down to 0.0001. Anything smaller than
that is just silly.
mode = Specifies the drawing mode.
0 > arc only
1 > Filled pie section
Can have gradients, textures, and hatches
2 > Poly arc. Draws a line from x,y to the
beginning and ending arc position.
$fb->draw_arc({
'x' => 100,
'y' => 100,
'radius' => 100,
'start_degrees' => -40, # Compass coordinates
'end_degrees' => 80,
'granularity => .05,
'mode' => 2 # The object hash has 'ARC', 'PIE',
# and 'POLY_ARC' as a means of filling
# this value.
});
* Only PIE is affected by the acceleration setting.
arc
Draws an arc of a circle at point x,y. This is an alias to draw_arc above, but no mode parameter needed.
x = x of center of circle
y = y of center of circle
radius = radius of circle
start_degrees = starting point, in degrees, of arc
end_degrees = ending point, in degrees, of arc
granularity = This is used for accuracy in drawing
the arc. The smaller the number, the
more accurate the arc is drawn, but it
is also slower. Values between 0.1
and 0.01 are usually good. Valid values
are any positive floating point number
down to 0.0001.
$fb->arc({
'x' => 100,
'y' => 100,
'radius' => 100,
'start_degrees' => -40,
'end_degrees' => 80,
'granularity => .05,
});
* This is not affected by the Acceleration setting
filled_pie
Draws a filled pie wedge at point x,y. This is an alias to draw_arc above, but no mode parameter needed.
x = x of center of circle
y = y of center of circle
radius = radius of circle
start_degrees = starting point, in degrees, of arc
end_degrees = ending point, in degrees, of arc
granularity = This is used for accuracy in drawing
the arc. The smaller the number, the
more accurate the arc is drawn, but it
is also slower. Values between 0.1
and 0.01 are usually good. Valid values
are any positive floating point number
down to 0.0001.
$fb->filled_pie({
'x' => 100,
'y' => 100,
'radius' => 100,
'start_degrees' => -40,
'end_degrees' => 80,
'granularity' => .05,
'gradient' => { # optional
'direction' => 'horizontal', # or vertical
'colors' => { # 2 to any number of transitions allowed
'red' => [255,255,0], # Red to yellow to cyan
'green' => [0,255,255],
'blue' => [0,0,255],
'alpha' => [255,255,255],
}
},
'texture' => { # Same as what blit_read or load_image returns
'width' => 320,
'height' => 240,
'image' => $raw_image_data
},
'hatch' => 'hatchname' # The exported array @HATCHES contains
# the names of all the hatches
});
* This is affected by the Acceleration setting
poly_arc
Draws a poly arc of a circle at point x,y. This is an alias to draw_arc above, but no mode parameter needed.
x = x of center of circle
y = y of center of circle
radius = radius of circle
start_degrees = starting point, in degrees, of arc
end_degrees = ending point, in degrees, of arc
granularity = This is used for accuracy in drawing
the arc. The smaller the number, the
more accurate the arc is drawn, but it
is also slower. Values between 0.1
and 0.01 are usually good. Valid values
are any positive floating point number
down to 0.0001.
$fb->poly_arc({
'x' => 100,
'y' => 100,
'radius' => 100,
'start_degrees' => -40,
'end_degrees' => 80,
'granularity' => .05,
});
* This is not affected by the Acceleration setting
ellipse
Draw an ellipse at center position x,y with XRadius, YRadius. Either a filled ellipse or outline is drawn based on the value of $filled. The optional factor value varies from the default 1 to change the look and nature of the output.
$fb->ellipse({
'x' => 200, # Horizontal center
'y' => 250, # Vertical center
'xradius' => 50,
'yradius' => 100,
'factor' => 1, # Anything other than 1 has funkiness
'pixel_size' => 4, # optional
'filled' => 1, # optional
## Only one of the following may be used
'gradient' => { # optional, but 'filled' must be set
'direction' => 'horizontal', # or vertical
'colors' => { # 2 to any number of transitions allowed
'red' => [255,255,0], # Red to yellow to cyan
'green' => [0,255,255],
'blue' => [0,0,255],
'alpha' => [255,255,255],
}
}
'texture' => { # Same format blit_read or load_image uses.
'width' => 320,
'height' => 240,
'image' => $raw_image_data
},
'hatch' => 'hatchname' # The exported array @HATCHES contains
# the names of all the hatches
});
* This is not affected by the Acceleration setting
circle
Draws a circle at point x,y, with radius 'radius'. It can be an outline, solid filled, or gradient filled. Outlined circles can have any pixel size.
$fb->circle({
'x' => 300, # Horizontal center
'y' => 300, # Vertical center
'radius' => 100,
'filled' => 1, # optional
'gradient' => { # optional
'direction' => 'horizontal', # or vertical
'colors' => { # 2 to any number of transitions allowed
'red' => [255,255,0], # Red to yellow to cyan
'green' => [0,255,255],
'blue' => [0,0,255],
'alpha' => [255,255,255],
}
},
'texture' => { # Same as what blit_read or load_image returns
'width' => 320,
'height' => 240,
'image' => $raw_image_data
},
'hatch' => 'hatchname' # The exported array @HATCHES contains
# the names of all the hatches
});
* This is affected by the Acceleration setting
polygon
Creates a polygon drawn in the foreground color value. The parameter 'coordinates' is a reference to an array of x,y values. The last x,y combination is connected automatically with the first to close the polygon. All x,y values are absolute, not relative.
It is up to you to make sure the coordinates are "sane". Weird things can result from twisted or complex filled polygons.
$fb->polygon({
'coordinates' => [
5,5,
23,34,
70,7
],
'pixel_size' => 1, # optional
'antialiased' => 1, # optional only for non-filled
'filled' => 1, # optional
## Only one of the following, "filled" must be set
'gradient' => { # optional
'direction' => 'horizontal', # or vertical
'colors' => { # 2 to any number of transitions allowed
'red' => [255,255,0], # Red to yellow to cyan
'green' => [0,255,255],
'blue' => [0,0,255],
'alpha' => [255,255,255],
}
},
'texture' => { # Same as what blit_read or load_image returns
'width' => 320,
'height' => 240,
'image' => $raw_image_data
},
'hatch' => 'hatchname' # The exported array @HATCHES contains
# the names of all the hatches
});
* Filled polygons are affected by the acceleration setting.
box
Draws a box from point x,y to point xx,yy, either as an outline, if 'filled' is 0, or as a filled block, if 'filled' is 1. You may also add a gradient or texture.
$fb->box({
'x' => 20,
'y' => 50,
'xx' => 70,
'yy' => 100,
'radius' => 0, # if rounded, optional
'pixel_size' => 1, # optional
'filled' => 1, # optional
## Only one of the following, "filled" must be set
'gradient' => { # optional
'direction' => 'horizontal', # or vertical
'colors' => { # 2 to any number of transitions allowed, and all colors must have the same number of transitions
'red' => [255,255,0], # Red to yellow to cyan
'green' => [0,255,255],
'blue' => [0,0,255],
'alpha' => [255,255,255], # Yes, even alpha transparency can vary
}
},
'texture' => { # Same as what blit_read or load_image returns
'width' => 320,
'height' => 240,
'image' => $raw_image_data
},
'hatch' => 'hatchname' # The exported array @HATCHES contains
# the names of all the hatches
});
rbox
Draws a box at point x,y with the width 'width' and height 'height'. It draws a frame if 'filled' is 0 or a filled box if 'filled' is 1. 'pixel_size' only applies if 'filled' is 0. Filled boxes draw faster than frames. Gradients or textures are also allowed.
$fb->rbox({
'x' => 100,
'y' => 100,
'width' => 200,
'height' => 150,
'radius' => 0, # if rounded, optional
'pixel_size' => 2, # optional
'filled' => 0, # optional
## Only one of the following, "filled" must be set
'gradient' => { # optional
'direction' => 'horizontal', # or vertical
'colors' => { # 2 to any number of transitions allowed
'red' => [255,255,0], # Red to yellow to cyan
'green' => [0,255,255],
'blue' => [0,0,255],
'alpha' => [255,255,255],
}
},
'texture' => { # Same as what blit_read or load_image returns
'width' => 320,
'height' => 240,
'image' => $raw_image_data
},
'hatch' => 'hatchname' # The exported array @HATCHES contains
# the names of all the hatches
});
rounded_box
This is an alias to rbox
set_color
Sets the drawing color in red, green, and blue, absolute 8 bit values.
Even if you are in 16 bit color mode, use 8 bit values. They will be automatically scaled.
$fb->set_color({
'red' => 255,
'green' => 255,
'blue' => 0,
'alpha' => 255
});
setcolor
This is an alias to 'set_color'
set_foreground_color
This is an alias to 'set_color'
set_b_color
Sets the background color in red, green, and blue values.
The same rules as set_color apply.
$fb->set_b_color({
'red' => 0,
'green' => 0,
'blue' => 255,
'alpha' => 255
});
setbcolor
This is an alias to 'set_b_color'
set_background_color
This is an alias to 'set_b_color'
fill
Does a flood fill starting at point x,y. It samples the color at that point and determines that color to be the "background" color, and proceeds to fill in, with the current foreground color, until the "background" color is replaced with the new color.
NOTE: The accelerated version of this routine may (and it is a small may) have issues. If you find any issues, then temporarily turn off C-acceleration when calling this method.
$fb->fill({'x' => 334, 'y' => 23});
* This one is greatly affected by the acceleration setting, and likely the one that may give the most trouble. I have found on some systems Imager just doesn't do what it is asked to, but on others it works fine. Go figure. Some of you are getting your entire screen filled and know you are placing the X,Y coordinate correctly, then disabling acceleration before calling this should fix it. Don't forget to re-enable acceleration when done.
replace_color
This replaces one color with another inside the clipping region. Sort of like a fill without boundary checking.
In 32 bit mode, the replaced alpha channel is ALWAYS set to 255.
$fb->replace_color({
'old' => { # Changed as of 5.56
'red' => 23,
'green' => 48,
'blue' => 98
},
'new' => {
'red' => 255,
'green' => 255,
'blue' => 0
}
});
* This is not affected by the Acceleration setting, and is just as fast in 16 bit as it is in 24 and 32 bit modes. Which means, very fast.
blit_copy
Copies a square portion of screen graphic data from x,y,w,h to x_dest,y_dest. It copies in the current drawing mode.
$fb->blit_copy({
'x' => 20,
'y' => 20,
'width' => 30,
'height' => 30,
'x_dest' => 200,
'y_dest' => 200
});
blit_move
Moves a square portion of screen graphic data from x,y,w,h to x_dest,y_dest. It moves in the current drawing mode. It differs from "blit_copy" in that it removes the graphic from the original location (via XOR).
It also returns the data moved like "blit_read"
$fb->blit_move({
'x' => 20,
'y' => 20,
'width' => 30,
'height' => 30,
'x_dest' => 200,
'y_dest' => 200,
'image' => $raw_image_data, # This is optional, but can speed things up
});
play_animation
Plays an animation sequence loaded from "load_image"
my $animation = $fb->load_image(
{
'file' => 'filename.gif',
'center' => CENTER_XY,
}
);
$fb->play_animation($animation,$rate_multiplier);
The animation is played at the speed described by the file's metadata multiplied by "rate_multiplier".
You need to enclose this in a loop if you wish it to play more than once.
acceleration
Enables/Disables all Imager or C language acceleration.
GFB uses the Imager library to do some drawing. In some cases, these may not function as they should on some systems. This method allows you to toggle this acceleration on or off.
When acceleration is off, the underlying (slower) Perl algorithms are used. It is advisable to leave acceleration on for those methods which it functions correctly, and only shut it off when calling the problem ones.
When called without parameters, it returns the current setting.
$fb->acceleration(HARDWARE); # Turn hardware acceleration ON, along with some C acceleration (HARDWARE IS NOT YET IMPLEMENTED!)
$fb->acceleration(SOFTWARE); # Turn C (software) acceleration ON
$fb->acceleration(PERL); # Turn acceleration OFF, using Perl
my $accel = $fb->acceleration(); # Get current acceleration state. 0 = PERL, 1 = SOFTWARE, 2 = HARDWARE (not yet implemented)
my $accel = $fb->acceleration('english'); # Get current acceleration state in an english string.
# "PERL" = PERL = 0
# "SOFTWARE" = SOFTWARE = 1
# "HARDWARE" = HARDWARE = 2
* The "Mask" and "Unmask" drawing modes are greatly affected by acceleration, as well as 16 bit conversions in image loading and ttf_print(ing).
perl
This is an alias to "acceleration(PERL)"
software
This is an alias to "acceleration(SOFTWARE)"
hardware
This is an alias to "acceleration(HARDWARE)"
blit_read
Reads in a square portion of screen data at x,y,width,height, and returns a hash reference with information about the block, including the raw data as a string, ready to be used with 'blit_write'.
Passing no parameters automatically grabs the clipping region (the whole screen if clipping is off).
my $blit_data = $fb->blit_read({
'x' => 30,
'y' => 50,
'width' => 100,
'height' => 100
});
Returns:
{
'x' => original X position,
'y' => original Y position,
'width' => width,
'height' => height,
'image' => string of image data for the block
}
All you have to do is change X and Y, and just pass it to "blit_write" and it will paste it there.
blit_write
Writes a previously read block of screen data at x,y,width,height.
It takes a hash reference. It draws in the current drawing mode.
$fb->blit_write({
'x' => 0,
'y' => 0,
'width' => 100,
'height' => 100,
'image' => $blit_data
});
blit_transform
This performs transformations on your blit objects.
You can only have one of "rotate", "scale", "merge", "flip", or make "monochrome". You may use only one transformation per call.
* blit_data (mandatory)
Used by all transformations. It's the image data to process, in the format that "blit_write" uses. See the example below.
* flip
Flips the image either "horizontally, "vertically, or "both"
* merge
Merges one image on top of the other. "blit_data" is the top image, and "dest_blit_data" is the background image. This takes into account alpha data values for each pixel (if in 32 bit mode).
This is very usefull in 32 bit mode due to its alpha channel capabilities.
* rotate
Rotates the "blit_data" image an arbitrary degree. Positive degree values are counterclockwise and negative degree values are clockwise.
Two types of rotate methods are available, an extrememly fast, but visually slightly less appealing method, and a slower, but looks better, method. Seriously though, the fast method looks pretty darn good anyway. I recommend "fast".
* scale
Scales the image to "width" x "height". This is the same as how scale works in "load_image". The "type" value tells it how to scale (see the example).
$fb->blit_transform(
{
# blit_data is mandatory
'blit_data' => { # Same as what blit_read or load_image returns
'x' => 0, # This is relative to the dimensions of "dest_blit_data" for "merge"
'y' => 0, # ^^
'width' => 300,
'height' => 200,
'image' => $image_data
},
'merge' => {
'dest_blit_data' => { # MUST have same or greater dimensions as 'blit_data'
'x' => 0,
'y' => 0,
'width' => 300,
'height' => 200,
'image' => $image_data
}
},
'rotate' => {
'degrees' => 45, # 0-360 degrees. Negative numbers rotate clockwise.
'quality' => 'high', # "high" or "fast" are your choices, with "fast" being the default
},
'flip' => 'horizontal', # or "vertical" or "both"
'scale' => {
'x' => 0,
'y' => 0,
'width' => 500,
'height' => 300,
'scale_type' => 'min' # 'min' = The smaller of the two
# sizes are used (default)
# 'max' = The larger of the two
# sizes are used
# 'nonprop' = Non-proportional sizing
# The image is scaled to
# width x height exactly.
},
'monochrome' => TRUE # Makes the image data monochrome
}
);
It returns the transformed image in the same format the other BLIT methods use. Note, the width and height may be changed! So always use the returned data as the correct new data.
{
'x' => 0, # copied from "blit_data"
'y' => 0, # copied from "blit_data"
'width' => 100, # width of transformed image data
'height' => 100, # height of transformed image data
'image' => $image # image data
}
* Rotate and Flip are affected by the acceleration setting.
clip_reset
Turns off clipping, and resets the clipping values to the full size of the screen.
$fb->clip_reset();
clip_off
This is an alias to 'clip_reset'
clip_set
Sets the clipping rectangle starting at the top left point x,y and ending at bottom right point xx,yy.
$fb->clip_set({
'x' => 10,
'y' => 10,
'xx' => 300,
'yy' => 300
});
clip_rset
Sets the clipping rectangle to point x,y,width,height
$fb->clip_rset({
'x' => 10,
'y' => 10,
'width' => 600,
'height' => 400
});
monochrome
Removes all color information from an image, and leaves everything in greyscale.
It applies the following formula to calculate greyscale:
grey_color = (red * 0.2126) + (green * 0.7155) + (blue * 0.0722)
Expects two parameters, 'image' and 'bits'. The parameter 'image' is a string containing the image data. The parameter 'bits' is how many bits per pixel make up the image. Valid values are 16, 24, and 32 only.
$fb->monochrome({
'image' => "image data",
'bits' => 32
});
It returns 'image' back, but now in greyscale (still the same RGB format though).
{
'image' => "monochrome image data"
}
* You should normally use "blit_transform", but this is a more raw way of affecting the data
ttf_print
Prints TrueType text on the screen at point x,y in the rectangle width,height, using the color 'color', and the face 'face' (using the Imager library as its engine).
Note, 'y' is the baseline position, not the top left of the bounding box. This is a change from before!!!
This is best called twice, first in bounding box mode, and then in normal mode.
Bounding box mode gets the actual values needed to display the text.
If draw mode is "normal", then mask mode is automatically used for best output.
my $bounding_box = $fb->ttf_print({
'x' => 20,
'y' => 100, # baseline position
'height' => 16,
'wscale' => 1, # Scales the width. 1 is normal
'color' => 'FFFF00FF', # Hex value of color 00-FF (RRGGBBAA)
'text' => 'Hello World!',
'font_path' => '/usr/share/fonts/truetype', # Optional
'face' => 'Arial.ttf', # Optional
'bounding_box' => TRUE,
'center' => CENTER_X,
'antialias' => TRUE
});
$fb->ttf_print($bounding_box);
Here's a shortcut:
$fb->ttf_print(
$fb->ttf_print({
'x' => 20,
'y' => 100, # baseline position
'height' => 16,
'color' => 'FFFF00FF', # RRGGBBAA
'text' => 'Hello World!',
'font_path' => '/usr/share/fonts/truetype', # Optional
'face' => 'Arial.ttf', # Optional
'bounding_box' => TRUE,
'rotate' => 45, # optonal
'center' => CENTER_X,
'antialias' => 1,
'shadow' => shadow size
})
);
Failures of this method are usually due to it not being able to find the font. Make sure you have the right path and name.
ttf_paragraph
Very similar to an ordinary Perl "print", but uses TTF fonts instead. It will automatically wrap text like a terminal.
This uses no bounding boxes, and is only needed to be called once. It uses a very simple wrapping model.
It uses the clipping rectangle. All text will be fit and wrapped within the clipping rectangle.
Text is started at "x" and wrapped to "x" for each line, no indentation.
* This does NOT scroll text. It merely truncates what doesn't fit. It returns where in the text string it last printed before truncation. It's also quite slow.
$fb->ttf_paragraph(
{
'text' => 'String to print',
'x' => 0, # Where to start printing
'y' => 20, #
'size' => 12, # Optional Font size, default is 16
'color' => 'FFFF00FF', # RRGGBBAA
'justify' => 'justified' # Optional justification, default
# is "left". Posible values are:
# "left", "right", "center", and
# "justified"
'line_spacing' => 5, # This adjusts the default line
# spacing by positive or negative
# amounts. The default is 0.
'face' => 'Ariel', # Optional, overrides the default
'font_path' => '/usr/share/fonts', # Optional, else uses the default
}
);
get_face_name
Returns the TrueType face name based on the parameters passed.
my $face_name = $fb->get_face_name({
'font_path' => '/usr/share/fonts/TrueType/',
'face' => 'FontFileName.ttf'
});
load_image
Loads an image at point x,y[,width,height]. To display it, pass it to blit_write.
If you give centering options, the position to display the image is part of what is returned, and is ready for blitting.
If 'width' and/or 'height' is given, the image is resized. Note, resizing is CPU intensive. Nevertheless, this is done by the Imager library (compiled C) so it is relatively fast.
$fb->blit_write(
$fb->load_image(
{
'x' => 0, # Optional (only applies if
# CENTER_X or CENTER_XY is not
# used)
'y' => 0, # Optional (only applies if
# CENTER_Y or CENTER_XY is not
# used)
'width' => 1920, # Optional. Resizes to this maximum
# width. It fits the image to this
# size.
'height' => 1080, # Optional. Resizes to this maximum
# height. It fits the image to this
# size
'scale_type' => 'min',# Optional. Sets the type of scaling
#
# 'min' = The smaller of the two
# sizes are used (default)
# 'max' = The larger of the two
# sizes are used
# 'nonprop' = Non-proportional sizing
# The image is scaled to
# width x height exactly.
'autolevels' => FALSE,# Optional. It does a color
# correction. Sometimes this
# works well, and sometimes it
# looks quite ugly. It depends
# on the image
'center' => CENTER_XY, # Optional
# Three centering options are available
# CENTER_X = center horizontally
# CENTER_Y = center vertically
# CENTER_XY = center horizontally and
# vertically. Placing it
# right in the middle of
# the screen.
'file' => 'RWBY_Faces.png', # Usually needs full path
'convertalpha' => TRUE, # Converts the color matching the global
# background color to have the same alpha
# channel value as the global background,
# which is beneficial for using 'merge'
# in 'blit_transform'.
'preserve_transparency' => FALSE,
# Preserve the transparency of GIFs for
# use with "mask_mode" playback.
# This can allow for slightly faster
# playback of animated GIFs on systems
# using the acceration features of this
# module. However, not all animated
# GIFs look right when this is done.
# the safest setting is to not use this,
# and playback using normal_mode.
}
)
);
If a single image is loaded, it returns a reference to an anonymous hash, of the format:
{
'x' => horizontal position calculated (or passed through),
'y' => vertical position calculated (or passed through),
'width' => Width of the image,
'height' => Height of the image,
'tags' => The tags of the image (hashref)
'image' => [raw image data]
}
If the image has multiple frames, then a reference to an array of hashes is returned:
# NOTE: X and Y positions can change frame to frame, so use them for each frame!
# Also, X and Y are based upon what was originally passed through, else they
# reference 0,0 (but only if you didn't give an X,Y value initially).
# ALSO: The tags may also specify offsets, and they will be taken into account.
[
{ # Frame 1
'x' => horizontal position calculated (or passed through),
'y' => vertical position calculated (or passed through),
'width' => Width of the image,
'height' => Height of the image,
'tags' => The tags of the image (hashref)
'image' => [raw image data]
},
{ # Frame 2 (and so on)
'x' => horizontal position calculated (or passed through),
'y' => vertical position calculated (or passed through),
'width' => Width of the image,
'height' => Height of the image,
'tags' => The tags of the image (hashref)
'image' => [raw image data]
}
]
screen_dump
Dumps the screen to a file given in 'file' in the format given in 'format'
Formats can be (they are case-insensitive):
* JPEG
The most widely used format. This is a "lossy" format. The default quality setting is 75%, but it can be overriden with the "quality" parameter.
* GIF
The CompuServe "Graphics Interchange Format". A very old and outdated format made specifically for VGA graphics modes, but still widely used. It only allows up to 256 "indexed" colors, so quality is very lacking. The "dither" paramter determines how colors are translated from 24 bit truecolor to 8 bit indexed.
* PNG
The Portable Network Graphics format. Widely used, very high quality.
* PNM
The Portable aNy Map format. These are typically "PPM" files. Not widely used.
* TGA
The Targa image format. This is a high-color, lossless format, typically used in photography
* TIFF
The Tagged Image File Format. Sort of an older version of PNG (but not the same, just similar in capability). Sometimes used in FAX formats.
$fb->screen_dump(
{
'file' => '/path/filename', # name of file to be written
'format' => 'jpeg', # jpeg, gif, png, pnm, tga, or tiff
# for JPEG formats only
'quality' => 75, # quality of the JPEG file 1-100% (the
# higher the number, the better the
# quality, but the larger the file)
# for GIF formats only
'dither' => 'floyd', # Can be "floyd", "jarvis" or "stucki"
}
);
RGB565_to_RGB888
Convert a 16 bit color value to a 24 bit color value. This requires the color to be a two byte packed string.
my $color24 = $fb->RGB565_to_RGB888(
{
'color' => $color16
}
);
RGB565_to_RGB8888
Convert a 16 bit color value to a 32 bit color value. This requires the color to be a two byte packed string. The alpha value is either a value passed in or the default 255.
my $color32 = $fb->RGB565_to_RGB8888(
{
'color' => $color16, # Required
'alpha' => 128 # Optional
}
);
RGB888_to_RGB565
Convert 24 bit color value to a 16 bit color value. This requires a three byte packed string.
my $color16 = $fb->RGB888_to_RGB565(
{
'color' => $color24
}
);
This simply does a bitshift, nothing more.
RGBA8888_to_RGB565
Convert 32 bit color value to a 16 bit color value. This requires a four byte packed string.
my $color16 = $fb->RGB8888_to_RGB565(
{
'color' => $color32,
}
);
This simply does a bitshift, nothing more
RGB888_to_RGBA8888
Convert 24 bit color value to a 32 bit color value. This requires a three byte packed string. The alpha value is either a value passed in or the default 255.
my $color32 = $fb->RGB888_to_RGBA8888(
{
'color' => $color24,
'alpha' => 64
}
);
This just simply adds an alpha value. No actual color conversion is done.
RGBA8888_to_RGB888
Convert 32 bit color value to a 24 bit color value. This requires a four byte packed string.
my $color24 = $fb->RGBA8888_to_RGB888(
{
'color' => $color32
}
);
This just removes the alpha value. No color conversion is actually done.
vsync
Waits for vertical sync
Waits for the vertical blank before returning
* Not all framebuffer drivers have this capability and ignore this call. Results may vary, as this cannot be emulated. The only way to know is to just test it.
which_console
Returns the active console and the expected console
my ($active_console, $expected_console) = $fb->which_console();
active_console
Indicates if the current console is the expected console. It returns true or false.
if ($self->active_console()) {
# Do something
}
wait_for_console
Blocks actions until the expected console is active. The expected console is determined at the time the module is initialized.
Due to speed considerations, YOU must do use this to do blocking, if desired. If you expect to be changing active consoles, then you will need to use this. However, if you do not plan to do ever change consoles when running this module, then don't use this feature, as your results will be faster.
If a TRUE or FALSE is passed to this, then you can enable or disable blocking for subsequent calls.
initialize_mouse
Turns on/off the mouse handler.
Note: This uses Perl's "alarm" feature. If you want to use threads, then don't use this to turn on the mouse.
# $fb->initialize_mouse(1); # Turn on the mouse handler
or
# $fb->initialize_mouse(0); # Turn off the mouse handler
poll_mouse
The mouse handler. The "initialize_mouse" routine sets this as the "alarm" routine to handle mouse events.
An alarm handler just works, but can possibly block if used as ... an alarm handler.
I suggest running it in a thread instead, using your own code.
get_mouse
Returns the mouse coordinates.
Return as an array:
my ($mouseb, $mousex, $mousey) = $fb->get_mouse();
Return as a hash reference:
my $mouse = $fb->get_mouse();
Returns
{
'button' => button value, # Button state according to bits
# Bit 0 = Left
# Bit 1 = Right
# Other bits according to driver
'x' => Mouse X coordinate,
'y' => Mouse Y coordinate,
}
set_mouse
Sets the mouse position
$fb->set_mouse(
{
'x' => 0,
'y' => 0,
}
);
* NOTE: Mouse support is very primitive and will not be further developed, as the framebuffer is not exactly mouse-friendly.
USAGE HINTS
GRADIENTS
Gradients can have any number (actually 2 or greater) of color key points (transitions). Vertical gradients cannot have more key points than the object is high. Horizontal gradients cannot have more key points that the object is wide. Just keep your gradients "sane" and things will go just fine.
Make sure the number of color key points matches for each primary color (red, green, and blue);
PERL OPTIMIZATION
This module is highly CPU dependent. So the more optimized your Perl installation is, the faster it will run.
THREADS
The module (using the 'threads' module) canNOT have separate threads calling the same object. You WILL crash. However, you can instantiate an object for each thread to use on the same framebuffer, and it will work just fine.
See the "examples/multiprocessing" directory for "threads_primitives.pl" as an example of a threading script that uses this module.
FORKS
For unthreaded Perl, Install the modules forks and forks::shared and you will have the same features as threads and threads::shared (and perhaps better performance for unthreaded perls).
MCE
Mario Roy has tested Graphics::Framebuffer with various methods to use the MCE modules for multiprocessing, and creating a single shared library. See the "README" file for more. I highly recommend this for multiprocessing, as it should save on memory.
BLITTING
Use "blit_read" and "blit_write" to save portions of the screen instead of redrawing everything. It will speed up response tremendously.
SPRITES
Someone asked me about sprites. Well, that's what blitting is for. You'll have to do your own collision detection. Use MASK_MODE and UNMASK_MODE for drawing, and XOR_MODE for removing.
Most framebuffer drivers do not have access to GPU features. It's just a memory map of the framebuffer.
Listen folks, this library does everything in software, so your results will vary depending on CPU speed and screen resolution, as well as blit resolution.
HORIZONTAL "MAGIC"
Horizontal lines and filled boxes draw very fast, even in Perl mode, seriously. Learn to exploit them.
PIXEL SIZE
Pixel sizes over 1 utilize a filled "box" or "circle" (negative numbers for circle) to do the drawing. This is why the larger the "pixel", the slower the draw.
MULTIPLE "HEADS" (monitors)
As long as each framebuffer for each display is accessible, you can open an instance of the module for each framebuffer and access each screen.
MAKING WINDOWS
So, you want to be able to manage some sort of windows...
You just instantiate a new instance of the module per "Window" and give it its own clipping region. This region is your drawing space for your window.
It is up to you to actually decorate (draw) the windows.
Nothing is preventing you from writing your own window handler, although I recommend just using X-Windows (and a different module) for that anyway.
RUNNING IN MICROSOFT WINDOWS
It doesn't work natively, (other than in emulation mode) and likely never will. However...
You can run Linux inside VirtualBox and it works fine. Put it in full screen mode, and voila, it's "running in Windows" in an indirect kinda-sorta way. Make sure you install the VirtualBox extensions, as it has the correct video driver for framebuffer access. It's as close as you'll ever get to get it running in MS Windows. Seriously...
This isn't a design choice, nor preference, nor some anti-Windows ego trip. It's simply because of the fact MS Windows does not allow file mapping of the display, nor variable memory mapping of the display (that I know of), both are the techniques this module uses to achieve its magic. DirectX is more like OpenGL in how it works, and thus defeats the purpose of this module. You're better off with SDL instead, if you want to draw in MS Windows from Perl.
* However, if someone knows how to access the framebuffer (or simulate one) in MS Windows, and be able to do it reasonably from within Perl, then send me instructions on how to do it, and I'll do my best to get it to work.
TROUBLESHOOTING
Ok, you've installed the module, but can't seem to get it to work properly. Here are some things you can try:
** make sure you turn on the SHOW_ERRORS parameter when calling new to create the object. This helps with troubleshooting (but turn it back off for normal use).
- You Have To Run From The Console
-
A console window doesn't count as "the console". You cannot use this module from within X-Windows. It won't work, and likely will only go into emulation mode if you do, or maybe crash, or even corrupt your X-Windows screen.
If you want to run your program within X-Windows, then you have the wrong module. Use SDL, QT, or GTK or something similar.
You MUST have a framebuffer based video driver for this to work. The device ("/dev/fb0" for example) must exist.
If it does exist, but is not "/dev/fb0", then you can define it in the new method with the FB_DEVICE parameter, although the module is pretty good at finding it automatically.
* It may be possible to get a framebuffer device with a proprietary driver by forcing Grub to go into a VESA VGA mode for the console (worked for me with NVidia).
- It's Crashing
-
Ok, segfaults suck. Believe me, I had plenty in the early days of writing this module. There is hope for you.
This is almost always caused by the module incorrectly calculating the framebuffer memory size, and it's guessing too large or small a memory footprint, and the system doesn't like it.
Try running the "primitives.pl" in the "examples" directory in the following way (assuming your screen is larger than 640x480):
perl examples/primitives.pl --x=640 --y=480
This forces the module to pretend it is rendering for a smaller resolution (by placing this screen in the middle of the actual one). If it works fine, then try changing the "x" value back to your screen's actual width, but still make the "y" value slightly smaller. Keep decreasing this "y" value until it works.
If you get this behavior, then it is a bug, and the author needs to be notified, although as of version 6.06 this should no longer be an issue.
- It Only Partially Renders
-
Yeah this can look weird. This is likely because there's some buffering going on. The module attempts to turn it off, but if, for some reason, it is buffering anyway, try adding the following to points in your code where displaying a full render is necessary:
$fb->_flush_screen();
This should force a full screen flush, but only use this if you really need it.
Why? You see, the framebuffer is actually a file. Therefore, file operations must be used to access it. File operations are buffered. Therefore buffers need to be flushed instead of cached for the framebuffer device. This module actually maps this file to a variable and even more weirdness results. Normally turning off buffering in Perl is easy, but on rare occasions it can be stubborn. Therefore, this command was made to force it to flush, if it isn't already.
- It Just Plain Isn't Working
-
Well, either your system doesn't have a framebuffer driver, or perhaps the module is getting confusing data back from it and can't properly initialize (see the previous items).
First, make sure your system has a framebuffer by seeing if /dev/fb0 (actually "fb" then any number) exists. If you don't see any "fb0" - "fb31" files inside "/dev" (or "/dev/fb/"), then you don't have a framebuffer driver running. You need to fix that first. Sometimes you have to manually load the driver with "modprobe -a drivername" (replacing "drivername" with the actual driver name).
Second, you did the above, but still nothing. You need to check permissions. The account you are running this under needs to have permission to use the screen. This typically means being a member of the "video" group. Let's say the account is called "username", and you want to give it permission. In a Linux (Debian/Ubuntu/Mint/RedHat/Fedora) environment you would use this to add "username" (your account name) to the "video" group:
sudo usermod -a -G video username
Once that is run (changing "username" to whatever your username is), log out, then log back in, and it should work.
- The Text Cursor Is Messing Things Up
-
It is? Well then turn it off. Use the $fb->cls('OFF') method to do it. Use $fb->cls('ON') to turn it back on.
If your script exits without turning the cursor back on, then it will still be off. To get your cursor back, just type the command "reset" (and make sure you turn it back on before your code exits, so it doesn't do that).
* UPDATE: The new default behavior is to do this for you via the RESET parameter when creating the object. See the new method documentation above for more information.
- TrueType Printing isn't working
-
This is likely caused by the Imager library either being unable to locate the font file, or when it was compiled, it couldn't find the FreeType development libraries, and was thus compiled without TrueType text support.
See the INSTALLATION instructions (above) on getting Imager properly compiled. If you have a package based Perl installation, then installing the Imager (usually "libimager-perl") package will always work. If you already installed Imager via CPAN, then you should uninstall it via CPAN, then go install the package version, in that order. You may also install "libfreetype6-dev" and then re-install Imager via CPAN with a forced install. If you don't want the package version but still want the CPAN version, then still uninstall what is there, then go an make sure the TrueType and FreeType development libraries are installed on your system, along with PNG, JPEG, and GIF development libraries. Now you can go to CPAN and install Imager.
- It's Too Slow
-
Ok, it does say a PERL graphics library in the description, if I am not mistaken. This means Perl is doing most of the work. This also means it is only as fast as your system and its CPU, as it does not use your GPU at all.
First, check to make sure the C acceleration routines are compiling properly. Call the "acceleration" method without parameters. It SHOULD return 1 and not 0 if C is properly compiling. If it's not, then you need to make sure "Inline::C" is properly installed in your Perl environment. THIS WILL BE THE BIGGEST HELP TO YOU, IF YOU GET THIS SOLVED FIRST.
Second, (and this is very advanced) you could try recompiling Perl with optimizations specific to your hardware. That can help, but this is very advanced and you should know what you are doing before attempting this. Keep in mind that if you do this, then ALL of the modules installed via your distribution packager won't work, and will have to be reinstalled via CPAN for the new perl. Try using perlbrew to do this simply for you.
You can also try simplifying your drawing to exploit the speed of horizontal lines. Horizonal line drawing is incredibly fast, even for very slow systems.
Only use pixel sizes of 1. Anything larger requires a box to be drawn at the pixel size you asked for. Pixel sizes of 1 only use plot to draw, (so no boxes) so it is much faster.
Try using 'polygon' to draw complex shapes instead of a series of plot or line commands.
Does your device have more than one core? Well, how about using threads (or MCE)? Just make sure you do it according to the examples in the "examples" directory. Yes, I know this can be too advanced for the average coder, but the option is there.
Plain and simple, your device just may be too slow for some CPU intensive operations, specifically anything involving animated images and heaviy blitting. If you must use images, then make sure they are already the right size for your needs. Don't force the module to resize them when loading, as this takes CPU time (and memory).
- Ask For Help
-
If none of these ideas work, then send me an email, and I may be able to get it functioning for you. Please run the dump.pl script inside the "examples" directory inside this module's package:
perl dump.pl
Please include the dump file it creates (dump.log) as a file attachment to your email. Please do not include it inline as part of the message text.
Also, please include a copy of your code (or at least the portion of it where you initialize this module and are having issues), AND explain to me your hardware and OS it is running under.
Screen shots and photos are also helpful.
KNOW THIS: I want to get it working on your system, and I will do everything I can to help you get it working, but there may be some conditions where that may not be possible. It's very rare (and I haven't seen it yet), but possible.
I am not one of those arrogant ogres that spout "RTFM" every time someone asks for help (although it helps if you do read the manual). I actually will help you. Please be patient, as I do have other responsibilities that may delay a response, but a response will come.
** Making the subject of your email "PERL GFB HELP" is most helpful for me, and likely will get your email seen sooner.
AUTHOR
Richard Kelsch <rich@rk-internet.com>
COPYRIGHT
Copyright © 2003-2024 Richard Kelsch, All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under the GNU software license.
LICENSE
GNU Public License Version 3
A copy of this license is included in the 'LICENSE' file in this distribution.
VERSION
Version 6.61 (Jul 10, 2024)
THANKS
My thanks go out to those using this module and submitting helpful patches and suggestions for improvement, as well as those who asked for help. Your requests for help actually gave me ideas.
Thank you Mario Roy for showing how to use MCE to multiprocess instead of threads. Very handy. Look for the "get_mce_demos" in the "examples" directory. NOTE: I do not support MCE bug issues.
TELL ME ABOUT YOUR PROJECT
I'd love to know if you are using this library in your project. So send me an email, with pictures and/or a URL (if you have one) showing what it is. If you have a YouTube video, then that would be cool to see too.
If project has a specific need that the module does not support (or support easy), then suggest a feature to me.
YOUTUBE
There is a YouTube channel with demonstrations of the module's capabilities. Eventually it will have examples of output from a variety of different types of hardware.
YouTube Graphics::Framebuffer Channel
GITHUB
git clone https://github.com/richcsst/Graphics-Framebuffer.git