tjko/jpegoptim: Lossy JPEG Compression with Size Targets
jpegoptim - utility to optimize/compress JPEG files
At a glance
- What is it?
- jpegoptim is a C command-line utility for recompressing JPEG files with libjpeg, including workflows for target file sizes, metadata removal, stdin and stdout, and parallel processing. It fits administrators and developers who need smaller JPEG assets, but its lossy optimization changes image data.
- Who is it for?
- Adopt jpegoptim when your JPEG workflow needs source-based, command-line compression and you can accept lossy changes or explicit size targets. Do not choose it as a lossless optimizer, a PNG or WebP converter, or a replacement for visual review.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 11 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What jpegoptim changes in a JPEG workflow
jpegoptim addresses a narrow but common operations problem: reducing the storage footprint of JPEG files without changing the surrounding workflow. It is intended for users who already have JPEG assets and need a command-line utility for local files, scripts, build steps, or batch processing. The primary language is C, and the program is built around the Independent JPEG Group's jpeg library, with libjpeg-turbo and mozjpeg identified as alternatives in the README.
The utility does not provide a general image conversion pipeline. Its scope is JPEG optimization and compression. The release history describes several image-oriented controls, including optimization thresholds, target sizes, progressive JPEG handling, JFIF marker handling, XMP markers, arithmetic coding as an experimental configure option, and metadata stripping options. Those features matter when a deployment must reduce transfer costs while retaining the JPEG format.
The central trade-off is visible in the `-S` and `--size` option. A target-size request enables lossy optimization, so the output is not merely a lossless repackaging of the original JPEG. The program can also use a threshold to decide whether an optimized file is sufficiently smaller before replacing or reporting it. Users who need exact pixel preservation should not treat those options as transparent compression.
libjpeg, in-memory processing, and JPEG output
According to the repository layout, optimization is implemented in the C program `jpegoptim.c` with supporting source files including `jpegsrc.c`, `jpegdest.c`, `jpegmarker.c`, and `misc.c`. The release history states that since v1.4.0, optimization uses memory rather than temporary files. That design reduces dependence on temporary-file storage during processing, while the program's input and output abstractions allow file-based and stream-based workflows.
The utility can process files directly, read from standard input, and send output to standard output. The README also describes `--files-from` and `--files-stdin` for supplying a list of files. These paths are useful for automation, but they also make invocation details important. For example, v1.5.6 specifically changed standard-input processing so that it behaves the same as processing from a file, and v1.5.1 fixed logging behavior when `--stdout` is used.
JPEG structure is not completely ignored. The project reports markers, handles JFIF and JFXX data, preserves progressive versus non-progressive mode by default from v1.5.4, and includes a NITF marker fix in the v1.5.7 history. The history also records fixes for corrupt JPEG handling, undefined behavior after `longjmp()`, and unsafe symlink behavior during file creation. These entries indicate that output compatibility and failure handling are part of the utility's core concerns rather than incidental packaging details.
Building jpegoptim from the source tarball
The README describes source installation rather than a package-manager workflow. The documented build sequence requires libjpeg version 6b or later, or a compatible libjpeg implementation such as libjpeg-turbo or mozjpeg. The command below follows the README exactly. The reader should first have the JPEG development library and compiler environment available.
The first block unpacks the documented tarball, enters its directory, configures the source tree, builds the program, strips symbols, and installs it according to the project's build files.
tar xzvf jpegoptim-1.5.7.tar.gz
cd jpegoptim-1.5.7
./configure
make
make strip
make installThe README also says that changes to the Makefile may be necessary, so this sequence should not be treated as a guarantee for every distribution or toolchain. The repository includes `configure`, `configure.in`, `Makefile.in`, `CMake/`, and `CMakeLists.txt`, which indicates that both configure-based and CMake-oriented build material is present. The documentation does not provide a separate CMake command sequence, so no invented invocation is added here.
After installation, the first useful operation is checking command-line help. The release history says that v1.5.7 changed `--help` output to go to stdout. The available options should be inspected in the installed version because the history contains version-specific additions such as `--retry`, `--save-extra`, `--auto-mode`, and `--workers`.
A first compression pass with thresholds and output files
jpegoptim's documented options support several common batch strategies. A simple first use is to process a file with the program's default optimization behavior. The README does not provide a complete flag-by-flag usage tutorial, so the safest first check is the installed help output rather than an invented example.
The release history identifies `--threshold` as the control for accepting an optimization only when it reduces the file enough. It also identifies `-S` and `--size` as target-size controls, while `-d` and `--dest` select an output destination. `--overwrite`, `--quiet`, and logging-related options affect how results are handled or reported. These features allow a script to avoid replacing every input unconditionally, but the exact command-line syntax should be taken from `jpegoptim --help` in the installed release.
The output behavior also depends on mode. `--stdout` sends the resulting JPEG to standard output, while ordinary file mode reads and writes files. `--save-extra` is described as preserving extra data, and the v1.5.7 history says it is honored in stdout mode. Marker choices are similarly explicit: `--strip-none`, `--keep-*` options, `--keep-jfif`, and `--strip-jfif` address metadata and JFIF handling. A batch policy should therefore be defined around the actual file set rather than applied blindly.
Parallel processing, retries, and auto-mode
For bulk directories or file lists, jpegoptim exposes `--workers=<max>` for parallel processing. The v1.5.7 history lists a fix for duplicate output when multiple workers or threads are used, as well as fixes to `--workers` and `--retry` option processing and a potential hang in `wait_for_worker()`. That history makes parallel mode a feature with clear failure-sensitive areas, especially when many files are processed at once.
The `--auto-mode` option is also documented in the release history. Its listed fixes include a loop that could occur during automatic mode, a regression where it applied only to the first file, and a problem where auto-mode could recompress its own lossy output. The final item is particularly relevant to pipelines: automatic optimization needs an input and output boundary that avoids feeding generated JPEG data back into another lossy optimization pass.
`--retry` was added in v1.5.6. The README does not define its retry conditions or scheduling semantics, so an operator should inspect `--help` and the man page `jpegoptim.1` before depending on it for a production batch process. The repository layout does provide a man page, but the excerpt does not reproduce its full operational guidance.
Limits for lossless expectations and format conversion
The main limitation is that “optimize” does not necessarily mean lossless. The release history explicitly connects `-S` and `--size` with lossy optimization, and the target-size feature is intended to influence the encoded image result. Threshold mode can also retain the original when savings are insufficient, but a target-size request changes the encoding trade-off.
jpegoptim is also not a universal image tool. The README identifies JPEG files as its input and describes JPEG encoder behavior, marker handling, and progressive JPEG support. It does not claim support for converting PNG, WebP, GIF, or other formats. A team looking for format conversion should choose a tool designed for that task and use jpegoptim only when the pipeline already produces JPEGs.
Corrupt, broken, or unusual JPEG files remain a practical boundary. The history includes fixes for crashes on broken images, a heap-buffer-overflow in stdin and stdout processing, NITF marker problems, and failures involving `longjmp()`. Those fixes improve safety, but they do not establish that every malformed or unusual JPEG is accepted. The project is a better fit for controlled JPEG assets than for an untrusted directory where every input must be processed successfully.
JPEG optimization compared with libjpeg conversion
A real alternative is a custom program built directly on libjpeg. Both approaches can decode and re-encode JPEG data, but they divide responsibility differently. jpegoptim supplies the command-line policy: threshold decisions, target sizes, metadata stripping, file lists, output destinations, workers, retries, and stdin and stdout handling. A custom libjpeg application would require implementing the relevant policy and file-handling behavior in application code.
This difference matters for automation. jpegoptim is easier to adopt as a batch utility when its documented options match the required behavior. It is less flexible when an application needs a custom encoding policy that the command does not expose, or when the program must participate in a larger application rather than operate as a filter. The README does not provide a complete matrix of supported encoder settings, so the comparison should be made against the installed `jpegoptim --help` and `jpegoptim.1`.
The GPL-3.0 license also affects adoption decisions. A team may use the utility as a separate command-line program, while distributing a modified or integrated version requires reviewing the license obligations. That is a licensing consideration, not legal advice, and the repository's `LICENSE` and `COPYRIGHT` files are the appropriate project-specific references.
Maintenance and upgrade implications for jpegoptim
The repository is not archived, and its last push was on 2026-10-11. The latest listed release is v1.5.6 from 2025-09-15, while the README identifies the checked-in version as v1.5.7beta. That distinction matters when planning an upgrade: the README's version string is not the same thing as the latest stable release in the release list.
The v1.5.7 history includes fixes for parallel workers, auto-mode, symlink handling, write failures under `-P`, NITF markers, `longjmp()` behavior, CSV escaping under RFC 4180, and other errors. It also includes safer temporary-file creation on platforms without `mkstemps()`, which is relevant when selecting a build platform. An upgrade can therefore change failure handling and output behavior, not merely speed.
The README lists Linux, macOS, and Windows as tested platforms. For Windows, it specifically says that `setargv.obj` is needed as a link option for wildcard expansion. Since the project is a GPL-3.0 C utility with source build files and platform notes, adoption cost includes checking libjpeg compatibility, understanding version-specific options, and reviewing whether the changes in a release affect an existing batch policy.
Editorial conclusion
Adopt jpegoptim when your JPEG workflow needs source-based, command-line compression and you can accept lossy changes or explicit size targets. Do not choose it as a lossless optimizer, a PNG or WebP converter, or a replacement for visual review. Before adoption, verify that your chosen libjpeg build is available, confirm the behavior of marker and metadata options for your files, and test representative images because compressed output quality is image-dependent.
Frequently asked questions
What does jpegoptim require before it can be built?
The README requires the Independent JPEG Group's jpeg library, version 6b or later. It also states that libjpeg-turbo and mozjpeg should work as alternatives.
Does jpegoptim support lossless JPEG optimization?
The release history identifies `-S` and `--size` as options that enable lossy optimization when targeting a file size. The documentation does not describe those target-size operations as lossless.
Can jpegoptim process files in parallel?
Yes. The release history documents `--workers=<max>` for parallel processing, along with fixes to worker output, worker exit-code handling, and a potential hang in `wait_for_worker()`.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/tjko-jpegoptim)Was this useful?