# JPEG to JPEG XL Batch Transcoder

Did you know you can transcode plain JPEG images to JPEG XL, and you can reconstruct the original bit-perfect JPEG?
The best part is that the transcoded JPEG XL images are typically around 20% smaller than the original.

This program uses all processor cores to quickly transcode Jpeg images to Jpeg XL images, while preserving directory structure and file modification times.
Non-JPEG files are copied to the new destination without modification.
You could say this works like rsync, but only locally, and while doing so it transcodes JPEG to JPEG XL.

## Under the hood

* Uses oneAPI Thread Building Blocks to schedule jobs.
* (Ab)uses boost::interprocess to memory map input and output files. Zero-copy transcoding increases performance and lowers memory usage.
* Encoder is Jpeg XL reference implementation.

## Usage

```
jxltree Jpeg to Jpeg XL Batch Transcoder
Usage: ./jxltree [OPTIONS] src_dir dest_dir

Positionals:
  src_dir TEXT REQUIRED       source directory
  dest_dir TEXT REQUIRED      destination directory

Options:
  -h,--help                   Print this help message and exit
  -r                          Reconstruct JPEG from JXL, instead of transcoding JPEG to JXL
  -v                          verbose; log operations
  -f                          overwrite if destination file exists
  -e INT [10]                 Compression effort
  -j INT [16]                 Number of threads
  --version                   Display program version information and exit
```

### Lossless Transcode (Jpeg → Jpeg XL)

```
jxltree src dest
```

- `src/01.jpg` and `src/a/2.JPEG` will be transcoded to `dest/01.jxl` and `dest/a/2.jxl` respectively.
- timestamps of transcoded jxl files will be identical to source Jpeg files.
- non-jpeg files, such as `mp4` or `mov`, will be copied without modification.
- use `-v` option to see progress while transcoding.
- use `-j` option to adjust the number of threads.
  - defaults to available number of threads.
  - watch out for memory (RAM) requirements. A thread takes around 1.5 GBytes of memory for high-res photos.

### Lossless Reconstruct (Jpeg XL → Jpeg)

```
jxltree -r src dest
```

- `src/01.jxl` and `src/a/2.jxl` will be transcoded to `dest/01.jpg` and `dest/a/2.jpg` respectively.
- timestamps of reconstructed jpg files will be identical to source jxl files.
- non-jxl files, such as `mp4` or `mov`, will be copied without modification.
- use `-v` option to see progress while reconstructing.
- use `-j` option to adjust the number of threads.
  - defaults to available number of threads.
  - reconstructing appears to take less memory than transcoding.

The jpg files reconstructed this way is bit-perfect identical to original Jpeg images.
Only Jxl files that are transcoded from Jpeg files can be reconstructed though.

## Building instructions

For Unix-like systems GNU Make is used to build this project.
For Windows, Visual Studio with bundled vcpkg and cmake is used.
Details are discussed in the following sections.

### Linux, FreeBSD and macOS

* boost::interprocess, libtbb, cli11, libjxl and development headers are required.
  * Debian and OpenSUSE appears to have these packages.
  * Also refer to Containerfile for example setup
* Please adjust header locations and optimization flags in Makefile
  * Tips for FreeBSD users: as of 15.0-RELEASE you need to add `-fexperimental-library` to `CXXFLAGS`
* Type make

### Windows

This instruction has been verified with Visual Studio 2026 on Windows 11.
Open Developer Command Prompt.

First you need to set path to correct compilers. For x64 build on x64 host try like:
```
"\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvars64.bat"
```

For arm64 build on x64 host try:
```
"\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvarsamd64_arm64.bat"
```

Next, build and install:

```
cmake --preset x64-release --fresh
cmake --build out/build/x64-release --clean-first
cmake --install out/build/x64-release
```

In place of `x64-release`, `arm64-release` or corresponding debug configurations `x64-debug` `arm64-debug` can be used.
Arm64 binaries can be cross-compiled on an x64 host, but I've never checked if the binary actually works on target because I don't have a Windows/arm64 PC.

Finally create distribution ZIP:

```
cpack --preset x64-release
```

