package probe import ( "encoding/binary" "os" "path/filepath" "testing" ) // buildJpegWithOrientation 拼一个带 Exif 方向标记的最小 JPEG: // SOI + APP1(Exif) + EOI,APP1 里只放 TIFF 头 + IFD0 一条 Orientation。 func buildJpegWithOrientation(t *testing.T, orientation uint16, bigEndian bool) []byte { t.Helper() var order binary.ByteOrder = binary.LittleEndian if bigEndian { order = binary.BigEndian } bom := []byte("II") if bigEndian { bom = []byte("MM") } // TIFF 头(8) + IFD0 计数(2) + 一条目(12) tiff := make([]byte, 0, 8+2+12) tiff = append(tiff, bom...) magic := make([]byte, 2) order.PutUint16(magic, 42) tiff = append(tiff, magic...) ifdOff := make([]byte, 4) order.PutUint32(ifdOff, 8) tiff = append(tiff, ifdOff...) count := make([]byte, 2) order.PutUint16(count, 1) tiff = append(tiff, count...) // 一条目:tag=0x0112 type=SHORT count=1 value=orientation entry := make([]byte, 12) order.PutUint16(entry[0:2], 0x0112) order.PutUint16(entry[2:4], 3) // SHORT order.PutUint32(entry[4:8], 1) // count order.PutUint16(entry[8:10], orientation) tiff = append(tiff, entry...) app1Data := append([]byte("Exif\x00\x00"), tiff...) segLen := len(app1Data) + 2 out := []byte{0xFF, 0xD8} // SOI out = append(out, 0xFF, 0xE1) lenB := make([]byte, 2) binary.BigEndian.PutUint16(lenB, uint16(segLen)) out = append(out, lenB...) out = append(out, app1Data...) out = append(out, 0xFF, 0xD9) // EOI return out } func TestReadExifOrientation(t *testing.T) { dir := t.TempDir() cases := []struct { name string ori uint16 bigEnd bool want int }{ {"le6", 6, false, 6}, {"be8", 8, true, 8}, {"le1", 1, false, 1}, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { p := filepath.Join(dir, c.name+".jpg") if err := os.WriteFile(p, buildJpegWithOrientation(t, c.ori, c.bigEnd), 0644); err != nil { t.Fatal(err) } if got := ReadExifOrientation(p); got != c.want { t.Fatalf("ReadExifOrientation = %d, want %d", got, c.want) } }) } // 非 JPEG 返回 0 p := filepath.Join(dir, "notjpeg.txt") if err := os.WriteFile(p, []byte("hello"), 0644); err != nil { t.Fatal(err) } if got := ReadExifOrientation(p); got != 0 { t.Fatalf("non-jpeg ReadExifOrientation = %d, want 0", got) } // 不存在的文件返回 0 if got := ReadExifOrientation(filepath.Join(dir, "missing.jpg")); got != 0 { t.Fatalf("missing ReadExifOrientation = %d, want 0", got) } } func TestNeedsDimensionSwap(t *testing.T) { cases := map[int]bool{ 1: false, 2: false, 3: false, 4: false, 5: true, 6: true, 7: true, 8: true, 0: false, 9: false, } for ori, want := range cases { if got := NeedsDimensionSwap(ori); got != want { t.Fatalf("NeedsDimensionSwap(%d) = %v, want %v", ori, got, want) } } }