JPEG2000压缩部分程序 用户名sff0605030213 密码13039979823
#include<stdio.h>
int CX,D,flg=0;
FILE*fin,*fout;
unsigned long A,C,BP,CT,B;
//LPS符号的值
unsigned long Qe[50]=
{0x5601,0x3401,0x1801,0x0ac1,0x0521,0x0221,0x5601,0x5401,
0x4801,0x3801,0x3001,0x2401,0x1c01,0x1601,0x5601,0x5401,
0x5101,0x4801,0x3801,0x3401,0x3001,0x2801,0x2401,0x2201,
0x1c01,0x1801,0x1601,0x1401,0x1201,0x1101,0x0ac1,0x09c1,
0x08a1,0x0521,0x0441,0x02a1,0x0221,0x0141,0x0111,0x0085,
0x0049,0x0025,0x0015,0x0009,0x0005,0x0001,0x5601};
//MPS编码时引起重归一化的情况下的下一个索引
unsigned long NMPS[50]=
{1,2,3,4,5,38,7,8,9,10,11,12,13,29,15,16,17,18,
19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,
35,36,37,38,39,40,41,42,43,44,45,45,46};
//LPS编码时引起重归一化的情况下的下一个索引
unsigned long NLPS[50]=
{1,6,9,12,29,33,6,14,14,14,17,18,20,21,14,14,15,
16,17,18,19,19,20,21,22,23,24,25,26,27,28,29,30,
31,32,33,34,35,36,37,38,39,40,41,42,43,46};
//MPS符号和LPS符号的检测翻转开关
unsigned int SWITCH[50]=
{1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0};
//19个CX符号对应的MPS符号
unsigned int MPS[20]={0,1,0,1,1,1,0,0,1,1,0,1,0,1,1,0,1,1,1};
//19个CX符号对应的索引值
unsigned int I[20]={0,3,1,6,7,9,11,13,16,25,32,10,8,21,18,28,17,23,30};
void INITENC();
void ENCODE();
void CODE1();
void CODE0();
void CODELPS();
void CODEMPS();
void RENORME();
void BYTEOUT();
void FLUSH();
void SETBITS();
void finput(char ch);
void foutput();
//初始化过程
void INITENC()
{
A=0x8000;//将A寄存器初始化为下限值0x8000(0.75)
C=0;//将C寄存器初始化为下限值0
if(flg==0)//对第一块编码时,B的初始值为0,否则
{//按上一块编码遗留的值
B=0;
flg=1;
}
CT=12;//将重归一化移位计数器初始化为12
if(B==0xFF)//若初始时B有0xFF的值,则需要进行位填充,
CT=13;//将CT置为13
}
//判决编码过程
void ENCODE()
{
if(D==0)
CODE0();//判决位为0的编码
else
CODE1();//判决位为1的编码
}
//判断对判决1调用的编码
void CODE1(){
if(MPS[CX]==1)//1为大概率符号进行MPS编码
CODEMPS();
else
CODELPS();//1为小概率符号进行LPS编码
}
//判断对判决0调用的编码
void CODE0()
{
if(MPS[CX]==0)//0为大概率符号进行MPS编码
CODEMPS();
else
CODELPS();//0为小概率符号进行LPS编码
}
//LPS编码过程
void CODELPS()
{
A=A-Qe[I[CX]];//计算MPS的概率区间的长度
if(A<Qe[I[CX]])//若MPS<LPS,区间交换,A值不变,
C=C+Qe[I[CX]];//改变区间下限C
else
A=Qe[I[CX]];//若MPS>LPS,A值取LPS概率,下限C不变
if(SWITCH[I[CX]]==1)//反转MPS符号检测
MPS[CX]=1-MPS[CX];
I[CX]=NLPS[I[CX]];//新索引设置
RENORME();//进行重归一化
}
//MPS编码过程
void CODEMPS()
{
A=A-Qe[I[CX]];//计算MPS的概率区间的长度
if(A&0x8000==0)//比较A与0x8000(0.75)的大小
{
if(A<Qe[I[CX]])//若MPS<LPS,区间交换,A值取LPS概率,
A=Qe[I[CX]];//下限C不变else//若MPS>LPS,区间交换,A值不变,
C=C+Qe[I[CX]];//改变区间下限C
I[CX]=NMPS[I[CX]];//新索引设置
RENORME();//进行重归一化
}
else
C=C+Qe[I[CX]];//若A大于0x8000(0.75),更新区间下限C
}
//重归一化过程
void RENORME()
{
while((A&0x8000)==0)//若A小于0x8000,则循环进行移位
{
A=A<<1;//A左移一位
C=C<<1;//为与A保持在同一精度,C也要左移一位
CT=CT-1;//移位计数器减一
if(CT==0)//移位计数器达到0时,进行压缩输出
BYTEOUT();
}
}
//压缩数据输出
void BYTEOUT()
{
if(B==0xFF)//B有0xFF的值,进行位填充
{
foutput();
B=C>>20;
C=C&0xFFFFF;
CT=7;
return;
}
else
{
if(C<0x8000000)//若进位位是0,直接输出
{foutput();//输出一个字节
B=C>>19;//将C的高位20位以后置B
C=C&0x7FFFF;//只将C的低位19位置新的C
CT=8;//移位计数器置为8
return;
}
else//若进位位1
{
B=B+1;//给输出缓冲字节加1
if(B==0xFF)//若B加一后达到0XFF,进行位填充
{
C=C&0x7FFFFFF;//清除进位位,以下为位填充过程
foutput();
B=C>>20;
C=C&0xFFFFF;
CT=7;
return;
}
else//若未达到0xFF,无需进行位填充
{
foutput();
B=C>>19;
C=C&0x7FFFF;
CT=8;
return;
}
}
}
return;
}
//编码器终结过程
void FLUSH()
{
SETBITS();//置1C=C<<CT;//CT位左移
BYTEOUT();//输出一个字节压缩数据
C=C<<CT;//CT位左移
BYTEOUT();//输出一个字节压缩数据
if(B==0xFF){}//若B达到0xFF,则丢弃
else foutput();//否则输出
}
//置为过程
void SETBITS()
{
unsigned long TEMPC;
TEMPC=C+A;//C寄存器与区间寄存器之和
C=C|0xFFFF;//将代码寄存器置1
if(C>=TEMPC)//去掉代码寄存器起始的一位
C=C-0x8000;
}
//数据输入过程
void finput(char ch)
{
int i,q;
D=ch-48;//取得判决位D的值
CX=0;
q=16;
for(i=1;i<=5;i++)//取得CX的值
{
fscanf(fin,"%c",&ch);
CX=CX+(ch-48)*q;
q=q/2;
}
}
//压缩数据输出过程
void foutput()
{
int i,t,num[10];
for(i=1;i<=8;i++)//由于计算先得到的是低位值,{//因此暂存在缓冲数组中
t=B%2;
num[i]=t;
B=B/2;
}
for(i=8;i>=1;i--)
fprintf(fout,"%d",num[i]);//输出一字节的压缩数据
}
//主函数
int main()
{
char ch;
INITENC();//算术编码器的初始化
fin=fopen("test.in","r");//打开输入文件
fout=fopen("test.out","w");//打开输出文件
while(fscanf(fin,"%c",&ch)!=EOF)
{
finput(ch);
ENCODE();//编码过程
}
FLUSH();//编码器处理的终结
fclose(fin);//关闭输入文件
fclose(fout);//关闭输出文件
return 0;
}
jpeg.rar_视频 JPEG_视频图像压缩
版权申诉
53 浏览量
2022-09-20
17:14:09
上传
评论
收藏 2KB RAR 举报
局外狗
- 粉丝: 66
- 资源: 1万+