文章目录

  • 前奏
  • jpg图片对比
  • jpg图片格式详解
  • 段的一般结构
  • 段类型
  • SOI文件头
  • APP0图像识别信息
  • DQT定义量化表
  • SOF0图像基本信息
  • DHT定义huffman表
  • SOS扫描行开始(图像数据开始)
  • EOI扫描行结尾
  • 其他段
    • COM(注释)
    • DRI(定义重新开始间隔)
  • JPEG压缩编码实例
  • 红色色块编码
  • 黑色色块编码
  • 对比结果
    • 开头:
    • 结尾
    • 省略部分分析

前奏

上次做了那个CTFBlink之后,对.jpg图片挺好奇的,于是准备来研究一下

jpg图片对比

jpg图片格式详解

JPEG图片格式组成部分:SOI(文件头)+APP0(图像识别信息)+DQT(定义量化表)+SOF0(图像基本信息)+DHT(定义Huffman表)+DRI(定义重新开始间隔)+SOS(扫描行开始)+EOI(文件尾)

JPEG文件的每个段都一定包含两部分一个是段的标识,它由两个字节构成:第一个字节是十六进制0xFF,第二个字节对于不同的段,这个值是不同的。

紧接着的两个字节存放的是这个段的长度(除了前面的两个字节0xFF和0xXX,X表示不确定。它们是不算到段的长度中)。

段的一般结构

名称 字节数 数据 说明
段标识 1 FF 每个新段的开始标识
段类型 1 类型编码(称作“标记码”)
段长度 2 包括段内容和段长度本身,不包括段标识和段类型
段内容 <=65533字节

段类型

段类型 标记码 说明
SOI D8 文件头
EOI D9 文件尾
SOF0 C0 帧开始(标准 JPEG)
SOF1 C1 同上
DHT C4 定义Huffman表(霍夫曼表)
SOS DA 扫描行开始
SOS DB 定义量化表
DRI D0 定义重新开始间隔
APP0 E0 定义交换格式和图像识别信息
COM FE 注释

说明:有的文章也将DNL段(标记码=DC,定义扫描行数)列为必须段

PS:段类型有30种,但只有10种是必须被所以程序识别的,其它的类型都可以忽略

SOI文件头

JPEG文件的开始2个字节都是FF D8这是JPEG协议规定的

名称 字节数
段标识 1 FF
段类型 1 D8

也就是这两个字节构成了JPEG文件头

APP0图像识别信息

APP0(图像识别信息)

名称 字节数 说明
段标识 1 FF
段类型 1 E0
段长度 2 0010 如果有RGB缩略图就=16+3*n(以下为段内容)
交换格式 5 4A46494600 “JFIF”的ASCII码
主版本号 1
次版本号 1
密度单位 1 0=无单位;1=点数/英寸;2=点数/厘米
X像素密度 2 水平方向的密度
Y像素密度 2 垂直方向的密度
缩略图X像素 1 缩略图水平像素数目
缩略图Y像素 1 缩略图垂直像素数目
(如果“缩略图X像素”和缩略图Y像素的值均>0,那么才有下面的数据)
n=缩略图像素总数=缩略图X像素*缩略图Y像素
  1. JFIF是JPEG File Interchange Forma的缩写,即JPEG文件交换格式,另外还有TIFF等格式,很少用
  2. “如果有RGB缩略图就=16+3*n”是什么意思呢?比如说“缩略图X像素”和“缩略图Y像素”的值均为48,就表示有一个48*48像素的缩略图(n=48*48),缩略图是24位真彩位图,用3个字节来表示一个像素,所以共占有3*n个字节。但大多数JPG文件都没有这个缩略图

  1. 图像识别信息头:2个字节 FF E0
  2. 段长度:00 10 =>16个字节
  3. 交换格式:4A 46 49 46 00=>此处为’JFIF’,一般我们用的都是JFIF的jpeg交换格式,但是也有TFIF的jpeg的交换格式,如果camera sensor直接输出的是jpeg图片,那么在其sensor寄存器可以设置使用JFIF还是TFIF
  4. 主版本号和次版本号一共2个字节:01 01 =>说明主版本号和次版本号都为1
  5. 单位密度1个字节:00=>表示此处使用的是无单位
  6. X像素密度2个字节:00 01 =>水平像素密度是1
  7. Y像素密度2个字节:00 01 =>水平像素密度是1
  8. 缩略图X像素:00=>没有缩略图
  9. 缩略图Y像素:00=>没有缩略图
  10. RGB缩略图:此处没有缩略图,所以是空的

