Plugins¶
How to use plugins¶
Plugins must be specified with the plugins
setting:
plugins = ['sigal.plugins.adjust', 'sigal.plugins.copyright']
You can either specify the name of the module which contains the plugin, or import the plugin before adding it to the list:
from sigal.plugins import copyright
plugins = ['sigal.plugins.adjust', copyright]
Note
Using an import like this will break the multiprocessing feature, because the settings dict must be serializable. So in most cases you should prefer the first option.
The plugin_paths
setting can be used to specify paths to search for plugins
(if they are not in the python path).
Write a new plugin¶
Plugins are based on signals with the blinker library. A plugin must subscribe to a signal (the list is given below). New signals can be added if need. See an example with the copyright plugin:
"""Plugin which add a copyright to the image.
Settings:
- ``copyright``: the copyright text.
- ``copyright_text_font``: the copyright text font - either system/user
font-name or absolute path to font.ttf file. If no font is specified, or
specified font is not found, the default font is used.
- ``copyright_text_font_size``: the copyright text font-size. If no font is
specified, this setting is ignored.
- ``copyright_text_color``: the copyright text color in a tuple (R, G, B)
with decimal RGB code, e.g. ``(255, 255, 255)`` is white.
- ``copyright_text_position``: the copyright text position in 2 tuple (left,
top). By default text would be positioned at bottom-left corner.
"""
import logging
from PIL import ImageDraw, ImageFont
from sigal import signals
logger = logging.getLogger(__name__)
def add_copyright(img, settings=None):
logger.debug("Adding copyright to %r", img)
draw = ImageDraw.Draw(img)
text = settings["copyright"]
font = settings.get("copyright_text_font", None)
font_size = settings.get("copyright_text_font_size", 10)
assert font_size >= 0
color = settings.get("copyright_text_color", (0, 0, 0))
bottom_margin = 3 # bottom margin for text
text_height = bottom_margin + 12 # default text height (of 15)
if font:
try:
font = ImageFont.truetype(font, font_size)
text_height = font.getsize(text)[1] + bottom_margin
except Exception: # load default font in case of any exception
logger.debug("Exception: Couldn't locate font %s, using default font", font)
font = ImageFont.load_default()
else:
font = ImageFont.load_default()
left, top = settings.get("copyright_text_position", (5, img.size[1] - text_height))
draw.text((left, top), text, fill=color, font=font)
return img
def register(settings):
if settings.get("copyright"):
signals.img_resized.connect(add_copyright)
else:
logger.warning("Copyright text is not set")
Signals¶
- sigal.signals.album_initialized(album)
Called after the
Album
is initialized.- Parameters:
album – the
Album
object.
- sigal.signals.gallery_initialized(gallery)
Called after the gallery is initialized.
- Parameters:
gallery – the
Gallery
object.
- sigal.signals.media_initialized(media)
Called after the
Media
(Image
orVideo
) is initialized.- Parameters:
media – the media object.
- sigal.signals.gallery_build(gallery)
Called after the gallery is build (after media are resized and html files are written).
- Parameters:
gallery – the
Gallery
object.
- sigal.signals.img_resized(img, settings=settings)
Called after the image is resized. This signal work differently, the modified image object must be returned by the registered function.
- Parameters:
img – the PIL image object.
settings – the settings dict.
List of plugins¶
Adjust plugin¶
Plugin which adjust the image after resizing.
Based on pilkit’s Adjust processor.
Settings:
adjust_options = {
'color': 1.0,
'brightness': 1.0,
'contrast': 1.0,
'sharpness': 1.0
}
Compress assets plugin¶
Plugin to compress static files for faster HTTP transfer.
Your web server must be configured in order to select pre-compressed files instead of the required one, to save CPU. For example, in nginx:
server {
gzip_static;
}
Currently, 3 methods are supported:
gzip
: No dependency required. This is the fastest, but also largest output.zopfli
: Requires zopfli. gzip compatible output with optimized size.brotli
: Requires brotli. Brotli is the best compressor for web usage.
Settings available as dictionary in compress_assets_options
:
method
: One ofgzip
,zopfli
orbrotli
.suffixes
: List of file suffixes eligible to compression. Default to['htm', 'html', 'css', 'js', 'svg']
Copyright plugin¶
Plugin which add a copyright to the image.
Settings:
copyright
: the copyright text.copyright_text_font
: the copyright text font - either system/user font-name or absolute path to font.ttf file. If no font is specified, or specified font is not found, the default font is used.copyright_text_font_size
: the copyright text font-size. If no font is specified, this setting is ignored.copyright_text_color
: the copyright text color in a tuple (R, G, B) with decimal RGB code, e.g.(255, 255, 255)
is white.copyright_text_position
: the copyright text position in 2 tuple (left, top). By default text would be positioned at bottom-left corner.
Encrypt plugin¶
Plugin to protect gallery by encrypting image files using a password.
Options:
encrypt_options = {
'password': 'password',
'ask_password': False,
'gcm_tag': 'randomly_generated',
'kdf_salt': 'randomly_generated',
'kdf_iters': 10000,
}
password
: The password used to encrypt the images on gallery build, and decrypt them when viewers access the gallery. No default value. You must specify a password.ask_password
: Whether or not viewers are asked for the password to view the gallery. If set toFalse
, the password will be present in the HTML files so the images are decrypted automatically. Defaults toFalse
.gcm_tag
,kdf_salt
,kdf_iters
: Cryptographic parameters used when encrypting the files.gcm_tag
,kdf_salt
are meant to be randomly generated,kdf_iters
defaults to 10000. Do not specify them in the config file unless you have good reasons to do so.
Note: The plugin caches the cryptographic parameters (but not the password) after the first build, so that incremental builds can share the same credentials. DO NOT CHANGE THE PASSWORD OR OTHER CRYPTOGRAPHIC PARAMETERS ONCE A GALLERY IS BUILT, or there will be inconsistency in encrypted files and viewers will not be able to see some of the images any more.
Compatibility with other plugins:
zip_gallery
: if you enable both this plugin and thezip_gallery
plugin, the generated zip archives will contain encrypted images, which is generally meaningless since viewers cannot easily decrypt them outside a browser.
Extended caching plugin¶
Decreases the time needed to build large galleries (e.g.: 25k images in 2.5s instead of 30s)
This plugin allows extended caching, which is useful for large galleries. Once a gallery has been built it caches all metadata for all media (markdown, exif, itpc) in the gallery target folder. Before the next run it restores them so that the image and metadata files do not have to be parsed again. For large galleries this can speed up the creation of index files dramatically.
Feeds plugin¶
Plugin which add RSS/ATOM feeds.
This plugin requires feedgenerator. It uses all the images and videos of the gallery, sorted by date, to show the most recent ones.
Settings:
rss_feed
andatom_feed
, see below.
Example:
rss_feed = {'feed_url': 'http://example.org/feed.rss', 'nb_items': 10}
atom_feed = {'feed_url': 'http://example.org/feed.atom', 'nb_items': 10}
Media page plugin¶
Plugin which generates HTML pages for each image.
Currently this plugin can be used only with the colorbox theme, the other themes have to be adapted.
For themes, the previous_media
and next_media
variables contain the
previous/next Media
objects.
Nomedia plugin¶
This plugin offers more fine-grained control over exluded images and folders, similarly to how it’s handled on Android.
To ignore a folder or image put a .nomedia
file next to it in its parent
folder and put its name into the file. E.g.:
content of folder:
IMG_3425.JPG, IMG_2426.JPG, IMG_2427.JPG, subfolder, .nomedia
content of .nomedia:
IMG_2426.JPG
IMG_2427.JPG
subfolder
will ignore all images but IMG_3425.JPG and the subfolder.
Alternatively, if you put a .nomedia
file into a folder and leave it blank
(i.e. an empty file called .nomedia
in a folder containing images), this
ignores the whole folder it’s located in (like on Android).
WARNING: When you have a pre-existing gallery from a previous run of sigal
adding a new .nomedia
file will not remove the newly ignored images/albums
from the existing gallery (only the entries in the parent gallery pointing to
it). They might still be reachable thereafter. Either remove the whole gallery
to be sure or remove the ignored files/folders inside the gallery to remove
them for good.
Non-media Files plugin¶
Plugin to index non-media files.
This plugin will copy the files into the build tree and generate generic thumbnails for the files. In-browser previews will likely fail, and it is up to the theme to provide correct support for downloads.
Settings available as dictionary in nonmedia_files_options
:
ext_as_thumb
: Enable simple thumbnail showing ext. Default toTrue
ignore_ext
: List of file extensions to ignore. Default to[".md"]
thumb_bg_color
: Background color for thumbnail. Accepts (r, g, b) tuple. Default to white(255, 255, 255)
.thumb_font
: Name or path to font file. Default toNone
to use the PIL built-in font.thumb_font_color
: Font color for thumbnail. Accepts (r, g, b) tuple. Default to black(0, 0, 0)
.thumb_font_size
: Font size for thumbnail. Must select a font to apply. Default to40
.
Note
Thumbnails are generated using the file extension text on a
background color. It is highly recommended to select a font
(such as "FreeMono.ttf"
), since the default PIL font does not
respect font size.
Watermark plugin¶
Plugin which adds a watermark to the image.
Based on http://code.activestate.com/recipes/362879-watermark-with-pil/ (Licensed under the PSF License).
Settings:
watermark
: path to the watermark image.watermark_position
: the watermark position either ‘scale’ or ‘tile’ or a 2-tuple giving the upper left corner, or a 4-tuple defining the left, upper, right, and lower pixel coordinate, or None (same as (0, 0)). If a 4-tuple is given, the size of the pasted image must match the size of the region.watermark_opacity
: the watermark opacity (0.0 to 1.0).
ZIP Gallery plugin¶
This plugin controls the generation of a ZIP archive for a gallery
If the zip_gallery
setting is set, it contains the location of a zip
archive with all original images of the corresponding directory.
To ignore a ZIP gallery generation for a particular album, put
a .nozip_gallery
file next to it in its parent folder. Only the existence
of this .nozip_gallery
file is tested. If no .nozip_gallery
file is
present, then make a ZIP archive with all media files.
Titleregexp plugin¶
This plugin modifies titles of galleries by using regular-expressions and simple string or character replacements. It is acting in two phases: First, all regular-expression-based modifications are carried out, second, string/character replacements are done.
The first phase may be interrupted if a match occurs by the ‘break’-setting individually per regular-expression part. Additionally, if a match occurs, string/character replacements may be added.
The second phase is done even if the first phase had been interrupted.
Settings:
titleregexp
with the following keys:regexp
, which is an array of dicts with ‘search’, ‘replace’, ‘break’ ‘substitute’ and ‘count’ keys. All but ‘break’ and ‘substitute’ are the arguments forre.subn
, without given ‘count’ all matches are replaced. If ‘break’ is anything but an empty string, the rest of theregexp
-array is being skipped. The ‘substitute’-key contains an array following thesubstitute
format explained in the next sentence and does string-replacement if the regular-expression matched.substitute
, which is an array of 2-element-arrays, of which the occurences of the first element will be replaced by the second element by thereplace
-method of strings.
Example:
titleregexp = {
'regexp' : [
{ 'search': r"^([0-9]*)-(.*)$", 'replace': r"\2 (\1)", 'count': 1,
'break': 1, substitute: [ ['ae','ä'] ] },
{ 'search': r"([a-z][a-z])([A-Z][a-z])", 'replace': r"\1 \2" }
],
'substitute' : [ [ '_', ' ' ] ]
}