• NodeJs 批量图片瘦身,重设尺寸和图片质量并保存到指定目录


    源代码(image-resize.js)

    /**
     * NodeJs 批量图片瘦身,重设尺寸和图片质量并保存到指定目录
     * 功能:批量图片瘦身,可指定宽度和图片质量并输出保存到指定目录
     * 使用:node image-resize.js
     * 扩展包:npm install images
     */
    
    // 安装并引用 images 模块处理图片瘦身
    const NmImages = require('images')
    // 引用 fs 文件系统模块
    const NmFs = require('fs')
    // 引用 path 路径处理模块
    const NmPath = require('path')
    
    // 配置信息
    const config = {
        // 图片格式后缀
        image_exts: ['jpg', 'png', 'gif', 'jpeg', 'webp', 'tiff'],
        // 图片大小与压缩质量配置
        quantity_config: {
            // 是否启用
            enable: true,
            // 注意:顺序必须从大到小
            values: [
                // 50 MB 以上 30
                {
                    size: 52428800,
                    quantity: 30
                },
                // 30 MB 以上 50
                {
                    size: 31457280,
                    quantity: 50
                },
                // 20 MB 以上 60
                {
                    size: 20971520,
                    quantity: 60
                },
                // 15 MB 以上 70
                {
                    size: 15728640,
                    quantity: 70
                },
                // 10 MB 以上 80
                {
                    size: 10485760,
                    quantity: 80
                },
                // 默认 80
                {
                    size: 0,
                    quantity: 80
                },
            ]
        }
    }
    
    /**
     * 批量生成缩略图到指定目录(目标目录的层级结构和来源目录保持一致)
     * @param {String} fromDir 来源目录
     * @param {String} toDir 目标目录
     * @param {Boolean} isDebug 是否调试模式。调试模式只会在控制台输出信息,不会真正操作文件
     * @param {Boolean} isSkipExists 是否跳过已存在的目标文件
     * @param {Number} width 图片宽度。最小 1080, 最大 3048
     * @param {Number} quality 图像质量
     */
    async function resizeImages(fromDir, toDir, isDebug = true, isSkipExists = true, width = 0, quality = 80) {
        if (!NmFs.existsSync(fromDir)) {
            console.log('path not exists: ', fromDir);
            return;
        }
        // 自动创建目标路径
        if (!isDebug && !NmFs.existsSync(toDir)) {
            NmFs.mkdirSync(toDir, {
                recursive: true
            });
        }
        // 自动补齐路径符
        const SEP = NmPath.sep;
        if (!fromDir.endsWith(SEP)) {
            fromDir += SEP;
        }
        if (!toDir.endsWith(SEP)) {
            toDir += SEP;
        }
        // 打开目录
        const dir = await NmFs.promises.opendir(fromDir);
        // 声明变量,优化内存
        let ext = '',
            newPath = '',
            currentPath = '',
            fromFileSize = '0 B',
            toFileSize = '0 B';
        for await (const dirent of dir) {
            // 当前路径
            currentPath = fromDir + dirent.name;
            newPath = toDir + dirent.name;
            // 处理目录
            if (dirent.isDirectory()) {
                // 如果当前路径是目录,则进入递归模式
                resizeImages(currentPath + SEP, newPath + SEP, isDebug, isSkipExists, width, quality);
                continue;
            }
            // 处理文件
            ext = NmPath.extname(dirent.name); // .jpg
            if (!ext) {
                continue;
            }
            ext = ext.substring(1).toLowerCase();
            // 过滤非图片格式的文件
            if (!config.image_exts.includes(ext)) {
                continue;
            }
            // 自动图片质量
            fromFileSize = NmFs.statSync(currentPath).size;
            if (config.quantity_config.enable) {
                for (let kv of config.quantity_config.values) {
                    if (fromFileSize > kv.size) {
                        quantity = kv.quantity;
                        break;
                    }
                }
            }
            fromFileSize = bytesFormatter(fromFileSize);
            // 重设图片尺寸并保存
            if (isDebug) {
                console.log(`[缩略图] [${fromFileSize}/${toFileSize}/Q${quantity}]`, currentPath, '=>', newPath);
                continue;
            }
            // 判断是否过滤已存在的目标文件
            if (isSkipExists && NmFs.existsSync(newPath)) {
                toFileSize = bytesFormatter(NmFs.statSync(newPath).size);
                console.log(`[已存在] [${fromFileSize}/${toFileSize}/Q${quantity}]`, currentPath, `=>`, newPath);
                continue;
            }
            // 照片瘦身
            try {
                if (width > 0) {
                    NmImages(currentPath).resize(width).save(newPath, {
                        quality: quality
                    });
                } else {
                    NmImages(currentPath).save(newPath, {
                        quality: quality
                    });
                }
                toFileSize = bytesFormatter(NmFs.statSync(newPath).size);
                console.log(`[缩略图] [${fromFileSize}/${toFileSize}/Q${quantity}]`, currentPath, '=>', newPath);
            } catch (error) {
                console.log(`[错误] [${fromFileSize}/${toFileSize}/Q${quantity}]`, currentPath, '=>', newPath);
            }
        }
    }
    
    //文件大小换算
    function bytesFormatter(bytes = 0) {
        if (bytes === 0) {
            return '0 B';
        }
        let k = 1024,
            sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
            i = Math.floor(Math.log(bytes) / Math.log(k));
        let num = bytes / Math.pow(k, i);
        // 优化:1023.999 KB 显示为 0.9xx MB
        if (num > 1000) {
            i += 1;
            num = bytes / Math.pow(k, i);
        }
        return num.toPrecision(3) + ' ' + sizes[i];
    }
    
    // 执行批量照片瘦身功能
    // 注意,会内存溢出,是image插件的问题,暂时没有解决办法,只能报错后重新运行,循环接力直到完成
    // NmImages.setGCThreshold(1024 * 1024 * 1024); // 设置内存自动回收阈值为 1GB。会出错!
    const FROM_PATH = 'F:\Downloads\Images';
    const TO_PATH = FROM_PATH + ' Lite';
    const IS_DEBUG = false;
    const IS_SKIP_EXISTS = true;
    resizeImages(FROM_PATH, TO_PATH, IS_DEBUG, IS_SKIP_EXISTS).catch(err => console.log(err))
    

    执行

    node image-resize.js
    
  • 相关阅读:
    c盘瘦身、windows解除上网限速、贴膜注意事项
    windows7导入k8s用户证书
    ubuntu报错解决和注意事项
    ubuntu默认root密码问题,第一次使用ubuntu需要设置root密码
    java程序员修炼之道
    选择器代码
    css的使用技巧资料
    移动开发的相关资料
    使用phantomjs生成网站快照
    PHP Simple HTML DOM Parser Manual-php解析DOM
  • 原文地址:https://www.cnblogs.com/sochishun/p/14289819.html
Copyright © 2020-2023  润新知