javascript एक छवि पर रखा जाने वाला सबसे अच्छा अग्रभूमि रंग प्रोग्राममैटिक रूप से निर्धारित करते हैं




node.js colors (3)

प्रमुख रंग ढूँढना

प्रदान किए गए स्निपेट दिखाता है कि कैसे एक प्रमुख रंग खोजने के लिए। यह छवि को अपने ह्यू, संतृप्ति और ल्यूमिनेंस घटकों में तोड़कर काम करता है।

छवि में कमी

प्रक्रिया को गति देने के लिए छवि को एक छोटी छवि से कम किया जाता है (इस मामले में 128 पिक्सेल 128)। कमी की प्रक्रिया के भाग में छवि के बाहर के कुछ पिक्सल भी ट्रिम होते हैं।

const IMAGE_WORK_SIZE = 128;
const ICOUNT = IMAGE_WORK_SIZE * IMAGE_WORK_SIZE;
if(event.type === "load"){
    rImage = imageTools.createImage(IMAGE_WORK_SIZE, IMAGE_WORK_SIZE);  // reducing image
    c = rImage.ctx;
    // This is where you can crop the image. In this example I only look at the center of the image
    c.drawImage(this,-16,-16,IMAGE_WORK_SIZE + 32, IMAGE_WORK_SIZE + 32); // reduce image size

मतलब luminance खोजें

कम होने के बाद मैं पिक्सल को एचएसएल मूल्यों में परिवर्तित करने और मतलब ल्यूमिनेंस प्राप्त करने में स्कैन करता हूं।

ध्यान दें कि luminance एक लघुगणक पैमाने पर है, इसलिए इसका मतलब यह है कि गिनती से विभाजित वर्गों के योग का वर्गमूल है।

pixels = imageTools.getImageData(rImage).data;
l = 0;
for(i = 0; i < pixels.length; i += 4){ 
    hsl = imageTools.rgb2hsl(pixels[i],pixels[i + 1],pixels[i + 2]);
    l += hsl.l * hsl.l;
}
l = Math.sqrt(l/ICOUNT);

चमक और संतृप्ति रेंज के लिए ह्यू हिस्टोग्राम

कोड संतृप्ति और luminance विस्तार की एक सीमा में प्रमुख रंग पा सकते हैं। उदाहरण में मैं केवल एक हद तक उपयोग करता हूं, लेकिन आप जितना चाहें उतने उपयोग कर सकते हैं। केवल पिक्सेल जो लम (लुमिनेन्स) के अंदर होते हैं और शनि (संतृप्ति) श्रेणी का उपयोग किया जाता है मैं पिक्सेल पास के लिए रंग का हिस्टोग्राम रिकॉर्ड करता हूं

रंग सीमाओं का उदाहरण (इनमें से एक)

hues = [{  // lum and sat have extent 0-100. high test is no inclusive hence high = 101 if you want the full range
        lum : {
            low :20,    // low limit lum >= this.lum.low
            high : 60,  // high limit lum < this.lum.high
            tot : 0,    // sum of lum values 
        },
        sat : { // all saturations from 0 to 100
            low : 0,
            high : 101,
            tot : 0, // sum of sat
        },
        count : 0, // count of pixels that passed
        histo : new Uint16Array(360), // hue histogram
    }]

उदाहरण के तौर पर मैं ल्यूमेंस का उपयोग स्वत: लैम रेंज सेट करने के लिए करता हूं।

hues[0].lum.low = l - 30;
hues[0].lum.high = l + 30;

एक बार सीमा निर्धारित की जाती है, तो मुझे प्रत्येक श्रेणी के लिए रंग का हिस्टोग्राम मिलता है (इस मामले में एक)

for(i = 0; i < pixels.length; i += 4){ 
    hsl = imageTools.rgb2hsl(pixels[i],pixels[i + 1],pixels[i + 2]);
    for(j = 0; j < hues.length; j ++){
        hr = hues[j]; // hue range
        if(hsl.l >= hr.lum.low && hsl.l < hr.lum.high){
            if(hsl.s >= hr.sat.low && hsl.s < hr.sat.high){
                hr.histo[hsl.h] += 1;
                hr.count += 1;
                hr.lum.tot += hsl.l * hsl.l;
                hr.sat.tot += hsl.s;
            }
        }
    }
}

ह्यू हिस्टोग्राम से वेटेड अर्थ आर्ट

फिर हिस्टोग्राम का उपयोग करके मुझे रेंज के लिए भारित माध्य रंग मिल जाएगा

// get weighted hue for image
// just to simplify code hue 0 and 1 (reds) can combine
for(j = 0; j < hues.length; j += 1){
    hr = hues[j];
    wHue = 0;
    hueCount = 0;
    hr.histo[1] += hr.histo[0];
    for(i = 1; i < 360; i ++){
        wHue += (i) * hr.histo[i];
        hueCount += hr.histo[i];
    }
    h = Math.floor(wHue / hueCount);
    s = Math.floor(hr.sat.tot / hr.count);
    l = Math.floor(Math.sqrt(hr.lum.tot / hr.count));
    hr.rgb = imageTools.hsl2rgb(h,s,l);
    hr.rgba = imageTools.hex2RGBA(imageTools.rgba2Hex4(hr.rgb));
}

और वह इसके बारे में है बाकी सिर्फ प्रदर्शन और सामान है उपरोक्त कोड को छवि टोल इंटरफ़ेस (प्रदान) की आवश्यकता होती है, जिसमें चित्रों को छेड़छाड़ करने के लिए उपकरण हैं I

बदसूरत पूरक

पाया रंग / एस के साथ आप क्या करते हैं आप पर निर्भर है यदि आप चाहते हैं कि पूरक रंग सिर्फ आरजीबी को imageTools.rgb2hsl परिवर्तित करें और 180 डिग्री को घुमाने के लिए, फिर वापस आरजीबी में परिवर्तित करें।

var hsl = imageTools.rgb2hsl(rgb.r, rgb.g, rgb.b);
hsl.h += 180;
var complementRgb = imageTools.rgb2hsl(hsl.h, hsl.s, hsl.l);

व्यक्तिगत रूप से केवल कुछ रंग अपने पूरक के साथ अच्छी तरह से काम करते हैं। फूस को जोड़ने से जोखिम भरा होता है, कोड के माध्यम से यह सिर्फ पागल होता है। छवि में रंगों के साथ छड़ी यदि आप उच्चारण रंग ढूंढना चाहते हैं तो लैम को कम करें और सीट रेंज करें प्रत्येक श्रेणी में पाए गए पिक्सेल की संख्या की गणना होगी, जो संबंधित हिस्टोग्राम में रंगों का उपयोग करके पिक्सल की सीमा का पता लगाएगा।

डेमो "पक्षियों की सीमा"

डेमो को मध्य ल्यूमिनेंस के चारों ओर प्रमुख रंग मिल जाता है और उस रंग का उपयोग करता है जो कि सीमा बनाने के लिए संतृप्ति और ल्यूमिनेंस का मतलब है।

डेमो को दिन के संग्रह की विकिपीडिया की छवियों से छवियों का उपयोग करते हुए, क्योंकि वे क्रॉस साइट पहुंच की अनुमति देते हैं।

var images = [
   // "https://upload.wikimedia.org/wikipedia/commons/f/fe/Goldcrest_1.jpg",
   "https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Cistothorus_palustris_CT.jpg/450px-Cistothorus_palustris_CT.jpg",
    "https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Black-necked_Stilt_%28Himantopus_mexicanus%29%2C_Corte_Madera.jpg/362px-Black-necked_Stilt_%28Himantopus_mexicanus%29%2C_Corte_Madera.jpg",     
    "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cc/Daurian_redstart_at_Daisen_Park_in_Osaka%2C_January_2016.jpg/573px-Daurian_redstart_at_Daisen_Park_in_Osaka%2C_January_2016.jpg",
    "https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Myioborus_torquatus_Santa_Elena.JPG/675px-Myioborus_torquatus_Santa_Elena.JPG",
    "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Great_tit_side-on.jpg/645px-Great_tit_side-on.jpg",
    "https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Sarcoramphus_papa_%28K%C3%B6nigsgeier_-_King_Vulture%29_-_Weltvogelpark_Walsrode_2013-01.jpg/675px-Sarcoramphus_papa_%28K%C3%B6nigsgeier_-_King_Vulture%29_-_Weltvogelpark_Walsrode_2013-01.jpg",,
    
];

function loadImageAddBorder(){
    if(images.length === 0){
        return ; // all done   
    }
    var imageSrc = images.shift();
    imageTools.loadImage(
        imageSrc,true,
        function(event){
            var pixels, topRGB, c, rImage, wImage, botRGB, grad, i, hsl, h, s, l, hues, hslMap, wHue, hueCount, j, hr, gradCols, border;
            const IMAGE_WORK_SIZE = 128;
            const ICOUNT = IMAGE_WORK_SIZE * IMAGE_WORK_SIZE;
            if(event.type === "load"){
                rImage = imageTools.createImage(IMAGE_WORK_SIZE, IMAGE_WORK_SIZE);  // reducing image
                c = rImage.ctx;
                // This is where you can crop the image. In this example I only look at the center of the image
                c.drawImage(this,-16,-16,IMAGE_WORK_SIZE + 32, IMAGE_WORK_SIZE + 32); // reduce image size
    
                pixels = imageTools.getImageData(rImage).data;
                h = 0;
                s = 0;
                l = 0;
                // these are the colour ranges you wish to look at
                hues = [{
                        lum : {
                            low :20,
                            high : 60,
                            tot : 0,
                        },
                        sat : { // all saturations
                            low : 0,
                            high : 101,
                            tot : 0,
                        },
                        count : 0,
                        histo : new Uint16Array(360),
                    }]
                for(i = 0; i < pixels.length; i += 4){ 
                    hsl = imageTools.rgb2hsl(pixels[i],pixels[i + 1],pixels[i + 2]);
                    l += hsl.l * hsl.l;
                }
                l = Math.sqrt(l/ICOUNT);
                hues[0].lum.low = l - 30;
                hues[0].lum.high = l + 30;
                for(i = 0; i < pixels.length; i += 4){ 
                    hsl = imageTools.rgb2hsl(pixels[i], pixels[i + 1], pixels[i + 2]);
                    for(j = 0; j < hues.length; j ++){
                        hr = hues[j]; // hue range
                        if(hsl.l >= hr.lum.low && hsl.l < hr.lum.high){
                            if(hsl.s >= hr.sat.low && hsl.s < hr.sat.high){
                                hr.histo[hsl.h] += 1;
                                hr.count += 1;
                                hr.lum.tot += hsl.l * hsl.l;
                                hr.sat.tot += hsl.s;
                            }
                        }
                    }
                }
                // get weighted hue for image
                // just to simplify code hue 0 and 1 (reds) can combine
                for(j = 0; j < hues.length; j += 1){
                    hr = hues[j];
                    wHue = 0;
                    hueCount = 0;
                    hr.histo[1] += hr.histo[0];
                    for(i = 1; i < 360; i ++){
                        wHue += (i) * hr.histo[i];
                        hueCount += hr.histo[i];
                    }
                    h = Math.floor(wHue / hueCount);
                    s = Math.floor(hr.sat.tot / hr.count);
                    l = Math.floor(Math.sqrt(hr.lum.tot / hr.count));
                    hr.rgb = imageTools.hsl2rgb(h,s,l);
                    hr.rgba = imageTools.hex2RGBA(imageTools.rgba2Hex4(hr.rgb));
                }
                gradCols = hues.map(h=>h.rgba);
                if(gradCols.length === 1){
                    gradCols.push(gradCols[0]); // this is a quick fix if only one colour the gradient needs more than one
                }
                border = Math.floor(Math.min(this.width / 10,this.height / 10, 64));
    
                wImage = imageTools.padImage(this,border,border);
                wImage.ctx.fillStyle = imageTools.createGradient(
                    c, "linear", 0, 0, 0, wImage.height,gradCols
                );
                wImage.ctx.fillRect(0, 0, wImage.width, wImage.height);
                wImage.ctx.fillStyle = "black";
                wImage.ctx.fillRect(border - 2, border - 2, wImage.width - border * 2 + 4, wImage.height - border * 2 + 4);           
                wImage.ctx.drawImage(this,border,border);
                wImage.style.width = (innerWidth -64) + "px";
                document.body.appendChild(wImage);
                setTimeout(loadImageAddBorder,1000);
            }
        }
        
    )
}

setTimeout(loadImageAddBorder,0);



/** ImageTools.js begin **/
var imageTools = (function () {
    // This interface is as is. 
    // No warenties no garenties, and 
    /*****************************/
    /* NOT to be used comercialy */
    /*****************************/
    var workImg,workImg1,keep; // for internal use
    keep = false; 
    const toHex = v => (v < 0x10 ? "0" : "") + Math.floor(v).toString(16);
    var tools = {
        canvas(width, height) {  // create a blank image (canvas)
            var c = document.createElement("canvas");
            c.width = width;
            c.height = height;
            return c;
        },
        createImage (width, height) {
            var i = this.canvas(width, height);
            i.ctx = i.getContext("2d");
            return i;
        },
        loadImage (url, crossSite, cb) { // cb is calback. Check first argument for status
            var i = new Image();
            if(crossSite){
                i.setAttribute('crossOrigin', 'anonymous');
            }
            i.src = url;
            i.addEventListener('load', cb);
            i.addEventListener('error', cb);
            return i;
        },
        image2Canvas(img) {
            var i = this.canvas(img.width, img.height);
            i.ctx = i.getContext("2d");
            i.ctx.drawImage(img, 0, 0);
            return i;
        },
        rgb2hsl(r,g,b){ // integers in the range 0-255
            var min, max, dif, h, l, s;
            h = l = s = 0;
            r /= 255;  // normalize channels
            g /= 255;
            b /= 255;
            min = Math.min(r, g, b);
            max = Math.max(r, g, b);
            if(min === max){  // no colour so early exit
                return {
                    h, s,
                    l : Math.floor(min * 100),  // Note there is loss in this conversion
                }
            }
            dif = max - min;
            l = (max + min) / 2;
            if (l > 0.5) { s = dif / (2 - max - min) }
            else { s = dif / (max + min) }
            if (max === r) {
                if (g < b) { h = (g - b) / dif + 6.0 }
                else { h = (g - b) / dif }                   
            } else if(max === g) { h = (b - r) / dif + 2.0 }
            else {h = (r - g) / dif + 4.0 }   
            h = Math.floor(h * 60);
            s = Math.floor(s * 100);
            l = Math.floor(l * 100);
            return {h, s, l};
        },
        hsl2rgb (h, s, l) { // h in range integer 0-360 (cyclic) and s,l 0-100 both integers
            var p, q;
            const hue2Channel = (h) => {
                h = h < 0.0 ? h + 1 : h > 1 ? h - 1 : h;
                if (h < 1 / 6) { return p + (q - p) * 6 * h }
                if (h < 1 / 2) { return q }
                if (h < 2 / 3) { return p + (q - p) * (2 / 3 - h) * 6 }
                return p;        
            }
            s = Math.floor(s)/100;
            l = Math.floor(l)/100;
            if (s <= 0){  // no colour
                return {
                    r : Math.floor(l * 255),
                    g : Math.floor(l * 255),
                    b : Math.floor(l * 255),
                }
            }
            h = (((Math.floor(h) % 360) + 360) % 360) / 360; // normalize
            if (l < 1 / 2) { q = l * (1 + s) } 
            else { q = l + s - l * s }
            p = 2 * l - q;        
            return {
                r : Math.floor(hue2Channel(h + 1 / 3) * 255),
                g : Math.floor(hue2Channel(h)         * 255),
                b : Math.floor(hue2Channel(h - 1 / 3) * 255),
            }    
            
        },        
        rgba2Hex4(r,g,b,a=255){
            if(typeof r === "object"){
                g = r.g;
                b = r.b;
                a = r.a !== undefined ? r.a : a;
                r = r.r;
            }
            return `#${toHex(r)}${toHex(g)}${toHex(b)}${toHex(a)}`; 
        },
        hex2RGBA(hex){ // Not CSS colour as can have extra 2 or 1 chars for alpha
                                  // #FFFF & #FFFFFFFF last F and FF are the alpha range 0-F & 00-FF
            if(typeof hex === "string"){
                var str = "rgba(";
                if(hex.length === 4 || hex.length === 5){
                    str += (parseInt(hex.substr(1,1),16) * 16) + ",";
                    str += (parseInt(hex.substr(2,1),16) * 16) + ",";
                    str += (parseInt(hex.substr(3,1),16) * 16) + ",";
                    if(hex.length === 5){
                        str += (parseInt(hex.substr(4,1),16) / 16);
                    }else{
                        str += "1";
                    }
                    return str + ")";
                }
                if(hex.length === 7 || hex.length === 9){
                    str += parseInt(hex.substr(1,2),16) + ",";
                    str += parseInt(hex.substr(3,2),16) + ",";
                    str += parseInt(hex.substr(5,2),16) + ",";
                    if(hex.length === 9){
                        str += (parseInt(hex.substr(7,2),16) / 255).toFixed(3);
                    }else{
                        str += "1";
                    }
                    return str + ")";                
                }
                return "rgba(0,0,0,0)";
            }
            
                
        },            
        createGradient(ctx, type, x, y, xx, yy, colours){ // Colours MUST be array of hex colours NOT CSS colours
                                                          // See this.hex2RGBA for details of format
            var i,g,c;
            var len = colours.length;
            if(type.toLowerCase() === "linear"){
                g = ctx.createLinearGradient(x,y,xx,yy);
            }else{
                g = ctx.createRadialGradient(x,y,xx,x,y,yy);
            }
            for(i = 0; i < len; i++){
                c = colours[i];
                if(typeof c === "string"){
                    if(c[0] === "#"){
                        c = this.hex2RGBA(c);
                    }
                    g.addColorStop(Math.min(1,i / (len -1)),c); // need to clamp top to 1 due to floating point errors causes addColorStop to throw rangeError when number over 1
                }
            }
            return g;
        },
        padImage(img,amount){
            var image = this.canvas(img.width + amount * 2, img.height + amount * 2);
            image.ctx = image.getContext("2d");
            image.ctx.drawImage(img, amount, amount);
            return image;
        },
        getImageData(image, w = image.width, h = image.height) {  // cut down version to prevent intergration 
            if(image.ctx && image.ctx.imageData){
                return image.ctx.imageData;
            }
            return (image.ctx || (this.image2Canvas(image).ctx)).getImageData(0, 0, w, h);
        },
    };
    return tools;
})();

/** ImageTools.js end **/

मैं एक नोड मॉड्यूल पर काम कर रहा हूं जो कि एक पृष्ठभूमि छवि पर सबसे अच्छा दिखेगा रंग को वापस कर देगा, जिसमें निश्चित रूप से कई रंग होंगे।

यहां तक ​​कि मेरे पास अब तक क्या है:

'use strict';

var randomcolor = require('randomcolor');
var tinycolor = require('tinycolor2');

module.exports = function(colors, tries) {
  var topColor, data = {};

  if (typeof colors == 'string') { colors = [colors]; }
  if (!tries) { tries = 10000; }

  for (var t = 0; t < tries; t++) {
    var score = 0, color = randomcolor(); //tinycolor.random();

    for (var i = 0; i < colors.length; i++) {
      score += tinycolor.readability(colors[i], color);
    }

    data[color] = (score / colors.length);

    if (!topColor || data[color] > data[topColor]) {
      topColor = color;
    }
  }

  return tinycolor(topColor);
};

तो जिस तरह से यह काम करता है सबसे पहले मैं इस स्क्रिप्ट को इस तरह से एक छवि में 6 सबसे प्रभावशाली रंगों के साथ प्रदान करता हूं:

[ { r: 44, g: 65, b: 54 },
  { r: 187, g: 196, b: 182 },
  { r: 68, g: 106, b: 124 },
  { r: 126, g: 145, b: 137 },
  { r: 147, g: 176, b: 169 },
  { r: 73, g: 138, b: 176 } ]

और फिर यह 10,000 अलग-अलग यादृच्छिक रंग उत्पन्न करेगा और फिर उन 6 के रंगों के साथ सबसे अच्छा औसत विपरीत अनुपात चुन लेगा।

समस्या यह है कि यादृच्छिक रंग जेनरेट करने के लिए मैं किस लिपि का उपयोग करता हूं, मैं मूल रूप से दी गई तस्वीरों की परवाह किए बिना उसी परिणाम प्राप्त करूँगा।

tinycolor2 साथ मैं हमेशा एक बहुत ही गहरे भूरे रंग (लगभग काला) या बहुत हल्के भूरे रंग (लगभग सफेद) के साथ समाप्त होता हूँ I और randomcolor रंग के साथ मैं या तो एक गहरे नीले या एक हल्के आड़ू रंग के साथ समाप्त होगा।

मेरी स्क्रिप्ट इस बारे में जाने का सबसे अच्छा तरीका नहीं है, लेकिन क्या किसी के पास कोई विचार है?

धन्यवाद


एक दिलचस्प समस्या की तरह लगता है!

प्रत्येक एल्गोरिदम जो आप रंग उत्पन्न करने के लिए उपयोग कर रहे हैं, उनके संबंधित यादृच्छिक रंग एल्गोरिदम में कुछ रंगों की ओर पूर्वाग्रह होता है।

आप जो देख रहे हैं वह प्रत्येक के लिए उस पूर्वाग्रह का अंतिम परिणाम है दोनों गहरा और हल्का रंग स्वतंत्र रूप से चयन कर रहे हैं

यह सामान्य रंगों के एक हैश रखने के लिए और रद्दी उत्पन्न रंगों का उपयोग करने के विरोध में हैश का उपयोग करने के लिए अधिक समझ सकता है।

किसी भी तरह से 'फिटनेस' चेक, एल्गोरिथ्म जो यह देखने के लिए जांचता है कि कौन से रंग का सबसे अच्छा औसत अंतर है, दोनों रंग सेटों के लिए हल्का और गहरा रंग चुनना है। यह समझ में आता है, हल्का चित्रों में गहरा पृष्ठभूमि होना चाहिए और गहरा छवियों को हल्का पृष्ठभूमि होना चाहिए।

यद्यपि आप स्पष्ट रूप से नहीं कह सकते हैं, मैं अपने नीचे डॉलर को शर्त लगा सकता हूं कि आप हल्के औसत छवियों के लिए गहरा पृष्ठभूमि और गहरे चित्रों पर उज्ज्वल पृष्ठभूमि देख रहे हैं।

वैकल्पिक रूप से रंगों के एक हैश का उपयोग करने के बजाय, आप एक से अधिक यादृच्छिक रंग पट्टियाँ उत्पन्न कर सकते हैं और नतीजे सेट को उनको औसत से जोड़ सकते हैं।

या 6 सबसे सामान्य होने वाले रंगों को लेने के बजाय, क्यों समग्र रंग ढाल नहीं लेते हैं और इसके खिलाफ प्रयास करें?

मैंने एक उदाहरण रखा है, जहां मुझे सबसे अधिक होने वाला रंग मिलता है और पूरक रंग पाने के लिए इसे उलटा जाता है। सिद्धांत में यह कम से कम एक पूरे के रूप में छवि के लिए एक अच्छा विपरीत अनुपात प्रदान करना चाहिए।

छवि में सबसे अधिक होने वाली रंग का उपयोग करना काफी अच्छी तरह से काम करता है। के रूप में नीचे मेरे उदाहरण में उल्लिखित यह एक ऐसी तकनीक है जो ब्लिंडमैन67 पुस्तकालयों को शामिल करने और गैर-आवश्यक कदमों के बड़े पैमाने पर सूझबूझ के बिना उपयोग करता है, मैंने उसी छवियों को उधार लिया जो Blindman67 ने परिणाम सेट की उचित तुलना के लिए उपयोग किया।

औसत रंग पाने के लिए जावास्क्रिप्ट के माध्यम से छवि के औसत रंग को देखें (प्राप्त getAverageRGB() जेम्स द्वारा लिखा गया)।

var images = [
  "https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Cistothorus_palustris_CT.jpg/450px-Cistothorus_palustris_CT.jpg",
  "https://upload.wikimedia.org/wikipedia/commons/thumb/3/37/Black-necked_Stilt_%28Himantopus_mexicanus%29%2C_Corte_Madera.jpg/362px-Black-necked_Stilt_%28Himantopus_mexicanus%29%2C_Corte_Madera.jpg",
  "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cc/Daurian_redstart_at_Daisen_Park_in_Osaka%2C_January_2016.jpg/573px-Daurian_redstart_at_Daisen_Park_in_Osaka%2C_January_2016.jpg",
  "https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Myioborus_torquatus_Santa_Elena.JPG/675px-Myioborus_torquatus_Santa_Elena.JPG",
  "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Great_tit_side-on.jpg/645px-Great_tit_side-on.jpg",
  "https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Sarcoramphus_papa_%28K%C3%B6nigsgeier_-_King_Vulture%29_-_Weltvogelpark_Walsrode_2013-01.jpg/675px-Sarcoramphus_papa_%28K%C3%B6nigsgeier_-_King_Vulture%29_-_Weltvogelpark_Walsrode_2013-01.jpg",
];

// append images
for (var i = 0; i < images.length; i++) {
  var img = document.createElement('img'),
div = document.createElement('div');
  img.crossOrigin = "Anonymous";

  img.style.border = '1px solid black';
  img.style.margin = '5px';

  div.appendChild(img);

  document.body.appendChild(div);
  (function(img, div) {
img.addEventListener('load', function() {
  var avg = getAverageRGB(img);
  div.style = 'background: rgb(' + avg.r + ',' + avg.g + ',' + avg.b + ')';
  img.style.height = '128px';
  img.style.width = '128px';
});
img.src = images[i];
  }(img, div));
}

function getAverageRGB(imgEl) { // not my work, see http://jsfiddle.net/xLF38/818/
  var blockSize = 5, // only visit every 5 pixels
defaultRGB = {
  r: 0,
  g: 0,
  b: 0
}, // for non-supporting envs
canvas = document.createElement('canvas'),
context = canvas.getContext && canvas.getContext('2d'),
data, width, height,
i = -4,
length,
rgb = {
  r: 0,
  g: 0,
  b: 0
},
count = 0;

  if (!context) {
return defaultRGB;
  }

  height = canvas.height = imgEl.offsetHeight || imgEl.height;
  width = canvas.width = imgEl.offsetWidth || imgEl.width;

  context.drawImage(imgEl, 0, 0);
  try {
data = context.getImageData(0, 0, width, height);
  } catch (e) {
return defaultRGB;
  }

  length = data.data.length;

  while ((i += blockSize * 4) < length) {
++count;
rgb.r += data.data[i];
rgb.g += data.data[i + 1];
rgb.b += data.data[i + 2];
  }

  // ~~ used to floor values
  rgb.r = ~~(rgb.r / count);
  rgb.g = ~~(rgb.g / count);
  rgb.b = ~~(rgb.b / count);

  return rgb;
}


यह इस बात पर निर्भर करता है कि पृष्ठभूमि छवि पर ओवरलेड टेक्स्ट कहां है। यदि पृष्ठभूमि में इसके कुछ भाग पर कुछ बड़ी सुविधा है, तो पाठ को उस स्थान से दूर रखा जाएगा, इसलिए छवि के उस भाग के साथ विपरीत होना चाहिए, लेकिन आप एक निश्चित रंग चुन सकते हैं या अन्य रंगों के पूरक भी कर सकते हैं छवि। मुझे लगता है कि व्यावहारिक रूप से आपको बोलने के लिए लोगों को आसानी से अग्रभूमि रंग को आसानी से स्लाइड / समायोजित करने के लिए विजेट बनाना होगा। या आपको यह वास्तव में प्रभावी ढंग से करने के लिए एक गहरी शिक्षा प्रणाली बनाने की आवश्यकता होगी





colors