首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Groovy 腳本批量生成圖片縮略圖:智能縮放與無損壓縮實戰

     編輯:Java 相關知識

Groovy 強大的 Java 生態互操作性與腳本簡潔性,使其成為圖片批量處理自動化的利器。本文提供一個生產級縮略圖生成腳本,支援等比縮放、長邊優先適配、小圖不放大、自動輸出命名,可直接用於 CMS 圖片預覽、電商商品縮略圖等場景。

核心腳本代碼

import javax.imageio.ImageIO
import java.io.File
import java.io.IOException
import java.awt.image.BufferedImage
import java.awt.Image
import java.awt.Graphics

/**
 * 生成縮略圖
 * @param input  源圖片 File
 * @param output 目標輸出 File
 * @param length 縮略圖長邊最大像素
 */
def createThumbnail(File input, File output, int length) throws IOException {
    if (!input.exists()) {
        throw new RuntimeException("Input file not exists: ${input.absolutePath}")
    }
    if (!output.exists()) {
        output.createNewFile()
    }

    BufferedImage srcImage = ImageIO.read(input)
    int realWidth = srcImage.getWidth()
    int realHeight = srcImage.getHeight()

    // 計算目標尺寸:等比縮放,長邊不超過 length
    int width, height
    if (realWidth < length && realHeight < length) {
        // 原圖小於目標尺寸,保持原大小(不放大)
        width = realWidth
        height = realHeight
    } else if ((length * realHeight) / realWidth > length) {
        // 高度為長邊,按高度壓縮
        width = (length * realWidth) / realHeight
        height = length
    } else {
        // 寬度為長邊,按寬度壓縮
        width = length
        height = (length * realHeight) / realWidth
    }

    // 高質量縮放
    Image scaled = srcImage.getScaledInstance(width, height, Image.SCALE_SMOOTH)
    BufferedImage targetImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
    Graphics g = targetImage.getGraphics()
    g.drawImage(scaled, 0, 0, null)
    g.dispose()

    // 輸出 JPEG,品質可通過 ImageWriteParam 進一步控制
    ImageIO.write(targetImage, "jpeg", output)
}

// ========== 批量處理主程式 ==========
def dir = new File("d:/var/wormser/sample")
dir.eachFile { f ->
    def name = f.name
    println "Processing: $name"

    // 輸出命名:原名_tb.jpg(如 photo.png -> photo_tb.jpg)
    def newFileName = name.replaceAll(/^([a-zA-Z0-9_]+)\.([a-zA-Z0-9]+)$/, "\$1_tb.jpg")
    def newFile = new File(dir.absolutePath + File.separator + newFileName)
    println "Output: $newFileName"

    createThumbnail(f, newFile, 160)  // 長邊 160px
}

關鍵技術點解析

1. 智能尺寸計算邏輯

  • 不放大原則:源圖長寬均小於目標長邊時保持原尺寸,避免無意義放大失真。
  • 長邊優先:通過交叉相乘比較 (length * realHeight) / realWidth > length 判斷長邊,等價於比較 realHeight > realWidth 但避免浮點運算。
  • 整數運算:寬高計算使用整數除法,自動向下取整,符合像素離散特性。

2. 高質量縮放

  • Image.SCALE_SMOOTH:採用雙立方插值算法,比 SCALE_FAST(鄰近插值)質量顯著更好,適合照片類圖片。
  • 繪製到 BufferedImage.TYPE_INT_RGB 畫布,確保輸出為標準 24 位 RGB JPEG,兼容性最佳。

3. 靈活的命名規則

正則 /^([a-zA-Z0-9_]+)\.([a-zA-Z0-9]+)$/ 捕獲文件名主體與副檔名,替換為 \$1_tb.jpg 統一輸出 JPEG 格式,便於前端統一處理。實際專案中可擴展為:

  • 保留原格式:\$1_tb.\$2
  • 加入哈希防衝突:\$1_tb_\${System.currentTimeMillis()}.\$2
  • 多尺寸輸出:\$1_tb160.\$2、\$1_tb320.\$2

進階增強版:支援品質控制、PNG 透明、遞歸目錄

import javax.imageio.*
import java.awt.image.*
import java.awt.*
import java.io.*

def createThumbnailAdvanced(File input, File output, int maxDim, float quality = 0.85f, boolean recursive = false) {
    def processFile = { File f ->
        if (!f.isFile() || !isImageFile(f)) return
        def outName = getOutputName(f, output)
        def outFile = new File(output, outName)
        createThumbnail(f, outFile, maxDim, quality)
    }

    if (recursive) {
        input.traverse(type: FileType.FILES, processFile)
    } else {
        input.eachFileMatch(~/.*\.(jpg|jpeg|png|bmp|gif|webp)/i, processFile)
    }
}

def isImageFile(File f) {
    f.name.toLowerCase().matches(".*\\.(jpg|jpeg|png|bmp|gif|webp)")
}

def getOutputName(File src, File outDir) {
    def name = src.name
    def base = name[0..name.lastIndexOf('.')-1]
    def ext = "jpg"  // 統一輸出 jpg,或保留原 ext
    "${base}_tb.${ext}"
}

def createThumbnail(File input, File output, int maxDim, float quality) {
    BufferedImage src = ImageIO.read(input)
    int w = src.width, h = src.height
    if (w <= maxDim && h <= maxDim) {
        // 直接複製或重編碼
        ImageIO.write(src, "jpg", output)
        return
    }
    // 計算尺寸(同前)
    // ...
    BufferedImage target = new BufferedImage(width, height, hasAlpha(src) ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB)
    Graphics2D g2d = target.createGraphics()
    g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC)
    g2d.drawImage(src, 0, 0, width, height, null)
    g2d.dispose()

    // 品質控制輸出
    ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next()
    ImageWriteParam param = writer.getDefaultWriteParam()
    param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT)
    param.setCompressionQuality(quality)
    try (FileImageOutputStream fos = new FileImageOutputStream(output)) {
        writer.setOutput(fos)
        writer.write(null, new IIOImage(target, null, null), param)
    }
}

def hasAlpha(BufferedImage img) {
    img.colorModel.hasAlpha()
}

// 使用範例
createThumbnailAdvanced(new File("d:/images"), new File("d:/thumbs"), 300, 0.9f, true)

部署與運行建議

  1. 安裝 Groovy:SDKMAN `sdk install groovy` 或下載二進制包配置 GROOVY_HOME。
  2. 運行:groovy thumbnail.groovy 或打包為 groovyc 編譯後用 java -cp ... 執行。
  3. 定時任務:Linux crontab / Windows 任務計劃程式定時掃描上傳目錄生成縮略圖。
  4. 記憶體調優:大圖處理時設定 -Xmx512m 避免 OOM,Groovy 啟動腳本可透過 JAVA_OPTS 傳遞。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved