• node实现自动化图片切割压缩, 部署页面


    图片切割部分参考:https://www.cnblogs.com/gating/p/12488443.html

      其他方法: https://www.jianshu.com/p/8c08a6b23054
           https://www.cnblogs.com/zycbloger/p/6230155.html
      

    文件结构部分

      imgclip
        images   ---图片切割后的存放目录
        img         ---源图片文件夹
        node_modules  --依赖包
        static    ---存放静态html文件

          index.html
        app.js   ---静态伺服启动文件
        clip_config.js   ---切割配置
        clip_images.js  ---切割图片模块
        package.json  

     

    实现图片切割过程:

    切割图片主要依赖   canvas库

    const {
        createCanvas,
        loadImage
    } = require("canvas");

    将图片用cavas转为画板 , 然后再讲画板切割出来 , 再然后将切割出来的画板 , 转为图片

    压缩图片过程

    压缩图片主要依赖   canvas库

    var images = require("images");

    cavas模块, images模块 , npm下载不顺的话 , 可以尝试yarn 和 cnpm


    渲染页面
      主要依赖app.js 配置静态伺服
      指定端口和静态文件目录 , 监听路由
      检测文件, 判断文件, 处理文件
      动态渲染dom结构


    index.html
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
        <title>Document</title>
        <style>
            body {
                width: 960px;
                margin: 0px auto;
            }
    
            html,
            body {
                margin: 0px;
                padding: 0;
            }
    
            .cell {
                float: left;
                margin: 10px;
                position: relative;
                width: 200px;
                height: 230px;
                cursor: pointer;
            }
    
            .cell span,
            .cell img {
                position: absolute;
            }
    
            .cell img {
                width: 200px;
                height: 200px;
                top: 0;
            }
    
            .cell span {
                width: 200px;
                height: 30px;
                line-height: 30px;
                top: 200px;
                left: 0px;
                text-align: center;
                font-size: 18px;
            }
    
            img {
                display: block;
            }
    
            img {
                display: block;
                border: 0;
            }
    
            .warp {
                width: 100%;
                overflow: hidden;
            }
    
            .warp img {
                position: relative;
                top: 0;
                left: 50%;
                transform: translateX(-50%);
            }
        </style>
    </head>
    
    <body>
        <div class="warp">

    app.js

    // 引入内置模块
    var http = require('http');
    var fs = require('fs');
    var url = require('url');
    var path = require('path');
    var querystring = require('querystring');
    const {
        resolve
    } = require('path');
    //导入配置
    const {
        entry,
        output,
        imgPrefix,
        imgUrl
    } = require('./clip_config.js');
    // 配置路径
    const entryPath = __dirname + "/" + entry
    const outputPath = __dirname + "/" + output
    
    // 引入自定义模块
    var clip_images = require('./clip_images.js');
    
    // 创建端口
    var port = 3000;
    // 创建服务
    var server = http.createServer();
    
    console.log(imgUrl)
    // 监听服务
    server.on("request", function (req, res) {
        if (req.url !== "/favicon.ico") {
            var urlObj = url.parse(req.url, true);
            var pathname = urlObj.pathname;
            if (pathname == "/" && req.method == "GET") {
                resHead(".html")
                res.end("<h1>请进入images目录</h1>");
                return;
            }
            if (pathname == "/images" && req.method == "GET") {
                let saveImageName = ''; //原名
                let currentImageName = '';
                fs.readdir(entryPath, function (err, files) {
                    if (files.length) {
                        files.forEach((file, index) => {
                            saveImageName = entryPath + "/" + file;
                            currentImageName = entryPath + "/aaa" + getExtname(file);
                            fs.rename(saveImageName, currentImageName, (err) => {
                                if (err) throw err;
                                clip_images("aaa" + getExtname(file))
                                fs.rename(currentImageName, saveImageName, (err) => {
                                    if (err) throw err;
                                })
                            })
                        })
                    } else {
                        throw err;
                    }
                })
    
                if (isDir(outputPath)) {
                    rDir(outputPath);
                } else {
    
                }
    
                //配置静态图片
            } else if (pathname == "/static/img/file.jpg" && req.method == "GET") {
                fs.readFile("./static/img/file.jpg", function (err, data) {
                    resHead(".jpg");
                    res.end(data);
                })
            } else if (pathname == "/static/img/css.jpg" && req.method == "GET") {
                fs.readFile("./static/img/css.jpg", function (err, data) {
                    resHead(".jpg");
                    res.end(data);
                })
            } else if (pathname == "/static/img/html.jpg" && req.method == "GET") {
                fs.readFile("./static/img/html.jpg", function (err, data) {
                    resHead(".jpg");
                    res.end(data);
                })
            } else if (pathname == "/static/img/js.jpg" && req.method == "GET") {
                fs.readFile("./static/img/js.jpg", function (err, data) {
                    resHead(".jpg");
                    res.end(data);
                })
            } else if (pathname == "/static/img/json.jpg" && req.method == "GET") {
                fs.readFile("./static/img/json.jpg", function (err, data) {
                    resHead(".jpg");
                    res.end(data);
                })
            } else if (pathname == "/static/img/txt.jpg" && req.method == "GET") {
                fs.readFile("./static/img/txt.jpg", function (err, data) {
                    resHead(".jpg");
                    res.end(data);
                })
            }
            fs.readFile("." + pathname, function (err, data) {
                fs.stat("." + pathname, function (err, stats) {
                    if (err) {
                        resHead(".html");
                        res.end("<h1>No file or No dir");
                        return;
                    }
                    if (stats.isDirectory()) {
                        rDir("." + pathname)
                    } else {
                        var mine = getExtname(pathname);
                        resHead(mine);
                        res.end(data)
                    }
                })
            });
    
            function isDir(p) { //判断是否是文件夹,如果是文件夹返回true,如果不是返回false
                var stats = fs.statSync(p);
                var flag = stats.isDirectory();
                return flag;
            }
    
            function rFile(p) { //如果不是文件夹,读取对应的文件,并展示
                fs.readFile(p, "utf8", function (err, data) {
                    var mine = getExtname(pathname);
                    resHead(mine);
                    res.end(data);
                })
            }
    
            function compareFiles(a, b) {
                console.log(a, b)
                return 1
            }
    
            function rDir(p) { //如果是文件夹,读取对应的文件夹,并展示
                var str = "";
                fs.readdir(p, function (err, files) {
                    if (files.length) { //files获取出来的
                        var data = fs.readFileSync("./static/index.html", "utf8");
                        str += data;
                        //排序
                        var lastNumRes = /d{1,3}.(png|jpg|gif|jpeg|webp)$/g;
                        var filesArr = [];
                        files.forEach((file, i) => {
                            filesArr[i] = file.replace(lastNumRes, (i + 1) + getExtname(file));
                        })
                        //渲染
                        for (var i = 0; i < filesArr.length; i++) {
                            var extname = getExtname(filesArr[i]); //后缀
                            str += setHtml(extname, filesArr[i], req.url); //渲染函数
                        }
                        str += `
                            <script>
                                function fun(a,b){
                                    window.location.href = a + "/" + b;
                                }
                            </script>
                            </body></html>`;
                        resHead(".html");
                        res.end(str);
                    } else {
                        resHead(".html");
                        str += "<h1>This folder has no content</h1>";
                        res.end(str);
                    }
                })
            }
    
            function getExtname(p) { //获取文件的后缀名
                var ext = path.extname(p);
                return ext;
            }
    
            function setHtml(extname, p, q) { //渲染HTML模板
                var extname = extname.slice(1)
                if (extname == "html") {
                    return `<div class="cell" onclick=fun('${req.url}','${p}')>
                        <img src="/static/img/${extname}.jpg" alt="">
                        <span>${p}</span>
                    </div>`
                } else if (extname == "css") {
                    return `<div class="cell" onclick=fun('${req.url}','${p}')>
                        <img src="/static/img/${extname}.jpg" alt="">
                        <span>${p}</span>
                    </div>`
                } else if (extname == "js") {
                    return `<div class="cell" onclick=fun('${req.url}','${p}')>
                        <img src="/static/img/${extname}.jpg" alt="">
                        <span>${p}</span>
                    </div>`
                } else if (extname == "json") {
                    return `<div class="cell" onclick=fun('${req.url}','${p}')>
                        <img src="/static/img/${extname}.jpg" alt="">
                        <span>${p}</span>
                    </div>`
                } else if (extname == "txt") {
                    return `<div class="cell" onclick=fun('${req.url}','${p}')>
                        <img src="/static/img/${extname}.jpg" alt="">
                        <span>${p}</span>
                    </div>`
                } else if (extname == "png") {
                    return `<img src="${imgUrl?imgUrl:q}/${p}" alt="">`
                } else if (extname == "jpg") {
                    return `<img src="${imgUrl?imgUrl:q}/${p}" alt="">`
                } else if (extname == ".jpeg") {
                    return `<img src="${imgUrl?imgUrl:q}/${p}" alt="">`
                } else if (extname == ".png") {
                    return `<img src="${imgUrl?imgUrl:q}/${p}" alt="">`
                } else if (extname == "") {
                    return `<div class="cell" onclick=fun('${req.url}','${p}')>
                        <img src="/static/img/file.jpg" alt="">
                        <span>${p}</span>
                    </div>`
                } else {
                    return `<h1>不支持该文件类型</h1>`
                }
            }
    
            function resHead(p) { //根据文件类型设置请求头
                if (p == "") {
                    return res.writeHead(200, {
                        'Content-Type': 'image/jpg'
                    });
                } else if (p == ".css") {
                    return res.writeHead(200, {
                        'Content-Type': 'text/css; charset=utf-8'
                    });
                } else if (p == ".js") {
                    return res.writeHead(200, {
                        'Content-Type': 'text/javascript; charset=utf-8'
                    });
                } else if (p == ".html") {
                    return res.writeHead(200, {
                        'Content-Type': 'text/html; charset=utf-8'
                    });
                } else if (p == ".json") {
                    return res.writeHead(200, {
                        'Content-Type': 'text/json; charset=utf-8'
                    });
                } else if (p == ".txt") {
                    return res.writeHead(200, {
                        'Content-Type': 'text/plain; charset=utf-8'
                    });
                } else if (p == ".png") {
                    return res.writeHead(200, {
                        'Content-Type': 'image/png'
                    });
                } else if (p == ".jpg") {
                    return res.writeHead(200, {
                        'Content-Type': 'image/jpg'
                    });
                } else if (p == ".jpeg") {
                    return res.writeHead(200, {
                        'Content-Type': 'image/jpg'
                    });
                } else if (p == ".gif") {
                    return res.writeHead(200, {
                        'Content-Type': 'image/gif'
                    });
                }
            }
        }
    })
    
    // 监听端口
    server.listen(port);
    console.log("server running in 127.0.0.1:" + port);

    clip_images.js

    // 创建写入流
    const {
        createWriteStream
    } = require("fs");
    const fs = require('fs');
    const path = require('path')
    var images = require("images");
    // 导入canvas库,用于裁剪图片
    const {
        createCanvas,
        loadImage
    } = require("canvas");
    //导入配置
    let {
        entry,
        output,
        imgPrefix,
        imgHeight
    } = require('./clip_config.js');
    
    // 配置路径
    const entryPath = __dirname + "/" + entry
    const outputPath = __dirname + "/" + output
    
    
    
    module.exports = async function clip_images(imgName) {
        //删除输出路径下的所有文件
        function deleteFolder(path) {
            let files = [];
            if (fs.existsSync(path)) {
                files = fs.readdirSync(path);
                files.forEach(function (file, index) {
                    let curPath = path + "/" + file;
                    if (fs.statSync(curPath).isDirectory()) {
                        deleteFolder(curPath);
                    } else {
                        fs.unlinkSync(curPath);
                    }
                });
                //  fs.rmdirSync(path);
            }
        }
        deleteFolder(outputPath)
        // 加载图片
        const image = await loadImage(entryPath + '/' + imgName);
        // 获取图片宽高
        const {
            width,
            height
        } = image;
        // 创建等宽登高的canvas
        const mainCanvas = createCanvas(width, height);
        // 获取canvas上下文
        const ctx = mainCanvas.getContext("2d");
        // 绘图
        ctx.drawImage(image, 0, 0);
        // oneHeight 获取一份的高度,   canvasX: canvas中的 X , 从哪里开始画
        let canvasX, oneHeight;
        canvasX = oneHeight = imgHeight;
        // 明确我们需要垂直分割成几份
        const num = (height / oneHeight) > Math.floor(height / oneHeight) ? //总张数
            Math.floor(height / oneHeight) + 1 : height / oneHeight;
        const lastHeight = (1 + (height / oneHeight - num)) * oneHeight; //最后一张的高度
        let imgUrl = '';
    
        for (let i = 0; i < num; i++) {
            if (i == (num - 1)) {
                oneHeight = lastHeight;
            }
            // 创建一份裁剪的canvas
            let clipCanvas = createCanvas(width, oneHeight);
            // 获取canvas上下文
            const clipCtx = clipCanvas.getContext("2d");
            // 通过 clipCtx 裁剪 mainCanvas
            clipCtx.drawImage(
                mainCanvas,
                0,
                canvasX * i,
                width,
                oneHeight,
                0,
                0,
                width,
                oneHeight
            );
    
            imgUrl = outputPath + `/${imgPrefix+(i + 1)}` + path.extname(imgName);
            fs.writeFileSync(imgUrl, clipCanvas.toBuffer(), 'binary', function (err) {
    
            })
            images(imgUrl)
                .save(imgUrl, {
                    quality: 95 //保存图片到文件,图片质量为50
                });
            // 主动释放内存
            clipCanvas = null;
        }
    };

    clip_config.js

    const ConfigObj = {
        imgHeight: 350, //裁剪图片的高度
        entry: "img", //输入路径
        output: "images", //输出路径
        imgPrefix: "aaa_", //输出图片名前缀
        // imgUrl: "https://img.hbhcdn.com/zhuanti/20841"  //配置图片src
    }
    
    module.exports = ConfigObj;

    package.json

    archiver   压缩文件库
    canvas库,用于裁剪图片

    compressing  压缩与解压

    images  图片处理

    unzip  解压zip

    bcryptjs 加密

    {
      "name": "clip",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo "Error: no test specified" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "dependencies": {
        "archiver": "^5.2.0",
        "bcryptjs": "^2.4.3",
        "canvas": "^2.6.1",
        "compressing": "^1.5.1",
        "images": "^3.2.3",
        "unzip": "^0.1.11"
      }
    }

     ...

      

  • 相关阅读:
    [LeetCode] Best Time to Buy and Sell Stock III
    [LeetCode] Implement strStr()
    [LeetCode] Wildcard Matching
    [LeetCode] Gray Code
    [LeetCode] Divide Two Integers
    [LeetCode] Flatten Binary Tree to Linked List
    [LeetCode] Binary Tree Maximum Path Sum
    [TopCoder][SRM] SRM 562 DIV 2
    推荐博客文章
    检测两点所确定直线上的像素坐标
  • 原文地址:https://www.cnblogs.com/wxyblog/p/14313749.html
Copyright © 2020-2023  润新知