📄 ueschergraphtobse.pas
字号:
unit UEscherGraphToBSE;
{$IFDEF LINUX}{$INCLUDE ../FLXCOMPILER.INC}{$ELSE}{$INCLUDE ..\FLXCOMPILER.INC}{$ENDIF}
{$IFDEF LINUX}{$INCLUDE ../FLXCONFIG.INC}{$ELSE}{$INCLUDE ..\FLXCONFIG.INC}{$ENDIF}
interface
uses Sysutils, Classes, XlsMessages, UEscherRecords, UXlsMD5, UFlxMessages;
{************************************************************************************}
{**} function ConvertGraphicToBSE(const Data: string; const DataType: TXlsImgTypes;
const DwgGroupCache: PEscherDwgGroupCache; const DwgCache: PEscherDwgCache):TEscherBSERecord ;
{************************************************************************************}
implementation
{$IFDEF USEPNGLIB}
//////////////////////////////// IMPORTANT ///////////////////////////////////////
//To be able to display PNG images and WMFs, you have to install TPNGImage from http://pngdelphi.sourceforge.net/
//If you don't want to install it, edit ../FLXCONFIG.INC and delete the line:
// "{$DEFINE USEPNGLIB}" on the file
//Note that this is only needed on Windows, CLX has native support for PNG
///////////////////////////////////////////////////////////////////////////////////
uses pngimage, zlibpas; //Note that PNGLIB changed units names. Make sure to download the *latest* version if you get an error in zlib.
///////////////////////////////////////////////////////////////////////////////////
//If you are getting an error here, please read the note above.
///////////////////////////////////////////////////////////////////////////////////
{$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: string; const DataType: TXlsImgTypes; const BlipData: TStream);
var
Tag: byte;
begin
Tag:=$FF;
BlipData.Write(Tag, SizeOf(Tag));
BlipData.Write(Data[1], Length(Data));
end;
{$IFDEF USEPNGLIB}
procedure XlsMetafilesToXls(const ImgData: string; const OutStream: TStream; const IsEMF: Boolean);
const
Z_OK=0;
Z_STREAM_END=1;
var
HeadOfs: LongWord;
ZL: TZStreamRec;
Buff: Array of char;
Res: integer;
begin
HeadOfs := 0;
if (not IsEMF and (Length(ImgData) > 4)) and (byte(ImgData[1]) = $D7) and (byte(ImgData[2]) = $CD) and (byte(ImgData[3]) = $C6) and (byte(ImgData[4]) = $9A) then
HeadOfs:= HeadOfs + 22;
//compress the image
FillChar(Zl, SizeOf(Zl), #0);
Zl.next_in:= @ImgData[1+ 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: string; 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: string; 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],1);BlipData.Write(Data[7+1],1); BlipData.Write(Zero,2);
BlipData.Write(Data[8+1],1);BlipData.Write(Data[9+1],1); BlipData.Write(Zero,2);
BlipData.Write(Data[10+1],1);BlipData.Write(Data[11+1],1);BlipData.Write(Zero,2);
BlipData.Write(Data[12+1],1);BlipData.Write(Data[13+1],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[9], 16);
WidthEMU := (PInt32Rec(@Data[1 + 24 + 8]).Value - PInt32Rec(@Data[1+ 24]).Value) * 360;
HeightEMU := (PInt32Rec(@Data[1 + 24 + 12]).Value - PInt32Rec(@Data[1+ 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: string; 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[1], 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 + -