📄 jpegdecode.pas
字号:
M_EOI: //图片结束
begin
Result:=FUNC_FORMAT_ERROR;
Exit;
end;
else
begin
if ((id and $f0)<>$d0) then
begin
llength:=MAKEWORD(Byte((lp+1)^),Byte(lp^));
lp:=lp+llength;
end
else lp:=lp+2;
end;
end;
end; //while
Result:=FUNC_OK;
end;
/////////////////////////////////////////////////////////////////
procedure InitTable;
var
i,j:SmallInt;
begin
sizei:=0;
sizej:=0;
ImgWidth:=0;
ImgHeight:=0;
rrun:=0;
vvalue:=0;
BitPos:=0;
CurByte:=0;
IntervalFlag:=FALSE;
restart:=0;
for i:=0 to 2 do
for j:=0 to 63 do
qt_table[i,j]:=0; //量化表
comp_num:=0;
HufTabIndex:=0;
for i:=0 to 2 do
comp_index[i]:=0;
for i:=0 to 3 do
for j:=0 to 15 do
begin
code_len_table[i,j]:=0;
code_pos_table[i,j]:=0;
huf_max_value[i,j]:=0;
huf_min_value[i,j]:=0;
end;
for i:=0 to 3 do
for j:=0 to 255 do
code_value_table[i,j]:=0;
for i:=0 to 10*64-1 do
begin
MCUBuffer[i]:=0;
QtZzMCUBuffer[i]:=0;
end;
for i:=0 to 63 do
begin
Y[i]:=0;
U[i]:=0;
V[i]:=0;
BlockBuffer[i]:=0;
end;
ycoef:=0;ucoef:=0;vcoef:=0;
end;
/////////////////////////////////////////////////////////////////////////
//调用顺序: Initialize_Fast_IDCT() :初始化
// DecodeMCUBlock() Huffman Decode
// IQtIZzMCUComponent() 反量化、反DCT
// GetYUV() Get Y U V
// StoreBuffer() YUV to RGB
/////////////////////////////////////////////////////////////////////////
function Decode:integer;
var
funcret:integer;
begin
Y_in_MCU:=SampRate_Y_H*SampRate_Y_V; //YDU YDU YDU YDU
U_in_MCU:=SampRate_U_H*SampRate_U_V; //cRDU
V_in_MCU:=SampRate_V_H*SampRate_V_V; //cBDU
H_YtoU:=SampRate_Y_H div SampRate_U_H;
V_YtoU:=SampRate_Y_V div SampRate_U_V;
H_YtoV:=SampRate_Y_H div SampRate_V_H;
V_YtoV:=SampRate_Y_V div SampRate_V_V;
Initialize_Fast_IDCT;
funcret:=DecodeMCUBlock;
while(funcret=FUNC_OK) do
begin //After Call DecodeMCUBUBlock()
inc(interval); //The Digital has been Huffman Decoded and
if((restart<>0) and ((interval mod restart)=0)) then //be stored in MCUBuffer(YDU,YDU,YDU,YDU
IntervalFlag:=TRUE // UDU,VDU) Every DU := 8*8
else
IntervalFlag:=FALSE;
IQtIZzMCUComponent(0); //反量化 and IDCT The Data in QtZzMCUBuffer
IQtIZzMCUComponent(1);
IQtIZzMCUComponent(2);
GetYUV(0); //得到Y cR cB
GetYUV(1);
GetYUV(2);
StoreBuffer; //To RGB
sizej:=sizej+DWORD(SampRate_Y_H*8);
if(sizej>=ImgWidth) then
begin
sizej:=0;
sizei:=sizei+DWORD(SampRate_Y_V*8);
end;
if ((sizej=0) and (sizei>=ImgHeight)) then
break;
funcret:=DecodeMCUBlock;
end;//while
Result:=funcret;
end;
////////////////////////////////////////////////////////////////////////////////
// 入口 QtZzMCUBuffer 出口 Y[] U[] V[]
////////////////////////////////////////////////////////////////////////////////
procedure GetYUV(flag:SmallInt);
var
H,VV:SmallInt;
temp:Integer;
i,j,k,hk:SmallInt;
buf,tempbuf:Pint;
pQtZzMCU:Pint;
begin
case flag of
0: //亮度分量
begin
H:=SampRate_Y_H;
VV:=SampRate_Y_V;
buf:=@Y;
pQtZzMCU:=Pint(@QtZzMCUBuffer);
end;
1: //红色分量
begin
H:=SampRate_U_H;
VV:=SampRate_U_V;
buf:=@U;
pQtZzMCU:=Pint(@QtZzMCUBuffer);
inc(pQtZzMCU,Y_in_MCU*64);
end;
2: //蓝色分量
begin
H:=SampRate_V_H;
VV:=SampRate_V_V;
buf:=@V;
pQtZzMCU:=Pint(@QtZzMCUBuffer);
inc(pQtZzMCU,(Y_in_MCU+U_in_MCU)*64);
end;
else
begin
H:=0;VV:=0;buf:=nil;pQtZzMCU:=nil;
end;
end;//end case
for i:=0 to VV-1 do
for j:=0 to H-1 do
for k:=0 to 7 do
for hk:=0 to 7 do
begin
temp:=(i*8+k)*SampRate_Y_H*8+j*8+hk;
tempbuf:=buf;
inc(tempbuf,temp);
tempbuf^:=Integer(pQtZzMCU^);
inc(pQtZzMCU);
end;
end;
///////////////////////////////////////////////////////////////////////////////
//将解出的字按RGB形式存储 lpbmp (BGR),(BGR) ......入口Y[] U[] V[] 出口lpPtr
///////////////////////////////////////////////////////////////////////////////
procedure StoreBuffer;
var
i,j:SmallInt;
lpbmp:PChar;
R,G,B:Byte;
yy,uu,vv,rr,gg,bb:integer;
begin
for i:=0 to SampRate_Y_V*8-1 do
begin // sizei表示行 sizej 表示列
if((sizei+DWORD(i))<ImgHeight) then
begin
lpbmp:=lpPtr+DWORD((ImgHeight-sizei-DWORD(i)-1)*LineBytes+sizej*3);
for j:=0 to SampRate_Y_H*8-1 do
begin
if((sizej+DWORD(j))<ImgWidth) then
begin
yy:=Y[i*8*SampRate_Y_H+j];
uu:=U[(i div V_YtoU)*8*SampRate_Y_H+j div H_YtoU]; //内插
vv:=V[(i div V_YtoV)*8*SampRate_Y_H+j div H_YtoV];
rr:=((yy shl 8)+18*uu+367*vv);
if rr<0 then
rr:=(rr shr 8) or (not (Integer(0)) shl (32-8))
else rr:=rr shr 8;
gg:=((yy shl 8)-159*uu-220*vv);
if gg<0 then
gg:=(gg shr 8) or (not (integer(0)) shl (32-8))
else gg:=gg shr 8;
bb:=((yy shl 8)+411*uu-29*vv);
if bb<0 then
bb:=(bb shr 8) or (not (Integer(0)) shl (32-8))
else bb:=bb shr 8;
R:=Byte(rr);
G:=Byte(gg);
B:=Byte(bb);
if ((rr and $ffffff00) <>0) then
if (rr>255) then R:=255
else if (rr<0) then R:=0;
if (gg and $ffffff00 <>0) then
if (gg>255) then G:=255
else if (gg<0) then G:=0;
if (bb and $ffffff00 <>0) then
if (bb>255) then B:=255
else if (bb<0) then B:=0;
lpbmp^:=Char(B);
inc(lpbmp);
lpbmp^:=Char(G);
inc(lpbmp);
lpbmp^:=Char(R);
inc(lpbmp);
end
else break;
end;
end
else break;
end;
end;
///////////////////////////////////////////////////////////////////////////////
//Huffman Decode MCU 出口 MCUBuffer 入口Blockbuffer[ ]
///////////////////////////////////////////////////////////////////////////////
function DecodeMCUBlock:integer;
var
lpMCUBuffer:PSmallInt;
i,j:SmallInt;
funcret:integer;
begin
if (IntervalFlag) then
begin
inc(lp,2);
ycoef:=0; //差值复位
ucoef:=0;
vcoef:=0;
BitPos:=0;
CurByte:=0;
end;
case comp_num of
//comp_num 指图的类型(彩色图、灰度图)
3: //彩色图
begin
lpMCUBuffer:=@MCUBuffer;
for i:=0 to SampRate_Y_H*SampRate_Y_V-1 do //Y
begin
funcret:=HufBlock(YDcIndex,YAcIndex); //解码4 * (8*8)
if (funcret<>FUNC_OK) then
begin
Result:=funcret;
Exit;
end;
BlockBuffer[0]:=BlockBuffer[0]+ycoef; //直流分量是差值,所以要累加。
ycoef:=BlockBuffer[0];
for j:=0 to 63 do
begin
lpMCUBuffer^:=BlockBuffer[j];
inc(lpMCUBuffer);
end;
end;
for i:=0 to SampRate_U_H*SampRate_U_V-1 do //U
begin
funcret:=HufBlock(UVDcIndex,UVAcIndex);
if (funcret<>FUNC_OK) then
begin
Result:=funcret;
Exit;
end;
BlockBuffer[0]:=BlockBuffer[0]+ucoef;
ucoef:=BlockBuffer[0];
for j:=0 to 63 do
begin
lpMCUBuffer^:=BlockBuffer[j];
inc(lpMCUBuffer);
end;
end;
for i:=0 to SampRate_V_H*SampRate_V_V-1 do //V
begin
funcret:=HufBlock(UVDcIndex,UVAcIndex);
if (funcret<>FUNC_OK) then
begin
Result:=funcret;
Exit;
end;
BlockBuffer[0]:=BlockBuffer[0]+vcoef;
vcoef:=BlockBuffer[0];
for j:=0 to 63 do
begin
lpMCUBuffer^:=BlockBuffer[j];
inc(lpMCUBuffer);
end;
end;
end;
1: //Gray Picture
begin
lpMCUBuffer:=@MCUBuffer;
funcret:=HufBlock(YDcIndex,YAcIndex);
if (funcret<>FUNC_OK) then
begin
Result:=funcret;
Exit;
end;
BlockBuffer[0]:=BlockBuffer[0]+ycoef;
ycoef:=BlockBuffer[0];
for j:=0 to 63 do
begin
lpMCUBuffer^:=BlockBuffer[j];
inc(lpMCUBuffer);
end;
for i:=0 to 127 do
begin
lpMCUBuffer^:=0;
inc(lpMCUBuffer);
end;
end;
else
begin
Result:=FUNC_FORMAT_ERROR;
Exit;
end;
end;//case
Result:=FUNC_OK;
end;
//////////////////////////////////////////////////////////////////
//Huffman Decode (8*8) DU 出口 Blockbuffer[ ] 入口 vvalue
//////////////////////////////////////////////////////////////////
function HufBlock(dchufindex:BYTE;achufindex:BYTE):integer;
var
count:SmallInt;
i:SmallInt;
funcret:integer;
begin
count:=0;
//dc
HufTabIndex:=dchufindex;
funcret:=DecodeElement; //Read Byte Dc
if(funcret<>FUNC_OK) then
begin
result:=funcret;
Exit;
end;
BlockBuffer[count]:=vvalue;//解出的直流系数
inc(count);
//ac
HufTabIndex:=achufindex;
while (count<64) do
begin //63 Bytes AC
funcret:=DecodeElement;
if(funcret<> FUNC_OK) then
begin
Result:= funcret;
Exit;
end;
if ((rrun=0) and (vvalue=0)) then
begin
for i:=count to 63 do
BlockBuffer[i]:=0;
count:=64;
end
else
begin
for i:=0 to rrun-1 do //前面的零
begin
BlockBuffer[count]:=0;
inc(count);
end;
BlockBuffer[count]:=vvalue;//解出的值
inc(count);
end;
end;
Result:=FUNC_OK;
end;
//////////////////////////////////////////////////////////////////////////////
//Huffman 解码 每个元素 出口 vvalue 入口 读文件ReadByte
//////////////////////////////////////////////////////////////////////////////
function DecodeElement:integer;
var
thiscode,tempcode:integer;
temp,valueex:Word;
codelen:SmallInt;
hufexbyte,runsize,tempsize,sign:BYTE;
newbyte,lastbyte:BYTE;
begin
if(BitPos>=1) then //BitPos指示当前比特位置
begin
dec(BitPos);
thiscode:=BYTE(CurByte shr BitPos); //取一个比特
CurByte:=CurByte and MyAnd[BitPos]; //清除取走的比特位
end
else //取出的一个字节已用完
begin //新取
lastbyte:=ReadByte; //读出一个字节
dec(BitPos); //and[]:=0x0,0x1,0x3,0x7,0xf,0x1f,0x2f,0x3f,0x4f
newbyte:=CurByte and MyAnd[BitPos]; //
thiscode:=lastbyte shr 7;
CurByte:=newbyte;
end;
codelen:=1;
//与Huffman表中的码字匹配,直自找到为止
while ((thiscode<huf_min_value[HufTabIndex,codelen-1]) or
(code_len_table[HufTabIndex,codelen-1]=0) or
(thiscode>huf_max_value[HufTabIndex,codelen-1])) do
begin
if(BitPos>=1) then begin //取出的一个字节还有
dec(BitPos);
tempcode:=BYTE(CurByte shr BitPos);
CurByte:=CurByte and MyAnd[BitPos];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -