JPEG:‎是一种使用有损压缩方法保存的图像格式。作为压缩的结果,输出图像是存储大小和图像质量之间的权衡。用户可以调整压缩级别以达到所需的质量级别,同时减小存储大小。如果对图像应用 10:1 压缩,图像质量的影响可以忽略不计。压缩值越高,图像质量下降越高。‎

JPEG压缩步骤

  1. 转换:将RGB格式的无压缩图片转换为YUV(亮度/色度)图片
  2. 降采样:对色度信息降采样,对亮度信息不做改变,可以减少色度信息的体积。(大面积着色原理)
  3. 分块:如果行数或列数不是 8 的倍数,则每个颜色分量的像素按称为"数据单位"的 8×2 像素组进行组织,底部行和最右侧列重复。‎
  4. DCT变换:对每个分块做DCT变换,每个分块最终得到一个8x8的数据块
  5. 量化:将变数据的值(浮点数)除以一个量化系数(QC),然后舍入为整数。
  6. 编码:对每个数据块使用游程编码(RLE)和Huffman编码
  7. 添加文件头

JPEG文件结构

JPEG文件内部使用分段的格式存储,每个分段的开始都是0xff,0xff后紧跟分段的标志,下面是各种分段对应的标志和分段的作用。

其中,带有载荷(Payload)的分段的载荷有特定的格式。

JPEG格式解析

一段C语言程序,能够将文件的各个段解析出来,直到遇到SOS段。

#include<stdio.h>
#include<malloc.h>
#include<math.h>
#include<string.h>typedef unsigned char byte;
typedef struct _app0_info_struct
{char format[5];byte main_ver;byte sub_ver;byte unit;short x_den;short y_den;byte thumb_x;byte thumb_y;
} AppInfo;typedef struct _sof0_info_struct {byte accur;short height;short width;byte comp;
} SOF0Info;typedef struct _sof0_comp_struct
{byte comId;byte sample;byte dqt_no;
} SOF0Comp;typedef struct _dht_struct {byte info;byte bit_table[16];
} DHTInfo;enum READ_S {INIT, FIND_SEG_START, READ_SEG_LENGTH, READ_SEG_CONT, COMMIT_SEG_INFO, END};
enum SEG_T {SOI=0xD8, EOI=0xD9, SOF0=0xC0, SOF1=0xC1, DHT=0xC4, SOS=0xDA, DQT=0xDB, DRI=0xDD, APP0=0xE0, APP1=0xE1, APP2=0xE2, COM=0xFE};void short_reverse(short *t){byte * ts = (byte *) t;ts[0] = ts[0] ^ ts[1];ts[1] = ts[0] ^ ts[1];ts[0] = ts[0] ^ ts[1];
}void read_app0(int len, byte * info){AppInfo app_info;memcpy(&app_info, info, len);short_reverse(&(app_info.x_den));short_reverse(&(app_info.y_den));printf("\t\t- format: %s\n", app_info.format);printf("\t\t- mVer: %d, sVer: %d\n", app_info.main_ver, app_info.sub_ver);printf("\t\t- unit: %d, x_den: %d, y_den: %d\n", app_info.unit, app_info.x_den, app_info.y_den);printf("\t\t- thumb: x: %d, y: %d\n", app_info.thumb_x, app_info.thumb_y);
}void read_sof0(int len, byte * info) {SOF0Info sof_info;SOF0Comp sof_comp;sof_info.accur = *info;info += 1;sof_info.height = *((short *) (info));info += 2;sof_info.width = *((short *) (info));info += 2;sof_info.comp = *info;info++;short_reverse(&(sof_info.height));short_reverse(&(sof_info.width));printf("\t\t- Accur: %d\n", sof_info.accur);printf("\t\t- Height: %d, Width: %d\n", sof_info.height, sof_info.width);printf("\t\t- Comps: %d\n", sof_info.comp);for(int i=0;i<sof_info.comp;i++){memcpy(&sof_comp, info + (i * 3), 3);printf("\t\t- Comp Id: %d, sample: %d, dqt: %d\n", sof_comp.comId, sof_comp.sample, sof_comp.dqt_no);}
}void read_dht(int len, byte *info){DHTInfo dht_info;memcpy(&dht_info, info, sizeof(DHTInfo));printf("\t\t- DHT#%d, %cC\n", dht_info.info>>4, dht_info.info&1?'A':'D');printf("\t\t- BitTable: ");int sum = 0;for(int i=0;i<16;i++){printf("%02x ", info[3+i]);sum += info[3+i];};printf(" (sum: %d)\n", sum);printf("\t\t- ValueTable: ");for(int i=0;i<sum && i<20;i++){printf("%02x ", info[3 + 16 +i]);};if(sum>=20) printf("...");printf("\n");
}int main(){printf("class2, analyze jpg file\n");FILE *fp;byte next_char;int read_state;enum READ_S s = INIT;short seg_len = 0;fp = fopen("./example_4.jpg", "r");enum SEG_T seg_t;while(1) {if(s==END) {break;}fread(&next_char, 1, 1, fp);if(next_char==0xff) {//printf("Read 0xff, skip to next byte\r\n");s  = FIND_SEG_START;continue;}if(s==INIT){if(next_char==0xff) {printf("Read next sector..\r\n");s  = FIND_SEG_START;}}else if(s==FIND_SEG_START) {printf("SEG \tLABEL: \t(%02x)", next_char);seg_t =  next_char;switch (seg_t){case SOI: printf("SOI: Start of Image\n"); break;case APP0: printf("APP0 Application specific\n"); break;case APP1: printf("APP1 Application specific\n"); break;case APP2: printf("APP2 Application specific\n"); break;case DQT: printf("DQT Define Quantization Table\n"); break;case SOF0: printf("SOF0 Start of Frame\n"); break;case DHT: printf("DHT Define Huffman Tables\n"); break;case SOS: printf("SOS Start Of Scan\n"); break;default:s = END;printf("UNKOWN: %02x", next_char);continue;break;}s = READ_SEG_LENGTH;}else if(s==READ_SEG_LENGTH){fseek(fp, -1, SEEK_CUR);byte *_seg_len = (byte *) malloc(sizeof(byte)*2);fread(_seg_len, 1, 2, fp);short_reverse((short *) _seg_len);seg_len = *((short *) _seg_len) - 2;free(_seg_len);printf("\tLEN: \t(%d)%04x\n", seg_len, seg_len);s = READ_SEG_CONT;}else if(s==READ_SEG_CONT) {fseek(fp, -1, SEEK_CUR);byte * info = (byte *) malloc(sizeof(byte)*seg_len);fread(info, 1, seg_len, fp);printf("\tINFO: \t");for(int i=0;i<seg_len && i<20;i++) {printf("%02X ", info[i]);}if(seg_len>20) printf("...");printf("\r\n");if(seg_t==APP0){read_app0(seg_len, info);}else if(seg_t==SOF0) {read_sof0(seg_len, info);}else if(seg_t==DHT){read_dht(seg_len, info);}printf("\n");free(info);s = INIT;}}return 0;
}

解析例子,解析某个JPEG文件的输出:


class2, analyze jpg file
SEG     LABEL:  (d8)SOI: Start of Image
SEG     LABEL:  (e0)APP0 Application specificLEN:    (14)000eINFO:   4A 46 49 46 00 01 01 01 01 2C 01 2C 00 00 - format: JFIF- mVer: 1, sVer: 1- unit: 1, x_den: 300, y_den: 300- thumb: x: 0, y: 0SEG     LABEL:  (e2)APP2 Application specificLEN:    (3158)0c56INFO:   49 43 43 5F 50 52 4F 46 49 4C 45 00 01 01 00 00 0C 48 4C 69 ...SEG     LABEL:  (db)DQT Define Quantization TableLEN:    (65)0041INFO:   00 03 02 02 03 02 02 03 03 03 03 04 03 03 04 05 08 05 05 04 ...SEG     LABEL:  (db)DQT Define Quantization TableLEN:    (65)0041INFO:   01 03 04 04 05 04 05 09 05 05 09 14 0D 0B 0D 14 14 14 14 14 ...SEG     LABEL:  (c0)SOF0 Start of FrameLEN:    (15)000fINFO:   08 02 AB 04 00 03 01 11 00 02 11 01 03 11 01 - Accur: 8- Height: 683, Width: 1024- Comps: 3- Comp Id: 1, sample: 17, dqt: 0- Comp Id: 2, sample: 17, dqt: 1- Comp Id: 3, sample: 17, dqt: 1SEG     LABEL:  (c4)DHT Define Huffman TablesLEN:    (27)001bINFO:   00 00 03 01 01 01 01 01 01 01 00 00 00 00 00 00 00 01 02 03 ...- DHT#0, DC- BitTable: 01 01 01 01 01 01 01 00 00 00 00 00 00 00 01 02  (sum: 10)- ValueTable: 03 00 04 05 06 07 08 09 00 00 SEG     LABEL:  (c4)DHT Define Huffman TablesLEN:    (69)0045INFO:   10 00 01 03 02 04 04 04 03 06 05 03 04 02 01 01 09 01 00 02 ...- DHT#1, DC- BitTable: 03 02 04 04 04 03 06 05 03 04 02 01 01 09 01 00  (sum: 52)- ValueTable: 02 11 03 21 04 12 31 41 05 13 51 61 06 22 71 81 14 32 91 07 ...SEG     LABEL:  (c4)DHT Define Huffman TablesLEN:    (26)001aINFO:   01 00 03 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01 02 ...- DHT#0, AC- BitTable: 01 01 01 01 01 01 00 00 00 00 00 00 00 00 00 01  (sum: 7)- ValueTable: 02 03 04 05 06 07 08 SEG     LABEL:  (c4)DHT Define Huffman TablesLEN:    (57)0039INFO:   11 00 02 02 01 03 03 01 05 06 06 03 01 00 02 02 03 00 01 02 ...- DHT#1, AC- BitTable: 02 01 03 03 01 05 06 06 03 01 00 02 02 03 00 01  (sum: 39)- ValueTable: 02 11 03 12 21 31 04 13 41 51 05 14 22 61 71 06 32 81 91 a1 ...SEG     LABEL:  (da)SOS Start Of ScanLEN:    (10)000aINFO:   03 01 00 02 11 03 11 00 3F 00 SEG     LABEL:  (00)UNKOWN: 00

【作业】JPG文件格式分析相关推荐

  1. 【数据压缩】第三周作业——WAV文件格式分析

    1 WAV文件格式概述 WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows ...

  2. 【数据压缩2】PNG文件格式分析

    目录 PNG文件格式概述 文件结构 PNG数据块结构 实例分析 关键数据块分析 (1)IHDR数据块 (2)PLTE调色板数据块 (3)IDAT图像数据块 (4)IEND图像结束数据 辅助数据块分析 ...

  3. PE文件和COFF文件格式分析——导出表的应用——一种摘掉Inline钩子(Unhook)的方法

    在日常应用中,某些程序往往会被第三方程序下钩子(hook).如果被下钩子的进程是我们的进程,并且第三方钩子严重影响了我们的逻辑和流程,我们就需要把这些钩子摘掉(Unhook).本件讲述一种在32位系统 ...

  4. PE文件和COFF文件格式分析——导出表的应用——通过导出表隐性加载DLL

    通过导出表隐性加载DLL?导出表?加载DLL?还隐性?是的.如果觉得不可思议,可以先看<PE文件和COFF文件格式分析--导出表>中关于"导出地址表"的详细介绍.(转载 ...

  5. PE文件和COFF文件格式分析——导出表的应用——一种插件模型

    可能在很多人想想中,只有DLL才有导出表,而Exe不应该有导出表.而在<PE文件和COFF文件格式分析--导出表>中,我却避开了这个话题.我就是想在本文中讨论下载Exe中存在导出表的场景. ...

  6. PE文件和COFF文件格式分析——导出表

    在之前的<PE可选文件头>相关博文中我们介绍了可选文件头中很多重要的属性,而其中一个非常重要的属性是(转载请指明来源于breaksoftware的CSDN博客) IMAGE_DATA_DI ...

  7. PE文件和COFF文件格式分析——RVA和RA相互计算

    之前几节一直是理论性质的东西非常多.本文将会讲到利用之前的知识得出一个一个非常有用的一个应用.(转载请指明来源于breaksoftware的csdn博客) 首先我们说下磁盘上A.exe文件和正在内存中 ...

  8. PE文件和COFF文件格式分析——节信息

    在<PE文件和COFF文件格式分析--签名.COFF文件头和可选文件头3>中,我们看到一些区块的信息都有偏移指向.而我们本文讨论的节信息是没有任何偏移指向的,所以它是紧跟在可选文件头后面的 ...

  9. PE文件和COFF文件格式分析--概述

    刚工作的时候,我听说某某大牛在做病毒分析时,只是用notepad打开病毒文件,就能大致猜到病毒的工作原理.当时我是佩服的很啊,同时我也在心中埋下了一个种子:我也得有这天.随着后来的工作进行,一些任务的 ...

  10. Linux内核文件vmlinux 和压缩后的bzImage文件格式分析

    Linux内核文件vmlinux 和压缩后的bzImage文件格式分析 ================= 1. 需要使用的命令 ================ readelf    -- 显示el ...

最新文章

  1. gps卫星位置计算程序matlab_卫星空间大地测量中GPS周跳探测的四种方法
  2. xFace3.x 开发技巧(1)---从web开发转向移动开发
  3. 最常见的HTTP错误
  4. 盒子模型阴影设置,爱奇艺阴影配置
  5. You must install pydot and graphviz for plotmodel to work报错如何处理
  6. 从零开始学视觉Transformer (8):卷积和Transformer结合的ViT
  7. 诗与远方:无题(五十四)- 曾经写给妹子的一首诗
  8. php mysql pdo出错_PHP / MySQL / PDO – 结果为false但没有DB错误消...
  9. 施密特:下个千亿美元市值公司将出在哪个行业
  10. 纯文字游戏编辑器_重新认识CocosCreator系列之三:立Flag啦,文字游戏编辑器!...
  11. 在c++和C中,malloc函数的头文件是什么?C头文件, <stdlib.h>;C++头文件, <cstdlib>
  12. Linux下查看用户列表和删除用户,详例
  13. python 回归方程及回归系数的显著性检验_使用Excel和python来做回归分析
  14. 初学者 深度学习 人工神经网络 可视化网站
  15. Premiere Pro 快捷键大全(2023版)
  16. 复利现值系数怎么用计算机计算,复利现值系数计算方法是怎样的?
  17. 如何理解最小相位信号就是振幅谱相同的信号中群延迟最小的那个?
  18. MIPI DSI协议
  19. 一文教你Kali信息收集
  20. 点关于点旋转计算新坐标

热门文章

  1. 特征工程:分类变量的处理方式总结
  2. 【渝粤题库】陕西师范大学400003西方政治思想史 作业(专升本)
  3. 新手必看 如何做好跨境电商
  4. net-tools is needed by mysql-community-server-5.7.21-1.el7.x86_64
  5. 挖掘机包络图matlab_matlab机器人 生成空间轨迹包络图(7)
  6. 单片机串口IAP原理
  7. 蓝桥杯比赛单片机文件组织
  8. 从游戏设计机制以及玩家心理特征到互联网产品
  9. QTreeView使用总结11,数据过滤,使用代理model,简单过滤
  10. RH135---Linux系统管理及网络服务之 linux中内核及加强型火墙管理 --Selinux