Metadata-Version: 2.4
Name: fotolab
Version: 0.39.2
Summary: A console program to manipulate photos.
Author-email: Kian-Meng Ang <kianmeng@cpan.org>
License-Expression: AGPL-3.0-or-later
Project-URL: Changelog, https://github.com/kianmeng/fotolab/blob/master/CHANGELOG.md
Project-URL: Issues, https://github.com/kianmeng/fotolab/issues
Project-URL: Source, https://github.com/kianmeng/fotolab
Keywords: photography,photo
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE.md
Requires-Dist: pillow
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Requires-Dist: pytest-randomly; extra == "test"
Requires-Dist: pytest-xdist; extra == "test"
Requires-Dist: scripttest; extra == "test"
Provides-Extra: doc
Requires-Dist: myst-parser; extra == "doc"
Requires-Dist: sphinx; extra == "doc"
Requires-Dist: sphinx-autodoc-typehints; extra == "doc"
Requires-Dist: sphinx-copybutton; extra == "doc"
Requires-Dist: furo; extra == "doc"
Provides-Extra: lint
Requires-Dist: pre-commit; extra == "lint"
Requires-Dist: ruff; extra == "lint"
Requires-Dist: mypy; extra == "lint"
Dynamic: license-file

# fotolab

A console program to manipulate photos.

## Installation

Stable version From PyPI using `uv`:

```console
uv tool install fotolab
```

Upgrade to latest stable version:

```console
uv tool upgrade fotolab
```

## Usage

```console
fotolab -h
```

<!--help !-->

```console
usage: fotolab [-h] [-o] [-q] [-v] [-d] [-V]
               {animate,auto,border,bw,contrast,crop,env,halftone,info,montage,resize,rotate,sharpen,watermark} ...

A console program to manipulate photos.

website: https://github.com/kianmeng/fotolab
changelog: https://github.com/kianmeng/fotolab/blob/master/CHANGELOG.md
issues: https://github.com/kianmeng/fotolab/issues

positional arguments:
  {animate,auto,border,bw,contrast,crop,env,halftone,info,montage,resize,rotate,sharpen,watermark}
                    sub-command help
    animate         animate an image
    auto            auto adjust (resize, contrast, and watermark) a photo
    border          add border to image
    bw              apply a black and white filter effect to an image
    contrast        contrast an image.
    crop            crop an image
    env             print environment information for bug reporting
    halftone        halftone an image
    info            info an image
    montage         montage a list of image
    resize          resize an image
    rotate          rotate an image
    sharpen         sharpen an image
    watermark       watermark an image

options:
  -h, --help        show this help message and exit
  -o, --overwrite   overwrite existing image
  -q, --quiet       suppress all logging
  -v, --verbose     show verbosity of debugging log, use -vv, -vvv for more details
  -d, --debug       show debugging log and stacktrace
  -V, --version     show program's version number and exit
```

<!--help !-->

### fotolab animate

```console
fotolab animate -h
```

<!--help-animate !-->

```console
usage: fotolab animate [-h] [-op] [-od OUTPUT_DIR] [-of OUTPUT_FILENAME]
                       [-f FORMAT] [-d DURATION] [-l LOOP]
                       [--webp-quality QUALITY] [--webp-lossless]
                       [--webp-method METHOD]
                       IMAGE_PATHS [IMAGE_PATHS ...]

positional arguments:
  IMAGE_PATHS           set the image filenames

options:
  -h, --help            show this help message and exit
  -op, --open           open the image using default program (default:
                        'False')
  -od, --output-dir OUTPUT_DIR
                        set default output folder (default: 'output')
  -of, --output-filename OUTPUT_FILENAME
                        set output filename (default: 'None')
  -f, --format FORMAT   set the image format (default: 'gif')
  -d, --duration DURATION
                        set the duration in milliseconds (must be a positive
                        integer, default: '2500')
  -l, --loop LOOP       set the loop cycle (default: '0')
  --webp-quality QUALITY
                        set WEBP quality (0-100, default: '80')
  --webp-lossless       enable WEBP lossless compression (default: 'False')
  --webp-method METHOD  set WEBP encoding method (0=fast, 6=slow/best,
                        default: '4')
```

<!--help-animate !-->

### fotolab auto

```console
fotolab auto -h
```

<!--help-auto !-->