DQT定义量化表

DQT(定义量化表)

名称 字节数 说明
段标识 1 FF
段类型 1 DB
段长度 2 43 其值=3+n(当只有一个QT时)(以下为段内容)
QT信息 1 0~3:QT号 ;4~7位:QT精度(0=8bit,1字节;否则=16bit,2字节)
QT n n=64*QT精度的字节数

说明:

  1. JPEG文件一般有2个DQT段,为Y值(亮度)定义1个,为C值(色度)定义1个
  2. 一个DQT段可以包含多个QT,每个都有自己的信息字节

此处有两个DQT数据,第一个是亮度的,第二个是色度的

  1. 定义量化表的头2个字节:FF DB
  2. 段长度2个字节: 00 43=>3(段长度2个字节,QT信息1个字节)+QT量化表的长度,此处QT量化表的长度是64
  3. QT信息1个字节:00=>0-3位是QT号,4-7位QT精度,此处是0,所以精度是8bit,即1个字节
  4. QT量化表:这个长度时根据QT信息确定的,上面QT精度为8bit,所以此处是64*1=64个字节

  1. 定义量化表的头2个字节:FF DB
  2. 段长度2个字节: 00 43=>3(段长度2个字节,QT信息1个字节)+QT量化表的长度,此处QT量化表的长度是64
  3. QT信息1个字节:01=>0-3位是QT号,即QT号是1,4-7位QT精度,此处是0,所以精度是8bit,即1个字节
  4. QT量化表:这个长度时根据QT信息确定的,上面QT精度为8bit,所以此处是64*1=64个字节

SOF0图像基本信息

SOF0(图像基本信息)

名称 字节数 说明
段标识 1 FF
段类型 1 C0
段长度 2 其值=8+组件数量*3 (以下为段内容)
样本精度 1 8 每个样本位数(大多数软件不支持12和16)
图片高度 2
图片宽度 2
组件数量 1 3 1=灰度图,3=YCbCr/YIQ,4=CMYK 彩色图(以下每个组件占用3个字节)
组件 ID 1 1=Y,2=Cb,3=Cr,4=I,5=Q
采样系数 1 0-3位:垂直采样系数 ;4-7位:水平采样系数
量化表号 1

说明:

  1. JPEG大都采用yCrCb色彩模型(y表示亮度,Cr表示红色分量,Cb表示蓝色分量),所以组件数量一般=3
  2. 样本就是单个像素的颜色分量,也可理解为一个样本就是一个组件
  3. 采样系数是实际采样方式与最高采样系数之比,而最高采样系数一般=0.5(分数表示为1/2)。比如说,垂直采样系数=2,那么2*0.5=1,表示实际采样方式是每个点采一个样,也就是逐点采样;如果垂直采样系数为1,那么:1*0.5=0.5(分数表示为1/2),表示每两个点采一个样

  1. 图像基本信息:FF C2(不知道为什么我这里是C2,我查到的是C0)
  2. 段长度2个字节:00 11 =>17=8+3*3,说明组件数量有3个
  3. 样本精度1个字节:08,每个样本的信息是8bit
  4. 样本高度2个字节:01 84 =>388图片高度与实际一致
  5. 样本宽度2个字节:02 6C =>620图片宽度与实际一致
  6. 组件数量1个字节:03=>代表YCbCr彩色图,有三个组件分别是Y,Cb,Cr
  7. 每个组件占用3个字节:第一个字节是组件ID,第二个字节是采样系数,第三个字节是量化表号

此处是:

  1. 01 11 00=>Y组件,垂直采样系数和水平采样系数都是1,量化标号是0
  2. 02 11 01=>Cb组件,垂直采样系数和水平采样系数都是1,量化标号是1
  3. 03 11 01=>Cr组件,垂直采样系数和水平采样系数都是1,量化标号是1

//此处可知三个组件都是隔点采样(标准的YUV422数据:Y采样是逐点采样,CbCr都是隔点采样)

DHT定义huffman表

DHT(定义Huffman表)

名称 字节数 说明
段标识 1 FF
段类型 1 DB
段长度 2 其值=19+n(当只有一个HT表时)(以下为段内容)
HT信息 1 0-3:HT号;4位:HT类型,0=DC表,1=AC表;5-7位:必须=0
HT位表 16 这16个数的和应该<=256
HT值表 n n=表头16个数的和

说明:

  1. JPEG文件里有2类Haffman表:一类用于DC(直流量),一类用于AC(交流量)。一般有4个表:亮度的DC和AC,色度的AC和DC。最多可有6个
  2. 一个DHT段可以包含多个HT表,每个都有自己的信息字节
  3. HT表是一个按递增次序代码长度排列的符号表

  1. 定义Huffman表头2个字节:FF C4
  2. 段长度2个字节:00 1D=>29=19(段长度2字节+HT信息1个字节+HT位表16个字节)+10(这个数代表HT表有10字节)
  3. HT信息1个字节:0-3位是HT号,4位是HT类型(0=DC表,1=AC表),5-7位必须为0。HT号位0,此表为DC表
  4. HT位表16个字节:这10个数字值和小于等于256
01 00 02 02 03 01 01 00 00 00 00 00 00 00 00  00=>共16个字节,加起来10(此处和段长度是相匹配的),说明HT表有10字节
  1. HT值表:
00 07 08 01 06 02 04 05 09 03

  1. 定义Huffman表头2个字节:FF C4
  2. 段长度2个字节:00 1C=>28=19(段长度2字节+HT信息1个字节+HT位表16个字节)+9(这个数代表HT表有9字节)
  3. HT信息1个字节:0-3位是HT号,4位是HT类型(0=DC表,1=AC表),5-7位必须为0。HT号位1,此表为AC表
  4. HT位表16个字节:这10个数字值和小于等于256
01 00 01 05 01 01 00 00 00 00 00 00 00 00 00 00=>共16个字节,加起来9(此处和段长度是相匹配的),说明HT表有9字节
  1. HT值表:
 00 01 02 03 04 05 07 06 08

SOS扫描行开始(图像数据开始)

SOS扫描行开始

名称 字节数 说明
段标识 1 FF
段类型 1 DA
段长度 2 000C 其值=6+2*扫描行内组件数量 (以下为段内容)
扫描行内组件数量 1 3 必须>=1,<=4(否则错误),通常=3(以下每个组件占用2字节)
组件ID 1 1=Y,2=Cb,3=Cr,4=I,5=Q
Huffman表号 1 0-3位:AC表号(其值=0……3);4-7位:DC表号(其值=0……3)
剩余3个字节 3 最后3个字节用途不明,忽略

说明:

  1. 紧跟SOS段后的是压缩的图像数据(一个个扫描行),数据存放顺序是从左到右,从上到下(经过压缩算法处理过后的)。

  1. 扫描行开始的头:FF DA
  2. 段长度2个字节:00 0C=>12=6(2个字节的段长度+1个字节扫描行内组件数量+3个字节的剩余位)+2*3(扫描行内组件数量,每个组件2个字节)
  3. 扫描行内组件数量,1个字节:03=>代表组件数量数3
  4. 每个组件占用2个字节:
    第一个字节是组件ID(1=Y,2=Cb,3=Cr,4=I,5=Q);第二个字节0-3AC表,4-7位是DC表。表号的值是0-3

01 00=>Y组件,AC表号是0,DC表号是0
02 10=>Cb组件,AC表号是0,DC表号是1
03 10=>Cr组件,AC表号是0,DC表号是1

EOI扫描行结尾

名称 字节数
段标识 1 FF
段类型 1 D9

这两个字节构成了JPEG文件尾

其他段

COM(注释)

名称 字节数 说明
段标识 1 FF
段类型 1 FE
段长度 2 其值=注释字符的字节数+2
段内容 注释字符

说明:有的JPEG文件没有这个段

DRI(定义重新开始间隔)

名称 字节数 说明
段标识 1 FF
段类型 1 DD
段长度 2 4(以下为段内容)
开始间隔 2 n 复位标记的间隔距离

说明:

  1. 开始间隔表示在压缩数据流中,每隔n个MCU块就有一个RST标记,RST标记将Huffman的解码数据流复位,DC也重新从0开始,因此,RST标记是一种复位标记
  2. RST标记是一种特殊的段,它只具有段标识和段类型(长度=2字节),但它不是独立的段,只能穿插在数据流中(文件头和文件尾也只有段标识和段类型,却都是独立的段)
  3. RST标记共有8个(RST0-RST7),从RST0起开始使用,然后是RST1……RST7,再从RST0重复
  4. RST标记的标识码是FFD0-FFD7,对应RST0-RST7
  5. 补充:这个不是必须段,很多JPEG都没有

JPEG压缩编码实例

DC是指直流系数,是8X8个像素的平均值;AC是交流系数,是8X8个像素的其它值,压缩数据的排列方式是:亮度DC,AC,色差DC,AC,色差DC,AC

  1. 每个分量如Y分量(DC+AC)完成后,如果还剩下位数,应该舍弃,后面的Cb是从下一个字节重新计算
  2. 如果编码到后面没有压缩数据了,后面实际编码数据用0填充
  3. 如果编码已经完成,那么剩余压缩数据用1填充

红色色块编码

51           45          00          14              51              45              00          7F
01010001    01000101    00000000    00010100        01010001        01000101        00000000    01111111

计算Y亮度分量=>

0101-0001 01-0001-01首先有一个DC系数需要计算出来
DC亮度

计算第一个色差分量 =>

在这里插入代码片

黑色色块编码

28               A2              8A          00          28              A2              8A              00
00101000        10100010        10001010    00000000    00101000        10100010        10001010        00000000

对比结果

开头:

结尾

省略部分分析

至F0行开始就是SOS扫描行,一直往下扫描,被省略的是B30行~4E60行,全是扫描行数据(也就是说全是图像数据),且加密数据,
所以我们尝试一下SOS扫描行开始段结束这里,加一个扫描行结束标志FF D9(那么图片肯定是可以显示出来的(也就是说可以打开),因为它的格式框架是正确的,只是没有内容而已)


然后保存

猜想正确,直接连马赛克都没了。所以的话,马赛克出现的原因只是因为绘图未完整而已(至于怎么个未完整法,因为是加密数据………………)

研究.jpg图片马赛克问题相关推荐

  1. 对图片马赛克区域的覆盖处理

    文章目录 前言 一.基本思路 二.python实现 1.使用的库 2.读取模板数据 3.边缘检测并二值化 4.模板匹配 5.膨胀.闭包.去除亮点 6.叠加到原始图像 总结 前言 前段时间知道了一个去除 ...

  2. matlab检测图片马赛克,python 检测图片是否有马赛克

    原理讲的很清晰,给原博主一个赞 边缘检测之后按照正方形检索来判定是否是马赛克内容 原理知晓了之后就很好做了 话说MATLAB转化为python的过程还是很有趣的 from PIL import Ima ...

  3. python图片马赛克_python 检测图片是否有马赛克

    原理讲的很清晰,给原博主一个赞 边缘检测之后按照正方形检索来判定是否是马赛克内容 原理知晓了之后就很好做了 话说MATLAB转化为python的过程还是很有趣的 from PIL import Ima ...

  4. android马赛克代码,android图片马赛克 mosaic

    android图片马赛克 mosaic https://github.com/shenkaige/andtools/blob/master/src/com/phodev/andtools/utils/ ...

  5. canvas 实现图片局部模糊_HTML5 Canvas图片马赛克模糊动画

    本文作者html5tricks,转载请注明出处 经常可以在网上或者电视上看到被马赛克模糊的图片或者视频,今天我们要利用 HTML代码如下 Change pixel resolution 32 定义了一 ...

  6. Java 简单图片 马赛克,黑白画,珠纹化,油画效果等处理技术 原理及实现 (简单UI)

    Java 图片马赛克,黑白画,珠纹化,油画效果等处理技术 原理及实现 1. 需要用到的包 java.awt // 用于创建用户界面和绘制图形图像的所有类 javax.swing // 提供一组&quo ...

  7. python去除图片马赛克_python 检测图片是否有马赛克

    首先是canny边缘检测,将图片的边缘检测出来,参考博客 原理讲的很清晰,给原博主一个赞 边缘检测之后按照正方形检索来判定是否是马赛克内容 原理知晓了之后就很好做了 话说matlab转化为python ...

  8. 图片马赛克怎么添加?图片马赛克添加方法分享!​

    图片马赛克怎么添加?在图像处理中,打马赛克是一种常用的保护隐私的方法.通过在敏感区域覆盖一层特定颜色的像素块,可以达到遮挡敏感信息的目的.最常见的颜色是黑色和白色,但也可以根据实际需要选择其他颜色.打 ...

  9. OpenCVC++实现图片马赛克效果

    图片马赛克效果 还没开学,在家闲来无事,就自己写了点代码实现了图片马赛克的效果.看了网上很多大佬的文章,决定还是自己动手来试试.配置环境为:OpenCV4.1.2+Visual Studio 马赛克原 ...

最新文章

  1. js的闭包与原型记录
  2. 系统管理员都要知道的 30 个 Linux 系统监控工具
  3. Scala swing和FX
  4. c 和 java 差异_java和C/C++的差异是什么
  5. python 深度 视差 计算_OpenCV-Python教程:49.立体图像的深度图
  6. vue 关闭弹如何销毁子组件_vue中的eventBus会产生内存泄漏吗
  7. mysql 表连接 on_MysQL中表连接中“using”和“on”之间的区别是什么?
  8. (30)FPGA面试技能提升篇(基尔霍夫定律)
  9. 禁用了ssh的密码认证方式导致无法登陆
  10. linux修改私钥的密码,linux使用密钥+密码登录ssh(centos7)
  11. etcd工作原理和部署指南
  12. Excel打开密码怎么解除
  13. html页面设置document类型,htmldocument类型
  14. 多线程并发编程知识点汇总
  15. iOS3DTouch功能实现
  16. 870987-63-6,Ir[dF(CF3)ppy]2(dtbbpy)PF6,(Ir[dF(CF3)ppy]2(dtbpy))PF6铱催化剂
  17. linux系统根文件系统构建
  18. 苏州计算机云联盟协会,【缤FUN社团】计算机协会
  19. Accurate, Dense, and Robust Multi-View Stereopsis论文分析与代码实现(一)
  20. 线下商店如何转型做新零售 怎么样顺利开展新零售模式?

热门文章

  1. 成功解决TypeError: unhashable type: 'numpy.ndarray'
  2. MAT之DT:DT实现根据乳腺肿瘤特征向量高精度预测肿瘤的是恶性还是良性
  3. pyhanlp 两种依存句法分类器
  4. 机器学习-过拟合和欠拟合以及正则化处理
  5. SpringMVC基础配置及使用
  6. NumPy学习笔记(一)
  7. requireJS 从概念到实战
  8. c++入门之浅入浅出类——分享给很多想形象理解的人
  9. 批量正则替换某文件夹中代码(div id=XXXX替换为div id=XXXX)
  10. 为什么我的vc6.0建立工程时显示不能访问类查文件类信息,类查看信息不可用