JPEG概述和头分析(C源码)
原创文章,转载请注明:JPEG概述和头分析(C源码) By Lucio.Yang
部分内容来自:w285868925,JPEG压缩标准
1.JPEG概述
JPEG是一个压缩标准,又可分为标准 JPEG、渐进式JPEG及JPEG2000三种:
①标准JPEG:以24位颜色存储单个光栅图像,是与平台无关的格式,支持最高级
别的压缩,不过,这种压缩是有损耗的。此类型图片在网页下载时只能由上而下依序显 示图片,直到图片资料全部下载完毕,才能看到全貌。
②渐进式 JPEG:渐进式JPG为标准JPG的改良格式,支持交错,可以在网页下载时,先呈现出图片的粗略外观后,再慢慢地呈现出完整的内容,渐进式JPG的文件 比标准JPG的文件要来得小。
③JPEG2000:新一代的影像压缩法,压缩品质更好,其压缩率比标准JPEG高约30%左右,同时支持有损 和无损压缩。一个极其重要的特征在于它能实现渐进传输,即先传输图像的轮廓,然后逐步传输数据,让图像由朦胧到清晰显示。
2.压缩算法
必要性:大数据量的图象信息会给存储器的存储容量,通信干线信道的带宽,以及计算机的处理速度增加极大的压力。单纯靠增加存储器容量,提高信道带宽以及计算机的处理速度等方法来解决这个问题是不现实的,这时就要考虑压缩。
压缩可分为两大类:第一类压缩过程是可逆的,也就是说,从压缩后的图象能够完全恢复出原来的图象,信息没有任何丢失,称为无损压缩;第二类压缩过程是不可逆的,无法完全恢复出原图象,信息有一定的丢失,称为有损压缩。
压缩编码的方法有很多,主要分成以下四大类:(1)象素编码;(2)预测编码;(3)变换编码;(4)其它方法。
选择哪一类压缩,要折衷考虑,尽管我们希望能够无损压缩,但是通常有损压缩的压缩比(即原图象占的字节数与压缩后图象占的字节数之比,压缩比越大,说明压缩效率越高)比无损压缩的高。
JPEG专家组开发了两种基本的压缩算法,一种是采用以离散余弦变换(Discrete
Cosine Transform,DCT)为基础的有损压缩算法,另一种是采用以预测技术为基础的无损压缩算法。使用有损压缩算法时,在压缩比为25:1的情况下,压缩后还原得到的图像与原始图像相比较,非图像专家难于找出它们之间的区别,因此得到了广泛的应用。例如,在VCD和DVD-Video电视图像压缩技术中,就使用JPEG的有损压缩算法来取消空间方向上的冗余数据 为了在保证图像质量的前提下进一步提高压缩比,近年来JPEG专家组正在制定JPEG2000标准,这个标准中将采用小波变换(Wavelet)算法。
JPEG压缩是有损压缩,它利用了人的视角系统的特性,使用量化和无损压缩编码相结合来去掉视角的冗余信息和数据本身的冗余信息。
压缩编码大致分成三个步骤:
1、使用正向离散余弦变换(Forward
Discrete Cosine Transform,FDCT)把空间域表示的图变换成频率域表示的图。
2、使用加权函数对DCT系数进行量化,这个加权函数对于人的视觉系统是最佳的。
3、使用霍夫曼可变字长编码器对量化系数进行编码。
3.标记段简介
压缩后的JPEG文件大体上可以分成以下两个部分:标记码(Tag)加压缩数据。
下面简单介绍标记段。
标记段的结构一般为:
SOI
DQT
DRI
SOF0
DHT
SOS
…
EOI
标记码由两个字节组成,高字节为0XFF,每个标记码之前可以填上个数不限的填充字节0XFF。
下面介绍一些常用的标记码的结构及其含义。
(1)SOI(Start of Image)
标记结构 字节数
0XFF 1
0XD8 1
可作为JPEG格式的判据(JFIF还需要APP0的配合)
(2)APP0(Application)
标记结构 字节数 意义
0XFF 1
0XE0 1
Lp 2 APP0标记码长度,不包括前两个字节0XFF,0XE0
Identifier 5 JFIF识别码 0X4A,0X46,0X49,0X46,0X00
Version 2 JFIF版本号 可为0X0101或者0X0102
Units 1 单位,等于零时表示未指定,为1表示英寸,为2表示
厘米
Xdensity 2 水平分辨率
Ydensity 2 垂直分辨率
Xthumbnail 1 水平点数
Ythumbnail 1 垂直点数
RGB0 3 RGB的值
RGB1 3 RGB的值
…
RGBn 3 RGB的值,n=Xthumbnail*Ythumbnail
APP0是JPEG保留给Application所使用的标记码,而JFIF将文件的相关信息定义在此标记中。
(3)DQT(Define Quantization Table)
标记结构 字节数 意义
0XFF 1
0XDB 1
Lq 2 DQT标记码长度,不包括前两个字节0XFF,0XDB
(Pq,Tq) 1 高四位Pq为量化表的数据精确度,Pq=0时,Q0~Qn的
值为8位,Pq=1时,Qt的值为16位,Tq表示量化表的
编号,为0~3。在基本系统中,Pq=0,Tq=0~1,也就是
说最多有两个量化表。
Q0 1或2 量化表的值,Pq=0时;为一个字节,Pq=1时,为两个
字节
Q1 1或2 量化表的值,Pq=0时;为一个字节,Pq=1时,为两个
字节
…
Qn 1或2 量化表的值,Pq=0时,为一个字节;Pq=1时,为两个
字节。n的值为0~63,表示量化表中64个值(之字形排
列)
(4)DRI(Define Restart Interval)
标记结构 字节数 意义
0XFF 1
0XDD 1
Lr 2 DRI标记码长度,不包括前两个字节0XFF,0XDD
Ri 2 重入间隔的MCU个数,Ri必须是一MCU行中MCU
(5)SOF(Start of Frame) 在基本系统中,只处理SOF0
标记结构 字节数 意义
0XFF 1
0XC0 1
Lf 2 SOF标记码长度,不包括前两个字节0XFF,0XC0
P 1 基本系统中,为0X08
Y 2 图象高度
X 2 图象宽度
Nf 1 Frame中的成分个数,一般为1或3,1代表灰度图,3
代表真彩图
C1 1 成分编号1
(H1,V1) 1 第一个水平和垂直采样因子
Tq1 1 该量化表编号
C2 1 成分编号2
(H2,V2) 1 第二个水平和垂直采样因子
Tq2 1 该量化表编号
…
Cn 1 成分编号n
(Hn,Vn) 1 第n个水平和垂直采样因子
Tqn 1 该量化表编号
(6)DHT(Define Huffman Table)
标记结构 字节数 意义
0XFF 1
0XC4 1
Lh 2 DHT标记码长度,不包括前两个字节0XFF,0XC4
(Tc,Th) 1
L1 1
L2 1
…
L16 1
V1 1
V2 1
…
Vt 1
(7)SOS(Start of Scan)
标记结构 字节数 意义
0XFF 1
0XDA 1
Ls 2 DHT标记码长度,不包括前两个字节0XFF,0XDA
Ns 1
Cs1 1
(Td1,Ta1) 1
Cs2 1
(Td2,Ta2) 1
…
CsNs 1
(TdNs,TaNs) 1
Ss 1
Se 1
(8)EOI(End of Image) 结束标志
标记结构 字节数 意义
0XFF 1
0XD9 1
4.头信息分析实例
/*
* File Name: jpegDe.c
* Author: 576632108@qq.com lucio
* Date: 2014.11.5
* Description: analyze the head info of jpeg
*/
#include <stdio.h>
#include <stdlib.h> typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG; int main(int argc, char **argv){
FILE *fp;
WORD window;
WORD temp;
int i=,j=,k=;
int found_count=;
int mark_head=0xFF;
int mark_part[]={0xD8,0xE0,0xDB,0xDD,0xC0,0xC4,0xDA,0xD9};
char mark_str[][]={"SOI","APP0","DQT","DRI","SOF0","DHT","SOS","EOI"};
int head,part;
int temp_head,temp_part;
int done=;
fp=fopen("KD.jpg","rb");
if(fp==){
printf("Can not open the file to read.\n");
return -;
}
while( ){
fseek(fp,i,SEEK_SET);
if(fread(&window,,,fp)!=){
printf("Can not read the info of the info header.\n");
fclose(fp);
return -;
}
head=window-(window/0x100)*0x100;//靠前的部分是高位
part=window/0x100;//靠后的部分是低位
if( head==mark_head ){
for ( j=;j<;j++ ){
if( part==mark_part[j] ){
printf("%s: %X-%X\n",mark_str[j],head,part);
if( j== ){//APP0
//此处不需要fseek,因为读的过程中指针移动
//Lp
if(fread(&temp,,,fp)!=){
printf("Can not read the info of the info header.\n");
fclose(fp);
return -;
}
temp_head=temp-(temp/0x100)*0x100;
temp_part=temp/0x100;
temp=temp_head+temp_part;
printf(" Lp: %d\n",temp);
//Identifier
printf(" Identifier: ");
for( k=;k<;k++ ){
if(fread(&temp,,,fp)!=){
printf("Can not read the info of the info header.\n");
fclose(fp);
return -;
}
temp_head=temp-(temp/0x100)*0x100;
temp_part=temp/0x100;
if( k!= ) printf("%02X-%02X-",temp_head,temp_part);
else printf("%02X",temp_head);
}
printf("\n");
//Version
fseek(fp,-,SEEK_CUR);
if(fread(&temp,,,fp)!=){
printf("Can not read the info of the info header.\n");
fclose(fp);
return -;
}
temp_head=temp-(temp/0x100)*0x100;
temp_part=temp/0x100;
temp=temp_head+temp_part;
printf(" Version: %02X-%02X\n",temp_head,temp_part);
//Units
if(fread(&temp,,,fp)!=){
printf("Can not read the info of the info header.\n");
fclose(fp);
return -;
}
printf(" Units: %02X\n",temp);
//Xdensity
if(fread(&temp,,,fp)!=){
printf("Can not read the info of the info header.\n");
fclose(fp);
return -;
}
temp_head=temp-(temp/0x100)*0x100;
temp_part=temp/0x100;
temp=temp_head+temp_part;
printf(" Xdensity: %d\n",temp);
//Ydensity
if(fread(&temp,,,fp)!=){
printf("Can not read the info of the info header.\n");
fclose(fp);
return -;
}
temp_head=temp-(temp/0x100)*0x100;
temp_part=temp/0x100;
temp=temp_head+temp_part;
printf(" Ydensity: %d\n",temp);
//Xthumbnail
if(fread(&temp,,,fp)!=){
printf("Can not read the info of the info header.\n");
fclose(fp);
return -;
}
temp_head=temp-(temp/0x100)*0x100;
temp_part=temp/0x100;
printf(" Xthumbnail: %d\n",temp_head);
//Ythumbnail
printf(" Ythumbnail: %d\n",temp_part);
}
i+=;
if( j== ) done=;
break;
}//if
}//for
}//if
i++;
if( done== ) break;
}
fclose(fp);
system("pause");
return ;
}
JPEG概述和头分析(C源码)的更多相关文章
- k8s client-go源码分析 informer源码分析(2)-初始化与启动分析
k8s client-go源码分析 informer源码分析(2)-初始化与启动分析 前面一篇文章对k8s informer做了概要分析,本篇文章将对informer的初始化与启动进行分析. info ...
- JVM源码分析-JVM源码编译与调试
要分析JVM的源码,结合资料直接阅读是一种方式,但是遇到一些想不通的场景,必须要结合调试,查看执行路径以及参数具体的值,才能搞得明白.所以我们先来把JVM的源码进行编译,并能够使用GDB进行调试. 编 ...
- k8s client-go源码分析 informer源码分析(3)-Reflector源码分析
k8s client-go源码分析 informer源码分析(3)-Reflector源码分析 1.Reflector概述 Reflector从kube-apiserver中list&watc ...
- Android源码分析--CircleImageView 源码详解
源码地址为 https://github.com/hdodenhof/CircleImageView 实际上就是一个圆形的imageview 的自定义控件.代码写的很优雅,实现效果也很好, 特此分析. ...
- 一 分析easyswoole源码(启动服务)
分析easyswoole源码 1以启动为例 //检查是否已经安装 installCheck();//检查锁文件是否存在,不存在结束 //启动服务 serverStart showLogo();//显示 ...
- 分析jQuery源码时记录的一点感悟
分析jQuery源码时记录的一点感悟 1. 链式写法 这是jQuery语法上的最大特色,也许该改改POJO里的set方法,和其他的非get方法什么的,可以把多行代码合并,减去每次 ...
- Linux内核(2) - 分析内核源码如何入手(上)
透过现象看本质,兽兽们无非就是一些人体艺术展示.同样往本质里看过去,学习内核,就是学习内核的源代码,任何内核有关的书籍都是基于内核,而又不高于内核的. 既然要学习内核源码,就要经常对内核代码进行分析, ...
- STM32F103 ucLinux开发之一(BOOT分析及源码)
STM32F103 ucLinux开发BOOT STM3210E-EVAL官方开发板主芯片STM32F103ZET6: 片内512K Flash,地址0x0800 0000 ~ 0x0807 FFFF ...
- Activiti架构分析及源码详解
目录 Activiti架构分析及源码详解 引言 一.Activiti设计解析-架构&领域模型 1.1 架构 1.2 领域模型 二.Activiti设计解析-PVM执行树 2.1 核心理念 2. ...
随机推荐
- SQL调优日志--内存问题
SQL调优日志--内存问题排查入门篇 概述 很多系统的性能问题,是由内存导致的.内存不够会导致页面频繁换入换出,IO队列高,进而影响数据库整体性能. 排查 内存对数据库性能非常重要.那么我当出现问 ...
- SQL Server 储存过程的output 参数
要做的参数的回传一方面要做到有储存过程的配合,再一方面也要有调用方法的配合,也就是说错误的调用方法是没有办法把值回传的. 下面是例子 --1.储存过程方面的配合 create procedure db ...
- SQL Server 数据类型陷阱
1. bit 类型:bit(1) 不要以为它只占一个位,事实上它要占一个字节!也就是说当n < 8 时都是这样的! 2. varchar(n) 这里的n不能大于8000,如果想要比8000大你 ...
- Android 5.x新特性之elevation(阴影),tinting(着色)以及clipping(剪裁)
快过年了,公司也没事做了, 自己也闲了下来,一天天呆着真没意思,闲来没事自己研究研究了Google I/O 2014 发布 Material Design设计,人性化的风格,丰富的色彩,使人机交互更完 ...
- CodeForces 235C Cyclical Quest(后缀自动机)
[题目链接] http://codeforces.com/contest/235/problem/C [题目大意] 给出一个字符串,给出一些子串,问每个子串分别在母串中圆环匹配的次数,圆环匹配的意思是 ...
- 1分钟搞定超慢SQL
前几天,一个用户的研发人员找到我了,说他们有个SQL语句非常慢,我说多慢?他们说:半个小时也没出结果.于是问他们要了SQL语句和执行计划,SQL语句就不能再这里贴出来了,下面是调整前的执行计划(略去某 ...
- Ubuntu下lamp(PHP+Mysql+Apache)搭建+完全卸载卸载方法
安装apache2 sudo apt-get install apache2 安装完成,运行如下命令重启下: sudo /etc/init.d/apache2 restart 在浏览器里输入http: ...
- IOS框架概览
iOS是执行在iPhone.iPod Touch或iPad上的操作系统,之前叫做iPhone OS,iOS与Mac OS X有共同的基础架构和底层技术.但iOS是依据移动设备的特点而设计的,所以和Ma ...
- 全国三级城市联动 js版
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- POJ 1459 Power Network(网络流 最大流 多起点,多汇点)
Power Network Time Limit: 2000MS Memory Limit: 32768K Total Submissions: 22987 Accepted: 12039 D ...