```console
usage: fotolab auto [-h] [-op] [-od OUTPUT_DIR] [-of OUTPUT_FILENAME]
                    [-t TITLE] [-w WATERMARK_TEXT]
                    IMAGE_PATHS [IMAGE_PATHS ...]

positional arguments:
  IMAGE_PATHS           set the image filenames

options:
  -h, --help            show this help message and exit
  -op, --open           open the image using default program (default:
                        'False')
  -od, --output-dir OUTPUT_DIR
                        set default output folder (default: 'output')
  -of, --output-filename OUTPUT_FILENAME
                        set output filename (default: 'None')
  -t, --title TITLE     set the tile (default: 'None')
  -w, --watermark WATERMARK_TEXT
                        set the watermark (default: 'kianmeng.org')
```

<!--help-auto !-->

### fotolab border

```console
fotolab border -h
```

<!--help-border !-->

```console
usage: fotolab border [-h] [-op] [-od OUTPUT_DIR] [-of OUTPUT_FILENAME]
                      [-c COLOR] [-w WIDTH] [-wt WIDTH] [-wr WIDTH]
                      [-wb WIDTH] [-wl WIDTH]
                      IMAGE_PATHS [IMAGE_PATHS ...]

positional arguments:
  IMAGE_PATHS           set the image filenames

options:
  -h, --help            show this help message and exit
  -op, --open           open the image using default program (default:
                        'False')
  -od, --output-dir OUTPUT_DIR
                        set default output folder (default: 'output')
  -of, --output-filename OUTPUT_FILENAME
                        set output filename (default: 'None')
  -c, --color COLOR     set the color of border (default: 'black')
  -w, --width WIDTH     set the width of border in pixels (default: '10')
  -wt, --width-top WIDTH
                        set the width of top border in pixels (default: '0')
  -wr, --width-right WIDTH
                        set the width of right border in pixels (default: '0')
  -wb, --width-bottom WIDTH
                        set the width of bottom border in pixels (default:
                        '0')
  -wl, --width-left WIDTH
                        set the width of left border in pixels (default: '0')
```

<!--help-border !-->

### fotolab bw

```console
fotolab bw -h
```

<!--help-bw !-->

```console
usage: fotolab crop [-h] [-op] [-od OUTPUT_DIR] [-of OUTPUT_FILENAME] -b BOX
                    IMAGE_PATHS [IMAGE_PATHS ...]

positional arguments:
  IMAGE_PATHS           set the image filenames

options:
  -h, --help            show this help message and exit
  -op, --open           open the image using default program (default:
                        'False')
  -od, --output-dir OUTPUT_DIR
                        set default output folder (default: 'output')
  -of, --output-filename OUTPUT_FILENAME
                        set output filename (default: 'None')
  -b, --box BOX         set the crop area as a 4-tuple (left, upper, right,
                        lower), e.g., '100,100,500,500'
```

<!--help-bw !-->

### fotolab contrast

```console
fotolab contrast -h
```

<!--help-contrast !-->

```console
usage: fotolab contrast [-h] [-op] [-od OUTPUT_DIR] [-of OUTPUT_FILENAME]
                        [-c CUTOFF]
                        IMAGE_PATHS [IMAGE_PATHS ...]

positional arguments:
  IMAGE_PATHS           set the image filenames

options:
  -h, --help            show this help message and exit
  -op, --open           open the image using default program (default:
                        'False')
  -od, --output-dir OUTPUT_DIR
                        set default output folder (default: 'output')
  -of, --output-filename OUTPUT_FILENAME
                        set output filename (default: 'None')
  -c, --cutoff CUTOFF   set the percentage (0-50) of lightest or darkest
                        pixels to discard from histogram (default: '1.0')
```

<!--help-contrast !-->

### fotolab crop

```console
fotolab crop -h
```

<!--help-crop !-->

```console
usage: fotolab crop [-h] [-op] [-od OUTPUT_DIR] [-of OUTPUT_FILENAME] -b BOX
                    IMAGE_PATHS [IMAGE_PATHS ...]

positional arguments:
  IMAGE_PATHS           set the image filenames

options:
  -h, --help            show this help message and exit
  -op, --open           open the image using default program (default:
                        'False')
  -od, --output-dir OUTPUT_DIR
                        set default output folder (default: 'output')
  -of, --output-filename OUTPUT_FILENAME
                        set output filename (default: 'None')
  -b, --box BOX         set the crop area as a 4-tuple (left, upper, right,
                        lower), e.g., '100,100,500,500'
```

