645 lines
18 KiB
Go
645 lines
18 KiB
Go
package main
|
||
|
||
//import (
|
||
// "fmt"
|
||
// "image"
|
||
// "image/color"
|
||
// "image/draw"
|
||
// "image/png"
|
||
// "io/ioutil"
|
||
// "os"
|
||
// "path/filepath"
|
||
// "strings"
|
||
// "sync"
|
||
// "time"
|
||
//
|
||
// "github.com/disintegration/imaging"
|
||
//)
|
||
//
|
||
////// ImageToPNGConverter 图片去白边并转为PNG
|
||
////type ImageToPNGConverter struct {
|
||
//// Threshold int
|
||
//// Margin int
|
||
//// BgColor color.RGBA
|
||
//// DetectColor *color.RGBA
|
||
//// KeepTransparent bool
|
||
//// PNGCompressLevel png.CompressionLevel
|
||
//// Quality int
|
||
////}
|
||
//
|
||
//// NewImageToPNGConverter 创建新的转换器
|
||
//func NewImageToPNGConverter(threshold, margin int, bgColor, detectColor *color.RGBA,
|
||
// keepTransparent bool, compressLevel png.CompressionLevel, quality int) *ImageToPNGConverter {
|
||
//
|
||
// // 默认背景色为白色
|
||
// bg := color.RGBA{R: 255, G: 255, B: 255, A: 255}
|
||
// if bgColor != nil {
|
||
// bg = *bgColor
|
||
// }
|
||
//
|
||
// return &ImageToPNGConverter{
|
||
// Threshold: threshold,
|
||
// Margin: margin,
|
||
// BgColor: bg,
|
||
// DetectColor: detectColor,
|
||
// KeepTransparent: keepTransparent,
|
||
// PNGCompressLevel: compressLevel,
|
||
// Quality: quality,
|
||
// }
|
||
//}
|
||
//
|
||
//// IsBackgroundColor 判断像素是否为背景色
|
||
//func (c *ImageToPNGConverter) IsBackgroundColor(pixel color.Color, hasAlpha bool) bool {
|
||
// r, g, b, a := pixel.RGBA()
|
||
//
|
||
// // 转换为8位值
|
||
// r8 := uint8(r >> 8)
|
||
// g8 := uint8(g >> 8)
|
||
// b8 := uint8(b >> 8)
|
||
// a8 := uint8(a >> 8)
|
||
//
|
||
// // 检查透明度
|
||
// if hasAlpha && a8 < 25 { // 透明度 > 90%
|
||
// return true
|
||
// }
|
||
//
|
||
// // 如果指定了检测颜色
|
||
// if c.DetectColor != nil {
|
||
// dr, dg, db, _ := c.DetectColor.RGBA()
|
||
// dr8 := uint8(dr >> 8)
|
||
// dg8 := uint8(dg >> 8)
|
||
// db8 := uint8(db >> 8)
|
||
//
|
||
// // threshold 是 int 类型,需要转换为 uint8 比较
|
||
// threshold8 := uint8(255 - c.Threshold)
|
||
// return absDiff(r8, dr8) <= threshold8 &&
|
||
// absDiff(g8, dg8) <= threshold8 &&
|
||
// absDiff(b8, db8) <= threshold8
|
||
// }
|
||
//
|
||
// // 自动检测白色/浅色背景
|
||
// // 注意:这里的 c.Threshold 是 int,需要转换为 uint8
|
||
// threshold8 := uint8(c.Threshold)
|
||
// return r8 >= threshold8 &&
|
||
// g8 >= threshold8 &&
|
||
// b8 >= threshold8
|
||
//}
|
||
//
|
||
//// FindBorders 查找图片的有效边界
|
||
//func (c *ImageToPNGConverter) FindBorders(img image.Image) image.Rectangle {
|
||
// bounds := img.Bounds()
|
||
// width := bounds.Dx()
|
||
// height := bounds.Dy()
|
||
//
|
||
// // 检查图像是否有alpha通道
|
||
// _, hasAlpha := img.(*image.NRGBA)
|
||
// if !hasAlpha {
|
||
// _, hasAlpha = img.(*image.RGBA)
|
||
// }
|
||
//
|
||
// // 初始化边界
|
||
// left := width
|
||
// top := height
|
||
// right := 0
|
||
// bottom := 0
|
||
//
|
||
// // 查找非背景区域
|
||
// for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
|
||
// for x := bounds.Min.X; x < bounds.Max.X; x++ {
|
||
// pixel := img.At(x, y)
|
||
// if !c.IsBackgroundColor(pixel, hasAlpha) {
|
||
// if x < left {
|
||
// left = x
|
||
// }
|
||
// if x > right {
|
||
// right = x
|
||
// }
|
||
// if y < top {
|
||
// top = y
|
||
// }
|
||
// if y > bottom {
|
||
// bottom = y
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
//
|
||
// // 如果没有找到非背景区域,返回整个图像
|
||
// if left > right || top > bottom {
|
||
// return bounds
|
||
// }
|
||
//
|
||
// // 添加边距
|
||
// left = max(bounds.Min.X, left-c.Margin)
|
||
// top = max(bounds.Min.Y, top-c.Margin)
|
||
// right = min(bounds.Max.X, right+c.Margin+1)
|
||
// bottom = min(bounds.Max.Y, bottom+c.Margin+1)
|
||
//
|
||
// return image.Rect(left, top, right, bottom)
|
||
//}
|
||
//
|
||
//// TrimImage 裁剪图片白边
|
||
//func (c *ImageToPNGConverter) TrimImage(img image.Image) image.Image {
|
||
// borders := c.FindBorders(img)
|
||
//
|
||
// // 创建一个新的图像并裁剪
|
||
// trimmed := imaging.Crop(img, borders)
|
||
// return trimmed
|
||
//}
|
||
//
|
||
//// ConvertToPNG 转换图片为PNG格式
|
||
//func (c *ImageToPNGConverter) ConvertToPNG(img image.Image, addBackground bool) image.Image {
|
||
// // 先裁剪白边
|
||
// trimmed := c.TrimImage(img)
|
||
//
|
||
// // 检查是否有alpha通道
|
||
// _, hasAlpha := trimmed.(*image.NRGBA)
|
||
// if !hasAlpha {
|
||
// _, hasAlpha = trimmed.(*image.RGBA)
|
||
// }
|
||
//
|
||
// if hasAlpha {
|
||
// if c.KeepTransparent {
|
||
// // 保持透明
|
||
// return trimmed
|
||
// } else if addBackground {
|
||
// // 添加背景色
|
||
// bg := image.NewRGBA(trimmed.Bounds())
|
||
// draw.Draw(bg, bg.Bounds(), &image.Uniform{C: c.BgColor}, image.Point{}, draw.Src)
|
||
// draw.Draw(bg, bg.Bounds(), trimmed, trimmed.Bounds().Min, draw.Over)
|
||
// return bg
|
||
// }
|
||
// } else {
|
||
// // 非透明图像
|
||
// if c.KeepTransparent {
|
||
// // 转换为RGBA
|
||
// rgba := image.NewRGBA(trimmed.Bounds())
|
||
// draw.Draw(rgba, rgba.Bounds(), trimmed, trimmed.Bounds().Min, draw.Src)
|
||
// return rgba
|
||
// }
|
||
// return trimmed
|
||
// }
|
||
//
|
||
// return trimmed
|
||
//}
|
||
//
|
||
//// ProcessImageFile 处理单个图片文件
|
||
//func (c *ImageToPNGConverter) ProcessImageFile(inputPath, outputPath string) map[string]interface{} {
|
||
// result := map[string]interface{}{
|
||
// "success": false,
|
||
// "input_path": inputPath,
|
||
// "output_path": outputPath,
|
||
// }
|
||
//
|
||
// // 打开图片文件
|
||
// file, err := os.Open(inputPath)
|
||
// if err != nil {
|
||
// result["error"] = err.Error()
|
||
// result["message"] = fmt.Sprintf("失败: %s - %s", filepath.Base(inputPath), err)
|
||
// return result
|
||
// }
|
||
// defer file.Close()
|
||
//
|
||
// // 解码图像
|
||
// img, format, err := image.Decode(file)
|
||
// if err != nil {
|
||
// result["error"] = err.Error()
|
||
// result["message"] = fmt.Sprintf("失败: %s - %s", filepath.Base(inputPath), err)
|
||
// return result
|
||
// }
|
||
//
|
||
// // 获取原始信息
|
||
// origBounds := img.Bounds()
|
||
// origSize := origBounds.Size()
|
||
// origArea := origSize.X * origSize.Y
|
||
//
|
||
// // 转换为PNG
|
||
// resultImg := c.ConvertToPNG(img, true)
|
||
//
|
||
// // 获取处理后的信息
|
||
// newBounds := resultImg.Bounds()
|
||
// newSize := newBounds.Size()
|
||
// newArea := newSize.X * newSize.Y
|
||
//
|
||
// // 计算尺寸减少比例
|
||
// sizeReduction := 0.0
|
||
// if origArea > 0 {
|
||
// sizeReduction = 1 - float64(newArea)/float64(origArea)
|
||
// }
|
||
//
|
||
// // 获取原始文件大小
|
||
// fileInfo, _ := os.Stat(inputPath)
|
||
// origFileSize := fileInfo.Size()
|
||
//
|
||
// // 保存为PNG
|
||
// outputFile, err := os.Create(outputPath)
|
||
// if err != nil {
|
||
// result["error"] = err.Error()
|
||
// result["message"] = fmt.Sprintf("失败: %s - %s", filepath.Base(inputPath), err)
|
||
// return result
|
||
// }
|
||
// defer outputFile.Close()
|
||
//
|
||
// encoder := png.Encoder{CompressionLevel: c.PNGCompressLevel}
|
||
// err = encoder.Encode(outputFile, resultImg)
|
||
// if err != nil {
|
||
// result["error"] = err.Error()
|
||
// result["message"] = fmt.Sprintf("失败: %s - %s", filepath.Base(inputPath), err)
|
||
// return result
|
||
// }
|
||
//
|
||
// // 获取新文件大小
|
||
// newFileInfo, _ := os.Stat(outputPath)
|
||
// newFileSize := newFileInfo.Size()
|
||
//
|
||
// // 计算文件大小变化
|
||
// fileSizeChange := 0.0
|
||
// if origFileSize > 0 {
|
||
// fileSizeChange = float64(newFileSize) / float64(origFileSize)
|
||
// }
|
||
//
|
||
// result["success"] = true
|
||
// result["orig_format"] = format
|
||
// result["orig_size"] = origSize
|
||
// result["new_size"] = newSize
|
||
// result["size_reduction"] = sizeReduction
|
||
// result["orig_file_size"] = origFileSize
|
||
// result["new_file_size"] = newFileSize
|
||
// result["file_size_change"] = fileSizeChange
|
||
// result["message"] = fmt.Sprintf("成功: %s (%s→PNG, %dx%d→%dx%d)",
|
||
// filepath.Base(inputPath), format, origSize.X, origSize.Y, newSize.X, newSize.Y)
|
||
//
|
||
// return result
|
||
//}
|
||
//
|
||
//// BatchPNGConverter 批量PNG转换器
|
||
//type BatchPNGConverter struct {
|
||
// converter *ImageToPNGConverter
|
||
// outputDir string
|
||
// statistics map[string]interface{}
|
||
// mu sync.Mutex
|
||
//}
|
||
//
|
||
//// NewBatchPNGConverter 创建批量转换器
|
||
//func NewBatchPNGConverter(converter *ImageToPNGConverter, outputDir string) *BatchPNGConverter {
|
||
// os.MkdirAll(outputDir, 0755)
|
||
// return &BatchPNGConverter{
|
||
// converter: converter,
|
||
// outputDir: outputDir,
|
||
// statistics: make(map[string]interface{}),
|
||
// }
|
||
//}
|
||
//
|
||
//// GetOutputPath 生成输出路径
|
||
//func (b *BatchPNGConverter) GetOutputPath(inputPath, suffix string) string {
|
||
// baseName := filepath.Base(inputPath)
|
||
// ext := filepath.Ext(baseName)
|
||
// nameWithoutExt := strings.TrimSuffix(baseName, ext)
|
||
//
|
||
// outputFilename := nameWithoutExt + suffix + ".png"
|
||
// return filepath.Join(b.outputDir, outputFilename)
|
||
//}
|
||
//
|
||
//// ProcessSingle 处理单张图片
|
||
//func (b *BatchPNGConverter) ProcessSingle(inputPath, outputPath, suffix string) map[string]interface{} {
|
||
// if outputPath == "" {
|
||
// outputPath = b.GetOutputPath(inputPath, suffix)
|
||
// }
|
||
//
|
||
// // 确保输出目录存在
|
||
// os.MkdirAll(filepath.Dir(outputPath), 0755)
|
||
//
|
||
// return b.converter.ProcessImageFile(inputPath, outputPath)
|
||
//}
|
||
//
|
||
//// ProcessBatch 批量处理图片
|
||
//func (b *BatchPNGConverter) ProcessBatch(inputPaths []string, suffix string, maxWorkers int) map[string]interface{} {
|
||
// startTime := time.Now()
|
||
//
|
||
// stats := map[string]interface{}{
|
||
// "total": len(inputPaths),
|
||
// "success": 0,
|
||
// "failed": 0,
|
||
// "total_size_reduction": 0.0,
|
||
// "total_file_size_orig": int64(0),
|
||
// "total_file_size_new": int64(0),
|
||
// "results": []map[string]interface{}{},
|
||
// }
|
||
//
|
||
// // 使用工作池
|
||
// var wg sync.WaitGroup
|
||
// semaphore := make(chan struct{}, maxWorkers)
|
||
// resultsChan := make(chan map[string]interface{}, len(inputPaths))
|
||
//
|
||
// for _, inputPath := range inputPaths {
|
||
// wg.Add(1)
|
||
// go func(path string) {
|
||
// defer wg.Done()
|
||
// semaphore <- struct{}{}
|
||
// defer func() { <-semaphore }()
|
||
//
|
||
// outputPath := b.GetOutputPath(path, suffix)
|
||
// result := b.ProcessSingle(path, outputPath, suffix)
|
||
// resultsChan <- result
|
||
// }(inputPath)
|
||
// }
|
||
//
|
||
// // 收集结果
|
||
// go func() {
|
||
// wg.Wait()
|
||
// close(resultsChan)
|
||
// }()
|
||
//
|
||
// completed := 0
|
||
// for result := range resultsChan {
|
||
// completed++
|
||
// b.mu.Lock()
|
||
// stats["results"] = append(stats["results"].([]map[string]interface{}), result)
|
||
//
|
||
// if result["success"].(bool) {
|
||
// stats["success"] = stats["success"].(int) + 1
|
||
// stats["total_size_reduction"] = stats["total_size_reduction"].(float64) + result["size_reduction"].(float64)
|
||
// stats["total_file_size_orig"] = stats["total_file_size_orig"].(int64) + result["orig_file_size"].(int64)
|
||
// stats["total_file_size_new"] = stats["total_file_size_new"].(int64) + result["new_file_size"].(int64)
|
||
// } else {
|
||
// stats["failed"] = stats["failed"].(int) + 1
|
||
// }
|
||
// b.mu.Unlock()
|
||
//
|
||
// fmt.Printf("[%d/%d] %s\n", completed, len(inputPaths), result["message"])
|
||
// }
|
||
//
|
||
// // 计算统计信息
|
||
// stats["elapsed_time"] = time.Since(startTime).Seconds()
|
||
// if stats["success"].(int) > 0 {
|
||
// stats["avg_size_reduction"] = stats["total_size_reduction"].(float64) / float64(stats["success"].(int))
|
||
// if stats["total_file_size_orig"].(int64) > 0 {
|
||
// stats["total_file_size_change"] = float64(stats["total_file_size_new"].(int64)) / float64(stats["total_file_size_orig"].(int64))
|
||
// } else {
|
||
// stats["total_file_size_change"] = 1.0
|
||
// }
|
||
// }
|
||
//
|
||
// return stats
|
||
//}
|
||
//
|
||
//// FindImageFiles 查找目录中的图片文件
|
||
//func FindImageFiles(directory string, recursive bool) []string {
|
||
// supportedExtensions := map[string]bool{
|
||
// ".jpg": true,
|
||
// ".jpeg": true,
|
||
// ".png": true,
|
||
// ".gif": true,
|
||
// ".bmp": true,
|
||
// ".tif": true,
|
||
// ".tiff": true,
|
||
// ".webp": true,
|
||
// ".jfif": true,
|
||
// ".ico": true,
|
||
// ".ppm": true,
|
||
// ".pgm": true,
|
||
// ".pbm": true,
|
||
// ".pnm": true,
|
||
// }
|
||
//
|
||
// var imagePaths []string
|
||
//
|
||
// if recursive {
|
||
// filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
|
||
// if err != nil {
|
||
// return err
|
||
// }
|
||
// if !info.IsDir() {
|
||
// ext := strings.ToLower(filepath.Ext(path))
|
||
// if supportedExtensions[ext] {
|
||
// imagePaths = append(imagePaths, path)
|
||
// }
|
||
// }
|
||
// return nil
|
||
// })
|
||
// } else {
|
||
// files, err := ioutil.ReadDir(directory)
|
||
// if err != nil {
|
||
// return imagePaths
|
||
// }
|
||
//
|
||
// for _, file := range files {
|
||
// if !file.IsDir() {
|
||
// ext := strings.ToLower(filepath.Ext(file.Name()))
|
||
// if supportedExtensions[ext] {
|
||
// imagePaths = append(imagePaths, filepath.Join(directory, file.Name()))
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
//
|
||
// return imagePaths
|
||
//}
|
||
//
|
||
//// PrintBanner 打印程序标题
|
||
//func PrintBanner() {
|
||
// banner := `
|
||
//╔══════════════════════════════════════════════════╗
|
||
//║ 图片去白边转PNG工具 v1.0 ║
|
||
//║ Image White Border Removal & PNG Converter ║
|
||
//╚══════════════════════════════════════════════════╝
|
||
//`
|
||
// fmt.Println(banner)
|
||
//}
|
||
//
|
||
//// PrintSummary 打印处理总结
|
||
//func PrintSummary(stats map[string]interface{}) {
|
||
// fmt.Println("\n" + strings.Repeat("=", 60))
|
||
// fmt.Println("📊 处理总结")
|
||
// fmt.Println(strings.Repeat("=", 60))
|
||
// fmt.Printf("📁 总共处理: %d 张图片\n", stats["total"])
|
||
// fmt.Printf("✅ 成功: %d 张\n", stats["success"])
|
||
// fmt.Printf("❌ 失败: %d 张\n", stats["failed"])
|
||
//
|
||
// if stats["success"].(int) > 0 {
|
||
// fmt.Printf("⏱️ 耗时: %.2f 秒\n", stats["elapsed_time"].(float64))
|
||
//
|
||
// if avgReduction, ok := stats["avg_size_reduction"]; ok {
|
||
// fmt.Printf("📐 平均尺寸减少: %.1f%%\n", avgReduction.(float64)*100)
|
||
// }
|
||
//
|
||
// if change, ok := stats["total_file_size_change"]; ok {
|
||
// changeVal := change.(float64)
|
||
// if changeVal < 1 {
|
||
// fmt.Printf("💾 总文件大小减少: %.1f%%\n", (1-changeVal)*100)
|
||
// } else if changeVal > 1 {
|
||
// fmt.Printf("💾 总文件大小增加: %.1f%%\n", (changeVal-1)*100)
|
||
// } else {
|
||
// fmt.Println("💾 总文件大小基本不变")
|
||
// }
|
||
// }
|
||
// }
|
||
// fmt.Println(strings.Repeat("=", 60))
|
||
//}
|
||
//
|
||
//// 辅助函数
|
||
//func absDiff(a, b uint8) uint8 {
|
||
// if a > b {
|
||
// return a - b
|
||
// }
|
||
// return b - a
|
||
//}
|
||
//
|
||
//func max(a, b int) int {
|
||
// if a > b {
|
||
// return a
|
||
// }
|
||
// return b
|
||
//}
|
||
//
|
||
//func min(a, b int) int {
|
||
// if a < b {
|
||
// return a
|
||
// }
|
||
// return b
|
||
//}
|
||
//
|
||
//func main() {
|
||
// // 直接设置参数值,不需要命令行输入
|
||
//
|
||
// // ============ 参数配置区 ============
|
||
// // 基础参数
|
||
// inputPath := "D:\\isbn_images\\result\\matched\\9771671688095.jpg" // 输入文件或目录路径
|
||
// outputPath := "D:\\isbn_images\\result\\matched\\output.png" // 输出文件路径(单文件模式)
|
||
// outputDir := "D:\\isbn_images\\result\\matched\\" // 输出目录路径(批量模式)
|
||
// suffix := "_trimmed" // 输出文件名后缀
|
||
//
|
||
// // 处理参数
|
||
// threshold := 240 // 背景检测阈值 (0-255)
|
||
// margin := 0 // 保留边距像素
|
||
// transparent := false // 保持透明背景
|
||
// compressLevel := 6 // PNG压缩级别 (0-9)
|
||
//
|
||
// // 批量处理参数
|
||
// recursive := false // 递归处理子目录
|
||
// jobs := 4 // 并行处理数
|
||
// force := true // 覆盖已存在的输出文件(设置为true不询问)
|
||
// verbose := true // 显示详细处理信息
|
||
// showBanner := true // 显示标题横幅
|
||
// // ============ 参数配置结束 ============
|
||
//
|
||
// if showBanner {
|
||
// PrintBanner()
|
||
// }
|
||
//
|
||
// // 创建转换器
|
||
// compressionLevel := png.DefaultCompression
|
||
// switch {
|
||
// case compressLevel <= 0:
|
||
// compressionLevel = png.NoCompression
|
||
// case compressLevel >= 9:
|
||
// compressionLevel = png.BestCompression
|
||
// default:
|
||
// // 使用默认压缩级别
|
||
// }
|
||
//
|
||
// converter := NewImageToPNGConverter(
|
||
// threshold,
|
||
// margin,
|
||
// &color.RGBA{R: 255, G: 255, B: 255, A: 255},
|
||
// nil,
|
||
// transparent,
|
||
// compressionLevel,
|
||
// 95,
|
||
// )
|
||
//
|
||
// batchConverter := NewBatchPNGConverter(converter, outputDir)
|
||
//
|
||
// // 检查输入路径
|
||
// info, err := os.Stat(inputPath)
|
||
// if err != nil {
|
||
// fmt.Printf("❌ 错误: 路径不存在 - %s\n", inputPath)
|
||
// return
|
||
// }
|
||
//
|
||
// if !info.IsDir() {
|
||
// // 单文件模式
|
||
// fmt.Printf("📄 处理单文件: %s\n", inputPath)
|
||
//
|
||
// // 如果outputPath为空,则生成默认输出路径
|
||
// if outputPath == "" {
|
||
// outputPath = batchConverter.GetOutputPath(inputPath, suffix)
|
||
// }
|
||
//
|
||
// // 检查输出文件是否存在,如果force为false则询问
|
||
// if _, err := os.Stat(outputPath); err == nil && !force {
|
||
// fmt.Printf("⚠️ 警告: 输出文件已存在 - %s\n", outputPath)
|
||
// fmt.Println("已设置force=true,直接覆盖")
|
||
// }
|
||
//
|
||
// result := batchConverter.ProcessSingle(inputPath, outputPath, suffix)
|
||
//
|
||
// if result["success"].(bool) {
|
||
// fmt.Printf("\n✅ %s\n", result["message"])
|
||
// fmt.Printf("💾 输出文件: %s\n", result["output_path"])
|
||
//
|
||
// if reduction, ok := result["size_reduction"]; ok {
|
||
// reductionVal := reduction.(float64)
|
||
// if reductionVal > 0 {
|
||
// fmt.Printf("📐 尺寸减少: %.1f%%\n", reductionVal*100)
|
||
// } else if reductionVal < 0 {
|
||
// fmt.Printf("📐 尺寸增加: %.1f%%\n", -reductionVal*100)
|
||
// }
|
||
// }
|
||
//
|
||
// if change, ok := result["file_size_change"]; ok {
|
||
// changeVal := change.(float64)
|
||
// if changeVal < 1 {
|
||
// fmt.Printf("💿 文件大小减少: %.1f%%\n", (1-changeVal)*100)
|
||
// } else if changeVal > 1 {
|
||
// fmt.Printf("💿 文件大小增加: %.1f%%\n", (changeVal-1)*100)
|
||
// }
|
||
// }
|
||
// } else {
|
||
// fmt.Printf("\n❌ %s\n", result["message"])
|
||
// }
|
||
// } else {
|
||
// // 批量模式
|
||
// fmt.Printf("📁 扫描目录: %s\n", inputPath)
|
||
// imageFiles := FindImageFiles(inputPath, recursive)
|
||
//
|
||
// if len(imageFiles) == 0 {
|
||
// fmt.Println("未找到支持的图片文件")
|
||
// return
|
||
// }
|
||
//
|
||
// fmt.Printf("找到 %d 张图片\n", len(imageFiles))
|
||
//
|
||
// // 检查输出目录,如果force为false则询问
|
||
// if _, err := os.Stat(outputDir); err == nil && !force {
|
||
// files, _ := ioutil.ReadDir(outputDir)
|
||
// if len(files) > 0 {
|
||
// fmt.Printf("⚠️ 警告: 输出目录不为空 - %s\n", outputDir)
|
||
// fmt.Println("已设置force=true,直接继续处理")
|
||
// }
|
||
// }
|
||
//
|
||
// fmt.Printf("📂 输出目录: %s\n", outputDir)
|
||
// fmt.Printf("⚡ 并行处理: %d 个线程\n", jobs)
|
||
// fmt.Println(strings.Repeat("-", 60))
|
||
//
|
||
// // 批量处理
|
||
// stats := batchConverter.ProcessBatch(imageFiles, suffix, jobs)
|
||
//
|
||
// // 打印总结
|
||
// PrintSummary(stats)
|
||
//
|
||
// // 显示失败详情
|
||
// if stats["failed"].(int) > 0 && verbose {
|
||
// fmt.Println("\n❌ 失败详情:")
|
||
// for _, result := range stats["results"].([]map[string]interface{}) {
|
||
// if !result["success"].(bool) {
|
||
// fmt.Printf(" %s: %s\n",
|
||
// filepath.Base(result["input_path"].(string)),
|
||
// result["error"])
|
||
// }
|
||
// }
|
||
// }
|
||
// }
|
||
//}
|