# simple-jpeg-encoder **Repository Path**: chendilin/simple-jpeg-encoder ## Basic Information - **Project Name**: simple-jpeg-encoder - **Description**: 一个轻量级的 JPEG 编码器实现,非常适合从零开始理解 JPEG 压缩的核心概念 - **Primary Language**: C - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2025-07-03 - **Last Updated**: 2025-10-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README [English](README.md) | 简体中文 | [Wiki (中文)](docs/Wiki.md) | [Wiki (English)](docs/Wiki_en.md) # 一个简单的C语言JPEG编码器 这是一个用C语言实现的、用于学习目的的简单JPEG编码器。它将一个PPM (P6) 格式的图像文件作为输入,并根据指定的质量因子生成一个符合基线DCT标准的JPEG文件。 这个项目的目的是清晰地展示JPEG压缩标准中的核心步骤,代码中包含了详细的中文注释,方便理解。 ## 主要特性 - **PPM输入**: 支持读取二进制的PPM (P6) 格式图像。 - **颜色空间转换**: 实现从 RGB 到 YCbCr 的颜色空间转换。 - **色度二次采样**: 支持 4:2:0 的色度二次采样,减小色度信息的数据量。 - **FDCT**: 对8x8的像素块执行正向离散余弦变换。 - **量化**: 根据用户设定的质量因子(1-100)对DCT系数进行量化。 - **霍夫曼编码**: 使用标准的霍夫曼表对量化后的系数进行编码。 - **标准JPEG输出**: 生成包含标准JPEG标记 (SOI, APP0, DQT, SOF0, DHT, SOS, EOI) 的 `.jpg` 文件。 ## 如何编译 你需要一个C语言编译器,例如 `gcc`。由于代码中使用了数学库 (`math.h`),编译时需要链接该库。 ```bash gcc jpeg_encoder.c -o jpeg_encoder -lm ``` ## 如何使用 编译后,你可以通过命令行运行编码器。 **用法:** ```bash ./jpeg_encoder <输入文件.ppm> <输出文件.jpg> <质量因子> ``` - `<输入文件.ppm>`: 输入的PPM P6格式图像文件。 - `<输出文件.jpg>`: 你想要保存的JPEG文件名。 - `<质量因子>`: 一个从1到100的整数,1表示最低质量,100表示最高质量。 **示例:** ```bash # 使用 "input.ppm" 文件,以80的质量生成 "output.jpg" ./jpeg_encoder input.ppm output.jpg 80 ``` ## JPEG 编码核心流程 本编码器遵循了JPEG基线标准的主要处理流程: 1. **读取PPM文件**: 解析PPM P6格式的头部信息和RGB像素数据。 2. **颜色转换与二次采样**: - 将每个像素的RGB值转换为YCbCr值。Y代表亮度,Cb和Cr代表色度。 - 对色度分量 (Cb, Cr) 进行4:2:0二次采样。这意味着在每2x2的像素块中,只保留一个Cb和一个Cr值,从而有效压缩数据。 3. **分块与Level Shift**: 将图像的每个分量(Y, Cb, Cr)分割成8x8的块,并将像素值从 [0, 255] 的范围平移到 [-128, 127]。 4. **正向离散余弦变换 (FDCT)**: 对每个8x8的块应用FDCT,将其从空间域转换到频率域。转换后,大部分能量会集中在左上角的低频系数上。 5. **量化**: - 根据用户指定的质量因子调整标准量化表。质量越低,量化值越大。 - 将FDCT变换后的8x8系数矩阵中的每个值除以量化表中对应位置的值并取整。这是JPEG压缩中有损处理的关键步骤,高频区域的系数在这一步后大部分会变为0。 6. **Z字形扫描与霍夫曼编码**: - 对量化后的8x8系数矩阵进行Z字形扫描,将二维矩阵转换为一维序列。这样可以把大量的0聚集在一起,方便后续的行程编码。 - **DC系数编码**: 对每个块的DC系数(第一个系数)进行差分编码,然后对差值进行霍夫曼编码。 - **AC系数编码**: 对AC系数(其余63个系数)进行行程编码(Run-Length Encoding, RLE),然后对RLE符号进行霍夫曼编码。 7. **写入JPEG文件**: - 按照JPEG标准格式,依次写入各种标记段(如DQT定义量化表,DHT定义霍夫曼表等)。 - 将编码后的压缩数据写入文件。 - 最后以EOI(图像结束)标记结尾。 ## 许可证 本项目采用 [MIT许可证](LICENSE)。