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.