//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//
// ExtractSwfPic 释放影片文件的图片
//
// sSwfName 影片文件名称
//
// 另外,本函数用到了两个外部变量: FileLength, FileBuf
// 本函数改写了它们的值
//
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
function ExtractSwfPic( sSwfName, sPicSavePath: String ): Boolean;
type
//Compiler选项Record Field Alignment必须设置为1,保证Record长度正确
//BMP文件头
BitmapFileHeadType = Record
B,M : Char;
bfSize : LongWord;
bfReserved1 : Word;
bfReserved2 : Word;
bfOffBits : LongWord;
end;
//BMP文件图像信息头
BitmapInfoHeadType = Record
biSize : LongWord;
biWidth : LongWord;
biHeight : LongWord;
biPlanes : Word;
biBitCount : Word;
biCompression : LongWord;
biSizeImage : LongWord;
biXPelsPerMeter : LongWord;
biYPelsPerMeter : LongWord;
biClrUsed : LongWord;
biClrImportant : LongWord;
end;
var
f : File;
fws : string[3]; //标示信息
version : Byte; //SWF文件版本号
b,b1,b2 : Byte;
Buf : Array of Byte;
FrameRate : real; //速率
FrameCount : Word; //总帧数
s : string;
TagID : Word; //Tag标示
TagLength : LongWord; //Tag长度
CurrentPos, //CurrentPos记录当前读写位置
FileLengthPos, //FileLengthPos记录FileLength参数位置
TagPos, //TagPos记录当前TagID位置
tmpPos : Integer; //内存读写位置
Filename : string; //存放SWF文件名(去掉了路径和扩展名)
l : LongWord;
BitmapID : Word;
BitmapOffset : LongWord;
BitmapBuf1,
BitmapBuf2 : Array of Byte;
JPEGEncoding,
JPEGImage : Array of Byte;
JPEGID : Word;
BitmapFormat : Byte;
BitmapWidth,BitmapHeight : Word;
BitmapColorTableSize1 : Byte; //BitmapFormat=3
BitmapColorTableSize2 : Word; //BitmapFormat=4
BitmapColorTableSize3 : LongWord; //BitmapFormat=5
BitmapColorTableSize : LongWord;
inStream : TMemoryStream;
zStream : TDecompressionStream;
BitmapFileHead : BitmapFileHeadType; //BMP文件头
BitmapInfoHead : BitmapInfoHeadType; //BMP文件图像定义数据
begin
Result := FALSE;
JPEGID := 0;
FileMode := fmOpenRead;
AssignFile( f, sSwfOpenName );
Reset( f, 1 );
SetLength( FileBuf, FileSize(f) );
BlockRead( f, FileBuf[0], Filesize(f) ); //将文件读入内存
CloseFile( f );
//下面为读取SWF文件的文件头Header部分
CurrentPos := 0;
//读取'FWS'标示
SetLength( fws, 3);
Move( FileBuf[CurrentPos], fws[1], 3 );
Inc( CurrentPos, 3 );
if fws = 'CWS' then
begin
SetLength( FileBuf, 0 );
ShowMessage( 'This SWF has be compressed, please restore it first.' );
exit;
end;
if fws <> 'FWS' then
begin
SetLength( FileBuf, 0 );
ShowMessage( 'This is not a Flash movie file.' );
exit;
end;
//读取版本号
Move( FileBuf[CurrentPos], version, Sizeof(version) );
Inc( CurrentPos, Sizeof(version) );
if Version < VERSION_ALLOW then
begin
SetLength( FileBuf, 0 );
ShowMessage('This SWF version is not 5 or higher, can not be operated currently.');
exit;
end;
//读取SWF文件长度
FileLengthPos := CurrentPos;
Move( FileBuf[CurrentPos], FileLength, Sizeof(FileLength) );
Inc( CurrentPos, Sizeof(FileLength) );
//读取XMin,XMax,YMin,YMax
//这里仅读出此四个值的存贮字节存放到Buf中,没有计算它们的实际值
Move( FileBuf[CurrentPos], b, 1 );
Inc( CurrentPos, 1 );
b2 := b shr 3; //得到Bit位数
b2 := 5 + b2 * 4;
while (b2 mod 8)<>0 do
begin
Inc(b2); //计算共有多少Bit位数
end;
b2 := (b2 div 8) -1; //计算共有多少字节Byte
SetLength( Buf, b2+1 );
Buf[0] := b;
Move( FileBuf[CurrentPos], Buf[1], b2 );
Inc( CurrentPos, b2 );
//读取FrameRate,b2为小数点前部分,b1为小数点后部分
Move( FileBuf[CurrentPos], b1, Sizeof(b1) );
Inc( CurrentPos, Sizeof(b1) );
Move( FileBuf[CurrentPos], b2, Sizeof(b2) );
Inc( CurrentPos, Sizeof(b2) );
s := IntToStr(b2) + '.' + IntToStr(b1);
FrameRate := StrToFloat(s);
//读取总帧数FrameCount
Move( FileBuf[CurrentPos], FrameCount, Sizeof(FrameCount) );
Inc( CurrentPos, Sizeof(FrameCount) );
s := sSwfName;
s := ExtractFileName( s );
while Pos('.',s) <> 0 do
begin
s := Copy( s, 1, Pos('.',s)-1 );
end;
Filename := s;
//下面为读取SWF文件的文件内容Tag部分
SetLength( JPEGImage, 0 );
SetLength( JPEGEncoding, 0 );
Repeat
TagPos := CurrentPos;
//读取TagID并得到TagLength
Move( FileBuf[CurrentPos], TagID, Sizeof(TagID) );
Inc( CurrentPos, Sizeof(TagID) );
TagLength := TagID and $3F;
TagID := TagID shr 6;
//如果是LongTag则读取下面的TagLength
if TagLength = $3F then
begin
Move( FileBuf[CurrentPos], TagLength, Sizeof(TagLength) );
Inc( CurrentPos, Sizeof(TagLength) );
end;
Case TagID of
21 : begin
//DefineBitsJPEG2图像
//很奇怪,每段值应该以JPEG定义的SOI开始,以EOI结束
//但是这里的BitmapJPEGEncoding部分却是相反,是FFD9 FFD8,而且中间无内容
//同时它的BitmapJPEGImage部分内容很全,包括了本应该位于BitmapJPEGEncoding
//中的DQT(FFDB)等内容
//查看多个Flash 5格式的Tag21都是这样的
Move( FileBuf[CurrentPos], BitmapID, Sizeof(BitmapID) );
Inc( CurrentPos, Sizeof(BitmapID) );
b := 0;
l := 0;
//那么只好先过滤掉前面无用的FFD9 FFD8
Repeat
Move( FileBuf[CurrentPos], b1, Sizeof(b1) );
Move( FileBuf[CurrentPos+1], b2, Sizeof(b2) );
if ( b1=$FF ) and ( b2=$D8 ) then
Inc(b);
Inc( CurrentPos, Sizeof(b1) );
Inc( l, Sizeof(b1) );
Until b>1;
Dec( CurrentPos, Sizeof(b1) ); //将多读出的当前$FF回退
Dec( l, Sizeof(b1) );
//将后面的BitmapJPEGImage部分直接生成JPG文件
l := TagLength -l -Sizeof(BitmapID);
AssignFile( f, sPicSavePath +Filename +'_Pic'+IntToStr(BitmapID) +'.JPG' );
ReWrite( f, 1 );
BlockWrite( f, FileBuf[CurrentPos], l );
CloseFile( f );
CurrentPos := CurrentPos +l;
end;
35 : begin
//DefineBitsJPEG3图像
//每段值以JPEG定义的SOI开始,以EOI结束
//SOI = Start Of Image = 'FFD8' 这个标记只在文件开始出现一次
//EOI = End Of Image = 'FFD9' JPG 文件都以 FFD9 结束
Move( FileBuf[CurrentPos], BitmapID, Sizeof(BitmapID) );
Inc( CurrentPos, Sizeof(BitmapID) );
l := TagLength -Sizeof(BitmapID);
tmpPos := CurrentPos +l; //先将下一个Tag的位置求出,存放到tmpPos中
Move( FileBuf[CurrentPos], BitmapOffset, Sizeof(BitmapOffset) );
Inc( CurrentPos, Sizeof(BitmapOffset) );
b := 0;
l := 0;
SetLength( BitmapBuf1, 0 );
Repeat
Move( FileBuf[CurrentPos], b1, Sizeof(b1) );
Move( FileBuf[CurrentPos+1], b2, Sizeof(b2) );
if (b1=$FF) and (b2=$D8) then
Inc(b);
SetLength( BitmapBuf1, Length(BitmapBuf1) +1 );
//将BitmapJPEGEncoding部分读入BitmapBuf1
Move( FileBuf[CurrentPos], BitmapBuf1[Length(BitmapBuf1)-1], Sizeof(b1) );
Inc( CurrentPos, Sizeof(b1) );
Inc( l, Sizeof(b1) );
Until b>1;
//此时BitmapBuf1中应该是BitmapEncoding的内容+$FF
//即 $FFD8 ...... $FFD9 FF,这5个控制字段是要去掉的
//BitmapEncoding中的内容是JPEG的DQT = Define Quantization Table = FFDB
//等内容
Dec( CurrentPos, Sizeof(b1) ); //将多读出的当前$FF回退
Dec( l,Sizeof(b1) );
b := 0;
SetLength( BitmapBuf2, 0 );
Repeat
Move( FileBuf[CurrentPos], b1, Sizeof(b1) );
Move( FileBuf[CurrentPos+1], b2, Sizeof(b2) );
if (b1=$FF) and (b2=$DA) then
Inc(b);
SetLength( BitmapBuf2, Length(BitmapBuf2) +1 );
//将BitmapJPEGInmage的SOS前面部分读入BitmapBuf2
//FFDA SOS = Start Of Scan是JPEG的图像开始部分,但是它在文件中必须位于
//DQT(FFDB)等内容的后面,所以此处读到这里就停止,以便插入BitmapBuf1
Move( FileBuf[CurrentPos], BitmapBuf2[Length(BitmapBuf2)-1], Sizeof(b1) );
Inc( CurrentPos, Sizeof(b1) );
Inc( l, Sizeof(b1) );
Until b>0;
Dec( CurrentPos, Sizeof(b1) ); //将多读出的当前$FF回退
Dec( l, Sizeof(b1) );
//由于后面的BitmapAlphaData内容对于JPEG文件没有意义,所以也就不读取了
AssignFile( f, sPicSavePath +Filename +'_Pic' +IntToStr(BitmapID)+'.JPG');
ReWrite( f, 1 );
BlockWrite( f, BitmapBuf2[0], Length(BitmapBuf2)-1 ); //-1表示去掉尾部多读出的FF
BlockWrite( f, BitmapBuf1[2], Length(BitmapBuf1)-5 ); //-5表示去掉FFD8 FFD9FF
l := BitmapOffset -l;
SetLength( BitmapBuf2, l );
//再将BitmapJPEGImage余下的部分读取写入
Move( FileBuf[CurrentPos], BitmapBuf2[0], l );
BlockWrite( f, BitmapBuf2[0], Length(BitmapBuf2) );
CloseFile( f );
CurrentPos := tmpPos;
end;
6 : begin
//DefineBits
//与Tag35的BitmapJPEGImage部分内容一致
Move( FileBuf[CurrentPos], BitmapID, Sizeof(BitmapID) );
Inc( CurrentPos, Sizeof(BitmapID) );
JPEGID := BitmapID;
l := TagLength -Sizeof(BitmapID);
SetLength( JPEGImage, l );
Move( FileBuf[CurrentPos], JPEGImage[0], l );
//由于不确定Tag6和Tag8哪个会在文件中先出现,所以检查JPEGEncoding是否为空
if Length(JPEGEncoding) <> 0 then begin
tmpPos := 0;
//也要先查找SOS的位置,以便插入DQT等BitmapJPEGEncoding内容
Repeat
Inc(tmpPos);
Until ( JPEGImage[tmpPos] = $FF ) and ( JPEGImage[tmpPos+1] = $DA );
AssignFile( f, sPicSavePath +Filename +'_Pic' +IntToStr(JPEGID)+'.JPG');
ReWrite( f, 1 );
BlockWrite( f, JPEGImage[0], tmpPos );
BlockWrite( f, JPEGEncoding[0], Length(JPEGEncoding) );
//写入SOS为开始的内容
BlockWrite( f, JPEGImage[tmpPos], Length(JPEGImage) -tmpPos );
CloseFile( f );
SetLength( JPEGImage, 0 );
end;
CurrentPos := CurrentPos +l;
end;
8 : begin
//JPEGTables
//与Tag35的BitmapJPEGEncoding部分内容一致
SetLength( JPEGEncoding, TagLength -4 ); //去掉头尾的 FFD8 FFD9
Move( FileBuf[CurrentPos+2], JPEGEncoding[0], TagLength-4 );
//由于不确定Tag6和Tag8哪个会在文件中先出现,所以检查JPEGImage是否为空
if Length(JPEGImage) <> 0 then
begin
tmpPos:=0;
//也要先查找SOS的位置,以便插入QDT等BitmapJPEGEncoding内容
Repeat
Inc(tmpPos);
Until ( JPEGImage[tmpPos]=$FF ) and ( JPEGImage[tmpPos+1] = $DA );
AssignFile( f, sPicSavePath +Filename +'_Pic' +IntToStr(JPEGID)+'.JPG');
ReWrite( f, 1);
BlockWrite( f, JPEGImage[0], tmpPos );
BlockWrite( f, JPEGEncoding[0], Length(JPEGEncoding) );
//写入SOS为开始的内容
BlockWrite( f,JPEGImage[tmpPos], Length(JPEGImage) -tmpPos );
CloseFile( f );
SetLength( JPEGImage, 0 );
end;
CurrentPos := CurrentPos +TagLength;
end;
36 : begin
//DefineBitsLossless和DefineBitsLossless2
//Tag20和Tag36的区别在于Color Table中分别记录的是RGB和RGBA
//BMP文件结构是BitmapFileHead+BitmapInfoHead+Color Table+Image Data
//其中的Color Table部分与这里的Color Table长度一致
//但是颜色位置不同,BMP文件存贮为BGR(A)
tmpPos :=CurrentPos +TagLength;
Move( FileBuf[CurrentPos], BitmapID,Sizeof(BitmapID) );
Inc( CurrentPos,Sizeof(BitmapID) );
Move( FileBuf[CurrentPos], BitmapFormat,Sizeof(BitmapFormat) );
Inc( CurrentPos,Sizeof(BitmapFormat) );
Move( FileBuf[CurrentPos], BitmapWidth,Sizeof(BitmapWidth) );
Inc( CurrentPos,Sizeof(BitmapWidth) );
Move( FileBuf[CurrentPos], BitmapHeight,Sizeof(BitmapHeight) );
Inc( CurrentPos,Sizeof(BitmapHeight) );
l := TagLength -Sizeof(BitmapID) -Sizeof(BitmapFormat) -Sizeof(BitmapWidth) -Sizeof(BitmapHeight);
case BitmapFormat of
3 : begin
Move( FileBuf[CurrentPos], BitmapColorTableSize1, Sizeof(BitmapColorTableSize1) );
Inc( CurrentPos,Sizeof(BitmapColorTableSize1) );
l := l -Sizeof(BitmapColorTableSize1);
BitmapColorTableSize := BitmapColorTableSize1;
end;
4 : begin
Move( FileBuf[CurrentPos], BitmapColorTableSize2, Sizeof(BitmapColorTableSize2) );
Inc( CurrentPos, Sizeof(BitmapColorTableSize2) );
l := l -Sizeof(BitmapColorTableSize2);
BitmapColorTableSize := BitmapColorTableSize2;
end;
5 : begin
Move( FileBuf[CurrentPos], BitmapColorTableSize3, Sizeof(BitmapColorTableSize3) );
Inc( CurrentPos, Sizeof(BitmapColorTableSize3) );
l := l -Sizeof(BitmapColorTableSize3);
BitmapColorTableSize := BitmapColorTableSize3;
end;
end;
//先将压缩的ZLIB数据读入BitmapBuf1
SetLength( BitmapBuf1, l );
Move( FileBuf[CurrentPos], BitmapBuf1[0], l );
inStream := TMemoryStream.Create;
inStream.Write( BitmapBuf1[0],l );
inStream.Position := 0;
zStream := TDecompressionStream.Create(inStream);
//Color Table也是以32数据为单位的,分别是 R G B (A)
//所以计算长度时要*4
//Image Data也是以32数据为单位的
case BitmapFormat of
3 : begin
l := BitmapWidth;
while (l mod 4)<>0 do inc(l); //长度不足32要补齐
l := ( (BitmapColorTableSize+1) * 4 )+( l * BitmapHeight );
end;
4 : begin
l := BitmapWidth;
while (l mod 2)<>0 do inc(l); //长度不足32要补齐
l := ( (BitmapColorTableSize+1) * 4 ) + ( l*BitmapHeight * 2 );
end;
5 : l:=( (BitmapColorTableSize+1) * 4 ) + ( BitmapWidth * BitmapHeight * 4 );
end;
//解压缩后的数据存入BitmapBuf2
SetLength( BitmapBuf2,l );
zStream.Read( BitmapBuf2[0],l );
zStream.Free;
inStream.Free;
//Color Table存入BitmapBuf1
SetLength( BitMapBuf1, (BitmapColorTableSize+1) * 4 );
for l:=0 to BitmapColorTableSize do
begin
//将Color Table中的RGB(A)值改为BMP文件的BGR(A)顺序
BitmapBuf1[l*4] := BitmapBuf2[l*4+2];
BitmapBuf1[l*4+1] := BitmapBuf2[l*4+1];
BitmapBuf1[l*4+2] := BitmapBuf2[l*4];
BitmapBuf1[l*4+3] := BitmapBuf2[l*4+3];
end;
//将BitmapBuf2中的Color Table内容去掉,仅保留Image Data
Move( BitmapBuf2[(BitmapColorTableSize+1)*4],
BitmapBuf2[0],
Length(BitmapBuf2)-((BitmapColorTableSize+1) * 4) );
SetLength( BitmapBuf2, Length(BitmapBuf2)-((BitmapColorTableSize+1)*4));
//生成BMP文件头BitmapFileHead
FillChar( BitmapFileHead, Sizeof(BitmapFileHead), 0 );
FillChar( BitmapInfoHead, Sizeof(BitmapInfoHead), 0 );
//BM标示
BitmapFileHead.B := 'B';
BitmapFileHead.M := 'M';
//总长度
BitmapFileHead.bfSize := Sizeof(BitmapFileHead)+Sizeof(BitmapInfoHead)+Length(BitmapBuf1)+Length(BitmapBuf2);
//Image Data开始位置
BitmapFileHead.bfOffBits := Sizeof(BitmapFileHead)+Sizeof(BitmapInfoHead)+Length(BitmapBuf1);
//生成BitmapInfoHead
BitmapInfoHead.biSize := Sizeof(BitmapInfoHead);
BitmapInfoHead.biWidth := BitmapWidth;
BitmapInfoHead.biHeight := BitmapHeight;
BitmapInfoHead.biPlanes := 1; //总为1
case BitmapFormat of
3 : BitmapInfoHead.biBitCount := 8;
4 : BitmapInfoHead.biBitCount := 16;
5 : BitmapInfoHead.biBitCount := 32;
end;
AssignFile( f, sPicSavePath +Filename +'_Pic' +IntToStr(BitmapID)+'.BMP');
ReWrite( f,1 );
BlockWrite( f, BitmapFileHead,Sizeof(BitmapFileHead));
BlockWrite( f, BitmapInfoHead,Sizeof(BitmapInfoHead));
BlockWrite( f, BitmapBuf1[0],Length(BitmapBuf1));
//由于BMP的Image Data原点位于左下角,而这里的Image Data原点位于左上角
//所以要一行一行的倒序写
for l := BitmapHeight-1 downto 0 do
begin
BlockWrite( f,
BitmapBuf2[l*(Length(BitmapBuf2) div BitmapHeight)],
(Length(BitmapBuf2) div BitmapHeight) );
end;
CloseFile( f );
CurrentPos := tmpPos;
end;
20 : begin
//DefineBitsLossless和DefineBitsLossless2
//Tag20和Tag36的区别在于Color Table中分别记录的是RGB和RGBA
//BMP文件结构是BitmapFileHead+BitmapInfoHead+Color Table+Image Data
//其中的Color Table部分与这里的Color Table长度一致
//但是颜色位置不同,BMP文件存贮为BGR(A)
tmpPos:=CurrentPos+TagLength;
Move(FileBuf[CurrentPos],BitmapID,Sizeof(BitmapID)); Inc(CurrentPos,Sizeof(BitmapID));
Move(FileBuf[CurrentPos],BitmapFormat,Sizeof(BitmapFormat)); Inc(CurrentPos,Sizeof(BitmapFormat));
Move(FileBuf[CurrentPos],BitmapWidth,Sizeof(BitmapWidth)); Inc(CurrentPos,Sizeof(BitmapWidth));
Move(FileBuf[CurrentPos],BitmapHeight,Sizeof(BitmapHeight)); Inc(CurrentPos,Sizeof(BitmapHeight));
l:=TagLength-Sizeof(BitmapID)-Sizeof(BitmapFormat)-Sizeof(BitmapWidth)-Sizeof(BitmapHeight);
case BitmapFormat of
3 : begin
Move(FileBuf[CurrentPos],BitmapColorTableSize1,Sizeof(BitmapColorTableSize1)); Inc(CurrentPos,Sizeof(BitmapColorTableSize1));
l:=l-Sizeof(BitmapColorTableSize1);
BitmapColorTableSize:=BitmapColorTableSize1;
end;
4 : begin
Move(FileBuf[CurrentPos],BitmapColorTableSize2,Sizeof(BitmapColorTableSize2)); Inc(CurrentPos,Sizeof(BitmapColorTableSize2));
l:=l-Sizeof(BitmapColorTableSize2);
BitmapColorTableSize:=BitmapColorTableSize2;
end;
5 : begin
Move(FileBuf[CurrentPos],BitmapColorTableSize3,Sizeof(BitmapColorTableSize3)); Inc(CurrentPos,Sizeof(BitmapColorTableSize3));
l:=l-Sizeof(BitmapColorTableSize3);
BitmapColorTableSize:=BitmapColorTableSize3;
end;
end;
//先将压缩的ZLIB数据读入BitmapBuf1
SetLength(BitmapBuf1,l);
Move(FileBuf[CurrentPos],BitmapBuf1[0],l);
inStream:=TMemoryStream.Create;
inStream.Write(BitmapBuf1[0],l);
inStream.Position:=0;
zStream:=TDecompressionStream.Create(inStream);
//Color Table是以24数据为单位的,分别是 R G B
//所以计算长度时要*3
//Image Data也是以32数据为单位的
case BitmapFormat of
3 : begin
l:=BitmapWidth;
while (l mod 4)<>0 do inc(l); //长度不足32要补齐
l:=((BitmapColorTableSize+1)*3)+(l*BitmapHeight);
end;
4 : begin
l:=BitmapWidth;
while (l mod 2)<>0 do inc(l); //长度不足32要补齐
l:=((BitmapColorTableSize+1)*3)+(l*BitmapHeight*2);
end;
5 : l:=((BitmapColorTableSize+1)*3)+(BitmapWidth*BitmapHeight*4);
end;
//解压缩后的数据存入BitmapBuf2
SetLength(BitmapBuf2,l);
zStream.Read(BitmapBuf2[0],l);
zStream.Free;
inStream.Free;
//Color Table存入BitmapBuf1
//要将RGB表扩展为BGR(A)表,长度*4
SetLength(BitMapBuf1,(BitmapColorTableSize+1)*4);
for l:=0 to BitmapColorTableSize do begin
//将Color Table中的RGB值改为BMP文件的BGR(A)顺序
BitmapBuf1[l*4]:=BitmapBuf2[l*3+2];
BitmapBuf1[l*4+1]:=BitmapBuf2[l*3+1];
BitmapBuf1[l*4+2]:=BitmapBuf2[l*3];
BitmapBuf1[l*4+3]:=0;
end;
//将BitmapBuf2中的Color Table内容去掉,仅保留Image Data
Move(BitmapBuf2[(BitmapColorTableSize+1)*3],BitmapBuf2[0],Length(BitmapBuf2)-((BitmapColorTableSize+1)*3));
SetLength(BitmapBuf2,Length(BitmapBuf2)-((BitmapColorTableSize+1)*3));
//生成BMP文件头BitmapFileHead
FillChar(BitmapFileHead,Sizeof(BitmapFileHead),0); FillChar(BitmapInfoHead,Sizeof(BitmapInfoHead),0);
//BM标示
BitmapFileHead.B:='B'; BitmapFileHead.M:='M';
//总长度
BitmapFileHead.bfSize:=Sizeof(BitmapFileHead)+Sizeof(BitmapInfoHead)+Length(BitmapBuf1)+Length(BitmapBuf2);
//Image Data开始位置
BitmapFileHead.bfOffBits:=Sizeof(BitmapFileHead)+Sizeof(BitmapInfoHead)+Length(BitmapBuf1);
//生成BitmapInfoHead
BitmapInfoHead.biSize:=Sizeof(BitmapInfoHead);
BitmapInfoHead.biWidth:=BitmapWidth;
BitmapInfoHead.biHeight:=BitmapHeight;
BitmapInfoHead.biPlanes:=1; //总为1
case BitmapFormat of
3 : BitmapInfoHead.biBitCount:=8;
4 : BitmapInfoHead.biBitCount:=16;
5 : BitmapInfoHead.biBitCount:=32;
end;
AssignFile( f, sPicSavePath +Filename+'_图像'+IntToStr(BitmapID)+'.BMP'); ReWrite(f,1);
BlockWrite( f, BitmapFileHead, Sizeof(BitmapFileHead) );
BlockWrite( f, BitmapInfoHead, Sizeof(BitmapInfoHead) );
BlockWrite( f, BitmapBuf1[0], Length(BitmapBuf1) );
//由于BMP的Image Data原点位于左下角,而这里的Image Data原点位于左上角
//所以要一行一行的倒序写
for l:=BitmapHeight-1 downto 0 do
begin
BlockWrite( f,
BitmapBuf2[l*(Length(BitmapBuf2) div BitmapHeight)],
(Length(BitmapBuf2) div BitmapHeight) );
end;
CloseFile(f);
CurrentPos:=tmpPos;
end;
else CurrentPos := CurrentPos +TagLength;
end;
Until TagID = 0;
SetLength( FileBuf, 0 );
SetLength( BitmapBuf1, 0 );
SetLength( BitmapBuf2, 0 );
SetLength( JPEGEncoding, 0 );
SetLength( JPEGImage,0 );
Result := TRUE;
end;