implementation
uses JpegDecode;
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
fileName:string;
Bf:BITMAPFILEHEADER;
MS:TMemoryStream;
pImg:Pointer;
begin
if OpenDialog1.Execute then
begin
fileName:=OpenDialog1.FileName;
if LoadJpegFile(FileName,pImg) then
begin
MS:=TMemoryStream.Create;
CopyMemory(@bf,pImg,sizeof(BITMAPFILEHEADER));
MS.Write(pImg^,bf.BfSize);
MS.Position:=0;
Image1.Picture.Bitmap.LoadFromStream(MS);
MS.Free;
FreeMem(pImg);
end else
ShowMessage('调用失败');
end;
end;
unit JpegDecode;
interface
uses Windows, SysUtils, Classes, WinTypes;
const
FUNC_OK = 0;
FUNC_MEMORY_ERROR = 1;
FUNC_FILE_ERROR = 2;
FUNC_FORMAT_ERROR = 3;
M_SOF0 = $c0;
M_DHT = $c4;
M_EOI = $d9;
M_SOS = $da;
M_DQT = $db;
M_DRI = $dd;
M_APP0 = $e0;
W1 = 2841; // 2048*sqrt(2)*cos(1*pi/16)
W2 = 2676; // 2048*sqrt(2)*cos(2*pi/16)
W3 = 2408; // 2048*sqrt(2)*cos(3*pi/16)
W5 = 1609; // 2048*sqrt(2)*cos(5*pi/16)
W6 = 1108; // 2048*sqrt(2)*cos(6*pi/16)
W7 = 565; // 2048*sqrt(2)*cos(7*pi/16)
Zig_Zag: array[0..7, 0..7] of Integer =
((0, 1, 5, 6, 14, 15, 27, 28),
(2, 4, 7, 13, 16, 26, 29, 42),
(3, 8, 12, 17, 25, 30, 41, 43),
(9, 11, 18, 24, 31, 40, 44, 53),
(10, 19, 23, 32, 39, 45, 52, 54),
(20, 22, 33, 38, 46, 51, 55, 60),
(21, 34, 37, 47, 50, 56, 59, 61),
(35, 36, 48, 49, 57, 58, 62, 63));
type
PShortInt = ^Shortint;
PSmallInt = ^Smallint;
PLongInt = ^Longint;
PByte = ^Byte;
PInt = ^Integer;
MyInt = array[0..7, 0..7] of Integer;
function LoadJpegFile(JpegFileName: string; var pImg: Pointer): Boolean;
function InitTag: Integer;
procedure InitTable;
function Decode: Integer;
function DecodeMCUBlock: Integer;
function HufBlock(dchufindex: Byte; achufindex: Byte): Integer;
function DecodeElement: Integer;
procedure IQtIZzMCUComponent(flag: Smallint);
procedure IQtIZzBlock(s: PSmallInt; d: PInt; flag: Smallint);
procedure GetYUV(flag: Smallint);
procedure StoreBuffer;
function ReadByte: Byte;
procedure Initialize_Fast_IDCT;
procedure Fast_IDCT(var block: MyInt);
procedure idctrow(var blk: MyInt);
procedure idctcol(var blk: MyInt);
implementation
var
//////////////////////////////////////////////////
ImgWidth: DWORD = 0;
ImgHeight: DWORD = 0;
lpImgData: PChar;
bf: BITMAPFILEHEADER;
bi: BITMAPINFOHEADER;
//////////////////////////////////////////////////////////
SampRate_Y_H, SampRate_Y_V: Smallint;
SampRate_U_H, SampRate_U_V: Smallint;
SampRate_V_H, SampRate_V_V: Smallint;
H_YtoU, V_YtoU, H_YtoV, V_YtoV: Smallint;
Y_in_MCU, U_in_MCU, V_in_MCU: Smallint;
lpJpegBuf: PChar;
lp, lpPtr: PChar;
qt_table: array[0..2, 0..63] of Smallint;
comp_num: Smallint;
comp_index: array[0..3] of Byte;
YDcIndex, YAcIndex, UVDcIndex, UVAcIndex: Byte;
HufTabIndex: Byte;
YQtTable, UQtTable, VQtTable: PSmallInt;
MyAnd: array[0..8] of Byte = (0, 1, 3, 7, $0f, $1f, $3f, $7f, $ff);
code_pos_table, code_len_table: array[0..3, 0..15] of Smallint;
code_value_table: array[0..3, 0..255] of Word;
huf_max_value, huf_min_value: array [0..3, 0..15] of Word;
BitPos, CurByte: Smallint;
rrun, vvalue: Smallint;
MCUBuffer: array[0..10 * 64 - 1] of Smallint;
QtZzMCUBuffer: array[0..10 * 64 - 1] of Integer;
BlockBuffer: array[0..63] of Smallint;
ycoef, ucoef, vcoef: Smallint;
IntervalFlag: Boolean;
Interval: Smallint = 0;
Y, U, V: array[0..4 * 64 - 1] of Integer;
sizei, sizej: DWORD;
restart: Smallint;
iclip: array[0..1023] of Longint;
LineBytes, NumColors: DWORD;
////////////////////////////////////////////////////////////////
function LoadJpegFile(JpegFileName: string; var pImg: Pointer): Boolean;
var
fjpg: TFileStream;
ImgSize: DWORD;
JpegBufSize: DWORD;
funcret: Integer;
lpImgDataTemp: PChar;
begin
fjpg := TFileStream.Create(JpegFileName, fmOpenRead);
//将Jpeg文件读入内存
JpegBufSize := fjpg.Size;
GetMem(lpJpegBuf, JpegBufSize);
fjpg.Read(lpJpegBuf^, JpegBufSize);
fjpg.Free;
InitTable;
funcret := InitTag;
if (funcret <> FUNC_OK) then //初始化表头不成功
begin
FreeMem(lpJpegBuf, JpegBufSize);
Result := false;
Exit;
end;
bi.biSize := SizeOf(BITMAPINFOHEADER); //定义BMP头
bi.biWidth := ImgWidth;
bi.biHeight := ImgHeight;
bi.biPlanes := 1;
bi.biBitCount := 24;
bi.biClrUsed := 0;
bi.biClrImportant := 0;
bi.biCompression := BI_RGB;
NumColors := 0;
LineBytes := DWORD((bi.biWidth * bi.biBitCount + 31) div 32 * 4);
ImgSize := LineBytes * DWORD(bi.biHeight); //变化后的图象空间
bf.bfType := $4d42; //'BM'
bf.bfSize := SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER)
+ NumColors * SizeOf(RGBQUAD) + ImgSize;
bf.bfOffBits := DWORD(NumColors * SizeOf(RGBQUAD) +
SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER));
GetMem(lpImgData, bf.bfSize); //分配变换后的存储空间
lpImgDataTemp := lpImgData;
CopyMemory(lpImgDataTemp, @bf, SizeOf(BITMAPFILEHEADER));
lpImgDataTemp := lpImgDataTemp + SizeOf(BITMAPFILEHEADER);
CopyMemory(lpImgDataTemp, @bi, SizeOf(BITMAPINFOHEADER));
lpPtr := lpImgData + bf.bfOffBits; //实际图象数据位置
if ((SampRate_Y_H = 0) or (SampRate_Y_V = 0)) then
begin
FreeMem(lpJpegBuf);
FreeMem(lpImgData);
Result := false;
Exit;
end;
funcret := Decode;
if (funcret = FUNC_OK) then //解码成功
begin
Result := true;
pImg := lpImgData;
FreeMem(lpJpegBuf);
Exit;
end
else
begin
FreeMem(lpImgData);
FreeMem(lpJpegBuf);
Result := false;
Exit;
end;
end;
////////////////////////////////////////////////////////////////////////////////
function InitTag: Integer;
var
finish: Boolean;
id: Byte;
llength: Smallint;
i, j, k: Smallint;
huftab1, huftab2: Smallint;
huftabindex: Smallint;
hf_table_index: Byte;
qt_table_index: Byte;
comnum: Byte;
lptemp: PChar;
ccount: Smallint;
begin
finish := false;
lp := lpJpegBuf + 2;//跳过两个字节SOI(0xFF,0xD8 Start of Image)
while (not finish) do
begin
id := Byte((lp + 1)^); //取出低位字节(高位在前,低位在后)
lp := lp + 2; //跳过取出的字节
case id of
M_APP0: //JFIF APP0 segment marker (0xE0)
begin
llength := MAKEWORD(Byte((lp + 1)^), Byte(lp^));
//MAKEWORD 转换Motorlora 与 intel 数据格式
lp := lp + llength;//Skip JFIF segment marker
end;
M_DQT: //定义量化表(0xFF,0xDB)
begin
llength := MAKEWORD(Byte((lp + 1)^), Byte(lp^));//(量化表长度)
qt_table_index := (Byte((lp + 2)^) and $0f);
//量化表信息bit 0..3: QT 号(0..3, 否则错误)
//bit 4..7: QT 精度, 0 = 8 bit, 否则 16 bit
lptemp := lp + 3;
//n 字节的 QT, n = 64*(精度+1)
if (llength < 80) then //精度为 8 bit
begin
for i := 0 to 63 do
begin
qt_table[qt_table_index, i] := Smallint(lptemp^);
Inc(lptemp);
end;
end
else //精度为 16 bit
begin
for i := 0 to 63 do
begin
qt_table[qt_table_index, i] :=
Smallint(lptemp^);
Inc(lptemp);
end;
qt_table_index := Byte(lptemp^) and $0f;
Inc(lptemp);
for i := 0 to 63 do
begin
qt_table[qt_table_index, i] := Smallint(lptemp^);
Inc(lptemp);
end;
end;
lp := lp + llength; //跳过量化表
end;
M_SOF0: //帧开始 (baseline JPEG 0xFF,0xC0)
begin
llength := MAKEWORD(Byte((lp + 1)^), Byte(lp^));
//长度 (高字节, 低字节), 8+components*3
ImgHeight := MAKEWORD(Byte((lp + 4)^), Byte((lp + 3)^));
//图片高度 (高字节, 低字节), 如果不支持 DNL 就必须 >0
ImgWidth := MAKEWORD(Byte((lp + 6)^), Byte((lp + 5)^));
//图片宽度 (高字节, 低字节), 如果不支持 DNL 就必须 >0
comp_num := Byte((lp + 7)^);
//components 数量(1 byte), 灰度图是 1, YCbCr/YIQ 彩色图是 3, CMYK 彩色图是 4
if ((comp_num <> 1) and (comp_num <> 3)) then
begin
Result := FUNC_FORMAT_ERROR;
Exit;
end;
if (comp_num = 3) then //YCbCr/YIQ 彩色图
begin
comp_index[0] := Byte((lp + 8)^);
//component id (1 = Y, 2 = Cb, 3 = Cr, 4 = I, 5 = Q)
SampRate_Y_H := Byte((lp + 9)^) shr 4; //水平采样系数
SampRate_Y_V := Byte((lp + 9)^) and $0f; //水平采样系数
YQtTable := PSmallInt(@qt_table[Byte((lp + 10)^)]);
//通过量化表号取得量化表地址
/// ShowMessage(IntToStr(YQtTable^));
comp_index[1] := Byte((lp + 11)^); //component id
SampRate_U_H := Byte((lp + 12)^) shr 4; //水平采样系数
SampRate_U_V := Byte((lp + 12)^) and $0f; //水平采样系数
UQtTable := PSmallInt(@qt_table[Byte((lp + 13)^)]);
//通过量化表号取得量化表地址
comp_index[2] := Byte((lp + 14)^); //component id
SampRate_V_H := Byte((lp + 15)^) shr 4; //水平采样系数
SampRate_V_V := Byte((lp + 15)^) and $0f; //水平采样系数
VQtTable := PSmallInt(@qt_table[Byte((lp + 16)^)]);
//通过量化表号取得量化表地址
end
else //灰度图
begin
comp_index[0] := Byte((lp + 8)^);
SampRate_Y_H := Byte((lp + 9)^) shr 4;
SampRate_Y_V := Byte((lp + 9)^) and $0f;
YQtTable := PSmallInt(@qt_table[Byte((lp + 10)^)]);
//灰度图的量化表都一样
comp_index[1] := Byte((lp + 8)^);
SampRate_U_H := 1;
SampRate_U_V := 1;
UQtTable := PSmallInt(@qt_table[Byte((lp + 10)^)]);
comp_index[2] := Byte((lp + 8)^);
SampRate_V_H := 1;
SampRate_V_V := 1;
VQtTable := PSmallInt(@qt_table[Byte((lp + 10)^)]);
end;
lp := lp + llength;
end;
M_DHT: //定义 Huffman Table(0xFF,0xC4)
begin
llength := MAKEWORD(Byte((lp + 1)^), Byte(lp^));
//长度 (高字节, 低字节)
if (llength < $d0) then // Huffman Table信息 (1 byte)
begin
huftab1 := Smallint(Byte((lp + 2)^) shr 4);
//huftab1=0,1(HT 类型,0 = DC 1 = AC)
huftab2 := Smallint(Byte((lp + 2)^) and $0f);
//huftab2=0,1(HT 号 ,0 = Y 1 = UV)
huftabindex := huftab1 * 2 + huftab2;
//0 = YDC 1 = UVDC 2 = YAC 3 = UVAC
lptemp := lp + 3;
for i := 0 to 15 do //16 bytes: 长度是 1..16 代码的符号数
begin
code_len_table[huftabindex, i] := Smallint(lptemp^);//码长为
Inc(lptemp);
//i的码字个数
end;
j := 0;
for i := 0 to 15 do //得出HT的所有码字的对应值
begin
if (code_len_table[huftabindex, i] <> 0) then
begin
k := 0;
while (k < code_len_table[huftabindex, i]) do
begin
code_value_table[huftabindex, k + j] := Smallint(lptemp^);
lptemp := lptemp + 1;
k := k + 1;
end;
j := j + k;
end;
end;
i := 0;
while (code_len_table[huftabindex, i] = 0) do //去掉代码的符号数为零
i := i + 1;
for j := 0 to i - 1 do
begin
huf_min_value[huftabindex, j] := 0; //码长为j的最小码字
huf_max_value[huftabindex, j] := 0; //码长为j的最大码字
end;
huf_min_value[huftabindex, i] := 0;
huf_max_value[huftabindex, i] := code_len_table[huftabindex, i] - 1;
for j := i + 1 to 15 do
begin
//码长为j的最小码字与最大码字
huf_min_value[huftabindex, j] :=
(huf_max_value[huftabindex, j - 1] + 1) shl 1;
huf_max_value[huftabindex, j] :=
huf_min_value[huftabindex, j] + code_len_table[huftabindex, j] - 1;
end;
code_pos_table[huftabindex, 0] := 0; //码起始位置
for j := 1 to 15 do
code_pos_table[huftabindex, j] :=
code_len_table[huftabindex, j - 1] + code_pos_table[huftabindex, j - 1];
lp := lp + llength;
end //if
else
begin
hf_table_index := Byte((lp + 2)^);
lp := lp + 2;
while (hf_table_index <> $ff) do
begin
huftab1 := Smallint(hf_table_index shr 4); //huftab1=0,1
huftab2 := Smallint(hf_table_index and $0f); //huftab2=0,1
huftabindex := huftab1 * 2 + huftab2;
lptemp := lp;
Inc(lptemp);
ccount := 0;
for i := 0 to 15 do
begin
code_len_table[huftabindex, i] :=
Smallint(lptemp^);
Inc(lptemp);
ccount := ccount + code_len_table[huftabindex, i];
end;
ccount := ccount + 17;
j := 0;
for i := 0 to 15 do
if (code_len_table[huftabindex, i] <> 0) then
begin
k := 0;
while (k < code_len_table[huftabindex, i]) do
begin
code_value_table[huftabindex, k + j] := Smallint(lptemp^);
Inc(lptemp);
Inc(k);
end;
j := j + k;
end;
i := 0;
while (code_len_table[huftabindex, i] = 0) do
Inc(i);
for j := 0 to i - 1 do
begin
huf_min_value[huftabindex, j] := 0;
huf_max_value[huftabindex, j] := 0;
end;
huf_min_value[huftabindex, i] := 0;
huf_max_value[huftabindex, i] := code_len_table[huftabindex, i] - 1;
for j := i + 1 to 15 do
begin
huf_min_value[huftabindex, j] :=
(huf_max_value[huftabindex, j - 1] + 1) shl 1;
huf_max_value[huftabindex, j] :=
huf_min_value[huftabindex, j] + code_len_table[huftabindex, j] - 1;
end;
code_pos_table[huftabindex, 0] := 0;
for j := 1 to 15 do
code_pos_table[huftabindex, j] :=
code_len_table[huftabindex, j - 1] + code_pos_table[huftabindex, j - 1];
lp := lp + ccount;
hf_table_index := Byte(lp^);
end; //while
end; //else
end;
M_DRI: //定义重新开始间隔, 细节附后
begin
llength := MAKEWORD(Byte((lp + 1)^), Byte(lp^));
restart := MAKEWORD(Byte((lp + 3)^), Byte((lp + 2)^));
lp := lp + llength;
end;
M_SOS: //扫描行开始0xff, 0xda (SOS)
begin
llength := MAKEWORD(Byte((lp + 1)^), Byte(lp^));//长度 (高字节, 低字节),
comnum := Byte((lp + 2)^);
//扫描行内组件的数量 (1 byte), 必须 >:= 1 , <:=4 (否则是错的) 通常是 3
if (comnum <> comp_num) then
//必须是 6+2*(扫描行内组件的数量)
begin
Result := FUNC_FORMAT_ERROR;
Exit;
end;
lptemp := lp + 3;
for i := 0 to comp_num - 1 do
begin //每组件的信息
if (Byte(lptemp^) = comp_index[0]) then
begin //1 byte :Component id
YDcIndex := Byte((lptemp + 1)^) shr 4; //Y 使用的 Huffman 表
YAcIndex := (Byte((lptemp + 1)^) and $0f) + 2;
end
else
begin
UVDcIndex := Byte((lptemp + 1)^) shr 4; //U,V
UVAcIndex := (Byte((lptemp + 1)^) and $0f) + 2;
end;
lptemp := lptemp + 2;
end; // for
lp := lp + llength;
finish := true;
end;
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 := 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 := 0;
QtZzMCUBuffer := 0;
end;
for i := 0 to 63 do
begin
Y := 0;
U := 0;
V := 0;
BlockBuffer := 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 := 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];
end
else
begin
lastbyte := ReadByte;
Dec(BitPos);
newbyte := CurByte and MyAnd[BitPos];
tempcode := Byte(lastbyte shr 7);
CurByte := newbyte;
end;
thiscode := (thiscode shl 1) + tempcode;
Inc(codelen);
if (codelen > 16) then
begin
Result := FUNC_FORMAT_ERROR;
Exit;
end;
end; //while
Temp := thiscode - huf_min_value[HufTabIndex, codelen - 1] +
code_pos_table[HufTabIndex, codelen - 1];
hufexbyte := Byte(code_value_table[HufTabIndex, Temp]);
rrun := Smallint(hufexbyte shr 4); //一个字节中,高四位是其前面的零的个数。
runsize := hufexbyte and $0f; //后四位为后面字的尺寸
if (runsize = 0) then
begin
vvalue := 0;
Result := FUNC_OK;
Exit;
end;
tempsize := runsize;
if (BitPos >= runsize) then
begin
BitPos := BitPos - runsize;
valueex := Byte(CurByte shr BitPos);
CurByte := CurByte and MyAnd[BitPos];
end
else
begin
valueex := CurByte;
tempsize := tempsize - BitPos;
while (tempsize > 8) do
begin
lastbyte := ReadByte;
valueex := (valueex shl 8) + Byte(lastbyte);
tempsize := tempsize - 8;
end; //while
lastbyte := ReadByte;
BitPos := BitPos - tempsize;
valueex := (valueex shl tempsize) + (lastbyte shr BitPos);
CurByte := lastbyte and MyAnd[BitPos];
end; //else
sign := valueex shr (runsize - 1);
if (sign <> 0) then
vvalue := valueex //解出的码值
else
begin
valueex := valueex xor $ffff;
Temp := $ffff shl runsize;
vvalue := -Smallint(valueex xor Temp);
end;
Result := FUNC_OK;
end;
/////////////////////////////////////////////////////////////////////////////////////
//反量化MCU中的每个组件 入口 MCUBuffer 出口 QtZzMCUBuffer
/////////////////////////////////////////////////////////////////////////////////////
procedure IQtIZzMCUComponent(flag: Smallint);
var
H, VV: Smallint;
i, j: Smallint;
pQtZzMCUBuffer, tempbuf1: Pint;
pMCUBuffer, tempbuf2: PSmallInt;
begin
case flag of
0:
begin
H := SampRate_Y_H;
VV := SampRate_Y_V;
pMCUBuffer := PSmallInt(@MCUBuffer); //Huffman Decoded
pQtZzMCUBuffer := Pint(@QtZzMCUBuffer);
end;
1:
begin
H := SampRate_U_H;
VV := SampRate_U_V;
pMCUBuffer := PSmallInt(@MCUBuffer);
Inc(pMCUBuffer, Y_in_MCU * 64);
pQtZzMCUBuffer := Pint(@QtZzMCUBuffer);
Inc(pQtZzMCUBuffer, Y_in_MCU * 64);
end;
2:
begin
H := SampRate_V_H;
VV := SampRate_V_V;
pMCUBuffer := PSmallInt(@MCUBuffer);
Inc(pMCUBuffer, (Y_in_MCU + U_in_MCU) * 64);
pQtZzMCUBuffer := Pint(@QtZzMCUBuffer);
Inc(pQtZzMCUBuffer, (Y_in_MCU + U_in_MCU) * 64);
end;
else
begin
H := 0;
pQtZzMCUBuffer := nil;
pMCUBuffer := nil;
VV := 0;
end;
end;//case
for i := 0 to VV - 1 do
for j := 0 to H - 1 do
begin
tempbuf2 := pMCUBuffer;
Inc(tempbuf2, (i * H + j) * 64);
tempbuf1 := pQtZzMCUBuffer;
Inc(tempbuf1, (i * H + j) * 64);
IQtIZzBlock(tempbuf2, tempbuf1, flag); //8*8DU
end;
end;
//要量化的字
//////////////////////////////////////////////////////////////////////////////////////////
//反量化 8*8 DU
//////////////////////////////////////////////////////////////////////////////////////////
procedure IQtIZzBlock(s: PSmallInt; d: PInt; flag: Smallint);
var
i, j: Smallint;
tag: Smallint;
pQt, temp1, temp3: PSmallInt;
buffer2: MyInt;
temp2: Pint;
offset: Smallint;
begin
case flag of
0: //亮度
begin
pQt := YQtTable; //量化表地址
// ShowMessage(IntTostr(YQtTable^));
offset := 128;
end;
1: //红
begin
pQt := UQtTable;
offset := 0;
end;
2: //蓝
begin
pQt := VQtTable;
offset := 0;
end;
else
pQt := nil;
offset := 0;
end;
for i := 0 to 7 do
for j := 0 to 7 do
begin
tag := Zig_Zag[i, j];
temp1 := s;
Inc(temp1, tag);
temp3 := pQt;
Inc(temp3, tag);
buffer2[i, j] := Integer(temp1^ * temp3^);
end;
Fast_IDCT(buffer2); //反DCT
for i := 0 to 7 do
for j := 0 to 7 do
begin
temp2 := d;
Inc(temp2, i * 8 + j);
temp2^ := buffer2[i, j] + offset;
end;
end;
///////////////////////////////////////////////////////////////////////////////
procedure Fast_IDCT(var block: MyInt);
begin
idctrow(block);
idctcol(block);
end;
///////////////////////////////////////////////////////////////////////////////
function ReadByte: Byte;
var
i: Byte;
begin
i := Byte(lp^); // lp 为解码的起始位置
lp := lp + 1;
if (i = $ff) then
lp := lp + 1;
BitPos := 8;
CurByte := i;
Result := i;
end;
///////////////////////////////////////////////////////////////////////
procedure Initialize_Fast_IDCT;
var
i: Smallint;
begin
for i := -512 to 511 do
begin
if i<-256 then
iclip[512 + i] := -256;
if i > 255 then
iclip[512 + i] := 255;
if (i >= -256) and (i <= 255) then
iclip[512 + i] := i;
end;
end;
////////////////////////////////////////////////////////////////////////
procedure idctrow(var blk: MyInt);
var
i, x0, x1, x2, x3, x4, x5, x6, x7, x8: Integer;
begin
//intcut
for i := 0 to 7 do
begin
x1 := blk[i, 4] shl 11;
x2 := blk[i, 6];
x3 := blk[i, 2];
x4 := blk[i, 1];
x5 := blk[i, 7];
x6 := blk[i, 5];
x7 := blk[i, 3];
if ((x1 or x2 or x3 or x4 or x5 or x6 or x7) = 0) then
begin
blk[i, 1] := blk[i, 0] shl 3;
blk[i, 2] := blk[i, 0] shl 3;
blk[i, 3] := blk[i, 0] shl 3;
blk[i, 4] := blk[i, 0] shl 3;
blk[i, 5] := blk[i, 0] shl 3;
blk[i, 6] := blk[i, 0] shl 3;
blk[i, 7] := blk[i, 0] shl 3;
blk[i, 0] := blk[i, 0] shl 3;
Continue;
end;
x0 := (blk[i, 0] shl 11) + 128; // for proper rounding in the fourth stage
//first stage
x8 := W7 * (x4 + x5);
x4 := x8 + (W1 - W7) * x4;
x5 := x8 - (W1 + W7) * x5;
x8 := W3 * (x6 + x7);
x6 := x8 - (W3 - W5) * x6;
x7 := x8 - (W3 + W5) * x7;
//second stage
x8 := x0 + x1;
x0 := x0 - x1;
x1 := W6 * (x3 + x2);
x2 := x1 - (W2 + W6) * x2;
x3 := x1 + (W2 - W6) * x3;
x1 := x4 + x6;
x4 := x4 - x6;
x6 := x5 + x7;
x5 := x5 - x7;
//third stage
x7 := x8 + x3;
x8 := x8 - x3;
x3 := x0 + x2;
x0 := x0 - x2;
if (181 * (x4 + x5) + 128) < 0 then
x2 := ((181 * (x4 + x5) + 128) shr 8) or
((not Integer(0)) shl (32 - 8))
else
x2 := (181 * (x4 + x5) + 128) shr 8;
if (181 * (x4 - x5) + 128) < 0 then
x4 := ((181 * (x4 - x5) + 128) shr 8) or
((not Integer(0)) shl (32 - 8))
else
x4 := (181 * (x4 - x5) + 128) shr 8;
//fourth stage
if x7 + x1 < 0 then
blk[i, 0] := ((x7 + x1) shr 8) or ((not Integer(0)) shl (32 - 8))
else
blk[i, 0] := (x7 + x1) shr 8;
if x3 + x2 < 0 then
blk[i, 1] := ((x3 + x2) shr 8) or ((not Integer(0)) shl (32 - 8))
else
blk[i, 1] := (x3 + x2) shr 8;
if x0 + x4 < 0 then
blk[i, 2] := ((x0 + x4) shr 8) or ((not Integer(0)) shl (32 - 8))
else
blk[i, 2] := (x0 + x4) shr 8;
if x8 + x6 < 0 then
blk[i, 3] := ((x8 + x6) shr 8) or ((not Integer(0)) shl (32 - 8))
else
blk[i, 3] := (x8 + x6) shr 8;
if x8 - x6 < 0 then
blk[i, 4] := ((x8 - x6) shr 8) or ((not Integer(0)) shl (32 - 8))
else
blk[i, 4] := (x8 - x6) shr 8;
if x0 - x4 < 0 then
blk[i, 5] := ((x0 - x4) shr 8) or ((not Integer(0)) shl (32 - 8))
else
blk[i, 5] := (x0 - x4) shr 8;
if x3 - x2 < 0 then
blk[i, 6] := ((x3 - x2) shr 8) or ((not Integer(0)) shl (32 - 8))
else
blk[i, 6] := (x3 - x2) shr 8;
if x7 - x1 < 0 then
blk[i, 7] := ((x7 - x1) shr 8) or ((not Integer(0)) shl (32 - 8))
else
blk[i, 7] := (x7 - x1) shr 8;
end;
end;
//////////////////////////////////////////////////////////////////////////////
procedure idctcol(var blk: MyInt);
var
j, x0, x1, x2, x3, x4, x5, x6, x7, x8: Integer;
Temp: Integer;
begin
//intcut
for j := 0 to 7 do
begin
x1 := blk[4, j] shl 8;
x2 := blk[6, j];
x3 := blk[2, j];
x4 := blk[1, j];
x5 := blk[7, j];
x6 := blk[5, j];
x7 := blk[3, j];
if ((x1 or x2 or x3 or x4 or x5 or x6 or x7) = 0) then
begin
if (blk[0, j] + 32) < 0 then
Temp := ((blk[0, j] + 32) shr 6) or
(not (Integer(0)) shl (32 - 6))
else
Temp := (blk[0, j] + 32) shr 6;
blk[1, j] := iclip[512 + Temp];
blk[2, j] := iclip[512 + Temp];
blk[3, j] := iclip[512 + Temp];
blk[4, j] := iclip[512 + Temp];
blk[5, j] := iclip[512 + Temp];
blk[6, j] := iclip[512 + Temp];
blk[7, j] := iclip[512 + Temp];
blk[0, j] := iclip[512 + Temp];
Continue;
end;
x0 := (blk[0, j] shl 8) + 8192;
//first stage
x8 := W7 * (x4 + x5) + 4;
if (x8 + (W1 - W7) * x4) < 0 then
x4 := ((x8 + (W1 - W7) * x4) shr 3) or
(not (Integer(0)) shl (32 - 3))
else
x4 := (x8 + (W1 - W7) * x4) shr 3;
if (x8 - (W1 + W7) * x5) < 0 then
x5 := ((x8 - (W1 + W7) * x5) shr 3) or
(not (Integer(0)) shl (32 - 3))
else
x5 := (x8 - (W1 + W7) * x5) shr 3;
x8 := W3 * (x6 + x7) + 4;
if (x8 - (W3 - W5) * x6) < 0 then
x6 := ((x8 - (W3 - W5) * x6) shr 3) or
(not (Integer(0)) shl (32 - 3))
else
x6 := (x8 - (W3 - W5) * x6) shr 3;
if (x8 - (W3 + W5) * x7) < 0 then
x7 := ((x8 - (W3 + W5) * x7) shr 3) or
(not (Integer(0)) shl (32 - 3))
else
x7 := (x8 - (W3 + W5) * x7) shr 3;
//second stage
x8 := x0 + x1;
x0 := x0 - x1;
x1 := W6 * (x3 + x2) + 4;
if (x1 - (W2 + W6) * x2) < 0 then
x2 := ((x1 - (W2 + W6) * x2) shr 3) or
(not (Integer(0)) shl (32 - 3))
else
x2 := (x1 - (W2 + W6) * x2) shr 3;
if (x1 + (W2 - W6) * x3) < 0 then
x3 := ((x1 + (W2 - W6) * x3) shr 3) or
(not (Integer(0)) shl (32 - 3))
else
x3 := (x1 + (W2 - W6) * x3) shr 3;
x1 := x4 + x6;
x4 := x4 - x6;
x6 := x5 + x7;
x5 := x5 - x7;
//third stage
x7 := x8 + x3;
x8 := x8 - x3;
x3 := x0 + x2;
x0 := x0 - x2;
if (181 * (x4 + x5) + 128) < 0 then
x2 := ((181 * (x4 + x5) + 128) shr 8) or
(not (Integer(0)) shl (32 - 8))
else
x2 := (181 * (x4 + x5) + 128) shr 8;
if (181 * (x4 - x5) + 128) < 0 then
x4 := ((181 * (x4 - x5) + 128) shr 8) or
(not (Integer(0)) shl (32 - 8))
else
x4 := (181 * (x4 - x5) + 128) shr 8;
//fourth stage
if x7 + x1 < 0 then
Temp := ((x7 + x1) shr 14) or (not (Integer(0)) shl (32 - 14))
else
Temp := (x7 + x1) shr 14;
blk[0, j] := iclip[512 + Temp];
if x3 + x2 < 0 then
Temp := ((x3 + x2) shr 14) or (not (Integer(0)) shl (32 - 14))
else
Temp := (x3 + x2) shr 14;
blk[1, j] := iclip[512 + Temp];
if x0 + x4 < 0 then
Temp := ((x0 + x4) shr 14) or (not (Integer(0)) shl (32 - 14))
else
Temp := (x0 + x4) shr 14;
blk[2, j] := iclip[512 + Temp];
if x8 + x6 < 0 then
Temp := ((x8 + x6) shr 14) or (not (Integer(0)) shl (32 - 14))
else
Temp := (x8 + x6) shr 14;
blk[3, j] := iclip[512 + Temp];
if x8 - x6 < 0 then
Temp := ((x8 - x6) shr 14) or (not (Integer(0)) shl (32 - 14))
else
Temp := (x8 - x6) shr 14;
blk[4, j] := iclip[512 + Temp];
if x0 - x4 < 0 then
Temp := ((x0 - x4) shr 14) or (not (Integer(0)) shl (32 - 14))
else
Temp := (x0 - x4) shr 14;
blk[5, j] := iclip[512 + Temp];
if x3 - x2 < 0 then
Temp := ((x3 - x2) shr 14) or (not (Integer(0)) shl (32 - 14))
else
Temp := (x3 - x2) shr 14;
blk[6, j] := iclip[512 + Temp];
if x7 - x1 < 0 then
Temp := ((x7 - x1) shr 14) or (not (Integer(0)) shl (32 - 14))
else
Temp := (x7 - x1) shr 14;
blk[7, j] := iclip[512 + Temp];
end;
end;
end.
用户1473556 2008-12-20 16:00