canvas 識別圖片顏色 解析圖片顏色

在線 預覽 http://jsrun.net/DjkKp/edit
github https://github.com/Taoqun/can...css

image.png
image.pnghtml

image.png
image.pnggit

image.png
image.pnggithub

image.png
image.pngcanvas

方法數組

  • getColorXY(x,y) 傳入座標點,獲取座標點的顏色值promise

  • getColors() 返回 promise 對象 解析完成以後返回圖片的顏色列表函數

屬性this

  • progress String 解析圖像時的進度 百分比spa

  • accuracy Number 解析圖像顏色時的精度

html

<body>
    <input type="file" id="file">
    <img src="" id="img">
    <p id="text"></p>
    <ul id="ul"></ul>
    <script src="./index.js"></script>
</body>

js方法

// 引入canvas_get_image_colors庫
// 實例代碼

let input = document.querySelector("#file")

input.addEventListener("change", (event) => {
    /**
     * 上傳圖片以後
     * 替換圖片
     * 執行方法
     */
    let img = document.querySelector("#img")
    let file = event.target.files[0]
    let fr = new FileReader() 

    fr.onload = (e) => {
        let n_img = new Image()
        n_img.src = e.target.result
        n_img.onload = (e) => {
            n_img.id = 'img'
            n_img.width = n_img.width
            n_img.height = n_img.height
            document.body.replaceChild(n_img, img)
            getImg()
        }
    }

    fr.readAsDataURL(file)
})

function getImg() {
    /**
     * 獲取圖片,實例化圖片
     * 執行方法
     * 解析完成,得到數組,操做回調函數
     * 
     */
    let img = document.querySelector("#img")
    let a = new getImgColor(img)
    
    // 獲取 座標 0 0 點的顏色值
    console.log(a.getColorXY(0, 0))

    a.getColors().then((arr) => {

        let ul = document.querySelector("#ul")
        let text = document.querySelector("#text")
            text.innerText = '共有' + arr.length + '個顏色';
        let str = ''

        arr.forEach((obj, index) => {
            str += `<li style="background-color:${obj['#']}">${obj['#']} - ${obj['index']}次</li>`;
        })

        ul.innerHTML = str
    })
}

canvas_get_image_colors.js庫

// 封裝函數庫
function getImgColor(img) {
    /**
     * @ param 傳入的圖片 
     * @ this.progress 解析圖片的進度 實時
     * @ this.canvas canvas元素
     * @ this.cvs context對象
     * @ this.accuracy Number 解析圖片顏色的精確度 1 - 7 數字選擇 
     *
     * 
     * @ anther taoqun <taoquns@foxmail.com>
     */

    this.canvas = document.createElement("canvas")
    this.canvas.width = img.width
    this.canvas.height = img.height
    this.cvs = this.canvas.getContext("2d")
    this.cvs.drawImage(img, 0, 0)
    this.accuracy = 5
    this.progress = ''
}
getImgColor.prototype.getColorXY = function(x, y) {

    /**
     * @param x Number x座標起點
     * @param y Number y座標起點
     * @return color Object 包含顏色的rgba #16進制顏色
     */

    let obj = this.cvs.getImageData(x, y, 1, 1)
    let arr = obj.data.toString().split(",")

    let first = parseInt(arr[0]).toString(16)
    first = first.length === 2 ? first : first + first

    let second = parseInt(arr[1]).toString(16)
    second = second.length === 2 ? second : second + second

    let third = parseInt(arr[2]).toString(16)
    third = third.length === 2 ? third : third + third

    let last = parseInt(arr.pop()) / 255
    last = last.toFixed(0)

    let color = {}
    color['rgba'] = 'rgba(' + arr.join(',') + ',' + last + ')'
    color['#'] = '#' + first + second + third
    return color
}
getImgColor.prototype.getColors = function() {

    /**
     * 避免圖片過大,阻塞卡死
     * 每加載一行像素,延遲20毫秒加載下一行
     * return Promise 
     * promise resolve 解析完成後,返回顏色的總計數組,降序排列
     * promise reject none
     */

    return (new Promise((resolve, reject) => {

        let arr = []
        let getY = (i) => {
            for(let j = 0; j < this.canvas.height; j++) {
                let obj = {}
                obj = this.getColorXY(i, j)
                obj.index = 1
                let is = true

                arr.forEach((item) => {
                    if (item['#'] === obj['#']) {
                        is = false
                        item.index += 1
                    }

                    let l = []

                    for (let i = 0; i < obj['#'].length; i++) {

                        if (item['#'].indexOf(obj['#'][i]) > -1) {
                            l.push('1')
                        }
                    }

                    let acc = (this.accuracy > 7) ? 7 : this.accuracy
                    acc = (this.accuracy < 1) ? 2 : this.accuracy
                    if (l.length > acc) {
                        is = false
                        item.index += 1
                    }
                })

                if (is) {
                    arr.push(obj)
                }
            }
        };

        let getX = (i) => {
            if (i < this.canvas.width) {

                getY(i)
                this.progress = (i / this.canvas.width * 100).toFixed(2) + '%'
                console.log(this.progress)
                setTimeout(() => {
                    getX(++i)
                }, 20)

            } else {

                this.progress = '100%'
                console.log( this.progress )

                resolve(arr.sort(function(a, b) {
                    return a.index < b.index ? 1 : (a.index > b.index ? -1 : 0)
                }))
            }
        };

        getX(0)

    }))
}

css

ul,li{
    list-style: none;
    margin: 0;
    padding: 0;
}
ul{
    margin: 20px auto;
    font-size: 0px;
}
ul li{
    display: inline-block;
    min-width: 100px;
    height: 50px;
    padding: 0 20px;
    margin: 1px;
    text-align: center;
    font-size: 15px;
    line-height: 50px;
    color: #000;
    border-radius: 4px;
    transition: all 0.3s linear 0s;
    cursor: pointer;
    border: 1px solid #e8e8e8;
}

ul li:hover{
    opacity: 0.8;
}
相關文章
相關標籤/搜索