📄 jpeg_ls.cpp
字号:
// JPEG_LS.cpp: implementation of the JPEG_LS class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HIC.h"
#include "JPEG_LS.h"
#include "math.h"
#include <time.h>
#include <sys\types.h>
#include <sys\timeb.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define RESET 64
#define NEAR 0
#define MIN_C -1000
#define MAX_C 20000
int J[32]={0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,5,5,6,6,7,7,8,9,10,11,12,13,14,15};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
JPEG_LS::JPEG_LS()
{
}
JPEG_LS::~JPEG_LS()
{
}
int JPEG_LS::LG(int Q)
{
int i;
for(i=0;(N[Q]<<i)<A[Q];i++);
return(i);
}
float JPEG_LS::CLAMP_1(float i)
{
if(i>MAXVAL||i<NEAR+1)
return(NEAR+1);
else
return(i);
}
float JPEG_LS::CLAMP_2(float i, float T1)
{
if(i>MAXVAL||i<T1)
return(T1);
else
return(i);
}
float JPEG_LS::CLAMP_3(float i, float T2)
{
if(i>MAXVAL||i<T2)
return(T2);
else
return(i);
}
void JPEG_LS::JPEG_LSCompress()
{
int i,j,Ra,Rb,Rc,Rd,Ix,D1,D2,D3;
int x,y;
int BASIC_T1=3,BASIC_T2=7,BASIC_T3=21;
float T1,T2,T3;
struct timeb start_time,end_time;
int second_d;
x=256;y=256;
CT=0;
Initial();
ftime(&start_time);
f=(int *)calloc((x+1)*(y+2),sizeof(int)); /*补零后的图像多两列,一行*/
if((fp=fopen("E:\\girl256.raw","rb"))==NULL)
{
AfxMessageBox("Can not Open File!");
return;
}
// 计算各参数的值
for(i=1;i<=x;i++)
for(j=1;j<=y;j++)
{
fread(f+i*(y+2)+j,1,1,fp);/*前面空一行,以作重建值。从第二行写起。此时补的行还是零,到后面预测时补入Rb等。*/
if(*(f+i*(y+2)+j)>MAXVAL)
MAXVAL=*(f+i*(y+2)+j);/*先求实际最大值*/
}
fclose(fp);
for(i=0;(1<<i)<=MAXVAL;i++);
MAXVAL=(1<<i)-1;/*规整到2的n次方故取大于实际MAXVAL的最小2的n次方*/
RANGE=((int)((MAXVAL+2*NEAR)/(2*NEAR+1)))+1;
qbpp=-(int)(floor(-log(RANGE)/log(2.0)));
bpp=__max(2,-(int)(floor(-log(MAXVAL+1)/log(2.0))));
LIMIT=2*(bpp+__max(8,bpp));
if(MAXVAL>=128){
T1=CLAMP_1((float)((int)(__min(MAXVAL,4095)+128)/256)*(BASIC_T1-2)+2+3*NEAR);
T2=CLAMP_2((float)((int)(__min(MAXVAL,4095)+128)/256)*(BASIC_T2-3)+3+5*NEAR,T1);
T3=CLAMP_3((float)((int)(__min(MAXVAL,4095)+128)/256)*(BASIC_T3-4)+4+7*NEAR,T2);}
else{
T1=CLAMP_1((float)__max(2,BASIC_T1/(int)(256/(MAXVAL+1))+3*NEAR));
T2=CLAMP_2((float)__max(3,BASIC_T2/(int)(256/(MAXVAL+1))+5*NEAR),T1);
T3=CLAMP_3((float)__max(4,BASIC_T3/(int)(256/(MAXVAL+1))+7*NEAR),T2);
}
// 对各数组的初始化
for(j=0;j<365;j++)
{
A[j]=__max(2,(RANGE+(1<<5))/(1<<6));
N[j]=1;
B[j]=0;
C[j]=0;
}
A[365]=A[0];
A[366]=A[0];
N[365]=1;
N[366]=1;
for(i=0;i<y+3;i++)
*(f+i)=0;/*第一行及第二行第一个全为零*/
if((fp=fopen("E:\\girl.raw","wb"))==NULL)
{
AfxMessageBox("Can not Open File!");
return;
}
while(RowX<=y&&LinX<=x)/*到计算时间之前为大循环,一个一个象素处理*/
{
Ra=(*(f+LinX*(y+2)+RowX-1));
Rb=(*(f+(LinX-1)*(y+2)+RowX));
Rc=(*(f+(LinX-1)*(y+2)+RowX-1));
Rd=(*(f+(LinX-1)*(y+2)+RowX+1));
Ix=(*(f+LinX*(y+2)+RowX));
D1=Rd-Rb;
D2=Rb-Rc;
D3=Rc-Ra;
// 选择编码方式
if((abs(D1)<=NEAR)&&(abs(D2)<=NEAR)&&(abs(D3)<=NEAR))
RunModeProcessing(x,y,Ra,Rb,Rc,Rd,Ix);
else
RegularModeProcessing(y,Ra,Rb,Rc,Rd,Ix,D1,D2,D3,T1,T2,T3);
RowX++;
if(RowX==y)/*原图像一行的结尾(是补零后的倒数第二个象素)*/
{
*(f+(LinX+1)*(y+2))=*(f+LinX*(y+2)+1);/*处理下一行的第一个象素的上下文:将Rb赋给a*/
*(f+LinX*(y+2)+y+1)=*(f+LinX*(y+2)+y);/*处理当前行最后一个象素的上下文:将Rb赋给d*/
EOLine=1;
}
else
EOLine=0;
if(RowX>y)/*补零后的最后一个象素*/
{
RowX=RowX-y;/*也即rowx=1*/
LinX++;
}
}
if(cnt>0)
code=code<<(8-cnt);
fwrite(&code,1,1,fp);
CT=CT+1;
fclose(fp);
ftime(&end_time);
// 计算编码时间
second_d=end_time.millitm-start_time.millitm;
second_d=second_d+(end_time.time-start_time.time)*1000;
// printf("The encoding costs:%.3f seconds.\n",(float)second_d/1000.0);
}
/***************************************************
游程编码子程序的定义
****************************************************/
void JPEG_LS::RunModeProcessing(int x, int y, int Ra, int Rb, int Rc, int Rd, int Ix)
{
int cnt1=0;
int RUNval=Ra;
int RUNcnt=0,TEMP,RItype;
int map,AQ,EMErrval,glimit,Errval,k,SIGN,Rx,Px;
unsigned interim;
output=0;
//计算游程长度
while(abs(Ix-RUNval)<=NEAR)
{
RUNcnt=RUNcnt+1;
Rx=RUNval;
*(f+LinX*(y+2)+RowX)=Rx;
if(EOLine==1)/*正好是最后一个,跳到长度编码*/
break;
else{
RowX=RowX+1;
if(RowX==y)
{
*(f+(LinX+1)*(y+2))=*(f+LinX*(y+2)+1);
*(f+LinX*(y+2)+y+1)=*(f+LinX*(y+2)+y);/*当前象素为本行最后一个时,对其Rd、下一行Ra赋值*/
EOLine=1;
}
Rb=*(f+(LinX-1)*(y+2)+RowX);
Ix=*(f+LinX*(y+2)+RowX);
}
}
/*对游程长度进行编码并向二进制文件中写入码流*/
while(RUNcnt>=(1<<J[RUNindex]))
{
output=(output<<1)+1;
cnt1++;
RUNcnt=RUNcnt-(1<<J[RUNindex]);
if(RUNindex<31)
RUNindex=RUNindex+1;
}/*当RUNlen小于整数值的rm时,跳出*/
if(EOLine==0||(EOLine==1&&(abs(Ix-RUNval)>NEAR)))/*情况1:被不同象素中断*/
{
output=output<<1;
cnt1++;
output=(output<<(J[RUNindex]))+RUNcnt;/*之前已经写入最逼近RUNlen的rm段,再左移一个rm段后,加入剩RUNlen下的部分*/
cnt1=cnt1+J[RUNindex];
if(RUNindex>0)
RUNindex--;
}
else if(RUNcnt>0)/*情况2:被行末尾中断*/
{
output=(output<<1)+1;
cnt1++;
}
pp=cnt;
cnt=cnt+cnt1;
writecode(&cnt,&pp,&output,&code);
if(EOLine==1&&(abs(Ix-RUNval)<=NEAR))
return;/*由于行的末尾终止,可正常结束,跳出此次游程模式*/
if(abs(Ra-Rb)<=NEAR)
RItype=1;
else
RItype=0;
if(RItype==1)
Px=Ra;
else
Px=Rb;
Errval=Ix-Px;
if((RItype==0)&&(Ra>Rb))
{
Errval=-Errval;
SIGN=-1;
}
else
SIGN=1;
if(NEAR>0){
if(Errval>0)
Errval=(Errval+NEAR)/(2*NEAR+1);
else
Errval=-(NEAR-Errval)/(2*NEAR+1);
Rx=Px+SIGN*Errval*(2*NEAR+1);
if(Rx<0)
Rx=0;
else if(Rx>MAXVAL)
Rx=MAXVAL;
}
else
Rx=Ix;
*(f+LinX*(y+2)+RowX)=Rx;
Errval=ModRange(Errval);
if(RItype==0)
TEMP=A[365];
else
TEMP=A[366]+(N[366]>>1);
Q=RItype+365;
/*将当前A[Q]暂存,借用完LG(Q)后还可进行正常操作*/
AQ=A[Q];
A[Q]=TEMP;
k=LG(Q);
if((k==0)&&(Errval>0)&&(2*Nn[Q-365]<N[Q]))
map=1;
else if((Errval<0)&&(2*Nn[Q-365]>=N[Q]))
map=1;
else if((Errval<0)&&(k!=0))
map=1;
else
map=0;
EMErrval=2*abs(Errval)-RItype-map;/*游程中断编码*/
glimit=LIMIT-J[RUNindex]-1;
interim=EMErrval;
interim=interim>>k;
if(interim<((unsigned)(glimit-qbpp-1)))
{
unsigned b,c;
output=0;
c=~(~0<<k);
b=c&EMErrval;
output=(output<<(interim+1))+1;
output=output<<k;
output=output+b;
pp=cnt;
cnt=cnt+interim+1+k;
writecode(&cnt,&pp,&output,&code);
}
else
{
unsigned b,c;
output=0;
output=(output<<(glimit-qbpp))+1;
output=output<<qbpp;
c=~(~0<<qbpp);
b=c&(EMErrval-1);
output=output+b;
pp=cnt;
cnt=cnt+glimit;
writecode(&cnt,&pp,&output,&code);
}
// 更新各个变量
if(Errval<0)
Nn[Q-365]=Nn[Q-365]+1;
A[Q]=AQ;
A[Q]=A[Q]+((EMErrval+1-RItype)>>1);
if(N[Q]==RESET)
{
A[Q]=A[Q]>>1;
N[Q]=N[Q]>>1;
Nn[Q-365]=Nn[Q-365]>>1;
}
N[Q]=N[Q]+1;
}
int JPEG_LS::ModRange(int a)
{
if(a<((0-RANGE)/2))
a=a+RANGE;
if(a>=((1+RANGE)/2))
a=a-RANGE;
return(a);
}
void JPEG_LS::writecode(int *cnt, int *pp, unsigned long *output, int *code)
{
unsigned long c;
if((*cnt)<8)
*code=(*code<<(*cnt-*pp))+(*output);/*以1byte为单位处理。把之前的码流向前推当前码流的长度,加入当前输出的码流*/
else{
while(*cnt>=8)
{
if(*cnt>32)/*以4byte为存储器最大值*/
{
*code=(*code<<(8-*pp));
fwrite(code,1,1,fp);/*把code指向的1×1个字节输出到fp所指的文件中*/
CT=CT+1;
counter++;
*code=0;
*cnt=*cnt-8;
}
else
{
*code=(*code<<(8-*pp))+(255&(*output>>(*cnt-8)));
fwrite(code,1,1,fp);
CT=CT+1;
counter++;
*code=0;
*cnt=*cnt-8;
}
}
c=~(~0<<*cnt);
*code=c&(*output);
}
}
void JPEG_LS::RunModeProcessing(int qbpp, int Ra, int Rb, int y)
{
int decode1=0;
int cnt=0,i;
unsigned long j;
int RItype,TEMP,AQ,Errval,EMErrval,flag,map,SIGN,k,Px,Rx,Q;
// 从码流中恢复EMErrval
if(size==0)
{
fread(&buffer,1,1,fp);
decode=buffer;
size=8;}/*以8bit为一个处理单位*/
size--;
while((1&(decode>>size))==1)
{
size--;
i=0;
while(i<(1<<J[RUNindex]))/*写一个Ra*/
{
*(f+LinX*(y+2)+RowX)=Ra;
RowX++;
if(RowX>y)
{
RowX--;
flag1=1;
}
i++;
if(flag1==1)
break;
}
if((i==(1<<J[RUNindex]))&&RUNindex<31)
RUNindex++;
if(size<0&&flag1==0)
{
fread(&buffer,1,1,fp);
decode=buffer;
size=7;
}/*一个单元处理完且游程仍未结束,处理下一个单元*/
if(flag1==1)
break;
}
//在已处理的位上置零
if(RowX==y&&flag1==1){/*情况1:在行末*/
if(size==-1)/*正好处理完一个单元且游程未结束*/
decode=0;/*处理器清零,完成游程解码*/
else/*对单元未处理完就已到行末*/
decode=(decode<<(32-size-1))>>(32-size-1);/*当被行末中断时,其剩下的rk位1前缀是1,所以也被前面的处理过size+1是未处理的,所以32-size-1表示在当前处理范围内已处理的。此操作表示将已处理的位置零*/
size=size+1;/*待处理的位数是size+1*/
flag1=0;
return;}/*游程解码结束*/
if(size==0)/*情况2:非行末,正好一个单元的最后一个是不同象素*/
decode2=0;
else
decode2=(decode<<(32-size))>>(32-size);/*剩下size个元素待处理*/
/***对长度小于rm的分段码字的处理***/
if(J[RUNindex]<=size)/*当有剩余比特出现时,且在当前处理单元内*/
{
output=(decode2>>(size-J[RUNindex]));/*将待处理的数据移至最右侧,即得到待处理的数据*/
if(J[RUNindex]==size)
decode=0;
else
decode=((decode<<(32-size+J[RUNindex]))>>(32-size+J[RUNindex]));/*将处理过的位置零*/
size=size-J[RUNindex];
}
else/*当前处理单元剩余的比特小于rk时*/
{
fread(&buffer,1,1,fp);
if(J[RUNindex]-size<=8)/*rk在下一个处理单元之内*/
decode1=decode2<<(J[RUNindex]-size);/*加入下一个单元中剩下部分的空间*/
while(J[RUNindex]-size>8)
{
decode1=decode1+(decode2<<(J[RUNindex]-size))+(buffer<<(J[RUNindex]-size-8));/*读入后面几个单元中rk部分.注意这里的加并不表示长度相加,而是在同一原点上叠加*/
J[RUNindex]=J[RUNindex]-8;
fread(&buffer,1,1,fp);
decode2=0;
}
output=decode1+(buffer>>(8+size-J[RUNindex]));/*右边第二项是当rk-size<8时,得到当前单元的剩余的rk,以接到n个满单元之后*/
if(J[RUNindex]-size==8)
decode=0;
else
decode=(buffer<<(32-8+J[RUNindex]-size))>>(32-8+J[RUNindex]-size);/*对前面已经处理过的(n个满单元及当前单元剩余rk)位置零*/
size=8-J[RUNindex]+size;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -