package probe import ( "encoding/binary" "fmt" "os" ) // probeBmp 读取 BMP 文件头中的宽高;自顶向下 BMP 的高度为负值,取绝对值。 // 兼容常见 info 头:BITMAPCOREHEADER(12B, OS/2)、BITMAPINFOHEADER(40B) 及更长的 V4/V5 变体。 func probeBmp(filePath string) (*ProbeResult, error) { f, err := os.Open(filePath) if err != nil { return nil, err } defer f.Close() var fileHeader struct { FileType [2]byte FileSize uint32 Reserved1 uint16 Reserved2 uint16 DataOffset uint32 } if err := binary.Read(f, binary.LittleEndian, &fileHeader); err != nil { return nil, err } if string(fileHeader.FileType[:]) != "BM" { return nil, fmt.Errorf("not a valid BMP file") } var infoSize uint32 if err := binary.Read(f, binary.LittleEndian, &infoSize); err != nil { return nil, err } switch { case infoSize >= 40: // BITMAPINFOHEADER(40B)/BITMAPV4HEADER(108B)/BITMAPV5HEADER(124B)/OS2(64B):宽高为 int32 var width, height int32 if err := binary.Read(f, binary.LittleEndian, &width); err != nil { return nil, err } if err := binary.Read(f, binary.LittleEndian, &height); err != nil { return nil, err } return &ProbeResult{Width: abs32(width), Height: abs32(height)}, nil case infoSize >= 12: // BITMAPCOREHEADER(12B, OS/2 1.x):宽高为 uint16 var width, height uint16 if err := binary.Read(f, binary.LittleEndian, &width); err != nil { return nil, err } if err := binary.Read(f, binary.LittleEndian, &height); err != nil { return nil, err } return &ProbeResult{Width: int(width), Height: int(height)}, nil default: return nil, fmt.Errorf("unsupported BMP info header size: %d", infoSize) } } func abs32(v int32) int { if v < 0 { return int(-v) } return int(v) }