js realizes gif picture to dynamic character painting

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <script type="text/javascript" src="./libgif.js"></script>
        <script>
            // let img = new Image();// store image information
            let canvas;// canvas instance
            let ctx;// brush
            let logo;// generated character painting
            let flag = 0;// load complete flag
            const IMAGE_SIZE = 200;// generate image size
            let imgList = [];
            let logoList = [];
            // load the canvas
            window.onload = () => {
                canvas = document. getElementById("canvas");
                ctx = canvas. getContext("2d");
            };
 
            // convert
            function toImg(img) {
                if (flag) alert("The image has not been loaded");
                console.log('Loading')
                // Clear character drawing
                logo = "";
                // Record the ratio first, if it is wide, then zoom the width first, and then use the ratio to calculate the length, and vice versa, here is to ensure that it does not exceed the set scale
                let rate = img. width / img. height;
                if (rate > 1) {
                    img.style.width = IMAGE_SIZE + 'px';
                    img.style.height = IMAGE_SIZE / rate + 'px';
                    img.width = IMAGE_SIZE;
                    img.height = IMAGE_SIZE / rate;
                } else {
                    img.style.height = IMAGE_SIZE + 'px';
                    img.style.width = IMAGE_SIZE * rate + 'px';
                    img.height = IMAGE_SIZE;
                    img.width = IMAGE_SIZE * rate;
                }
                
                ctx. clearRect(0, 0, canvas. width, canvas. height)
                // draw the image on the canvas
                ctx. drawImage(img, 0, 0, img. width, img. height);
 
                // Get pixel information from canvas
                let imgData;
                try {
                    imgData = ctx.getImageData(0, 0, img.width, img.height);
                } catch {
                    alert("The picture failed to load, please re-select the picture or refresh the page.");
                }
                
                // read color and scale
                let scale = parseInt(document. getElementById("thisSize"). value);
                let color = document.getElementById("thisColor").value !== "false";
                // Adjust the size of the characters, and adjust the size here to pursue higher precision
                let size = 8 - scale;
                // set zoom zoom
                document.querySelector("#rightDiv").style.zoom = size / 6;
 
                // Generate body, read characters one by one
                for (let i = 0; i < img. height; i = i + size) {
                    for (let j = 0; j < img. width; j = j + size) {
                        const curPoint = (i * img.width + j) * 4; // ×4 is because 1 is r, 2 is g, 3 is b, 4 is a, four are a set of rgba values
                        const [r, g, b] = imgData. data. slice(curPoint, curPoint + 3);
 
                        const gray = r * 0.3 + g * 0.6 + b * 0.1; // Calculate the gray value
                        const thisColor = `rgba(${r},${g},${b})`; // Save pixel rgb value
                        color ? toText(gray, thisColor) : toText(gray); // If there is a color, the rgb value will be converted, if there is no color, it will not be converted
                    }
                    logo + = "</br>";
                }
                logoList. push(logo);
                // document.getElementById("rightDiv").innerHTML = logo; // fill string to html
            }
 
            // read the image
            function getImg() {
                let file = document.getElementById("upButton").files[0];
                imgList = []
                if (/(image\/gif)/.test(file.type)) {
                       pre_load_gif(file)
                        return;
                }
                addImgList(file)
            }

            function addImgList(file){
                let img = new Image()
                flag ++ ;
                var reader = new FileReader();
                reader.readAsDataURL(file);
                reader.onload = function () {
                    img.src = reader.result;
                    imgList. push(img)
                    flag--;
                    if(!flag){
                        alert('loading complete')
                    }
                };
            }
 
            // Convert characters according to grayscale, add color
            function toText(g, thisColor) {
                if (thisColor) logo + = `<span style='color:${thisColor}'>`;
 
                if (g <= 40) logo + = "?";
                else if (g > 40 & amp; & amp; g <= 80) logo + = "》";
                else if (g > 80 & amp; & amp; g <= 120) logo + = "!";
                else if (g > 120 & amp; & amp; g <= 160) logo + = ":";
                else if (g > 160 & amp; & amp; g <= 200) logo + = "~";
                else if (g > 200 & amp; & amp; g <= 240) logo + = ";";
                else logo + = ".";
 
                if (thisColor) logo + = "</span>";
            }

            function pre_load_gif(gif_source) {
                const gifImg = document. createElement('img');
                // The gif library needs the img tag to configure the following two attributes
                gifImg.setAttribute('rel:animated_src', URL.createObjectURL(gif_source))
                gifImg.setAttribute('rel:auto_play', '0')
                // Create a new gif instance
                var rub = new SuperGif({ gif: gifImg } );
                rub.load(() => {
                    for (let i=1; i <= rub. get_length(); i ++ ) {
                        // traverse each frame of the gif instance
                        rub. move_to(i);
                        // Convert the canvas of each frame into a file object
                        let cur_file = convertCanvasToImage(rub.get_canvas(), gif_source.name.replace('.gif', '') + `-${i}`)
                        // imgList. push({
                        // file_name: cur_file.name,
                        // url: URL.createObjectURL(cur_file),
                        // file: cur_file,
                        // })
                        addImgList(cur_file)
                    }
                });
            }

            // implement
            let timer;
            function start(){
                if (flag){
                    alert("The picture has not been loaded yet");
                    return
                }
                if(timer){
                    clearInterval(timer)
                }
                logoList=[]
                imgList.forEach((item)=>{
                    toImg(item)
                })
                let i = 0;
                if(logoList. length){
                    if(logoList. length > 1){
                       timer = setInterval(()=>{
                            document.getElementById("rightDiv").innerHTML = logoList[i];
                            i = (i + 1)%logoList.length
                        }, 100)
                    }else{
                        document.getElementById("rightDiv").innerHTML = logoList[i];
                    }
                    
                }else{
                    alert('Please select the file first')
                }
                
            }
            function dataURLtoFile(dataurl, filename) {
                const arr = dataurl. split(',');
                const mime = arr[0].match(/:(.*?);/)[1];
                const bstr = atob(arr[1]);
                var n = bstr. length;
                const u8arr = new Uint8Array(n);
                while (n--) {
                    u8arr[n] = bstr. charCodeAt(n);
                }
                return new File([u8arr], filename, {type:mime});
            }
            function convertCanvasToImage(canvas, filename) {
                return dataURLtoFile(canvas.toDataURL('image/png'), filename);
            }
        </script>
        <title>Image to character</title>
    </head>
 
    <body>
        <!-- Image upload -->
        <form id="uf">
            <input type="file" name="file" id="upButton" onchange="getImg()" />
        </form>
 
        <!-- Select character drawing size -->
        Please enter character drawing resolution:
        <select id="thisSize">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
            <option value="4">4</option>
            <option value="5">5</option>
            <option value="7">7</option>
        </select>
 
        <!-- select color -->
        Whether to use color:
        <select id="thisColor">
            <option value="true">Yes</option>
            <option value="false">No</option>
        </select>
 
        <!-- Execute button -->
        <button onclick="start()">Start execution</button>
 
        <!-- Auxiliary canvas, set to hidden -->
        <div id="leftDiv">
            <canvas id="canvas" width="600" height="600" style="display: none;">Canvas</canvas>
        </div>
 
        <!-- build location -->
        <div id="rightDiv" style="font-family: 'Consolas'; line-height: 0.9;"></div>
    </body>
</html>

The libgif used is downloaded here

refer to