Skip to content

libjpeg-turbo

UI & GraphicsGraphics / Image ProcessingC

What it is

libjpeg-turbo is a high-speed version of the standard JPEG image codec library, using SIMD instructions (MMX, SSE2, NEON, AltiVec) to accelerate JPEG compression and decompression.

libjpeg-turbo provides functions to read, write, and manipulate JPEG images efficiently. It supports standard JPEG features, including color spaces, sampling factors, and progressive JPEGs. Applications often use it for image viewers, editors, and servers requiring fast JPEG processing.

Installation

sudo apt install libjpeg-turbo8-dev

Getting started

The smallest useful thing you can do with it, and what each part means.

Reading a JPEG image
#include <stdio.h>
#include <jpeglib.h>
int main() {
    FILE *infile = fopen("image.jpg", "rb");
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);
    jpeg_stdio_src(&cinfo, infile);
    jpeg_read_header(&cinfo, TRUE);
    jpeg_start_decompress(&cinfo);

    int row_stride = cinfo.output_width * cinfo.output_components;
    JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1);

    while (cinfo.output_scanline < cinfo.output_height) {
        jpeg_read_scanlines(&cinfo, buffer, 1);
        // Process buffer[0] here
    }

    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    fclose(infile);
    return 0;
}
Reads a JPEG image from file using libjpeg-turbo and iterates over scanlines for processing.
Writing a JPEG image
#include <stdio.h>
#include <jpeglib.h>
int main() {
    FILE *outfile = fopen("output.jpg", "wb");
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, outfile);

    cinfo.image_width = 100;
    cinfo.image_height = 100;
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;

    jpeg_set_defaults(&cinfo);
    jpeg_start_compress(&cinfo, TRUE);

    JSAMPROW row_pointer[1];
    unsigned char row[100*3]; // Fill row with pixel data
    while(cinfo.next_scanline < cinfo.image_height) {
        row_pointer[0] = row;
        jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }

    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);
    fclose(outfile);
    return 0;
}
Writes a simple 100x100 RGB JPEG image to disk using libjpeg-turbo.

Advanced usage

Where the library earns its place over a simpler alternative.

Using TurboJPEG API for faster processing
#include <turbojpeg.h>
tjhandle handle = tjInitDecompress();
int width, height, jpegSubsamp;
unsigned char *jpegBuf;
tjDecompressHeader3(handle, jpegBuf, jpegSize, &width, &height, &jpegSubsamp);
unsigned char *dstBuf = malloc(width*height*3);
tjDecompress2(handle, jpegBuf, jpegSize, dstBuf, width, 0, height, TJPF_RGB, TJFLAG_FASTDCT);
tjDestroy(handle);
Demonstrates using the TurboJPEG API for extremely fast JPEG decompression with SIMD acceleration.
Compressing image with TurboJPEG
tjhandle handle = tjInitCompress();
tjCompress2(handle, srcBuf, width, 0, height, TJPF_RGB, &jpegBuf, &jpegSize, TJSAMP_420, 90, TJFLAG_FASTDCT);
tjDestroy(handle);
Compresses an RGB image buffer into JPEG format efficiently using TurboJPEG.

Errors and fixes

The failures you are most likely to hit, and what actually resolves them.

JPEG error during decompression
Ensure input JPEG data is valid and `jpeg_std_error` is set for proper error handling.
Memory allocation failure
Check available memory and properly free buffers after use.

Best practices

  • Use the TurboJPEG API for performance-critical JPEG encoding/decoding.
  • Always free buffers and destroy handles to prevent memory leaks.
  • Leverage SIMD-optimized flags for faster computation.
  • Validate image dimensions and color formats before processing.
  • Use libjpeg-turbo in place of libjpeg where speed is essential.

Background

Why it exists, and what it was reacting to.

libjpeg-turbo was created to provide faster JPEG encoding and decoding than the standard libjpeg library. It maintains full ABI and API compatibility with libjpeg, making it easy to replace in existing projects while gaining significant performance improvements.