CAD dwg文件缩略图提取

1,684 阅读2分钟

dwg 文件数据结构

在文件的第13位到16位的四个字节,保存预览图像数据的起地址(示例值:58 00 00 00),从该地址起,数据主要构成为如下表:

地址属性 地址 长度 示例数值 说明
SN(start sentinel) 58-67 16 1F 25 6D 07 D4 36 28 28 9D 57 CA 3F 9D 44 10 2B 图像数据开始标志,16字节常值,不会改变,否则表示文件损坏。
oversize 68-6B 4 AB 4D 00 00 数据的总长度,包括从type到BMP/WMF data 末的地址长度
type 6C 1 02 图像的类型02-BMP;03-WMF,就两种;这里示例值是02,没有03数据。
header code 6D 1 01 图像文件头代码,必是01
header address 6E-71 4 7F 00 00 00 图像文件头起地址
header size 72-75 4 50 00 00 00 图像文件头数据长度
data code 76 1 02/03 图像BMP/WMF代码
data address 77-7A 4 CF 00 00 00(7F+50=CE) 图像BMP/WMF数据起地址
data size 7B-7E 4 48 4D 00 00 图像BMP/WMF数据长度
header data 7F-CE 50 ...... 图像文件头数据,长度源于header size
BMP/WMF data CF-4D16 4D48 ...... 图像BMP/WMF数据,长度源于data size
EN 4D17-4E26 10 E0 DA 92 F8 2B C9 D7 D 7 62 AB 35 C0 62 BB EF D4 结束16字节,常值

python3 读取文件缩略图

# coding:utf-8

import io
from PIL import Image
import struct

# ================= #
# dwg 文件缩略图提取  #
# ================= #

def read_fmt(fmt, fp):
    fmt_size = struct.calcsize(fmt)
    data = fp.read(fmt_size)
    try:
        assert len(data) == fmt_size, 'read=%d, expected=%d' % (len(data), fmt_size)
    except AssertionError:
        fp.seek(-len(data), 1)
        raise
    return struct.unpack(fmt, data)

def thumbnail(filePath, savePath):
    with open(filePath, 'rb') as fd:
        fd.seek(13, 0)
        pos_sentinel = read_fmt('I', fd)[0] # I 表示读取4个字节整数
        fd.seek(pos_sentinel+26, 0)
        header_size = read_fmt('I', fd)[0]
        fd.seek(5, 1)
        data_size = read_fmt('I', fd)[0]
        fd.seek(header_size, 1)

        png_data = fd.read(data_size)

        print(header_size, data_size)
        if data_size != len(png_data):
            raise Exception("dwg 解析错误!")

        imgio = io.BytesIO(png_data)
        with Image.open(imgio) as image:
            image.save(savePath, 'PNG')

if __name__ == "__main__":
    thumbnail('/Users/xx/claw.dwg', '/Users/xxx/dwgpic2.png')