Skip to content

Latest commit

 

History

12 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Image Compression using DCT and Huffman Encoding

A small, self-contained image compressor that shows how a JPEG-like codec actually works, end to end. It takes a 24-bit BMP and produces a much smaller .sjpg file, and it can decode that file back into a BMP.

The goal is to show how compression algorithms work - every stage is plain, readable C++ with no third-party dependencies.

Pipeline

RGB  ->  YCbCr  ->  4:2:0 chroma subsampling  ->  NxN DCT  ->  quantisation
     ->  zig-zag scan  ->  differential DC + run-length AC  ->  Huffman bitstream
  • Colour transform: RGB is converted to YCbCr, and every plane is level-shifted so it is centred on zero, which is what the DCT and the quantisation tables expect.
  • Chroma subsampling: Cb and Cr are halved in both directions (4:2:0), because the eye is far less sensitive to colour detail than to brightness detail. Can be turned off with --no-subsampling.
  • DCT: each plane is split into NxN blocks and transformed with a separable orthonormal DCT-II. Blocks that hang off the right or bottom edge are filled by replicating the edge samples.
  • Quantisation: the baseline JPEG (Annex K) tables, scaled to the requested quality and block size. This is the only lossy step.
  • Entropy coding: coefficients are read out in zig-zag order so they run from low to high frequency. DC values are stored as differences between neighbouring blocks; AC values are run-length coded as (zero run, magnitude) pairs and then Huffman coded. Luma and chroma get their own code tables, which are stored in the file so the decoder can rebuild them exactly.

Compilation

  1. Clone the repository:
git clone https://github.com/jholaj/SimpleJPEGCompress.git
cd SimpleJPEGCompress
  1. Build:
make                # or: g++ -std=c++17 -O2 -Iinclude -o compressor src/*.cpp
  1. Create a test image and run it:
mkdir -p samples results
python3 tools/make_sample.py samples/sample.bmp

./compressor samples/sample.bmp results/sample.sjpg -q 75 --preview results/preview.bmp
./compressor -d results/sample.sjpg results/decoded.bmp

Usage

./compressor [options] <input.bmp> <output.sjpg>   compress
./compressor -d <input.sjpg> <output.bmp>          decompress
Option Description
-q, --quality <1-100> Quality. Lower means a smaller file and more visible artefacts (default: 75).
-b, --block-size <2-32> DCT block size (default: 8, as in JPEG).
--no-subsampling Keep chroma at full resolution (4:4:4). Larger file, better colour edges.
--preview <file.bmp> Also decode the result and write it as a BMP, reporting the PSNR.
-d, --decompress Decode a .sjpg back into a BMP.
-h, --help Show help.

Input must be an uncompressed 24-bit or 32-bit BMP (top-down and bottom-up row order are both accepted). Output BMPs are always written as 24-bit.

Results

Compressing the 640x400 sample above (750 KiB as a BMP):

Quality Output Ratio PSNR
1 1.9 KiB 393:1 23.3 dB
25 5.6 KiB 135:1 31.5 dB
50 9.4 KiB 80:1 33.3 dB
75 18.5 KiB 41:1 34.5 dB
90 42.6 KiB 18:1 35.5 dB
100 141.7 KiB 5.3:1 37.4 dB

The same generator at 1920x1080 (python3 tools/make_sample.py samples/hd.bmp 1920 1080, 5.9 MiB as a BMP) compresses to 139 KiB at -q 75 in about 0.1 s.

Tests

make test        # zig-zag, DCT/IDCT, quantisation tables, Huffman, codec round trip
make sanitize    # the same tests under AddressSanitizer and UndefinedBehaviorSanitizer

Known Issues / Limitations

  • Image formats: only BMP is read and written. The compressed .sjpg container is specific to this project and is not a real JPEG file, so ordinary image viewers cannot open it — use -d to convert back to BMP.
  • Block sizes other than 8: supported, but the quantisation table is resampled from the 8x8 baseline table, so -b 8 gives the best quality per byte.
  • Single-threaded: fast enough for large images in practice, but the DCT is a straightforward matrix multiplication rather than a fast DCT.

About

Image compression using DCT, quantization, and Huffman encoding.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages