DWG プレビューイメージ DwgThumbnail (2017/08/20)
DWG ファイルに格納されているプレビューイメージ (BITMAP, PNG) を取り出します。
unit DwgThumbnailUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, FileCtrl, ExtCtrls, PNGImage;
type
TDWGHeader = record
ImKind: Byte;
StAddr: DWord;
ImSize: DWord;
end;
// プロトタイプ
function DwgThumbnail(const dwgname: TFileName; bmp : TBitmap): boolean;
implementation
function DwgThumbnail(const dwgname: TFileName; bmp: TBitmap): boolean;
var
DWGHeader : TDWGHeader;
Offset : Longint;
Images : Byte;
BitmapFileHeader : TBitmapFileHeader;
BitmapInfoHeader : TBitmapInfoHeader;
DwgF : TFileStream;
Tempmem : TMemoryStream;
buf : array [0..3] of Ansichar;
vernum : integer;
PngImage: TPngImage;
begin
result := True;
try
// DWG ファイルストリーム
DwgF:= TFileStream.Create(DwgName, fmOpenRead);
try
// DWG Version の取得
// 'AC10xx' の'AC' を読み飛ばす
DwgF.Seek($02, soFromBeginning);
// 'AC10xx' の数字部分 '10xx' を取得
DwgF.ReadBuffer(buf, 4);
vernum := StrToIntDef(string(buf), 0);
if (vernum > 1012) then begin
// ファイル先頭から 13byte
DwgF.Seek($0D, soFromBeginning);
// オフセット
DwgF.ReadBuffer(Offset, 4);
DwgF.Seek($14 + Offset, soFromBeginning);
// ブロックイメージの数
DwgF.ReadBuffer(Images, 1);
DwgF.Seek($1E + Offset, soFromBeginning);
// 格納イメージの種類
DwgF.ReadBuffer(DWGHeader.ImKind, 1);
// データブロックの開始アドレス
DwgF.ReadBuffer(DWGHeader.StAddr, 4);
// データのサイズ(バイト数)
DwgF.ReadBuffer(DWGHeader.ImSize, 4);
//------------------------------------------------------BITMAP
if (DWGHeader.ImKind = 2) then begin
//ビットマップのヘッダーを取得
DwgF.Seek(DWGHeader.StAddr, soFromBeginning);
DwgF.ReadBuffer(BitmapInfoHeader, 40);
with BitmapFileHeader do begin
// "BM"
bfType := $4D42;
// ファイルサイズ
bfSize := 14 + DWGHeader.ImSize;
bfReserved1 := 0;
bfReserved2 := 0;
// イメージへのオフセット
//bfOffBits := bfSize - BitmapInfoHeader.biSizeimage;
bfOffBits := 14 + 40 + 4 * 256; // = 1078
end;
Tempmem := TMemoryStream.Create;
try
Tempmem.Write(BitmapFileHeader, 14);
DwgF.Seek(DWGHeader.StAddr, soFromBeginning);
Tempmem.CopyFrom(DwgF, DWGHeader.ImSize);
Tempmem.Seek(0, 0);
try
bmp.LoadFromStream(Tempmem);
except
Abort;
end;
finally
Tempmem.Free;
end;
end
//------------------------------------------------------PNG
else if DWGHeader.ImKind = 6 then begin
// ストリームの先頭に
DwgF.Seek(DWGHeader.StAddr, soFromBeginning);
Tempmem := TMemoryStream.Create;
try
// コピー
Tempmem.CopyFrom(DwgF, DWGHeader.ImSize);
Tempmem.Seek(0, 0);
try
PngImage := TPngImage.Create;
PngImage.LoadFromStream(Tempmem);
bmp.Assign(PngImage);
PngImage.Free;
except
Abort;
end;
finally
Tempmem.Free;
end;
end;
end;
finally
DwgF.Free;
end;
except
result := false;
Abort;
end;
end;
end.