谢谢老哥:'( 还是会出错,我插入了
“invalid JPEG format: short Huffman data ”- panic: runtime error: invalid memory address or nil pointer dereference[signal 0xc0000005 code=0x0 addr=0x20 pc=0x89355c]goroutine 115 [running]:main.main.func1.1() D:/img/composite_img.go:145 +0x13ccreated by main.main.func1 D:/img/composite_img.go:138 +0x225exit status 2
复制代码- package mainimport ( _ "embed" "fmt" "github.com/fogleman/gg" "github.com/golang/freetype/truetype" "github.com/spf13/viper" "image" "image/color" "image/jpeg" "io/ioutil" "os" "log" "path" "path/filepath" "strings" "sync" "time" "zip2excel/pkg")type ImgInfoList struct { Path string ImgInfo []ImgInfo}type ImgInfo struct { Path string Size int64 Name string Suffix string}type taskInfo struct { Path string Name string X int Y int}type imgDraw struct { Im image.Image X int Y int StringX float64 StringY float64 StringText string}type Config struct { ImgFormat []string CompositeDir string CompositeLineNum int}var config = new(Config)//go:embed f.ttfvar ttf []bytefunc init() { viper.SetConfigType("toml") viper.SetConfigName("config") viper.AddConfigPath("./") configFile := "./config.toml" if err := viper.ReadInConfig(); err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); ok { if err := os.MkdirAll(filepath.Dir(configFile), 0766); err != nil { panic(err) } f, err := os.Create(configFile) if err != nil { panic(err) } defer f.Close() if err := viper.WriteConfig(); err != nil { panic(err) } } else { panic(err) } } if err := viper.Unmarshal(config); err != nil { panic(err) }}func main() { loadStart := time.Now() const NX = 115 const NY = 75 const NXInterval = 30 const NYInterval = 100 strMaxWidth := 115 / 13 imgListArr := getImgList(config.CompositeDir) for _, imgInfoList := range imgListArr { var lineNum = config.CompositeLineNum imgList := imgInfoList.ImgInfo dir := imgInfoList.Path //fmt.Printf("n1 的类型 %T", n1) filename := dir + "/" +"composite.jpeg" //fmt.Println("filename",filename) _, err := os.Stat(filename) // 通过获取文件信息进行判断 if err != nil { //fmt.Println("不存在") } else { continue } imgNum := len(imgList) columnNum := imgNum / lineNum if imgNum%lineNum != 0 { columnNum++ } if imgNum < lineNum { lineNum = imgNum } //fmt.Println(lineNum, columnNum) dc := gg.NewContext(lineNum*(NX+NXInterval)-NXInterval, columnNum*(NY+NYInterval)) dc.SetColor(color.RGBA{R: 39, G: 39, B: 39, A: 255}) dc.Clear() ttfFont, _ := truetype.Parse(ttf) face := truetype.NewFace(ttfFont, &truetype.Options{ Size: 13, }) dc.SetFontFace(face) dc.SetColor(color.RGBA{R: 194, G: 194, B: 194, A: 255}) imgI := 0 var wg sync.WaitGroup taskChan := make(chan taskInfo, 10) imgChan := make(chan imgDraw, 10) taskSuccessChan := make(chan bool, 10) go func() { for { select { case info := <-taskChan: go func() { defer wg.Done() var x, y int im,err:= gg.LoadImage(info.Path) if err != nil { log.Printf("LoadImage(%s) error: %v", info.Path, err) } if im.Bounds().Size().X < im.Bounds().Size().Y { im = ScaleImage(im, NY, NX) x, y = info.X*(NX+NXInterval)+(NX-NY)/2, info.Y*(NY+NYInterval) } else { im = ScaleImage(im, NX, NY) x, y = info.X*(NX+NXInterval), info.Y*(NY+NYInterval)+(NX-NY)/2 } imgChan <- imgDraw{ Im: im, X: x, Y: y, StringX: float64(info.X * (NX + NXInterval)), StringY: float64(info.Y*(NY+NYInterval) + NY + 58), StringText: info.Name, } <-taskSuccessChan }() case imgDrawInfo := <-imgChan: dc.DrawImage(imgDrawInfo.Im, imgDrawInfo.X, imgDrawInfo.Y) str := getString(imgDrawInfo.StringText, strMaxWidth*2-1) dc.DrawStringWrapped(str, imgDrawInfo.StringX, imgDrawInfo.StringY, 0, 0, NX, 0, gg.AlignCenter) wg.Done() } } }() for y := 0; y < columnNum; y++ { if imgI >= imgNum { break } for x := 0; x < lineNum; x++ { if imgI >= imgNum { break } taskChan <- taskInfo{ Path: imgList[imgI].Path + "/" + imgList[imgI].Name, Name: imgList[imgI].Name, X: x, Y: y, } taskSuccessChan <- true wg.Add(2) imgI++ } } wg.Wait() im := dc.Image() f, err := os.Create(dir + "/composite.jpeg") if err != nil { panic(err) } jpeg.Encode(f, im, nil) fileName := strings.Replace(dir,".\\操作区", "", -1) defer func() { fmt.Println("缩略图生成耗时: ",time.Now().Sub(loadStart).Seconds(),"ms ",fileName) }() }}func getString(str string, maxLen int) string { text := "" w := 0 strSize := 0 for _, c := range []rune(str) { if pkg.IsHalfwidth(c) { strSize = 1 } else { strSize = 2 } w += strSize if w >= maxLen { text += "..." break } text += string(c) } return text}// ScaleImage 缩放图片func ScaleImage(image image.Image, x, y int) image.Image { //loadStart := time.Now()/* defer func() { fmt.Printf("缩放耗时: %v\n", time.Now().Sub(loadStart).Seconds()) }() */ w := image.Bounds().Size().X h := image.Bounds().Size().Y dc := gg.NewContext(x, y) var ax = float64(x) / float64(w) var ay = float64(y) / float64(h) dc.Scale(ax, ay) dc.DrawImage(image, 0, 0) return dc.Image()}func getImgList(p string) (imgInfoListArr []ImgInfoList) { files, _ := ioutil.ReadDir(p) var imgInfoList ImgInfoList imgInfoList.Path = p for _, file := range files { if !file.IsDir() { fileName := file.Name() fileSuffix := strings.ToLower(path.Ext(fileName)) if pkg.StringsContains(config.ImgFormat, fileSuffix) { imgInfoList.ImgInfo = append(imgInfoList.ImgInfo, ImgInfo{ Path: p, Size: file.Size(), Name: fileName, Suffix: fileSuffix, }) } } else { imgInfoListArr = append(imgInfoListArr, getImgList(p+"/"+file.Name())...) } } if len(imgInfoList.ImgInfo) > 10 { imgInfoListArr = append(imgInfoListArr, imgInfoList) } return imgInfoListArr}
复制代码 |