Project 10: Payload Image Compressor (Space JPEG)
Build a lightweight image compressor using DCT + quantization, packetize the result for downlink, and measure quality with PSNR.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Level 3: Advanced |
| Time Estimate | 1-2 weeks |
| Main Programming Language | C |
| Alternative Programming Languages | Python |
| Coolness Level | Level 3: Bandwidth Magician |
| Business Potential | Level 3: Payload Pipeline Tooling |
| Prerequisites | Linear algebra basics, image formats, bitwise ops |
| Key Topics | DCT, quantization, packetization, PSNR |
1. Learning Objectives
By completing this project, you will:
- Implement block-based DCT compression for grayscale images.
- Design quantization tables to trade quality vs size.
- Packetize compressed output for downlink constraints.
- Measure compression quality using PSNR.
- Understand how payload data is adapted to tiny bandwidths.
2. All Theory Needed (Per-Concept Breakdown)
DCT and Quantization for Image Compression
Fundamentals The Discrete Cosine Transform (DCT) converts image blocks from spatial domain to frequency domain. Most image energy is in low-frequency components; high-frequency components can be quantized more aggressively or discarded. Quantization reduces precision to achieve compression but introduces loss. By adjusting quantization tables, you control the tradeoff between image quality and compressed size. This is the core of JPEG-like compression.
Deep Dive into the concept The DCT operates on small blocks, typically 8x8 pixels. For each block, you compute 64 DCT coefficients. The DC coefficient represents the average intensity, while AC coefficients represent higher frequency variations. Natural images tend to have most energy in low-frequency components; therefore you can quantize higher-frequency coefficients more aggressively with minimal perceptual loss.
Quantization is performed by dividing each coefficient by a quantization table and rounding. Larger quantization values reduce precision and lead to more zeros in high-frequency coefficients. These zeros are then easy to compress with run-length encoding. The quantization table is the most powerful control knob for compression ratio. In space systems, you might accept higher loss to reduce downlink time. You should design a simple quantization table and allow a “quality factor” to scale it.
Implementing DCT efficiently is challenging in C, but for this project you can use a straightforward matrix-based implementation. Focus on correctness first; optimize later. Ensure that your pixel values are centered (e.g., subtract 128) before DCT to match JPEG conventions. After inverse DCT, add 128 back and clamp values to [0,255].
Quality assessment requires a metric. PSNR (Peak Signal-to-Noise Ratio) is commonly used. It is derived from mean squared error (MSE) between original and reconstructed images. PSNR in dB gives a quantitative measure of quality; values above ~30 dB are typically acceptable for many applications. In a payload context, PSNR is a way to justify a compression ratio.
How this fit on projects This concept drives Section 3.2 compression requirements and Section 6 testing (PSNR evaluation). It connects to P07 downlink scheduling.
Definitions & key terms
- DCT -> Frequency transform for block-based compression.
- Quantization -> Reducing coefficient precision to compress.
- PSNR -> Quality metric derived from MSE.
Mental model diagram (ASCII)
Image Block -> DCT -> Quantize -> (zeros) -> Encode
How it works (step-by-step, with invariants and failure modes)
- Split image into 8x8 blocks.
- Subtract 128 and compute DCT.
- Divide by quantization table and round.
- Encode coefficients.
- Decode and inverse DCT to reconstruct.
Invariants: block size fixed; coefficients computed consistently; quantization reversible.
Failure modes: incorrect centering, wrong quantization scaling, overflow.
Minimal concrete example
coeff[i][j] = round(dct[i][j] / qtable[i][j]);
Common misconceptions
- “Lossless compression is enough” -> Downlink constraints require lossy.
- “Quantization only affects size” -> It directly affects image quality.
Check-your-understanding questions
- Why does DCT concentrate energy in low frequencies?
- How does quantization affect PSNR?
- Why subtract 128 before DCT?
Check-your-understanding answers
- Natural images vary slowly; low frequencies dominate.
- Larger quantization lowers PSNR (more error).
- Centers data around zero to reduce DC bias.
Real-world applications
- Earth observation payload data compression.
- Bandwidth-limited image transmission.
Where you’ll apply it
- See Section 3.2 and Section 6.2.
- Also used in: P07-priority-telemetry-scheduler-the-traffic-cop.md
References
- Gonzalez & Woods, Digital Image Processing
- Wallace, The JPEG Still Picture Compression Standard
Key insights Most of an image is low-frequency; compress where it hurts least.
Summary DCT + quantization is the practical core of space-friendly image compression.
Homework/Exercises to practice the concept
- Compute DCT of a simple 8x8 block by hand for a constant image.
Solutions to the homework/exercises
- Only the DC coefficient is non-zero.
Packetization and Error Resilience
Fundamentals Compressed images must be packetized for downlink. Packetization splits a compressed bitstream into fixed-size chunks with headers and sequence numbers. This allows loss detection and partial reconstruction if packets are lost. Packetization is not just a transport detail; it shapes how much data you can recover when packets drop.
Deep Dive into the concept A compressed image bitstream is typically a sequence of variable-length codes. If you lose a portion of the stream, the decoder may lose synchronization. Therefore packetization should include resynchronization markers or structure. In JPEG, restart markers allow the decoder to resynchronize after loss. For this project, you can implement a simple packetization scheme where each packet carries a block index and payload length. This allows you to drop or reorder blocks without breaking the entire image. The tradeoff is overhead: each packet header consumes bytes, reducing net payload.
Sequence numbers are essential. They allow the ground system to detect missing packets and request retransmission (if possible) or accept partial reconstructions. In many CubeSats, retransmission is not feasible, so you design the packetization to maximize useful data even with loss. A block-based scheme works well: each packet contains a full 8x8 block of quantized coefficients. If you lose a packet, only that block is missing. You can fill missing blocks with zeros or interpolate.
Packet size choice matters. Larger packets are more efficient but risk losing more data if a packet is corrupted. Smaller packets increase overhead but reduce loss impact. In a low-power downlink, you might choose a moderate size (e.g., 256 bytes) to balance these tradeoffs. Your scheduler from P07 can use packet sizes to plan downlink bandwidth.
Determinism requires fixed packetization rules and consistent block ordering. When reconstructing, you should produce the same image given the same packet set. Include a packet header with fields: image_id, block_index, total_blocks, payload_length, checksum. The checksum helps detect corruption. If a checksum fails, mark the block as missing and log the error.
How this fit on projects This concept drives Section 3.5 data formats and Section 6 testing (packet loss scenarios) and ties to P07 scheduling.
Definitions & key terms
- Packetization -> Splitting data into packets with headers.
- Restart marker -> Resynchronization point for compressed streams.
- Checksum -> Data integrity check.
Mental model diagram (ASCII)
Compressed Stream -> Packets -> Downlink -> Reassemble -> Image
How it works (step-by-step, with invariants and failure modes)
- Split compressed data into packets.
- Add headers with block index and checksum.
- Transmit packets; record sequence numbers.
- Reassemble at ground; fill missing blocks.
Invariants: packet headers consistent; block indices unique.
Failure modes: mis-ordered packets, checksum failure, missing blocks.
Minimal concrete example
struct pkt { uint16_t img_id; uint16_t block; uint16_t len; uint16_t crc; };
Common misconceptions
- “Compression is independent of packetization” -> Packetization affects recoverability.
- “Losing a packet just reduces quality” -> It can corrupt the entire stream if not structured.
Check-your-understanding questions
- Why include block indices in packets?
- What is the cost of smaller packets?
- How do you reconstruct missing blocks?
Check-your-understanding answers
- To place blocks correctly and detect loss.
- Higher overhead per payload byte.
- Fill with zeros or interpolate neighboring blocks.
Real-world applications
- Downlink of Earth observation imagery.
- Deep-space imaging with limited bandwidth.
Where you’ll apply it
- See Section 3.5 data format and Section 6.2 loss tests.
- Also used in: P07-priority-telemetry-scheduler-the-traffic-cop.md
References
- CCSDS Image Data Compression recommendations
- Gonzalez & Woods, Digital Image Processing
Key insights Packetization is part of compression; it determines what survives loss.
Summary Good packetization preserves partial images even under packet loss.
Homework/Exercises to practice the concept
- Design a packet header for 256-byte payloads and estimate overhead.
Solutions to the homework/exercises
- Example header 8 bytes -> overhead 3.1%.
3. Project Specification
3.1 What You Will Build
A CLI tool that compresses a grayscale image using DCT + quantization, packetizes the compressed output, reconstructs the image, and reports PSNR.
3.2 Functional Requirements
- DCT compression: 8x8 block transform and quantization.
- Packetization: block-based packets with headers.
- Reconstruction: inverse DCT to rebuild image.
- Quality metrics: PSNR and compression ratio.
3.3 Non-Functional Requirements
- Determinism: fixed quantization tables and block ordering.
- Efficiency: process 1024x1024 images in < 5s.
- Robustness: handle packet loss by reconstructing partial images.
3.4 Example Usage / Output
$ ./img_compress input.pgm output.bin
[OK] Original: 1024x1024 (1.0 MB)
[OK] Compressed: 120 KB (8.3x reduction)
[PSNR] 34.2 dB
3.5 Data Formats / Schemas / Protocols
Packet header format:
img_id (2B) | block_index (2B) | payload_len (2B) | crc16 (2B)
3.6 Edge Cases
- Image dimensions not divisible by 8.
- Large quantization factors causing banding.
- Packet loss during reconstruction.
3.7 Real World Outcome
A compressed payload file and reconstructed image with PSNR report.
3.7.1 How to Run (Copy/Paste)
./img_compress input.pgm out.bin --quality 50 --packet 256
3.7.2 Golden Path Demo (Deterministic)
- Use
samples/lena.pgmwith quality 50. - Compare output to
golden_psnr.txt.
3.7.3 Failure Demo (Deterministic)
./img_compress missing.pgm out.bin
Expected: error message and exit code 2.
3.7.4 If CLI: Exact Terminal Transcript
$ ./img_compress samples/lena.pgm out.bin --quality 50
[OK] Original: 512x512
[OK] Compressed: 62 KB
[PSNR] 33.1 dB
ExitCode=0
4. Solution Architecture
4.1 High-Level Design
Input Image -> DCT+Quantize -> Packetize -> Output
|
+-> Reconstruct + PSNR
4.2 Key Components
| Component | Responsibility | Key Decisions |
|---|---|---|
| DCT Engine | Transform blocks | 8x8 block size |
| Quantizer | Apply quant tables | Quality scaling |
| Packetizer | Build packets | Packet size |
| Evaluator | PSNR computation | Metric choices |
4.3 Data Structures (No Full Code)
typedef struct { uint16_t img_id; uint16_t block; uint16_t len; uint16_t crc; } pkt_hdr_t;
4.4 Algorithm Overview
Key Algorithm: Compression pipeline
- Split image into blocks.
- Apply DCT and quantization.
- Encode coefficients and packetize.
- Reconstruct and compute PSNR.
Complexity Analysis:
- Time: O(N) blocks.
- Space: O(block_size).
5. Implementation Guide
5.1 Development Environment Setup
cc -O2 -Wall -Wextra -o img_compress src/*.c
5.2 Project Structure
project-root/
+-- src/
+-- samples/
+-- README.md
5.3 The Core Question You’re Answering
“How do you send useful images over tiny bandwidth?”
5.4 Concepts You Must Understand First
- DCT and quantization.
- Packetization and loss recovery.
- PSNR evaluation.
5.5 Questions to Guide Your Design
- What quality factor yields acceptable PSNR?
- What packet size balances overhead and loss impact?
- How do you handle non-multiple-of-8 images?
5.6 Thinking Exercise
Compute PSNR for a 1-bit error in a 256x256 image.
5.7 The Interview Questions They’ll Ask
- “Why use DCT for compression?”
- “How do you recover from packet loss?”
- “What does PSNR measure?”
5.8 Hints in Layers
Hint 1: Start with DCT and inverse DCT on a single block.
Hint 2: Add quantization and verify reconstruction.
Hint 3: Implement packet headers and block indexing.
Hint 4: Add PSNR calculation and quality reporting.
5.9 Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| Image compression | Gonzalez & Woods | DCT/Compression |
| JPEG standard | Wallace, JPEG Standard | Core algorithms |
| Data formats | CCSDS image compression | Overview |
5.10 Implementation Phases
Phase 1: DCT + IDCT (4-5 days)
Goals: correct transform and reconstruction. Tasks: implement 8x8 DCT/IDCT; test with simple blocks. Checkpoint: reconstruction error small with no quantization.
Phase 2: Quantization (3-4 days)
Goals: reduce size with acceptable quality. Tasks: add quant tables and quality factor. Checkpoint: PSNR within target range.
Phase 3: Packetization (3-4 days)
Goals: structure data for downlink. Tasks: design packet header, block indexing, CRC. Checkpoint: packet loss simulation yields partial image.
5.11 Key Implementation Decisions
| Decision | Options | Recommendation | Rationale |
|---|---|---|---|
| Block size | 8x8 / 16x16 | 8x8 | JPEG standard |
| Packet size | 128 / 256 / 512 | 256 | Balanced overhead |
| Quality control | fixed / scalable | scalable | Adjustable tradeoff |
6. Testing Strategy
6.1 Test Categories
| Category | Purpose | Examples |
|---|---|---|
| Unit Tests | DCT correctness | known blocks |
| Integration Tests | Compression pipeline | lena.pgm |
| Edge Case Tests | Packet loss | drop 10% packets |
6.2 Critical Test Cases
- No quantization: reconstruction nearly identical.
- Quality 50: PSNR > 30 dB.
- Packet loss: image reconstructed with missing blocks.
6.3 Test Data
samples/lena.pgm
7. Common Pitfalls & Debugging
7.1 Frequent Mistakes
| Pitfall | Symptom | Solution |
|---|---|---|
| Missing centering | DC bias in output | Subtract/add 128 |
| Overflow | artifacts | clamp to [0,255] |
| Wrong block ordering | scrambled image | consistent indexing |
7.2 Debugging Strategies
- Visualize reconstructed images at different quality factors.
- Print coefficient histograms to verify zeros increase.
7.3 Performance Traps
Naive DCT is slow; keep images small for tests.
8. Extensions & Challenges
8.1 Beginner Extensions
- Add run-length encoding for zeros.
8.2 Intermediate Extensions
- Add Huffman coding for entropy compression.
8.3 Advanced Extensions
- Implement restart markers for resync.
9. Real-World Connections
9.1 Industry Applications
- Earth observation payload compression.
- Remote sensing imaging pipelines.
9.2 Related Open Source Projects
- libjpeg (reference JPEG implementation).
- CCSDS image compression reference code.
9.3 Interview Relevance
- Shows applied signal processing and systems thinking.
10. Resources
10.1 Essential Reading
- Gonzalez & Woods, Digital Image Processing.
- Wallace, JPEG Standard.
10.2 Video Resources
- Image compression lectures.
10.3 Tools & Documentation
- PGM image format docs.
10.4 Related Projects in This Series
11. Self-Assessment Checklist
11.1 Understanding
- I can explain DCT and quantization.
- I can compute PSNR from MSE.
- I can describe packetization tradeoffs.
11.2 Implementation
- Compression ratio and PSNR reported.
- Packet loss simulation works.
- Deterministic output with fixed parameters.
11.3 Growth
- I can implement entropy coding.
12. Submission / Completion Criteria
Minimum Viable Completion:
- DCT-based compression and reconstruction.
Full Completion:
- Packetization and PSNR reporting.
Excellence (Going Above & Beyond):
- Add entropy coding and restart markers.