Open-source project
libjpeg-turbo/libjpeg-turbo avatar
libjpeg-turbo/libjpeg-turbo

libjpeg-turbo: the JPEG codec that keeps the old API and adds SIMD

Main libjpeg-turbo repository

4,445 stars1,189 forksCNOASSERTION

At a glance

What is it?
A C library that claims to run two to six times faster than libjpeg while staying API and ABI compatible with it, plus a friendlier TurboJPEG layer for new code and ten nonstandard colorspaces that skip a pixel copy.
Who is it for?
libjpeg-turbo is the right default for anything that decodes or encodes JPEG on x86, ARM or PowerPC hardware, because dropping it in behind the libjpeg v6b interface costs almost nothing and the project's own versioning policy makes old branches easy to pin. The TurboJPEG API is worth learning for new code, since it avoids the manual buffer juggling that dominates libjpeg usage.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 4 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 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A libjpeg replacement that agrees with libjpeg on the wire

The pitch is unusual for a performance library: libjpeg-turbo does not want you to change your code. Its libjpeg API implementation is described as both API/ABI-compatible and mathematically compatible with libjpeg v6b, which is the version a large amount of existing software was compiled against. For a maintainer facing a slow decoder, that matters more than a clean interface. Swap the shared library, keep the struct layouts, keep the function names, and the binary you already shipped keeps working.

The speed comes from SIMD instructions applied to baseline and progressive JPEG compression and decompression, and the project's own claim is that on systems with common CPU architectures it is generally two to six times as fast as libjpeg with everything else held equal. That number comes from the README, not from a benchmark you can rerun here, and it is scoped to architectures where the vector code actually exists. On other systems the README still claims an advantage, attributing it to Huffman coding routines rather than to the vector paths.

The lineage explains why the compatibility promise is so firm. The project started as libjpeg/SIMD, an MMX-accelerated derivative of libjpeg v6b, picked up substantial work from the TigerVNC and VirtualGL projects in 2009, and split out as an independent project in early 2010. It is also an ISO/IEC and ITU-T reference implementation of the JPEG standard, which is a different kind of credibility claim from being fast: this is code other implementations are checked against.

TurboJPEG and libjpeg are not two speeds of the same thing

The README is explicit that there is no meaningful performance difference between the two APIs when both are used for similar operations. The difference is ergonomic, and it is large. TurboJPEG compresses and decompresses entirely in memory, and it adds operations that are awkward through the lower layer, such as producing planar YUV images and running several lossless transforms on one image in a single pass. The README recommends TurboJPEG for anyone using the library for the first time.

The libjpeg API is harder and more capable. It is the de facto industry interface for JPEG work, and programs written against it are the reason the compatibility work exists at all. The repository points new TurboJPEG users at `src/tjcomp.c`, `src/tjdecomp.c` and `src/tjtran.c` for working examples, and Java users at `TJComp.java`, `TJDecomp.java` and `TJTran.java` under `jna/`. For the lower API it points at `src/cjpeg.c` and `src/djpeg.c`, which are also the `cjpeg` and `djpeg` command line tools most Linux distributions package.

That leaves a straightforward decision rule. Porting an existing codebase means staying on libjpeg, because rewriting call sites to TurboJPEG would cost more than the SIMD win returns. Writing something new means starting at TurboJPEG, because the alternative is managing Huffman tables and restart markers by hand.

Ten colorspace constants that read and write pixels in your native order

Most JPEG libraries hand you YCbCr and make you convert. libjpeg-turbo adds ten constants that let the codec read red, green and blue from wherever they sit in your 32-bit pixel, or write them straight back out:

c
JCS_EXT_RGB   /* red/green/blue */
JCS_EXT_BGR   /* blue/green/red */
JCS_EXT_RGBA  /* red/green/blue/alpha */
JCS_EXT_BGRA  /* blue/green/red/alpha */
JCS_EXT_ABGR  /* alpha/blue/green/red */
JCS_EXT_ARGB  /* alpha/red/green/blue */

Set `cinfo.in_color_space` when compressing or `cinfo.out_color_space` when decompressing and the library handles the channel ordering itself. On a machine where your framebuffer is already BGRX, that removes a full-image conversion pass, which on large images is usually a larger cost than the DCT itself.

There is a detail worth reading twice, because it will cost you a rendering bug if you miss it. In the RGBX, BGRX, XBGR and XRGB variants, the X byte is undefined and the library will write whatever it likes there for speed. The four alpha variants guarantee 0xFF, interpreted as opaque. If your application treats X as an alpha channel and you picked the non-alpha constant, you get garbage transparency. The README tells you to test for support at compile time with `#ifdef JCS_EXTENSIONS` and `#ifdef JCS_ALPHA_EXTENSIONS`, and notes that at run time an unsupported value produces a "Bogus input colorspace" error you can trap. `src/jcstest.c` in the tree demonstrates both checks.

Why emulating the v7 and v8 ABIs still matters

libjpeg v7 and v8 both added features that required extending the compression and decompression structures, and because those structures are exposed rather than opaque, extending them broke backward ABI compatibility. Binaries compiled against v7 or v8 therefore stopped working when libjpeg-turbo came along, since libjpeg-turbo grew out of the v6b code base and does not carry those additions.

The response was an optional build that emulates the v7 and v8 ABIs. The README is candid about the motivation: v7 and v8 are less widely used than v6b, but enough programs, including a few Linux distributions, depended on them that there was demand for a drop-in path. It also says the feature exists primarily so already-compiled applications can move over rather than rebuild.

The practical consequence is that a configure flag decides whether you get v6b behaviour or emulated v7 or v8 behaviour, and the choice affects which prebuilt binary you want. This is also the single strongest argument for the compatibility-first design: without the emulation build, upgrading meant recompiling every dependent program, and that cost is exactly what keeps a codec pinned to an old release for years.

Stable, beta and maintenance lines labelled in every release

Every release note carries two labels, and they are not the same thing. Release 3.2.0 from 2026-06-30 is marked code quality Stable and support category Active. Release 3.1.90 from 2026-03-27 is marked code quality Beta and support category EOL, which is the giveaway that 3.1.90 was a development snapshot on the way to 3.2.0 rather than a destination. Release 3.1.4.1, published the same day, is Stable but only Maintenance.

Reading those three labels together tells you the support surface: 3.2.0 is where fixes land, 3.1.4.1 receives backports, and the 3.1.90 branch is closed. A packaging target that wants the newest code takes 3.2.0; one that needs stability with narrower change takes 3.1.4.1.

The release notes also carry a distribution policy that trip automation up if it is ignored. Only the hand-built tarball counts: `libjpeg-turbo-3.2.0.tar.gz` is called the official source archive, and the notes state plainly that the automatically generated "Source code" assets are not supported. Signing methods are documented separately on the project site, and so is which official binary packages go with which release. Anything automating a download should read both pages before pinning a URL.

The license field says NOASSERTION, the README says three BSD licenses

GitHub reports no recognized license identifier for this repository. The README says something different and more useful: libjpeg-turbo is covered by three compatible BSD-style open source licenses, with `LICENSE.md` in the repository root holding the roll-up of terms. Both statements are in the repository, and the practical reading is that the project uses a custom multi-license grant that no SPDX detector recognizes, not that terms are missing. Read `LICENSE.md` before shipping anything that depends on it.

The tree gives a good sense of what the project actually is. `src/` holds the codec, `simd/` the assembly and intrinsics, `doc/` the API documentation including `libjpeg.txt`, `test/` and `testimages/` the test suite, `fuzz/` fuzzing targets, `jna/` the Java bindings, `win/` the Windows build, `sharedlib/` the shared library build, `cmakescripts/` the CMake helpers, and `release/` the release tooling. `README.ijg` sits next to `README.md`, which reflects the code's origin in the Independent JPEG Group implementation.

Financing is explicit too. The README asks for sponsorship through GitHub Sponsors and states that the money funds the labor to maintain the library, support users and land bug fixes, which is how a project with no commercial vendor stays independent. The repository was last pushed on 2026-09-22 and is not archived.

Editorial conclusion

libjpeg-turbo is the right default for anything that decodes or encodes JPEG on x86, ARM or PowerPC hardware, because dropping it in behind the libjpeg v6b interface costs almost nothing and the project's own versioning policy makes old branches easy to pin. The TurboJPEG API is worth learning for new code, since it avoids the manual buffer juggling that dominates libjpeg usage. Two things to check before committing: the license identifier GitHub reports is NOASSERTION while the README describes three BSD-style licenses, so read LICENSE.md rather than the metadata field, and confirm the bundled SIMD paths on your target architecture rather than assuming the speed claim transfers.

Frequently asked questions

How do I install libjpeg-turbo?

The README carries no install commands. It points builders at BUILDING.md in the repository root for complete instructions, and the release notes point at the project's Downloads and DigitalSignatures pages for official binaries and their signatures. On most Linux distributions you do not build it yourself, since libjpeg-turbo is what the common libjpeg packages already provide.

Is libjpeg-turbo API compatible with libjpeg?

Yes for v6b, and optionally for v7 and v8. The README states the libjpeg API implementation is both API/ABI-compatible and mathematically compatible with libjpeg v6b. Because v7 and v8 extended the exposed structures and broke ABI, emulating those ABIs is a separate optional build rather than the default.

Which API should new code use, TurboJPEG or libjpeg?

The README recommends TurboJPEG for first-time users because it works in memory and offers operations that are awkward through the underlying interface, such as planar YUV output and several simultaneous lossless transforms. It also states there is no significant performance advantage between the two when used for similar work, so the choice is about interface, not speed.

What license does libjpeg-turbo use?

GitHub reports NOASSERTION for the license identifier, while the README says the project is covered by three compatible BSD-style open source licenses with the terms rolled up in LICENSE.md at the repository root. Treat LICENSE.md as authoritative rather than the metadata field.

Official sources

  1. Issues
  2. libjpeg-turbo/libjpeg-turbo on GitHub
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/libjpeg-turbo-libjpeg-turbo.svg)](https://hysenlabs.com/projects/libjpeg-turbo-libjpeg-turbo)