<!--help-crop !-->

### fotolab halftone

```console
fotolab halftone -h
```

<!--help-halftone !-->

```console
usage: fotolab halftone [-h] [-op] [-od OUTPUT_DIR] [-of OUTPUT_FILENAME]
                        [-ba] [-c CELLS] [-g]
                        IMAGE_PATHS [IMAGE_PATHS ...]

positional arguments:
  IMAGE_PATHS           set the image filenames

options:
  -h, --help            show this help message and exit
  -op, --open           open the image using default program (default:
                        'False')
  -od, --output-dir OUTPUT_DIR
                        set default output folder (default: 'output')
  -of, --output-filename OUTPUT_FILENAME
                        set output filename (default: 'None')
  -ba, --before-after   generate a GIF showing before and after changes
  -c, --cells CELLS     set number of cells across the image width (default:
                        50)
  -g, --grayscale       convert image to grayscale before applying halftone
```

<!--help-halftone !-->

### fotolab info

```console
fotolab info -h
```

<!--help-info !-->

```console
usage: fotolab info [-h] [-s] [--camera] [--datetime] IMAGE_FILENAME

positional arguments:
  IMAGE_FILENAME  set the image filename

options:
  -h, --help      show this help message and exit
  -s, --sort      show image info by sorted field name
  --camera        show the camera maker details
  --datetime      show the datetime
```

<!--help-info !-->

### fotolab rotate

```console
fotolab rotate -h
```

<!--help-rotate !-->

```console
usage: fotolab rotate [-h] [-op] [-od OUTPUT_DIR] [-of OUTPUT_FILENAME]
                      [-r ROTATION] [-cw]
                      IMAGE_PATHS [IMAGE_PATHS ...]

positional arguments:
  IMAGE_PATHS           set the image filenames

options:
  -h, --help            show this help message and exit
  -op, --open           open the image using default program (default:
                        'False')
  -od, --output-dir OUTPUT_DIR
                        set default output folder (default: 'output')
  -of, --output-filename OUTPUT_FILENAME
                        set output filename (default: 'None')
  -r, --rotation ROTATION
                        Rotation angle in degrees (default: '0')
  -cw, --clockwise      Rotate clockwise (default: 'False)
```

<!--help-rotate !-->

### fotolab montage

```console
fotolab montage -h
```

<!--help-montage !-->

```console
usage: fotolab montage [-h] [-op] [-od OUTPUT_DIR] [-of OUTPUT_FILENAME]
                       [-b BORDER] [-bc COLOR]
                       IMAGE_PATHS [IMAGE_PATHS ...]

positional arguments:
  IMAGE_PATHS           set the image filenames

options:
  -h, --help            show this help message and exit
  -op, --open           open the image using default program (default:
                        'False')
  -od, --output-dir OUTPUT_DIR
                        set default output folder (default: 'output')
  -of, --output-filename OUTPUT_FILENAME
                        set output filename (default: 'None')
  -b, --border BORDER   set the border width for each image (default: '0')
  -bc, --border-color COLOR
                        set the border color for each image (default: 'black')
```

<!--help-montage !-->

### fotolab resize

```console
fotolab resize -h
```

<!--help-resize !-->

```console
usage: fotolab resize [-h] [-op] [-od OUTPUT_DIR] [-of OUTPUT_FILENAME] [-c]
                      [-l CANVAS_COLOR] [-W WIDTH] [-H HEIGHT]
                      [-ar ASPECT_RATIO]
                      IMAGE_PATHS [IMAGE_PATHS ...]

positional arguments:
  IMAGE_PATHS           set the image filenames

options:
  -h, --help            show this help message and exit
  -op, --open           open the image using default program (default:
                        'False')
  -od, --output-dir OUTPUT_DIR
                        set default output folder (default: 'output')
  -of, --output-filename OUTPUT_FILENAME
                        set output filename (default: 'None')
  -c, --canvas          paste image onto a larger canvas
  -l, --canvas-color CANVAS_COLOR
                        the color of the extended larger canvas(default:
                        'black')
  -W, --width WIDTH     set the width of the image (default: '600')
  -H, --height HEIGHT   set the height of the image (default: '277')
  -ar, --aspect-ratio ASPECT_RATIO
                        set the aspect ratio of the image (e.g., '16:9',
                        '4:3')
```

