//初始化d_buffer的数据
int InitTag(void)
{
BOOL finish=FALSE;
u8 id;
short llength;
short i,j,k;
short huftab1,huftab2;
short huftabindex;
u8 hf_table_index;
u8 qt_table_index;
u8 comnum;//最长为256个字节
unsigned char *lptemp;
short colorount;
lp=jpg_buffer+2;//跳过两个字节SOI(0xFF,0xD8 Start of Image)
lp-=P_Cal(lp);
while (!finish)
{
id=*(lp+1);//取出低位字节(高位在前,低位在后)
lp+=2; //跳过取出的字节
lp-=P_Cal(lp);
switch (id)
{
case M_APP0: //JFIF APP0 segment marker (0xE0)
//标志应用数据段的开始
llength=MAKEWORD(*(lp+1),*lp);//得到应用数据段长度
lp+=llength;
lp-=P_Cal(lp);
break;
case M_DQT: //定义量化表标记(0xFF,0xDB)
llength=MAKEWORD(*(lp+1),*lp);//(量化表长度)两个字节
qt_table_index=(*(lp+2))&0x0f;//量化表信息bit 0..3: QT 号(0..3, 否则错误)
//bit 4..7: QT 精度, 0 = 8 bit, 否则 16 bit
lptemp=lp+3; //n 字节的 QT, n = 64*(精度+1)
//d_buffer里面至少有有512个字节的余度,这里最大用到128个字节
if(llength<80) //精度为 8 bit
{
for(i=0;i<64;i++)qt_table[qt_table_index]
=(short)*(lptemp++);
}
else //精度为 16 bit
{
for(i=0;i<64;i++)qt_table[qt_table_index]=(short)*(lptemp++);
qt_table_index=(*(lptemp++))&0x0f;
for(i=0;i<64;i++)qt_table[qt_table_index]=(short)*(lptemp++);
}
lp+=llength; //跳过量化表
lp-=P_Cal(lp);
break;
case M_SOF0: //帧开始 (baseline JPEG 0xFF,0xC0)
llength=MAKEWORD(*(lp+1),*lp); //长度 (高字节, 低字节), 8+components*3
 ICINFO.ImgHeight=MAKEWORD(*(lp+4),*(lp+3));//图片高度 (高字节, 低字节), 如果不支持 DNL 就必须 >0
 ICINFO.ImgWidth=MAKEWORD(*(lp+6),*(lp+5)); //图片宽度 (高字节, 低字节), 如果不支持 DNL 就必须 >0
comp_num=*(lp+7);//components 数量(1 u8), 灰度图是 1, YCbCr/YIQ 彩 {MOD}图是 3, CMYK 彩 {MOD}图是 4
if((comp_num!=1)&&(comp_num!=3))return FUNC_FORMAT_ERROR;// 格式错误
if(comp_num==3) //YCbCr/YIQ 彩 {MOD}图
{
comp_index[0]=*(lp+8); //component id (1 = Y, 2 = Cb, 3 = Cr, 4 = I, 5 = Q)
SampRate_Y_H=(*(lp+9))>>4; //水平采样系数
SampRate_Y_V=(*(lp+9))&0x0f;//垂直采样系数
YQtTable=(short *)qt_table[*(lp+10)];//通过量化表号取得量化表地址
comp_index[1]=*(lp+11); //component id
SampRate_U_H=(*(lp+12))>>4; //水平采样系数
SampRate_U_V=(*(lp+12))&0x0f; //垂直采样系数
UQtTable=(short *)qt_table[*(lp+13)];//通过量化表号取得量化表地址
comp_index[2]=*(lp+14); //component id
SampRate_V_H=(*(lp+15))>>4; //水平采样系数
SampRate_V_V=(*(lp+15))&0x0f; //垂直采样系数
VQtTable=(short *)qt_table[*(lp+16)];//通过量化表号取得量化表地址
}
else //component id
{
comp_index[0]=*(lp+8);
SampRate_Y_H=(*(lp+9))>>4;
SampRate_Y_V=(*(lp+9))&0x0f;
YQtTable=(short *)qt_table[*(lp+10)];//灰度图的量化表都一样
comp_index[1]=*(lp+8);
SampRate_U_H=1;
SampRate_U_V=1;
UQtTable=(short *)qt_table[*(lp+10)];
comp_index[2]=*(lp+8);
SampRate_V_H=1;
SampRate_V_V=1;
VQtTable=(short *)qt_table[*(lp+10)];
}
lp+=llength;
lp-=P_Cal(lp);
break;
case M_DHT: //定义哈夫曼表(0xFF,0xC4)
llength=MAKEWORD(*(lp+1),*lp);//长度 (高字节, 低字节)
if (llength<0xd0) // Huffman Table信息 (1 u8)
{
huftab1=(short)(*(lp+2))>>4; //huftab1=0,1(HT 类型,0 = DC 1 = AC)
huftab2=(short)(*(lp+2))&0x0f; //huftab2=0,1(HT 号 ,0 = Y 1 = UV)
huftabindex=huftab1*2+huftab2; //0 = YDC 1 = UVDC 2 = YAC 3 = UVAC
lptemp=lp+3;//!!!
//在这里可能出现余度不够,多于512字节,则会导致出错!!!!
for (i=0; i<16; i++) //16 bytes: 长度是 1..16 代码的符号数
code_len_table[huftabindex]=(short)(*(lptemp++));//码长为i的码字个数
j=0;
for (i=0; i<16; i++) //得出HT的所有码字的对应值
{
if(code_len_table[huftabindex]!=0)
{
k=0;
while(k<code_len_table[huftabindex])
{
code_value_table[huftabindex][k+j]=(short)(*(lptemp++));//最可能的出错地方
k++;
}
j+=k;
}
}
i=0;
while (code_len_table[huftabindex]==0)i++;
for (j=0;j<i;j++)
{
huf_min_value[huftabindex][j]=0;
huf_max_value[huftabindex][j]=0;
}
huf_min_value[huftabindex]=0;
huf_max_value[huftabindex]=code_len_table[huftabindex]-1;
for (j=i+1;j<16;j++)
{
huf_min_value[huftabindex][j]=(huf_max_value[huftabindex][j-1]+1)<<1;
huf_max_value[huftabindex][j]=huf_min_value[huftabindex][j]+code_len_table[huftabindex][j]-1;
}
code_pos_table[huftabindex][0]=0;
for (j=1;j<16;j++)
code_pos_table[huftabindex][j]=code_len_table[huftabindex][j-1]+code_pos_table[huftabindex][j-1];
lp+=llength;
lp-=P_Cal(lp);
}//if
else
{
hf_table_index=*(lp+2);
lp+=2;
lp-=P_Cal(lp);
while (hf_table_index!=0xff)
{
huftab1=(short)hf_table_index>>4; //huftab1=0,1
huftab2=(short)hf_table_index&0x0f; //huftab2=0,1
huftabindex=huftab1*2+huftab2;
lptemp=lp+1;
colorount=0;
for (i=0; i<16; i++)
{
code_len_table[huftabindex]=(short)(*(lptemp++));
colorount+=code_len_table[huftabindex];
}
colorount+=17;
j=0;
for (i=0; i<16; i++)
{
if(code_len_table[huftabindex]!=0)
{
k=0;
while(k<code_len_table[huftabindex])
{
code_value_table[huftabindex][k+j]=(short)(*(lptemp++));//最可能出错的地方,余度不够
k++;
}
j+=k;
}
}
i=0;
while (code_len_table[huftabindex]==0)i++;
for (j=0;j<i;j++)
{
huf_min_value[huftabindex][j]=0;
huf_max_value[huftabindex][j]=0;
}
huf_min_value[huftabindex]=0;
huf_max_value[huftabindex]=code_len_table[huftabindex]-1;
for (j=i+1;j<16;j++)
{
huf_min_value[huftabindex][j]=(huf_max_value[huftabindex][j-1]+1)<<1;
huf_max_value[huftabindex][j]=huf_min_value[huftabindex][j]+code_len_table[huftabindex][j]-1;
}
code_pos_table[huftabindex][0]=0;
for (j=1;j<16;j++)
code_pos_table[huftabindex][j]=code_len_table[huftabindex][j-1]+code_pos_table[huftabindex][j-1];
lp+=colorount;
lp-=P_Cal(lp);
hf_table_index=*lp;
} //while
} //else
break;
case M_DRI://定义差分编码累计复位的间隔
llength=MAKEWORD(*(lp+1),*lp);
restart=MAKEWORD(*(lp+3),*(lp+2));
lp+=llength;
lp-=P_Cal(lp);
break;
case M_SOS: //扫描开始 12字节
llength=MAKEWORD(*(lp+1),*lp);
comnum=*(lp+2);
if(comnum!=comp_num)return FUNC_FORMAT_ERROR; //格式错误
lptemp=lp+3;//这里也可能出现错误
//这里也可能出错,但是几率比较小了
for (i=0;i<comp_num;i++)//每组件的信息
{
if(*lptemp==comp_index[0])
{
YDcIndex=(*(lptemp+1))>>4; //Y 使用的 Huffman 表
YAcIndex=((*(lptemp+1))&0x0f)+2;
}
else
{
UVDcIndex=(*(lptemp+1))>>4; //U,V
UVAcIndex=((*(lptemp+1))&0x0f)+2;
}
lptemp+=2;//comp_num<256,但是2*comp_num+3可能>=512
}
lp+=llength;
lp-=P_Cal(lp);
finish=TRUE;
break;
case M_EOI:return FUNC_FORMAT_ERROR;//图片结束 标记
default:
if ((id&0xf0)!=0xd0)
{
llength=MAKEWORD(*(lp+1),*lp);
lp+=llength;
lp-=P_Cal(lp);
}
else lp+=2;
break;
} //switch
} //while
return FUNC_OK;
}
以上黄 {MOD}部分注销的,可以有两个好处:
1.节约代码空间。
2.可以显示更多的图片。(原子提供的原代码只能显示:原子提供的开发板特定图片和BMP图片,到别的地方拷来的图片则不能显示)。如果你注销掉上面的黄 {MOD}代码,可以显示所有的JPG和BMP图片。
3.显示速度变快了。
注销理由:
注销掉的是if内的代码:if内的代码有个Huffman表长度限制。而else内的代码则没有Huffman表长的限制。那么else的代码可以包容if的条件。所以if内的代码多余。
另:我觉得case M-HDT内的下面代码,太啰嗦。原因:huffman树的权值表内,所有的在原子提供的代码处理上,没有和码数表有关系,所以,根本不需要这么啰嗦处理。如下:
j=0;
for (i=0; i<16; i++) //得出HT的所有码字的对应值
{
if(code_len_table[huftabindex]!=0)
{
k=0;
while(k<code_len_table[huftabindex])
{
code_value_table[huftabindex][k+j]=(short)(*(lptemp++));//最可能的出错地方
k++;
}
j+=k;
}
}
我的处理是:
j=0;
for(i=0;i<16;i++)
{
j+=code_len_table[huftabindex];
}/*本段也可以让j=【本Tag段的长度-19来实现,更简单:2Byte指本段长度,1B码表类型和编号,16B码数表,这三项是固定的。】*/
for(i=0;i<j;i++)
{
code_value_table[huftabindex]=(short)(*(pTemp++));/*直接全部读入即可。*/
}
因为else段内的频繁指针处理,保证了1024的jpg_buffer能足够容纳任意长的Huffman表。(这里的任意长指一个huffman表权值,一般不会太长,即使太长,也可以用指针处理来实现。)
以上修改后,所有的JPG和BMP都能显示,不管他们的像素的宽度是否是1024*768还是什么,都能更快处理并显示出来。
我原来自己拷一些图片用原子代码来显示,结果显示空白。经过上述处理后,所有的JPG和BMP图片都能显示了...........
我的实验做到了,你的呢?
一周热门 更多>