📄 tmsueschergraphtobse.pas
字号:
unit tmsUEscherGraphToBSE;
{$INCLUDE ..\FLXCOMPILER.INC}
{$INCLUDE ..\FLXCONFIG.INC}
interface
uses Sysutils, Classes, tmsXlsMessages, tmsUEscherRecords, tmsUXlsMD5, tmsUFlxMessages;
{************************************************************************************}
{**} function ConvertGraphicToBSE(const Data: ByteArray; const DataType: TXlsImgTypes;
const DwgGroupCache: PEscherDwgGroupCache; const DwgCache: PEscherDwgCache):TEscherBSERecord ;
{************************************************************************************}
implementation
{$IFDEF USEPNGLIB}
uses
{$IFDEF DELPHI2008UP}
zlib; //This changed in Delphi 2009 again. Now this units are included in delphi
{$ELSE}
flxzlibpas;
{$ENDIF}
{$ENDIF}
type
TBSEHeader= packed record
btWin32: byte; // Required type on Win32
btMacOS: byte; // Required type on Mac
rgbUid: TMd5Digest; // Identifier of blip
tag: word; // currently unused
size: LongWord; // Blip size in stream
cRef: LongWord; // Reference count on the blip
foDelay: LongWord; // File offset in the delay stream
usage: byte; // How this blip is used (MSOBLIPUSAGE)
cbName: byte; // length of the blip name
unused2: byte; // for the future
unused3: byte; // for the future
end;
TWMFBlipHeader = packed record
m_rgbUid: TMd5Digest; { The secondary, or data, UID - should always be set. }
{ Metafile Blip overhead = 34 bytes. m_cb gives the number of
bytes required to store an uncompressed version of the file, m_cbSave
is the compressed size. m_mfBounds gives the boundary of all the
drawing calls within the metafile (this may just be the bounding box
or it may allow some whitespace, for a WMF this comes from the
SetWindowOrg and SetWindowExt records of the metafile). }
m_cb: Longint; // Cache of the metafile size
m_rcBounds: Array[0..3] of Longint; // Boundary of metafile drawing commands
m_ptSize: Array[0..1] of Longint; // Size of metafile in EMUs
m_cbSave: Longint; // Cache of saved size (size of m_pvBits)
m_fCompression: byte; // MSOBLIPCOMPRESSION
m_fFilter: byte; // always msofilterNone
end;
procedure LoadDataBMP(const Data: ByteArray; const DataType: TXlsImgTypes; const BlipData: TStream);
var
Tag: byte;
begin
Tag:=$FF;
BlipData.Write(Tag, SizeOf(Tag));
BlipData.Write(Data[0], Length(Data));
end;
{$IFDEF USEPNGLIB}
procedure XlsMetafilesToXls(const ImgData: ByteArray; const OutStream: TStream; const IsEMF: Boolean);
const
Z_OK=0;
Z_STREAM_END=1;
var
HeadOfs: LongWord;
ZL: TZStreamRec;
Buff: ByteArray;
Res: integer;
begin
HeadOfs := 0;
if (not IsEMF and (Length(ImgData) > 4)) and (ImgData[0] = $D7) and (ImgData[1] = $CD) and (ImgData[2] = $C6) and (ImgData[3] = $9A) then
HeadOfs:= HeadOfs + 22;
//compress the image
FillChar(Zl, SizeOf(Zl), 0);
Zl.next_in:= @ImgData[HeadOfs];
Zl.avail_in:= Length(ImgData) - Integer(HeadOfs);
SetLength(Buff, 2048); //Arbitrary block size
Zl.next_out:=@Buff[0];
Zl.avail_out:=Length(Buff);
if DeflateInit_(ZL, 9, zlib_version, SIZEOF(TZStreamRec))<> Z_OK then
raise Exception.Create(ErrInvalidWmf);
while Zl.avail_in > 0 do
begin
Res:= deflate(ZL, Z_NO_FLUSH);
if (Res<> Z_OK) then
raise Exception.Create(ErrInvalidWmf);
OutStream.Write(Buff[0], Length(Buff) - Zl.avail_out) ;
Zl.next_out:=@Buff[0];
Zl.avail_out:=Length(Buff);
end;
Zl.next_in := nil;
Zl.avail_in := 0;
while deflate(ZL, Z_FINISH) <>Z_STREAM_END do
begin
OutStream.Write(Buff[0], Length(Buff) - Zl.avail_out);
Zl.next_out:=@Buff[0];
Zl.avail_out:=Length(Buff);
end;
if (Zl.avail_out > 0) then
begin
OutStream.Write(Buff[0], Length(Buff) - Zl.avail_out)
end;
Res := deflateEnd(ZL);
if (Res<> Z_OK) then
raise Exception.Create(ErrInvalidWmf);
end;
{$ELSE}
procedure XlsMetafilesToXls(const ImgData: ByteArray; const OutStream: TStream; const IsEMF: Boolean);
begin
raise Exception.Create('To insert WMF files you need to instal TPngImage');
end;
{$ENDIF}
type
Int32Rec = record
Value: Longint;
end;
PInt32Rec = ^Int32Rec;
procedure LoadDataWMF(const Data: ByteArray; const DataType: TXlsImgTypes; const BlipData: TStream);
var
cb: LongWord;
ptSize: Array of byte;
OtherDat: Array of byte;
StreamPos: Int64;
Zero: word;
WidthEMU, HeightEMU: integer;
begin
Zero := 0;
cb := length(Data);
BlipData.Write(cb, sizeof(cb));
if DataType in [xli_Wmf] then
begin
BlipData.Write(Data[6],1);BlipData.Write(Data[7],1); BlipData.Write(Zero,2);
BlipData.Write(Data[8],1);BlipData.Write(Data[9],1); BlipData.Write(Zero,2);
BlipData.Write(Data[10],1);BlipData.Write(Data[11],1);BlipData.Write(Zero,2);
BlipData.Write(Data[12],1);BlipData.Write(Data[13],1);BlipData.Write(Zero,2);
SetLength (ptSize, 8);
ptSize[0] := 24;
ptSize[1] := 240;
ptSize[2] := 255;
ptSize[3] := 0;
ptSize[4] := 24;
ptSize[5] := 240;
ptSize[6] := 255;
ptSize[7] := 0;
BlipData.Write(ptSize[0], Length(ptSize));
end
else
begin
BlipData.Write(Data[8], 16);
WidthEMU := (PInt32Rec(@Data[24 + 8]).Value - PInt32Rec(@Data[24]).Value) * 360;
HeightEMU := (PInt32Rec(@Data[24 + 12]).Value - PInt32Rec(@Data[24 + 4]).Value) * 360;
BlipData.Write(WidthEmu, SizeOf(WidthEMU));
BlipData.Write(HeightEmu, SizeOf(HeightEMU));
end;
SetLength (OtherDat, 6);
OtherDat[0] := 0;
OtherDat[1] := 0;
OtherDat[2] := 0;
OtherDat[3] := 0;
OtherDat[4] := 0;
OtherDat[5] := 254;
StreamPos := BlipData.Position;
BlipData.Write(OtherDat[0], 6);
if DataType = xli_Emf then
XlsMetafilesToXls(Data, BlipData, true) else
XlsMetafilesToXls(Data, BlipData, false);
BlipData.Position := StreamPos;
cb := LongWord(BlipData.Size-StreamPos-6);
BlipData.Write(cb, sizeof(cb));
BlipData.Position := BlipData.Size;
end;
{************************************************************************************}
function ConvertGraphicToBSE(const Data: ByteArray; const DataType: TXlsImgTypes;
const DwgGroupCache: PEscherDwgGroupCache; const DwgCache: PEscherDwgCache):TEscherBSERecord;
var
Eh: TEscherRecordHeader;
BSEHeader: TBSEHeader;
Md5Stream: TMd5Stream;
BlipData: TMemoryStream;
BlipHeader: TEscherRecordHeader;
begin
FillChar(BSEHeader, SizeOf(BSEHeader), 0);
Md5Stream:=TMd5Stream.Create;
try
Md5Stream.Write(Data[0], Length(Data));
BSEHeader.rgbUid:= Md5Stream.GetDigest;
finally
FreeAndNil(Md5Stream);
end;
// FillChar(BSEHeader, SizeOf(BSEHeader), 0);
BlipData:=TMemoryStream.Create;
try
//Common header
BlipData.Write(BSEHeader.rgbUid, SizeOf(BSEHeader.rgbUid));
// Specific info
if DataType in [xli_JPEG, xli_PNG, xli_BMP] then
LoadDataBMP(Data, DataType, BlipData) else
LoadDataWMF(Data, DataType, BlipData);
BSEHeader.btWin32:= XlsImgConv[DataType];
BSEHeader.btMacOS:= msoblipPICT;
BSEHeader.tag:=$FF;
BSEHeader.size:= BlipData.Size+ SizeOf(BlipHeader);
BSEHeader.cRef:=0;
BSEHeader.foDelay:=0;
Eh.Id:= MsofbtBSE;
Eh.Pre:=2 + XlsImgConv[DataType] shl 4;
Eh.Size:=BSEHeader.size + SizeOf(BSEHeader);
Result:= TEscherBSERecord.Create(Eh, DwgGroupCache, DwgCache, DwgGroupCache.BStore);
BlipHeader.Id:= XlsBlipHeaderConv[DataType];
BlipHeader.Pre:= XlsBlipSignConv[DataType] shl 4;
BlipHeader.Size:=BlipData.Size;
BlipData.Position:=0;
Result.CopyFromData(@BSEHeader, BlipHeader, BlipData);
finally
FreeAndNil(BlipData);
end; //finally
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -