PerlSub - Release Notes
Copyright 2026-2027 by The Software Samurai.
On the web: http://www.SoftwareSam.us/
Software released under GNU GPL3, and documentation released under FDL1.3
This document describes version 0.0.01 of PerlSub.
This program is free software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details. .
Developed under: Perl v:5.40.3
libheif v:1.19.8
Description
This package includes two simple Perl scripts which demonstrate the use of subroutines in Perl.
'subtest.pl'
------------
This simple program demonstrates the use of "call-by-reference" versus "call-by-value" parameters.
'heic.pl'
---------
This is a more complex example which demonstrates the various ways Perl subroutines can be built and invoked.
The code itself is constructed as a front-end for the third-party utility program, "heif-dec" (heif-decode), which
converts Apple(tm) HEIC-encoded images to other image formats.
The Perl source demonstrates subroutine access even without the external utility; however, for full functionality,
"heif-dec" should be installed on the target system. See below for additional information.
'create_archive.pl'
-------------------
Also included is an example utility script used for creating distribution archives.
This Perl script takes no argments; simply navigate to the install directory and invoke the script:
cd PerlSub/install
./create_archive
This should create an archive file identical to the original archive downloaded from the website.
A useful feature is that it extracts a copy of the distro version number from the source data
which is then incorporated into the name of the archive file.
Once the functionality is understood, the program structure and function can easily be adapted for any set of
source files regardless of the complexity of the source tree.
Download and unpack the distribution archive.
Command-line Options for ‘heic.pl’
Usage: heic.pl SOURCE_FILE [TARGET_FILE] [OPTIONS]
- SOURCE_FILE — Source File Name(s) (required)
Filename of a High-Efficiency-Image-Container (HEIC-encoded) file located in the current working directory (CWD).
Source file(s) may be specified in exactly one of three ways:
- as the first argument:
heic.pl Orange.heic
- '–src' option (in any argument position)
heic.pl -e=png -src=Orange.heic
- '–all' option (in any argument position)
Used to specify that all HEIC-encoded files in the CWD are to be processed.
heic.pl -all -e=jpeg -q=75
Note that if the '-all' option is used, then any individual source or target filenames
specified will be ignored.
- TARGET_FILE Target File Name (optional)
Name of target file, optionally including a filename extension indicating the target encoding.
The target filename may be specified in either of two ways:
- as the second argument (following the source filename):
heic.pl Orange.heic Tangerine.png
- '–trg' option (in any argument position):
heic.pl -src=Orange.heic -q=80 -trg=Tangerine.jpg
Parsing Logic
- If no target filename specified, the target takes the base name of the source file(s) and the
filename extension is taken from the '-e' option if specified, else default extension/encoding
(jpg) is used.
heic.pl Orange.heic yields: Orange.jpg
heic.pl Orange.heic -e=png yields: Orange.png
- If a target filename is specified with no filename extension, the extension/encoding is
taken from the '-e' option, if specified, else the default extension and
encoding are used.
heic.pl Orange.heic Grape yields: Grape.jpg
heic.pl Orange.heic -e=tif -trg=Grape yields: Grape.tif
- If target is specified with filename extension (target encoding), the extension will be compared
against the list of supported extensions/encodings.
heic.pl Orange.heic Grape.png yields: Grape.png
heic.pl Orange.heic -trg=Grape.tif yields: Grape.tif
heic.pl Orange.heic Grape.xyz yields: ERROR!
- If both filename and '-e' option specified, then the '-e' option overrides
target filename extension.
heic.pl Orange.heic Grape.tif -e=png yields: Grape.png
- If the '-all' (all source) option is used, then the target filename(s) will be be constructed
from the source filenames, and the individual target specification will be ignored; however,
if an encoding was specified, it will be retained unless overridden by a subsequent
'-e' option.
heic.pl -all -trg=Grape.tif yields: Orange.tif Apple.tif Grape.tif etc.
heic.pl -all -trg=Grape.tif -e=png yields: Orange.png Apple.png Grape.png etc.
- –e=ENCODING (optional)
Specifies target encoding AND target filename extension, (case insensitive). Do not include a
leading '.' character. If specified, the '-e'
option overrides the target filename extension (if any).
Encoding Options: jpg (default), jpeg, tif, tiff, png, y4m (See below for details.) Example:
heic.pl Orange.heic -e=png
- –q=QUALITY (optional)
For JPEG (‘lossy’) compression only, specify the compression level (the integer percentage
of the original source data retained). Range: 10 – 100 (default: 92)
heic.pl Orange.heic Target.jpg -q=65
The '-q' option does not apply to lossless encoding formats (PNG, TIF, Y4M).
- –v Verbose Output (optional)
By default, the intermediate results and any warning messages produced by the 'heif-dec' application
are silently discarded. If verbose output is specified, however, then a copy of the invocation command
used to call 'heif-dec' as well as the interim results of the conversion process
will be reported.
heic.pl Orange.heic Target.png -v
- – –version (optional)
Display application version number and copyright information, then exit. This option overrides all other arguments.
heic.pl --version
- – –help[less] –h[l] (optional)
Display a list of command line options, then exit.
This option overrides all other arguments except '--version'.
- The '--help' or '-h' option writes the command-line help
directly to the terminal window.
- The '--helpless' or '-hl' option redirects the command-line
help through the 'less' utility.
Command-line Options for ‘subtest.pl’
The
'subtest.pl' example program demonstrates the syntax used for calling various subroutines, as well
as the syntax used within the subroutines to access the parameters specified by the caller. In the examples shown, the labels
“
call” and “
ref” indicate this syntax used
for the individual tests.
Usage: subtest.pl [ -a | -p=WIDTH ]
- If called without parameters, execute the first three tests:
subtest1 - Anonymous, by-reference:
call: subtest1 ( $data ) ;
ref : print "$_[0]" ;
subtest2 - Named, by-value:
call: subtest2 ( $data ) ;
ref : print "$data" ;
subtest3 - Named, by-reference:
call: subtest3 ( \$data ) ;
ref : print "$$data" ;
- If called with: subtest.pl -a ('A' is for Array),
execute the fourth test: subtest4().
subtest4 - Anonymous, by-reference, (locally aliased):
call: subtest4 ( \@data ) ;
ref : my ($arrayPtr) = @_ ;
print "$arrayPtr->[$indx]" ;
- If called with: subtest.pl -p=WIDTH ('P' is for Padding),
execute the string padding test
where WIDTH is an integer value in the range: 18 <= WIDTH <= 120. If the specified value is out
of range, then value will be set to closest limit. If invoked without a value, then the default
value (36) will be used.
padTest - Named, by-value:
call: padTest ( $trgWidth ) ;
ref : print "$trgWidth" ;
Technical Notes On Perl Subroutines:
The functionality available in any Perl script depends heavily
upon the version of Perl installed and the modules loaded.
This script uses the standard modules available by default
for the version currently installed.
The Perl version used for development of this project is:
v5.40.4
The pragma used at the top of the file is:
use v5.40
Calling subroutines in Perl (v5.36+)
- Unnamed parameters are pass-by-reference: ($_[0] is an alias for caller's variable).
When the subroutine changes the contents of pass-by-reference, then caller's data has been changed.
my $Apple = "original data" ;
PolishApple ( $Apple ) ;
print "$Apple" ; # yields "new data"
sub PolishApple
{ $_[0] = "new data" ; }
- Named parameters are pass-by-value: ($a is a copy of caller's variable)
my $Apple = "original data" ;
PolishApple ( $Apple ) ;
print "$Apple" ; # yields "original data"
sub PolishApple ( $a )
{ $a = "new data" ; }
- Named pass-by-reference parameters:
Perl syntax does not yet support named pass-by-reference; however, there is kludgy work-around:
($a is reference (pointer) to caller's variable, and the $$
de-references the pointer to caller's object).
my $Apple = "original data" ;
PolishApple ( \$Apple ) ;
print "$Apple" ; # yields "new data"
sub PolishApple ( $a )
{ $$a = "new data" ; }
- Perl experimental modules (v:5.36) provide for a similar syntax for pass-by-reference which affects only the
subroutine itself. (\$a is an alias for caller's variable).
This experimental pragma is not used in heic.pl.
use experimental 'refaliasing', 'signatures' ;
my $Apple = "original data" ;
PolishApple ( $Apple ) ;
print "$Apple" ; # yields "new data"
sub PolishApple ( \$a )
{ $a = "new data" ; }
- Passing an array as a subroutine parameter:
Because most Perl variables are handled as arrays, even if the array contains only one element or one
scalar value, passing an array to a subroutine by reference is actually more straight-forward
than non-array parameters. In the example below, four subroutines are defined and called.
- FruitSaladA
is defined without named parameters, so any argument(s) passed to it
are referenced by the default array alias: @_. This is a pass-by-reference value,
so the subroutine can access each member of the caller's array using an indexing variable.
my $buff = @_[$indxA] ;
- FruitSaladB
is defined with one named parameter. By default, named parameters are pass-by-value.
To put it another way, it is a a copy of the caller's data.
In this example, however, a special syntax is used for the call: \@FruitBowl which indicates
a pass-by-reference value which is effectively a pointer to the caller's data. The called subroutine can then use it
as a pointer to the caller's array.
$buff = $fPtr->[$indxA] ;
- FruitSaladC and FruitSaladD. Unlike FruitSaladB
these subroutines receive not just a pointer to an array, but rather a pointer to an array of arrays. Note that
the call syntax is the same as for FruitSaladB, but the parameter is defined differently within the
subroutine itself.
The functionality of FruitSaladC and FruitSaladD is identical; however,
a different type of addressing is demonstrated for each:
— FruitSaladC addressess the data as an array embedded within another array (which it is).
my $buff = $fArray[0][$indxA] ;
— FruitSaladD assigns a pointer to the first embedded array for simpler access.
my $fPtr = @fArray[0] ;
my $buff = $fPtr->[$indxA] ;
Note that as an Easter Egg, the following
sequence is fully functional under subtest.pl -f ('F' is for Fruit)
my @FruitBowl = ( "Apple", "Orange", "Pear", "Peach", "Kumquat" ) ;
FruitSaladA ( @FruitBowl ) ;
FruitSaladB ( \@FruitBowl ) ;
FruitSaladC ( \@FruitBowl ) ;
FruitSaladD ( \@FruitBowl ) ;
# (anonymous pass-by-reference array parameter) #
sub FruitSaladA
{
my $itemCnt = scalar @_ ; # number of elements in array
my $indxA = $itemCnt - 1 ;
my $indxB = 0 ; # array item indices
my $buff ; # temp buffer
while ( $indxA > $indxB ) # Shuffle the elements.
{
$buff = @_[$indxA] ;
@_[$indxA] = @_[$indxB] ;
@_[$indxB] = $buff ;
$indxA-- ;
$indxB++ ;
}
} # FruitSaladA() #
# (named pass-by-reference array pointer) #
sub FruitSaladB ( $fPtr )
{
my $itemCnt = scalar @$fPtr ; # number of elements in array
my $indxA = $itemCnt - 1 ;
my $indxB = 0 ; # array item indices
my $buff ; # temp buffer
while ( $indxA > $indxB ) # Shuffle the elements.
{
$buff = $fPtr->[$indxA] ;
$fPtr->[$indxA] = $fPtr->[$indxB] ;
$fPtr->[$indxB] = $buff ;
$indxA-- ;
$indxB++ ;
}
} # FruitSaladB() #
# (named by-reference array of arrays) #
sub FruitSaladC ( @fArray )
{
my $itemCnt = @{$fArray[0]} ; # number of elements in array (note funky syntax)
my $indxA = $itemCnt - 1 ;
my $indxB = 0 ; # array item indices
my $buff ; # temp buffer
while ( $indxA > $indxB ) # Shuffle the elements.
{
$buff = $fArray[0][$indxA] ;
$fArray[0][$indxA] = $fArray[0][$indxB] ;
$fArray[0][$indxB] = $buff ;
$indxA-- ;
$indxB++ ;
}
} # FruitSaladC() #
# (named by-reference array of arrays) #
sub FruitSaladD ( @fArray )
{
my $fPtr = @fArray[0] ;
my $itemCnt = scalar @$fPtr ; # number of elements in array
my $indxA = $itemCnt - 1 ;
my $indxB = 0 ; # array item indices
my $buff ; # temp buffer
while ( $indxA > $indxB ) # Shuffle the elements.
{
$buff = $fPtr->[$indxA] ;
$fPtr->[$indxA] = $fPtr->[$indxB] ;
$fPtr->[$indxB] = $buff ;
$indxA-- ;
$indxB++ ;
}
} # FruitSaladD() #
Calling subroutines in Perl v6.0 "Raku" (Racoon?)
To date, the author has had no interest in exploring Racoon; which in our view, is
just another semi-useless scripting language, pretending to be a programming language.
If the author changes his mind, (which hasn't happened since the introduction of C++98),
we'll let you know.
HEIC Encoding and the ‘heif-dec’ image conversion utility:
High Efficiency Image Container encoding was developed by the Moving Picture Experts Group (MPEG),
ISO/IEC 23008-12. The first major player to adopt this encoding was Apple(tm) with iOS-11.
HEIC encoding (.heic extension) is now the default iPhone image format. It is technically efficient, but
at this time, we aren’t sure whether we want to pollute our Linux systems with this image format.
Fortunately, the 'heif-dec' utility converts a file from .heic format to one of the following formats:
JPEG: 'jpg', 'jpeg' - Joint Photographic Experts Group
TIFF: 'tif', 'tiff' - Tag Image File Format
'png' - Portable Network Graphics
'y4m' - YUV4MPEG2 (uncompressed)
Y4M is a lossless encoding used primarily for testing codecs.
(the output is huge!)
Each source image file contains a magic-number sequence in the header:
1) "ftypmif1" generic version of HEIC encoding.
2) "ftypheic" indicates the specific codec used for encoding.
3) "ftypheix" indicates a "compatible" codec used for encoding
The
'heif-dec' utility is distributed as part of the
'libheif-tools' package.
(Copyright © 2017 struktur AG)
The libheif package is available on GitHub or through RPM Fusion. If your system is not yet set up for 'rpmfusion',
first enable it, then:
sudo dnf install libheif-tools libheif-freeworld
or
sudo apt update && sudo apt install libheif-examples
- The "documentation" for 'heif-dec' can be accessed as:
info heif-dec
This single-page document can claim to be documentation ONLY because the info reader
can read it, and not because it actually documents anything.
- The command-line help indicates support for the above target image formats; however,
the documentation does not include any mention of the 'tif/tiff' encoding, presumably
because the document has not been updated since 2017.
- The 'heif-convert' utility is a legacy version of the same tool, but is deprecated
in newer environments. It appears that 'heif-convert' is now simply a backward-compatibility symlink to
'heif-dec'.
- The likely reason that the utility is so simple is that the algorithm is intended primarily for integration into other
tools, and that the stand-alone version is simply a reference model. (The authors may dispute this evaluation.)
- Note that 'heif-dec' will silently overwrite existing targets; however, the
'heic.pl' utility does not allow such amateur-hour functionality.
- The 'heif-dec' utility ignores the case of the specified encoding, and always writes the target filename extension
in lowercase.
- Note that 'heif-dec' offers several command-line options for image tweaking.
The heic.pl demonstration program ignores these options because implementing them would tend to obscure
the primary value of this example code, which is to describe the various ways in which Perl subroutines
can be constructed and called.