// // 八叉树算法// (function () {//     var OctreeNode = function () {//         this.isLeaf = false;//         this.pixelCount = 0;//         this.red = 0;//         this.green = 0;//         this.blue = 0;//         this.children = [null, null, null, null, null, null, null, null];//         this.next = null;//     }//     var root = null,//         leafNum = 0,//         colorMap = null,//         reducible = null;//     function createNode(index, level) {//         var node = new OctreeNode();//         if (level === 7) {//             node.isLeaf = true;//             leafNum++;//         } else {//             // 将其丢到第 level 层的 reducible 链表中//             node.next = reducible[level];//             reducible[level] = node;//         }//         return node;//     }//     function addColor(node, color, level) {//         if (node.isLeaf) {//             node.pixelCount += 1;//             node.red += color.r;//             node.green += color.g;//             node.bllue += color.b;//         }//         else {//             var str = "";//             var r = color.r.toString(2);//             var g = color.g.toString(2);//             var b = color.b.toString(2);//             while (r.length < 8) r = '0' + r;//             while (g.length < 8) g = '0' + g;//             while (b.length < 8) b = '0' + b;//             str += r[level];//             str += g[level];//             str += b[level];//             var index = parseInt(str, 2);//             if (null === node.children[index]) {//                 node.children[index] = createNode(index, level + 1);//             }//             if (undefined === node.children[index]) {//                 console.log(index, level, color.r.toString(2));//             }//             addColor(node.children[index], color, level + 1);//         }//     }//     function reduceTree() {//         // 找到最深层次的并且有可合并节点的链表//         var level = 6;//         while (null == reducible[level]) {//             level -= 1;//         }//         // 取出链表头并将其从链表中移除//         var node = reducible[level];//         reducible[level] = node.next;//         // 合并子节点//         var r = 0;//         var g = 0;//         var b = 0;//         var count = 0;//         for (var i = 0; i < 8; i++) {//             if (null === node.children[i]) continue;//             r += node.children[i].red;//             g += node.children[i].green;//             b += node.children[i].blue;//             count += node.children[i].pixelCount;//             leafNum--;//         }//         // 赋值//         node.isLeaf = true;//         node.red = r;//         node.green = g;//         node.blue = b;//         node.pixelCount = count;//         leafNum++;//     }//     function buidOctree(imageData, maxColors) {//         var total = imageData.length / 4;//         for (var i = 0; i < total; i++) {//             // 添加颜色//             addColor(root, {//                 r: imageData[i * 4],//                 g: imageData[i * 4 + 1],//                 b: imageData[i * 4 + 2]//             }, 0);//             // 合并叶子节点//             while (leafNum > maxColors) reduceTree();//         }//     }//     function colorsStats(node, object) {//         if (node.isLeaf) {//             var r = parseInt(node.red / node.pixelCount);//             var g = parseInt(node.green / node.pixelCount);//             var b = parseInt(node.blue / node.pixelCount);//             var color = r + ',' + g + ',' + b;//             if (object[color]) object[color] += node.pixelCount;//             else object[color] = node.pixelCount;//             return;//         }//         for (var i = 0; i < 8; i++) {//             if (null !== node.children[i]) {//                 colorsStats(node.children[i], object);//             }//         }//     }//     window.themeColor = function (img, callback) {//         var canvas = document.createElement('canvas'),//             ctx = canvas.getContext('2d'),//             width = 0,//             height = 0,//             imageData = null,//             length = 0,//             blockSize = 1;//         width = canvas.width = img.width;//         height = canvas.height = img.height;//         ctx.drawImage(img, 0, 0, width, height);//         imageData = ctx.getImageData(0, 0, width, height).data;//         root = new OctreeNode();//         colorMap = {};//         reducible = {};//         leafNum = 0;//         buidOctree(imageData, 8)//         colorsStats(root, colorMap)//         var arr = [];//         for (var key in colorMap) {//             arr.push(key);//         }//         arr.sort(function (a, b) {//             return colorMap[a] - colorMap[b];//         })//         arr.forEach(function (item, index) {//             arr[index] = item.split(',')//         })//         callback(arr)//     }// })()// 中位切分法(function () {    /**     * 颜色盒子类     *     * @param {Array} colorRange    [[rMin, rMax],[gMin, gMax], [bMin, bMax]] 颜色范围     * @param {any} total   像素总数, imageData / 4     * @param {any} data    像素数据集合     */    function ColorBox(colorRange, total, data) {        this.colorRange = colorRange;        this.total = total;        this.data = data;        this.volume = (colorRange[0][1] - colorRange[0][0]) * (colorRange[1][1] - colorRange[1][0]) * (colorRange[2][1] - colorRange[2][0]);        this.rank = this.total * (this.volume);    }    ColorBox.prototype.getColor = function () {        var total = this.total;        var data = this.data;        var redCount = 0,            greenCount = 0,            blueCount = 0;        for (var i = 0; i < total; i++) {            redCount += data[i * 4];            greenCount += data[i * 4 + 1];            blueCount += data[i * 4 + 2];        }        return [parseInt(redCount / total), parseInt(greenCount / total), parseInt(blueCount / total)];    }    // 获取切割边    function getCutSide(colorRange) {   // r:0,g:1,b:2        var arr = [];        for (var i = 0; i < 3; i++) {            arr.push(colorRange[i][1] - colorRange[i][0]);        }        return arr.indexOf(Math.max(arr[0], arr[1], arr[2]));    }    // 切割颜色范围    function cutRange(colorRange, colorSide, cutValue) {        var arr1 = [];        var arr2 = [];        colorRange.forEach(function (item) {            arr1.push(item.slice());            arr2.push(item.slice());        })        arr1[colorSide][1] = cutValue;        arr2[colorSide][0] = cutValue;        return [arr1, arr2];    }    // 找到出现次数为中位数的颜色    function getMedianColor(colorCountMap, total) {        var arr = [];        for (var key in colorCountMap) {            arr.push({                color: parseInt(key),                count: colorCountMap[key]            })        }        var sortArr = __quickSort(arr);        var medianCount = 0;        var medianColor = 0;        var medianIndex = Math.floor(sortArr.length / 2)        for (var i = 0; i <= medianIndex; i++) {            medianCount += sortArr[i].count;        }        return {            color: parseInt(sortArr[medianIndex].color),            count: medianCount        }        // 另一种切割颜色判断方法,根据数量和差值的乘积进行判断,自己试验后发现效果不如中位数方法,但是少了排序,性能应该有所提高        // var count = 0;        // var colorMin = arr[0].color;        // var colorMax = arr[arr.length - 1].color        // for (var i = 0; i < arr.length; i++) {        //     count += arr[i].count;        //     var item = arr[i];        //     if (count * (item.color - colorMin) > (total - count) * (colorMax - item.color)) {        //         return {        //             color: item.color,        //             count: count        //         }        //     }        // }        return {            color: colorMax,            count: count        }        function __quickSort(arr) {            if (arr.length <= 1) {                return arr;            }            var pivotIndex = Math.floor(arr.length / 2),                pivot = arr.splice(pivotIndex, 1)[0];            var left = [],                right = [];            for (var i = 0; i < arr.length; i++) {                if (arr[i].count <= pivot.count) {                    left.push(arr[i]);                }                else {                    right.push(arr[i]);                }            }            return __quickSort(left).concat([pivot], __quickSort(right));        }    }    // 切割颜色盒子    function cutBox(colorBox) {        var colorRange = colorBox.colorRange,            cutSide = getCutSide(colorRange),            colorCountMap = {},            total = colorBox.total,            data = colorBox.data;        // 统计出各个值的数量        for (var i = 0; i < total; i++) {            var color = data[i * 4 + cutSide];            if (colorCountMap[color]) {                colorCountMap[color] += 1;            }            else {                colorCountMap[color] = 1;            }        }        var medianColor = getMedianColor(colorCountMap, total);        var cutValue = medianColor.color;        var cutCount = medianColor.count;        var newRange = cutRange(colorRange, cutSide, cutValue);        var box1 = new ColorBox(newRange[0], cutCount, data.slice(0, cutCount * 4)),            box2 = new ColorBox(newRange[1], total - cutCount, data.slice(cutCount * 4))        return [box1, box2];    }    // 队列切割    function queueCut(queue, num) {        while (queue.length < num) {            queue.sort(function (a, b) {                return a.rank - b.rank            });            var colorBox = queue.pop();            var result = cutBox(colorBox);            queue = queue.concat(result);        }        return queue.slice(0, 8)    }    function themeColor(img, callback) {        var canvas = document.createElement('canvas'),            ctx = canvas.getContext('2d'),            width = 0,            height = 0,            imageData = null,            length = 0,            blockSize = 1,            cubeArr = [];        width = canvas.width = img.width;        height = canvas.height = img.height;        ctx.drawImage(img, 0, 0, width, height);        imageData = ctx.getImageData(0, 0, width, height).data;        var total = imageData.length / 4;        var rMin = 255,            rMax = 0,            gMin = 255,            gMax = 0,            bMin = 255,            bMax = 0;        // 获取范围        for (var i = 0; i < total; i++) {            var red = imageData[i * 4],                green = imageData[i * 4 + 1],                blue = imageData[i * 4 + 2];            if (red < rMin) {                rMin = red;            }            if (red > rMax) {                rMax = red;            }            if (green < gMin) {                gMin = green;            }            if (green > gMax) {                gMax = green;            }            if (blue < bMin) {                bMin = blue;            }            if (blue > bMax) {                bMax = blue;            }        }        var colorRange = [[rMin, rMax], [gMin, gMax], [bMin, bMax]];        var colorBox = new ColorBox(colorRange, total, imageData);        var colorBoxArr = queueCut([colorBox], 8);        var colorArr = [];        for (var j = 0; j < colorBoxArr.length; j++) {            colorBoxArr[j].total && colorArr.push(colorBoxArr[j].getColor())        }        callback(colorArr);    }    window.themeColor = themeColor})()