package imageproc import ( "fmt" "image" "github.com/airbusgeo/godal" log "github.com/sirupsen/logrus" "gocv.io/x/gocv" ) func GTiffToJPG(ftiff, fjpg string, reversed bool) error { // 打开 TIFF 文件 ds, err := godal.Open(ftiff) if err != nil { log.Printf("Error opening TIFF file %s: %v", ftiff, err) return err } defer ds.Close() bands := ds.Bands() log.Infof("TIFF file %s has %d bands", ftiff, len(bands)) // 获取图像大小 width := bands[0].Structure().SizeX height := bands[0].Structure().SizeY bandsCnt := len(bands) // 创建 16 位图像矩阵 var img gocv.Mat defer img.Close() if bandsCnt == 1 { img = gocv.NewMatWithSize(height, width, gocv.MatTypeCV16UC1) } else { bandsCnt = 3 // 只取前三个波段 img = gocv.NewMatWithSize(height, width, gocv.MatTypeCV16UC3) } // 读取每个波段并存储到图像矩阵中 for i := 0; i < bandsCnt; i++ { band := bands[i] data := make([]uint16, width*height) err = band.Read(0, 0, data, width, height) if err != nil { fmt.Printf("Error reading band %d: %v\n", i, err) return err } // 将 16 位数据存储到图像的相应通道 for y := 0; y < height; y++ { for x := 0; x < width; x++ { value := data[y*width+x] img.SetShortAt(y, x*bandsCnt+i, int16(value)) } } } // 重采样图像 gocv.Resize(img, &img, image.Point{X: img.Cols() / 2, Y: img.Rows() / 2}, 0, 0, gocv.InterpolationCubic) // 创建 8 位图像矩阵 img8 := gocv.NewMat() defer img8.Close() if bandsCnt == 1 { img.ConvertToWithParams(&img8, gocv.MatTypeCV8UC1, 1.0/256.0*2, 0) } else { img.ConvertToWithParams(&img8, gocv.MatTypeCV8UC3, 1.0/256.0*2, 0) if reversed { channels := gocv.Split(img8) gocv.Merge([]gocv.Mat{channels[2], channels[1], channels[0]}, &img8) for _, ch := range channels { ch.Close() } } } ok := gocv.IMWrite(fjpg, img8) if !ok { err = fmt.Errorf("error saving %s", fjpg) return err } return nil }