refactor(image-scan): 优化黑暗壁纸扫描和移动功能

- 将单次扫描改为一次性批量扫描所有图片,提升性能效率
- 新增按黑暗等级分类功能,支持多级阈值(95%, 85%, 75%, 65%, 55%)
- 实现并发worker池处理图片,提高扫描速度
- 添加详细的处理进度显示和统计信息
- 分离扫描、筛选、移动逻辑到独立函数便于维护
- 修复原代码中的重复扫描问题,减少磁盘I/O操作
This commit is contained in:
2024-05-07 21:00:45 +08:00
parent a96f0f9015
commit 9c39c2c76b
+147 -27
View File
@@ -346,7 +346,7 @@ func analyzeImage(img image.Image) (darkScore float64, avgColor color.RGBA, widt
return darkScore, color.RGBA{avgR, avgG, avgB, 255}, width, height return darkScore, color.RGBA{avgR, avgG, avgB, 255}, width, height
} }
// 查找并移动黑色壁纸 // findAndMoveDarkWallpapers 查找并移动黑色壁纸(单次扫描版本)
func findAndMoveDarkWallpapers(config Config) ([]WallpaperInfo, error) { func findAndMoveDarkWallpapers(config Config) ([]WallpaperInfo, error) {
var darkWallpapers []WallpaperInfo var darkWallpapers []WallpaperInfo
var mu sync.Mutex var mu sync.Mutex
@@ -483,36 +483,156 @@ func main() {
fmt.Println(strings.Repeat("=", 40)) fmt.Println(strings.Repeat("=", 40))
time.Sleep(time.Second * 5) time.Sleep(time.Second * 5)
// 亮度依次递增 // 定义多个黑暗阈值等级
targetDarkThresholds := []int{95, 85, 75, 65, 55, 45, 35, 25, 15} targetDarkThresholds := []int{95, 85, 75, 65, 55}
for _, threshold := range targetDarkThresholds {
// 源目录,包含壁纸
config.TargetDir = "../" + baseDirName + "_dark_wallpapers_" + strconv.Itoa(threshold) // 目标目录
config.DarkThreshold = float64(threshold) / 100.0 // 黑暗阈值
config.MinWidth = 1280
config.MinHeight = 720
config.CopyMode = false // false=移动,true=复制
config.Verbose = true
fmt.Printf("源目录: %s\n", config.SourceDir) // 第一步:一次性扫描所有图片,分析黑暗程度
fmt.Printf("目标目录: %s\n", config.TargetDir) fmt.Println("\n🔍 开始扫描图片...")
fmt.Printf("黑暗阈值: %.2f\n", config.DarkThreshold) allWallpapers, err := scanAllImages(config)
fmt.Printf("最小分辨率: %dx%d\n", config.MinWidth, config.MinHeight)
fmt.Printf("模式: %s\n", map[bool]string{true: "复制", false: "移动"}[config.CopyMode])
fmt.Println()
// 执行查找和移动
wallpapers, err := findAndMoveDarkWallpapers(config)
if err != nil { if err != nil {
log.Fatalf("处理失败: %v", err) log.Fatalf("扫描失败: %v", err)
} }
// 显示结果 fmt.Printf("\n✅ 扫描完成!共找到 %d 张符合条件的图片\n", len(allWallpapers))
printSummary(wallpapers, config)
//// 保存结果到日志文件 // 第二步:根据黑暗等级分类并移动到不同目录
//if len(wallpapers) > 0 { for _, threshold := range targetDarkThresholds {
// saveResultsToLog(wallpapers, config) darkThreshold := float64(threshold) / 100.0 // 转换为小数形式(如 0.95)
//} targetDir := "../" + baseDirName + "_dark_wallpapers_" + strconv.Itoa(threshold)
fmt.Printf("\n" + strings.Repeat("=", 60) + "\n")
fmt.Printf("📁 处理黑暗等级 ≥ %d%% 的图片\n", threshold)
fmt.Printf(" 目标目录: %s\n", targetDir)
fmt.Println(strings.Repeat("=", 60))
// 筛选出符合当前黑暗阈值的图片
filteredWallpapers := filterWallpapersByDarkness(allWallpapers, darkThreshold)
if len(filteredWallpapers) == 0 {
fmt.Printf(" ⚠️ 没有符合黑暗等级 ≥ %d%% 的图片\n", threshold)
continue
}
fmt.Printf(" 找到 %d 张符合条件的图片\n", len(filteredWallpapers))
// 移动这些图片到对应目录
movedCount, err := moveWallpapersToTarget(filteredWallpapers, targetDir, config.CopyMode)
if err != nil {
log.Printf("⚠️ 移动部分文件时出错: %v", err)
}
fmt.Printf(" ✓ 成功移动/复制 %d 张图片\n", movedCount)
}
fmt.Println("\n🎉 所有操作完成!")
}
// scanAllImages 一次性扫描所有图片并分析黑暗程度
func scanAllImages(config Config) ([]WallpaperInfo, error) {
var allWallpapers []WallpaperInfo
var mu sync.Mutex
var wg sync.WaitGroup
// 创建worker池
jobs := make(chan string, 100)
results := make(chan *WallpaperInfo, 100)
// 启动worker
for i := 0; i < config.Parallel; i++ {
wg.Add(1)
go func(workerID int) {
defer wg.Done()
for path := range jobs {
if config.Verbose {
fmt.Printf("Worker %d 处理: %s\n", workerID, filepath.Base(path))
}
wp, err := processImageFile(path, config)
if err != nil {
// 静默跳过不符合条件的图片
continue
}
results <- wp
}
}(i)
}
// 收集结果
go func() {
for wp := range results {
mu.Lock()
allWallpapers = append(allWallpapers, *wp)
mu.Unlock()
}
}()
// 遍历源目录,发送任务
var processedCount int
err := filepath.WalkDir(config.SourceDir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return nil
}
if d.IsDir() {
return nil
}
ext := strings.ToLower(filepath.Ext(path))
if supportedExts[ext] {
processedCount++
jobs <- path
}
return nil
})
close(jobs)
wg.Wait()
close(results)
// 按黑暗程度排序(从高到低)
sort.Slice(allWallpapers, func(i, j int) bool {
return allWallpapers[i].DarkScore > allWallpapers[j].DarkScore
})
fmt.Printf(" 扫描文件总数: %d\n", processedCount)
fmt.Printf(" 符合条件的图片: %d\n", len(allWallpapers))
return allWallpapers, err
}
// filterWallpapersByDarkness 根据黑暗阈值筛选图片
func filterWallpapersByDarkness(wallpapers []WallpaperInfo, minDarkScore float64) []WallpaperInfo {
var filtered []WallpaperInfo
for _, wp := range wallpapers {
if wp.DarkScore >= minDarkScore {
filtered = append(filtered, wp)
} }
} }
return filtered
}
// moveWallpapersToTarget 将图片移动到指定目标目录
func moveWallpapersToTarget(wallpapers []WallpaperInfo, targetDir string, copyMode bool) (int, error) {
movedCount := 0
var firstErr error
for _, wp := range wallpapers {
// 创建临时配置用于移动文件
tempConfig := Config{
TargetDir: targetDir,
CopyMode: copyMode,
}
if err := moveOrCopyFile(&wp, tempConfig); err != nil {
if firstErr == nil {
firstErr = err
}
continue
}
movedCount++
}
return movedCount, firstErr
}