<!--help-resize !-->

### fotolab sharpen

```console
fotolab sharpen -h
```

<!--help-sharpen !-->

```console
usage: fotolab sharpen [-h] [-op] [-od OUTPUT_DIR] [-of OUTPUT_FILENAME]
                       [-r RADIUS] [-p PERCENT] [-t THRESHOLD] [-ba]
                       IMAGE_PATHS [IMAGE_PATHS ...]

positional arguments:
  IMAGE_PATHS           set the image filenames

options:
  -h, --help            show this help message and exit
  -op, --open           open the image using default program (default:
                        'False')
  -od, --output-dir OUTPUT_DIR
                        set default output folder (default: 'output')
  -of, --output-filename OUTPUT_FILENAME
                        set output filename (default: 'None')
  -r, --radius RADIUS   set the radius or size of edges (default: '1')
  -p, --percent PERCENT
                        set the amount of overall strength of sharpening
                        effect (default: '100')
  -t, --threshold THRESHOLD
                        set the minimum brightness changed to be sharpened
                        (default: '3')
  -ba, --before-after   generate a GIF showing before and after changes
```

<!--help-sharpen !-->

### fotolab watermark

```console
fotolab watermark -h
```

<!--help-watermark !-->

```console
usage: fotolab watermark [-h] [-op] [-od OUTPUT_DIR] [-of OUTPUT_FILENAME]
                         [-t WATERMARK_TEXT]
                         [-p {top-left,top-right,bottom-left,bottom-right}]
                         [-pd PADDING] [--padding-x PADDING_X]
                         [--padding-y PADDING_Y] [-fs FONT_SIZE]
                         [-fc FONT_COLOR] [-ow OUTLINE_WIDTH]
                         [-oc OUTLINE_COLOR] [-a ALPHA_VALUE] [--camera]
                         [-l | --lowercase | --no-lowercase]
                         IMAGE_PATHS [IMAGE_PATHS ...]

positional arguments:
  IMAGE_PATHS           set the image filenames

options:
  -h, --help            show this help message and exit
  -op, --open           open the image using default program (default:
                        'False')
  -od, --output-dir OUTPUT_DIR
                        set default output folder (default: 'output')
  -of, --output-filename OUTPUT_FILENAME
                        set output filename (default: 'None')
  -t, --text WATERMARK_TEXT
                        set the watermark text (default: 'kianmeng.org')
  -p, --position {top-left,top-right,bottom-left,bottom-right}
                        set position of the watermark text (default: 'bottom-
                        left')
  -pd, --padding PADDING
                        set the padding of the watermark text relative to the
                        image (default: '15')
  --padding-x PADDING_X
                        set the horizontal padding of the watermark text
                        relative to the image (overrides --padding for x-axis)
  --padding-y PADDING_Y
                        set the vertical padding of the watermark text
                        relative to the image (overrides --padding for y-axis)
  -fs, --font-size FONT_SIZE
                        set the font size of watermark text (default: '12')
  -fc, --font-color FONT_COLOR
                        set the font color of watermark text (default:
                        'white')
  -ow, --outline-width OUTLINE_WIDTH
                        set the outline width of the watermark text (default:
                        '2')
  -oc, --outline-color OUTLINE_COLOR
                        set the outline color of the watermark text (default:
                        'black')
  -a, --alpha ALPHA_VALUE
                        set the transparency of the watermark text (0-255,
                        where 0 is fully transparent and 255 is fully opaque;
                        default: '128')
  --camera              use camera metadata as watermark
  -l, --lowercase, --no-lowercase
                        lowercase the watermark text
```

<!--help-watermark !-->

### fotolab env

```console
fotolab env -h
```

<!--help-env !-->

```console
usage: fotolab env [-h]

options:
  -h, --help  show this help message and exit
```

<!--help-env !-->

## Copyright and License

Copyright (C) 2024,2025 Kian-Meng Ang

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero 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 Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program. If not, see <https://www.gnu.org/licenses/>.

The fish logo used in the documentation generated by Sphinx is a public domain
drawing of male freshwater phase [Sockeye (red) salmon (Oncorhynchus nerka)]
(https://en.wikipedia.org/w/index.php?oldid=1186575702) from
<https://commons.wikimedia.org/entity/M2787002>.
