fix: BMP头解析、移动语义与空文件处理

- probe/bmp: 兼容 BITMAPCOREHEADER(12B) 等 info 头变体,按 Size 字段分支解析
- mover: moveOne 返回三态结果,复制成功但删源失败时明确告警,不再静默视为完全成功
- scanner: 跳过 0 字节文件,避免空文件进入 MIME/ffprobe 探测
This commit is contained in:
2025-04-15 21:05:26 +08:00
parent a667f7fa35
commit 7e49accf2b
3 changed files with 52 additions and 22 deletions
+31 -15
View File
@@ -6,7 +6,8 @@ import (
"os"
)
// probeBmp 读取 BMP 文件头中的宽高;自顶向下 BMP 的高度为负值,取绝对值
// 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 {
@@ -27,24 +28,39 @@ func probeBmp(filePath string) (*ProbeResult, error) {
if string(fileHeader.FileType[:]) != "BM" {
return nil, fmt.Errorf("not a valid BMP file")
}
var infoHeader struct {
Size uint32
Width int32
Height int32
Planes uint16
BitsPerPixel uint16
Compression uint32
SizeImage uint32
XPelsPerMeter int32
YPelsPerMeter int32
}
if err := binary.Read(f, binary.LittleEndian, &infoHeader); err != nil {
var infoSize uint32
if err := binary.Read(f, binary.LittleEndian, &infoSize); err != nil {
return nil, err
}
return &ProbeResult{Width: abs(infoHeader.Width), Height: abs(infoHeader.Height)}, nil
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 abs(v int32) int {
func abs32(v int32) int {
if v < 0 {
return int(-v)
}