| //初始化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 彩色图是 3, CMYK 彩色图是 4
 if((comp_num!=1)&&(comp_num!=3))return FUNC_FORMAT_ERROR;// 格式错误
 if(comp_num==3)      //YCbCr/YIQ 彩色图
 {
 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;
 }
 以上黄色部分注销的,可以有两个好处:
 1.节约代码空间。
 2.可以显示更多的图片。(原子提供的原代码只能显示:原子提供的开发板特定图片和BMP图片,到别的地方拷来的图片则不能显示)。如果你注销掉上面的黄色代码,可以显示所有的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图片都能显示了...........我的实验做到了,你的呢?
 |