研究.jpg图片马赛克问题
文章目录
- 前奏
- 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像素 |
JFIF
是JPEG File Interchange Forma的缩写,即JPEG文件交换格式,另外还有TIFF等格式,很少用- “如果有RGB缩略图就=
16+3*n
”是什么意思呢?比如说“缩略图X像素”和“缩略图Y像素”的值均为48,就表示有一个48*48
像素的缩略图(n=48*48
),缩略图是24位真彩位图,用3个字节来表示一个像素,所以共占有3*n
个字节。但大多数JPG文件都没有这个缩略图
- 图像识别信息头:2个字节 FF E0
- 段长度:00 10 =>16个字节
- 交换格式:4A 46 49 46 00=>此处为’JFIF’,一般我们用的都是JFIF的jpeg交换格式,但是也有TFIF的jpeg的交换格式,如果camera sensor直接输出的是jpeg图片,那么在其sensor寄存器可以设置使用JFIF还是TFIF
- 主版本号和次版本号一共2个字节:01 01 =>说明主版本号和次版本号都为1
- 单位密度1个字节:00=>表示此处使用的是无单位
- X像素密度2个字节:00 01 =>水平像素密度是1
- Y像素密度2个字节:00 01 =>水平像素密度是1
- 缩略图X像素:00=>没有缩略图
- 缩略图Y像素:00=>没有缩略图
- 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精度的字节数 |
说明:
- JPEG文件一般有2个DQT段,为Y值(亮度)定义1个,为C值(色度)定义1个
- 一个DQT段可以包含多个QT,每个都有自己的信息字节
此处有两个DQT数据,第一个是亮度的,第二个是色度的
- 定义量化表的头2个字节:FF DB
- 段长度2个字节: 00 43=>3(段长度2个字节,QT信息1个字节)+QT量化表的长度,此处QT量化表的长度是64
- QT信息1个字节:00=>0-3位是QT号,4-7位QT精度,此处是0,所以精度是8bit,即1个字节
- QT量化表:这个长度时根据QT信息确定的,上面QT精度为8bit,所以此处是64*1=64个字节
- 定义量化表的头2个字节:FF DB
- 段长度2个字节: 00 43=>3(段长度2个字节,QT信息1个字节)+QT量化表的长度,此处QT量化表的长度是64
- QT信息1个字节:01=>0-3位是QT号,即QT号是1,4-7位QT精度,此处是0,所以精度是8bit,即1个字节
- 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 |
说明:
- JPEG大都采用yCrCb色彩模型(y表示亮度,Cr表示红色分量,Cb表示蓝色分量),所以组件数量一般=3
- 样本就是单个像素的颜色分量,也可理解为一个样本就是一个组件
- 采样系数是实际采样方式与最高采样系数之比,而最高采样系数一般=0.5(分数表示为1/2)。比如说,垂直采样系数=2,那么
2*0.5=1
,表示实际采样方式是每个点采一个样,也就是逐点采样;如果垂直采样系数为1,那么:1*0.5=0.5
(分数表示为1/2),表示每两个点采一个样
- 图像基本信息:FF C2(不知道为什么我这里是C2,我查到的是C0)
- 段长度2个字节:00 11 =>17=8+3*3,说明组件数量有3个
- 样本精度1个字节:08,每个样本的信息是8bit
- 样本高度2个字节:01 84 =>388图片高度与实际一致
- 样本宽度2个字节:02 6C =>620图片宽度与实际一致
- 组件数量1个字节:03=>代表YCbCr彩色图,有三个组件分别是Y,Cb,Cr
- 每个组件占用3个字节:第一个字节是组件ID,第二个字节是采样系数,第三个字节是量化表号
此处是:
- 01 11 00=>Y组件,垂直采样系数和水平采样系数都是1,量化标号是0
- 02 11 01=>Cb组件,垂直采样系数和水平采样系数都是1,量化标号是1
- 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个数的和 |
说明:
- JPEG文件里有2类Haffman表:一类用于DC(直流量),一类用于AC(交流量)。一般有4个表:亮度的DC和AC,色度的AC和DC。最多可有6个
- 一个DHT段可以包含多个HT表,每个都有自己的信息字节
- HT表是一个按递增次序代码长度排列的符号表
- 定义Huffman表头2个字节:FF C4
- 段长度2个字节:00 1D=>29=19(段长度2字节+HT信息1个字节+HT位表16个字节)+10(这个数代表HT表有10字节)
- HT信息1个字节:0-3位是HT号,4位是HT类型(0=DC表,1=AC表),5-7位必须为0。HT号位0,此表为DC表
- HT位表16个字节:这10个数字值和小于等于256
01 00 02 02 03 01 01 00 00 00 00 00 00 00 00 00=>共16个字节,加起来10(此处和段长度是相匹配的),说明HT表有10字节
- HT值表:
00 07 08 01 06 02 04 05 09 03
- 定义Huffman表头2个字节:FF C4
- 段长度2个字节:00 1C=>28=19(段长度2字节+HT信息1个字节+HT位表16个字节)+9(这个数代表HT表有9字节)
- HT信息1个字节:0-3位是HT号,4位是HT类型(0=DC表,1=AC表),5-7位必须为0。HT号位1,此表为AC表
- HT位表16个字节:这10个数字值和小于等于256
01 00 01 05 01 01 00 00 00 00 00 00 00 00 00 00=>共16个字节,加起来9(此处和段长度是相匹配的),说明HT表有9字节
- 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个字节用途不明,忽略 |
说明:
- 紧跟SOS段后的是压缩的图像数据(一个个扫描行),数据存放顺序是从左到右,从上到下(经过压缩算法处理过后的)。
- 扫描行开始的头:FF DA
- 段长度2个字节:00 0C=>12=6(2个字节的段长度+1个字节扫描行内组件数量+3个字节的剩余位)+2*3(扫描行内组件数量,每个组件2个字节)
- 扫描行内组件数量,1个字节:03=>代表组件数量数3
- 每个组件占用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 | 复位标记的间隔距离 |
说明:
- 开始间隔表示在压缩数据流中,每隔n个MCU块就有一个RST标记,RST标记将Huffman的解码数据流复位,DC也重新从0开始,因此,RST标记是一种复位标记
- RST标记是一种特殊的段,它只具有段标识和段类型(长度=2字节),但它不是独立的段,只能穿插在数据流中(文件头和文件尾也只有段标识和段类型,却都是独立的段)
- RST标记共有8个(RST0-RST7),从RST0起开始使用,然后是RST1……RST7,再从RST0重复
- RST标记的标识码是FFD0-FFD7,对应RST0-RST7
- 补充:这个不是必须段,很多JPEG都没有
JPEG压缩编码实例
DC是指直流系数,是8X8个像素的平均值;AC是交流系数,是8X8个像素的其它值,压缩数据的排列方式是:亮度DC,AC,色差DC,AC,色差DC,AC
- 每个分量如Y分量(DC+AC)完成后,如果还剩下位数,应该舍弃,后面的Cb是从下一个字节重新计算
- 如果编码到后面没有压缩数据了,后面实际编码数据用0填充
- 如果编码已经完成,那么剩余压缩数据用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图片马赛克问题相关推荐
- 对图片马赛克区域的覆盖处理
文章目录 前言 一.基本思路 二.python实现 1.使用的库 2.读取模板数据 3.边缘检测并二值化 4.模板匹配 5.膨胀.闭包.去除亮点 6.叠加到原始图像 总结 前言 前段时间知道了一个去除 ...
- matlab检测图片马赛克,python 检测图片是否有马赛克
原理讲的很清晰,给原博主一个赞 边缘检测之后按照正方形检索来判定是否是马赛克内容 原理知晓了之后就很好做了 话说MATLAB转化为python的过程还是很有趣的 from PIL import Ima ...
- python图片马赛克_python 检测图片是否有马赛克
原理讲的很清晰,给原博主一个赞 边缘检测之后按照正方形检索来判定是否是马赛克内容 原理知晓了之后就很好做了 话说MATLAB转化为python的过程还是很有趣的 from PIL import Ima ...
- android马赛克代码,android图片马赛克 mosaic
android图片马赛克 mosaic https://github.com/shenkaige/andtools/blob/master/src/com/phodev/andtools/utils/ ...
- canvas 实现图片局部模糊_HTML5 Canvas图片马赛克模糊动画
本文作者html5tricks,转载请注明出处 经常可以在网上或者电视上看到被马赛克模糊的图片或者视频,今天我们要利用 HTML代码如下 Change pixel resolution 32 定义了一 ...
- Java 简单图片 马赛克,黑白画,珠纹化,油画效果等处理技术 原理及实现 (简单UI)
Java 图片马赛克,黑白画,珠纹化,油画效果等处理技术 原理及实现 1. 需要用到的包 java.awt // 用于创建用户界面和绘制图形图像的所有类 javax.swing // 提供一组&quo ...
- python去除图片马赛克_python 检测图片是否有马赛克
首先是canny边缘检测,将图片的边缘检测出来,参考博客 原理讲的很清晰,给原博主一个赞 边缘检测之后按照正方形检索来判定是否是马赛克内容 原理知晓了之后就很好做了 话说matlab转化为python ...
- 图片马赛克怎么添加?图片马赛克添加方法分享!
图片马赛克怎么添加?在图像处理中,打马赛克是一种常用的保护隐私的方法.通过在敏感区域覆盖一层特定颜色的像素块,可以达到遮挡敏感信息的目的.最常见的颜色是黑色和白色,但也可以根据实际需要选择其他颜色.打 ...
- OpenCVC++实现图片马赛克效果
图片马赛克效果 还没开学,在家闲来无事,就自己写了点代码实现了图片马赛克的效果.看了网上很多大佬的文章,决定还是自己动手来试试.配置环境为:OpenCV4.1.2+Visual Studio 马赛克原 ...
最新文章
- js的闭包与原型记录
- 系统管理员都要知道的 30 个 Linux 系统监控工具
- Scala swing和FX
- c 和 java 差异_java和C/C++的差异是什么
- python 深度 视差 计算_OpenCV-Python教程:49.立体图像的深度图
- vue 关闭弹如何销毁子组件_vue中的eventBus会产生内存泄漏吗
- mysql 表连接 on_MysQL中表连接中“using”和“on”之间的区别是什么?
- (30)FPGA面试技能提升篇(基尔霍夫定律)
- 禁用了ssh的密码认证方式导致无法登陆
- linux修改私钥的密码,linux使用密钥+密码登录ssh(centos7)
- etcd工作原理和部署指南
- Excel打开密码怎么解除
- html页面设置document类型,htmldocument类型
- 多线程并发编程知识点汇总
- iOS3DTouch功能实现
- 870987-63-6,Ir[dF(CF3)ppy]2(dtbbpy)PF6,(Ir[dF(CF3)ppy]2(dtbpy))PF6铱催化剂
- linux系统根文件系统构建
- 苏州计算机云联盟协会,【缤FUN社团】计算机协会
- Accurate, Dense, and Robust Multi-View Stereopsis论文分析与代码实现(一)
- 线下商店如何转型做新零售 怎么样顺利开展新零售模式?
热门文章
- 成功解决TypeError: unhashable type: 'numpy.ndarray'
- MAT之DT:DT实现根据乳腺肿瘤特征向量高精度预测肿瘤的是恶性还是良性
- pyhanlp 两种依存句法分类器
- 机器学习-过拟合和欠拟合以及正则化处理
- SpringMVC基础配置及使用
- NumPy学习笔记(一)
- requireJS 从概念到实战
- c++入门之浅入浅出类——分享给很多想形象理解的人
- 批量正则替换某文件夹中代码(div id=XXXX替换为div id=XXXX)
- 为什么我的vc6.0建立工程时显示不能访问类查文件类信息,类查看信息不可用