Static web gallery generator
Project description
Mikula
Static image gallery generator inspired by Jekyll and JAlbum. Mikula is written in Python and supports uploads to AWS S3.
Motivation
I used JAlbum some time ago. With enough tweaking to the themes it produced acceptable results but I always wanted more flexibility in designing my albums. Jekyll inspired me to create my own gallery generator in Python, so here it is, welcome Mikula.
Name
Mikula is a Ukrainian version of name Nicholas.
Installation
Python
You will need Python version 3.8 or above to run Mikula. If you don't have Python 3.8 installed on your system follow the instructions on python.org.
Pip
Pip
is python package manager. Check that you have the correct version installed by running:
pip --version
You should see pip version number and python path with (python 3.8)
or higher at the end.
If you see a different version number or get command not found
install pip:
python3.8 -m pip install pip
You might also want to upgrade pip to the latest version:
python3.8 -m pip install --upgrade pip
Install Mikula with pip
With pip set up, install Mikula
pip install mikula
If you don't have administrator's privileges or don't want to install it globally, run the following command:
pip install --user mikula
When updating from a previous version:
pip install --upgrade mikula
Check your installation:
mikula --version
Getting Started with Mikula
Create a directory for your new gallery
Mikula is a command-line tool, so fire up your favourite Terminal program. Create a directory for your new gallery. For example:
mkdir ~/mikula-gallery
or
mkdir ~/Desktop/mikula-gallery
Navigate into this directory:
cd ~/mikula-gallery
or
cd ~/Desktop/mikula-gallery
Initialise Mikula
When you run
mikula init
it will create a stub gallery consisting of one album, including one picture and three pages: Home, About and Contact.
Put your source files (images and text) into the source
directory. Create a subdirectory for each album in the gallery.
When you build your gallery it will be saved in the build
directory. You can use Mikula to deploy it to AWS S3 bucket
(provided you have an AWS account with sufficient priviligies) or upload it manually to your web server.
Configure AWS credentials
If you choose to use AWS S3 to host your gallery, provide Mikula with your AWS credentials by running this command:
mikula configure
This step is optional if you use a different hosting method.
Build the gallery
Run
mikula build
to generate your gallery in the build
directory.
Try it
You can test the results by running a local web server:
mikula serve
You gallery should be available on http://localhost:5000 Optionally, you can specify a different port number, for example:
mikula serve --port 1234
will run the server on http://localhost:1234
Deployment
Run
mikula deploy --bucket <bucket-name> --region <AWS-region>
to deploy the website on AWS S3.
Alternatively, copy the content of the build
directory to your web server. For example:
scp -rp build user@example.com:/www/
will copy all the files and subdirectories from build
into /www/
on your server.
Theme Customisation
Mikula themes can be customised. To create a new theme based on an existing one use the following command:
mikula customise --theme <my-awesome-theme> --prototype <default> --destination <theme-directory>
This will copy the prototype theme in the specified destination directory.
The custom theme can be used with the build
command:
mikula build --theme <my-awesome-theme>
Markdown metadata
You can add metadata in the beginning of your Markdown file. The metadata block starts and finishes with a line containing three dashes:
---
title: Funny cat's images
---
# Images of cats
This page contains a collection of amusing feline pictures.
The following metadata fields are recognised by Mikula:
Field | Value | Description |
---|---|---|
page_title | string | Page title displayed by the browser |
title | string | Album or image title displayed on the parent page |
thumbnail | file path | Name of the file to be used as an album thumbnail |
exclude_thumbnail | {true, false} | Set to true to exclude album thumbnail from the gallery. Default is true |
place_before | {true, false} | Set to place the text before the image(s). Default is false. |
exif | list | Extract information from EXIF data. See below for a list of supported tags. |
show_exif | {true, false} | Set to true to show minimal EXIF data below the image. |
You can also define your own fields and use them in the document.
Using metadata
Here is an example of how you can include metadata in your markdown document. Suppose you have an image file sunflowers.jpg
which is taken with Canon EOS 450D and has the EXIF data embedded in the image file. If we now create a markdown file
sunflowers.md
with the following content:
---
page_title: Garden - Sunflowers
title: Sunflowers
place_before: false
exif:
- Model
- DateTime
- ISOSpeedRatings
- ShutterSpeedValue
- FNumber
---
# {{title}}
Picture of sunflowers taken on {{exif["DateTime"]}} in my garden with {{exif["Make"]}} {{exif["Model"]}}.
ISO speed {{exif["ISOSpeedRatings"]}}, shutter speed {{exif["ShutterSpeedValue"]}} at f{{exif["FNumber"]}}.
the page rendered by Mikula will include the image followed by the text:
Sunflowers
Picture of sunflowers taken on 2018:05:13 10:13:46 in my garden with Canon EOS 450D.
ISO speed 100, shutter speed 1/500 at f1.4.
Supported EXIF tags
The following EXIF Tags are supported:
Tag ID | Tag Name |
---|---|
0X000B | ProcessingSoftware |
0X00FE | NewSubfileType |
0X00FF | SubfileType |
0X0100 | ImageWidth |
0X0101 | ImageLength |
0X0102 | BitsPerSample |
0X0103 | Compression |
0X0106 | PhotometricInterpretation |
0X0107 | Thresholding |
0X0108 | CellWidth |
0X0109 | CellLength |
0X010A | FillOrder |
0X010D | DocumentName |
0X010E | ImageDescription |
0X010F | Make |
0X0110 | Model |
0X0111 | StripOffsets |
0X0112 | Orientation |
0X0115 | SamplesPerPixel |
0X0116 | RowsPerStrip |
0X0117 | StripByteCounts |
0X0118 | MinSampleValue |
0X0119 | MaxSampleValue |
0X011A | XResolution |
0X011B | YResolution |
0X011C | PlanarConfiguration |
0X011D | PageName |
0X0120 | FreeOffsets |
0X0121 | FreeByteCounts |
0X0122 | GrayResponseUnit |
0X0123 | GrayResponseCurve |
0X0124 | T4Options |
0X0125 | T6Options |
0X0128 | ResolutionUnit |
0X0129 | PageNumber |
0X012D | TransferFunction |
0X0131 | Software |
0X0132 | DateTime |
0X013B | Artist |
0X013C | HostComputer |
0X013D | Predictor |
0X013E | WhitePoint |
0X013F | PrimaryChromaticities |
0X0140 | ColorMap |
0X0141 | HalftoneHints |
0X0142 | TileWidth |
0X0143 | TileLength |
0X0144 | TileOffsets |
0X0145 | TileByteCounts |
0X014A | SubIFDs |
0X014C | InkSet |
0X014D | InkNames |
0X014E | NumberOfInks |
0X0150 | DotRange |
0X0151 | TargetPrinter |
0X0152 | ExtraSamples |
0X0153 | SampleFormat |
0X0154 | SMinSampleValue |
0X0155 | SMaxSampleValue |
0X0156 | TransferRange |
0X0157 | ClipPath |
0X0158 | XClipPathUnits |
0X0159 | YClipPathUnits |
0X015A | Indexed |
0X015B | JPEGTables |
0X015F | OPIProxy |
0X0200 | JPEGProc |
0X0201 | JpegIFOffset |
0X0202 | JpegIFByteCount |
0X0203 | JpegRestartInterval |
0X0205 | JpegLosslessPredictors |
0X0206 | JpegPointTransforms |
0X0207 | JpegQTables |
0X0208 | JpegDCTables |
0X0209 | JpegACTables |
0X0211 | YCbCrCoefficients |
0X0212 | YCbCrSubSampling |
0X0213 | YCbCrPositioning |
0X0214 | ReferenceBlackWhite |
0X02BC | XMLPacket |
0X1000 | RelatedImageFileFormat |
0X1001 | RelatedImageWidth |
0X1002 | RelatedImageLength |
0X4746 | Rating |
0X4749 | RatingPercent |
0X800D | ImageID |
0X828D | CFARepeatPatternDim |
0X828E | CFAPattern |
0X828F | BatteryLevel |
0X8298 | Copyright |
0X829A | ExposureTime |
0X829D | FNumber |
0X83BB | IPTCNAA |
0X8649 | ImageResources |
0X8769 | ExifOffset |
0X8773 | InterColorProfile |
0X8822 | ExposureProgram |
0X8824 | SpectralSensitivity |
0X8825 | GPSInfo |
0X8827 | ISOSpeedRatings |
0X8828 | OECF |
0X8829 | Interlace |
0X882A | TimeZoneOffset |
0X882B | SelfTimerMode |
0X9000 | ExifVersion |
0X9003 | DateTimeOriginal |
0X9004 | DateTimeDigitized |
0X9101 | ComponentsConfiguration |
0X9102 | CompressedBitsPerPixel |
0X9201 | ShutterSpeedValue |
0X9202 | ApertureValue |
0X9203 | BrightnessValue |
0X9204 | ExposureBiasValue |
0X9205 | MaxApertureValue |
0X9206 | SubjectDistance |
0X9207 | MeteringMode |
0X9208 | LightSource |
0X9209 | Flash |
0X920A | FocalLength |
0X920B | FlashEnergy |
0X920C | SpatialFrequencyResponse |
0X920D | Noise |
0X9211 | ImageNumber |
0X9212 | SecurityClassification |
0X9213 | ImageHistory |
0X9214 | SubjectLocation |
0X9215 | ExposureIndex |
0X9216 | TIFF/EPStandardID |
0X927C | MakerNote |
0X9286 | UserComment |
0X9290 | SubsecTime |
0X9291 | SubsecTimeOriginal |
0X9292 | SubsecTimeDigitized |
0X9C9B | XPTitle |
0X9C9C | XPComment |
0X9C9D | XPAuthor |
0X9C9E | XPKeywords |
0X9C9F | XPSubject |
0XA000 | FlashPixVersion |
0XA001 | ColorSpace |
0XA002 | ExifImageWidth |
0XA003 | ExifImageHeight |
0XA004 | RelatedSoundFile |
0XA005 | ExifInteroperabilityOffset |
0XA20B | FlashEnergy |
0XA20C | SpatialFrequencyResponse |
0XA20E | FocalPlaneXResolution |
0XA20F | FocalPlaneYResolution |
0XA210 | FocalPlaneResolutionUnit |
0XA214 | SubjectLocation |
0XA215 | ExposureIndex |
0XA217 | SensingMethod |
0XA300 | FileSource |
0XA301 | SceneType |
0XA302 | CFAPattern |
0XA401 | CustomRendered |
0XA402 | ExposureMode |
0XA403 | WhiteBalance |
0XA404 | DigitalZoomRatio |
0XA405 | FocalLengthIn35mmFilm |
0XA406 | SceneCaptureType |
0XA407 | GainControl |
0XA408 | Contrast |
0XA409 | Saturation |
0XA40A | Sharpness |
0XA40B | DeviceSettingDescription |
0XA40C | SubjectDistanceRange |
0XA420 | ImageUniqueID |
0XA430 | CameraOwnerName |
0XA431 | BodySerialNumber |
0XA432 | LensSpecification |
0XA433 | LensMake |
0XA434 | LensModel |
0XA435 | LensSerialNumber |
0XA500 | Gamma |
0XC4A5 | PrintImageMatching |
0XC612 | DNGVersion |
0XC613 | DNGBackwardVersion |
0XC614 | UniqueCameraModel |
0XC615 | LocalizedCameraModel |
0XC616 | CFAPlaneColor |
0XC617 | CFALayout |
0XC618 | LinearizationTable |
0XC619 | BlackLevelRepeatDim |
0XC61A | BlackLevel |
0XC61B | BlackLevelDeltaH |
0XC61C | BlackLevelDeltaV |
0XC61D | WhiteLevel |
0XC61E | DefaultScale |
0XC61F | DefaultCropOrigin |
0XC620 | DefaultCropSize |
0XC621 | ColorMatrix1 |
0XC622 | ColorMatrix2 |
0XC623 | CameraCalibration1 |
0XC624 | CameraCalibration2 |
0XC625 | ReductionMatrix1 |
0XC626 | ReductionMatrix2 |
0XC627 | AnalogBalance |
0XC628 | AsShotNeutral |
0XC629 | AsShotWhiteXY |
0XC62A | BaselineExposure |
0XC62B | BaselineNoise |
0XC62C | BaselineSharpness |
0XC62D | BayerGreenSplit |
0XC62E | LinearResponseLimit |
0XC62F | CameraSerialNumber |
0XC630 | LensInfo |
0XC631 | ChromaBlurRadius |
0XC632 | AntiAliasStrength |
0XC633 | ShadowScale |
0XC634 | DNGPrivateData |
0XC635 | MakerNoteSafety |
0XC65A | CalibrationIlluminant1 |
0XC65B | CalibrationIlluminant2 |
0XC65C | BestQualityScale |
0XC65D | RawDataUniqueID |
0XC68B | OriginalRawFileName |
0XC68C | OriginalRawFileData |
0XC68D | ActiveArea |
0XC68E | MaskedAreas |
0XC68F | AsShotICCProfile |
0XC690 | AsShotPreProfileMatrix |
0XC691 | CurrentICCProfile |
0XC692 | CurrentPreProfileMatrix |
0XC6BF | ColorimetricReference |
0XC6F3 | CameraCalibrationSignature |
0XC6F4 | ProfileCalibrationSignature |
0XC6F6 | AsShotProfileName |
0XC6F7 | NoiseReductionApplied |
0XC6F8 | ProfileName |
0XC6F9 | ProfileHueSatMapDims |
0XC6FA | ProfileHueSatMapData1 |
0XC6FB | ProfileHueSatMapData2 |
0XC6FC | ProfileToneCurve |
0XC6FD | ProfileEmbedPolicy |
0XC6FE | ProfileCopyright |
0XC714 | ForwardMatrix1 |
0XC715 | ForwardMatrix2 |
0XC716 | PreviewApplicationName |
0XC717 | PreviewApplicationVersion |
0XC718 | PreviewSettingsName |
0XC719 | PreviewSettingsDigest |
0XC71A | PreviewColorSpace |
0XC71B | PreviewDateTime |
0XC71C | RawImageDigest |
0XC71D | OriginalRawFileDigest |
0XC71E | SubTileBlockSize |
0XC71F | RowInterleaveFactor |
0XC725 | ProfileLookTableDims |
0XC726 | ProfileLookTableData |
0XC740 | OpcodeList1 |
0XC741 | OpcodeList2 |
0XC74E | OpcodeList3 |
0XC761 | NoiseProfile |
Not all of these tags will be available in the EXIF created by your camera or scanner.
Installing from source
Get the source
Clone the project repository from GitHub:
git clone https://github.com/RomanKosobrodov/mikula.git
Install dependencies
You will need development requirements:
pip install -r requirements-dev.txt
As usual, it is a good idea to use a virtual environment.
Run Mikula
To run the package installed from source use the following command:
python -m mikula <command> <options>
Where <command>
is one of init
, configure
, build
, serve
or deploy
, and <options>
are
command arguments. Run
python -m mikula -h
to get a list of all supported commands and arguments.
Package and upload to PyPI
Run setup.py
to build the package and twine
to upload it to PyPI:
rm dist/*
rm -rf build/*
python3.8 setup.py sdist bdist_wheel
twine upload dist/*
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.