From c8f3d0bf382f75d7dca6a63ce9117d949b3a9db5 Mon Sep 17 00:00:00 2001 From: wood chen Date: Tue, 22 Oct 2024 19:32:22 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=9B=E4=B8=80=E6=AD=A5=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- encoder/prefetch.go | 38 ++++++++++++++----- encoder/process.go | 90 ++++++++++++++++++++++++++++++--------------- handler/remote.go | 2 +- handler/router.go | 21 +---------- helper/helper.go | 2 +- 5 files changed, 92 insertions(+), 61 deletions(-) diff --git a/encoder/prefetch.go b/encoder/prefetch.go index d739245..4369444 100644 --- a/encoder/prefetch.go +++ b/encoder/prefetch.go @@ -1,11 +1,11 @@ package encoder import ( - "fmt" "os" "path" "path/filepath" "sync" + "sync/atomic" "time" "webp_server_go/config" "webp_server_go/helper" @@ -16,18 +16,30 @@ import ( func PrefetchImages() { sTime := time.Now() - log.Infof("Prefetching using %d cores", config.Jobs) + log.Infof("开始预取图像,使用 %d 个核心", config.Jobs) // 使用固定大小的工作池来限制并发 workerPool := make(chan struct{}, config.Jobs) var wg sync.WaitGroup all := helper.FileCount(config.Config.ImgPath) - bar := progressbar.Default(all, "Prefetching...") + log.Infof("总共需要处理 %d 个文件", all) + bar := progressbar.Default(all, "预取进度") + + var processedCount int32 // 用于计数处理的文件数 err := filepath.Walk(config.Config.ImgPath, func(picAbsPath string, info os.FileInfo, err error) error { - if err != nil || info.IsDir() || !helper.CheckAllowedType(picAbsPath) { + if err != nil { + log.Warnf("访问文件时出错: %s, 错误: %v", picAbsPath, err) + return nil + } + if info.IsDir() { + log.Debugf("跳过目录: %s", picAbsPath) + return nil + } + if !helper.CheckAllowedType(picAbsPath) { + log.Debugf("跳过不支持的文件类型: %s", picAbsPath) return nil } @@ -37,18 +49,25 @@ func PrefetchImages() { workerPool <- struct{}{} // 获取工作槽 defer func() { <-workerPool }() // 释放工作槽 + log.Debugf("开始处理文件: %s", picAbsPath) + metadata := helper.ReadMetadata(picAbsPath, "", config.LocalHostAlias) avifAbsPath, webpAbsPath, jxlAbsPath := helper.GenOptimizedAbsPath(metadata, config.LocalHostAlias) - _ = os.MkdirAll(path.Dir(avifAbsPath), 0755) - - log.Infof("Prefetching %s", picAbsPath) + if err := os.MkdirAll(path.Dir(avifAbsPath), 0755); err != nil { + log.Warnf("创建目录失败: %s, 错误: %v", path.Dir(avifAbsPath), err) + return + } supported := map[string]bool{ "raw": true, "webp": true, "avif": true, "jxl": true, } ConvertFilter(picAbsPath, jxlAbsPath, avifAbsPath, webpAbsPath, config.ExtraParams{Width: 0, Height: 0}, supported, nil) + + atomic.AddInt32(&processedCount, 1) + log.Debugf("文件处理完成: %s (进度: %d/%d)", picAbsPath, atomic.LoadInt32(&processedCount), all) + _ = bar.Add(1) }() @@ -58,8 +77,9 @@ func PrefetchImages() { wg.Wait() // 等待所有工作完成 if err != nil { - log.Errorln(err) + log.Errorf("遍历目录时发生错误: %v", err) } + elapsed := time.Since(sTime) - _, _ = fmt.Fprintf(os.Stdout, "Prefetch complete in %s\n\n", elapsed) + log.Infof("预取完成,共处理 %d 个文件,耗时 %s", atomic.LoadInt32(&processedCount), elapsed) } diff --git a/encoder/process.go b/encoder/process.go index c39fae1..d0d0089 100644 --- a/encoder/process.go +++ b/encoder/process.go @@ -17,14 +17,14 @@ func resizeImage(img *vips.ImageRef, extraParams config.ExtraParams) error { imgHeightWidthRatio := float32(imageHeight) / float32(imageWidth) - // Here we have width, height and max_width, max_height - // Both pairs cannot be used at the same time + //这里我们有宽度、高度和 max_width、max_height + //两对不能同时使用 - // max_height and max_width are used to make sure bigger images are resized to max_height and max_width - // e.g, 500x500px image with max_width=200,max_height=100 will be resized to 100x100 - // while smaller images are untouched + //max_height 和 max_width 用于确保将更大的图像调整为 max_height 和 max_width + //例如,max_width=200,max_height=100 的 500x500px 图像将调整为 100x100 + //而较小的图像则保持不变 - // If both are used, we will use width and height + //如果两者都使用,我们将使用宽度和高度 if extraParams.MaxHeight > 0 && extraParams.MaxWidth > 0 { // If any of it exceeds @@ -32,8 +32,8 @@ func resizeImage(img *vips.ImageRef, extraParams config.ExtraParams) error { // Check which dimension exceeds most heightExceedRatio := float32(imageHeight) / float32(extraParams.MaxHeight) widthExceedRatio := float32(imageWidth) / float32(extraParams.MaxWidth) - // If height exceeds more, like 500x500 -> 200x100 (2.5 < 5) - // Take max_height as new height ,resize and retain ratio + // 如果高度超过更多,例如 500x500 -> 200x100 (2.5 < 5) + // 以max_height为新高度,调整大小并保留比例 if heightExceedRatio > widthExceedRatio { err := img.Thumbnail(int(float32(extraParams.MaxHeight)/imgHeightWidthRatio), extraParams.MaxHeight, 0) if err != nil { @@ -104,65 +104,95 @@ func resizeImage(img *vips.ImageRef, extraParams config.ExtraParams) error { } func ResizeItself(raw, dest string, extraParams config.ExtraParams) { - log.Infof("Resize %s itself to %s", raw, dest) + log.Infof("开始调整图像大小: 源文件=%s, 目标文件=%s", raw, dest) - // we need to create dir first - var err = os.MkdirAll(path.Dir(dest), 0755) - if err != nil { - log.Error(err.Error()) + // 创建目标目录 + if err := os.MkdirAll(path.Dir(dest), 0755); err != nil { + log.Errorf("创建目标目录失败: %v", err) + return } + // 加载图像 img, err := vips.LoadImageFromFile(raw, &vips.ImportParams{ FailOnError: boolFalse, }) if err != nil { - log.Warnf("Could not load %s: %s", raw, err) + log.Warnf("加载图像失败: 文件=%s, 错误=%v", raw, err) return } - _ = resizeImage(img, extraParams) + defer img.Close() + + // 调整图像大小 + if err := resizeImage(img, extraParams); err != nil { + log.Warnf("调整图像大小失败: %v", err) + return + } + + // 移除元数据(如果配置要求) if config.Config.StripMetadata { + log.Debug("正在移除图像元数据") img.RemoveMetadata() } - buf, _, _ := img.ExportNative() - _ = os.WriteFile(dest, buf, 0600) - img.Close() + + // 导出图像 + buf, _, err := img.ExportNative() + if err != nil { + log.Errorf("导出图像失败: %v", err) + return + } + + // 写入文件 + if err := os.WriteFile(dest, buf, 0600); err != nil { + log.Errorf("写入目标文件失败: 文件=%s, 错误=%v", dest, err) + return + } + + log.Infof("图像大小调整成功: 目标文件=%s", dest) } // Pre-process image(auto rotate, resize, etc.) func preProcessImage(img *vips.ImageRef, imageType string, extraParams config.ExtraParams) error { - // Check Width/Height and ignore image formats + log.Debugf("开始预处理图像: 类型=%s, 宽度=%d, 高度=%d", imageType, img.Metadata().Width, img.Metadata().Height) + + // 检查宽度/高度并忽略特定图像格式 switch imageType { case "webp": if img.Metadata().Width > config.WebpMax || img.Metadata().Height > config.WebpMax { + log.Warnf("WebP图像尺寸超限: 宽度=%d, 高度=%d, 最大限制=%d", img.Metadata().Width, img.Metadata().Height, config.WebpMax) return errors.New("WebP:图像太大") } - imageFormat := img.Format() - if slices.Contains(webpIgnore, imageFormat) { - // Return err to render original image + if slices.Contains(webpIgnore, img.Format()) { + log.Infof("WebP编码器忽略图像类型: %s", img.Format()) return errors.New("WebP 编码器:忽略图像类型") } case "avif": if img.Metadata().Width > config.AvifMax || img.Metadata().Height > config.AvifMax { + log.Warnf("AVIF图像尺寸超限: 宽度=%d, 高度=%d, 最大限制=%d", img.Metadata().Width, img.Metadata().Height, config.AvifMax) return errors.New("AVIF:图像太大") } - imageFormat := img.Format() - if slices.Contains(avifIgnore, imageFormat) { - // Return err to render original image + if slices.Contains(avifIgnore, img.Format()) { + log.Infof("AVIF编码器忽略图像类型: %s", img.Format()) return errors.New("AVIF 编码器:忽略图像类型") } } - // Auto rotate - err := img.AutoRotate() - if err != nil { + // 自动旋转 + if err := img.AutoRotate(); err != nil { + log.Errorf("图像自动旋转失败: %v", err) return err } + log.Debug("图像自动旋转完成") + + // 额外参数处理 if config.Config.EnableExtraParams { - err = resizeImage(img, extraParams) - if err != nil { + log.Debug("开始应用额外图像处理参数") + if err := resizeImage(img, extraParams); err != nil { + log.Errorf("应用额外图像处理参数失败: %v", err) return err } + log.Debug("额外图像处理参数应用完成") } + log.Debug("图像预处理完成") return nil } diff --git a/handler/remote.go b/handler/remote.go index b160267..7f44da3 100644 --- a/handler/remote.go +++ b/handler/remote.go @@ -42,7 +42,7 @@ func downloadFile(filepath string, url string) error { if resp.StatusCode != fiber.StatusOK { log.Errorf("获取远程图像时远程返回 %s", resp.Status) - return fmt.Errorf("unexpected status: %s", resp.Status) + return fmt.Errorf("意外的状态: %s", resp.Status) } // 创建目标文件 diff --git a/handler/router.go b/handler/router.go index 1c9dd65..b2cff92 100644 --- a/handler/router.go +++ b/handler/router.go @@ -108,25 +108,6 @@ func Convert(c *fiber.Ctx) error { } } - // 新增:检查是否为WebP格式 - // if strings.ToLower(path.Ext(filename)) == ".webp" { - // log.Infof("原始图像已经是WebP格式: %s", reqURI) - // var webpImagePath string - // if proxyMode { - // // 对于代理模式,确保文件已经被下载 - // metadata = fetchRemoteImg(realRemoteAddr, targetHostName) - // webpImagePath = path.Join(config.Config.RemoteRawPath, targetHostName, metadata.Id) - // } else { - // webpImagePath = path.Join(config.Config.ImgPath, reqURI) - // } - - // // 检查文件是否存在 - // if helper.FileExists(webpImagePath) { - // // 直接返回原WebP图片 - // return c.SendFile(webpImagePath) - // } - // } - if !helper.CheckAllowedType(filename) { msg := "不允许的文件扩展名 " + filename log.Warn(msg) @@ -220,7 +201,7 @@ func Convert(c *fiber.Ctx) error { return c.SendFile(dest) } - // Check the original image for existence, + // 检查原始图像是否存在, if !helper.ImageExists(rawImageAbs) { helper.DeleteMetadata(reqURIwithQuery, targetHostName) msg := "Image not found!" diff --git a/helper/helper.go b/helper/helper.go index 07ec4e1..78af66a 100644 --- a/helper/helper.go +++ b/helper/helper.go @@ -180,7 +180,7 @@ func FindSmallestFiles(files []string) string { for _, f := range files { stat, err := os.Stat(f) if err != nil { - log.Warnf("%s not found on filesystem", f) + log.Warnf("在文件系统上找不到 %s", f) continue } if stat.Size() < small || small == 0 {