user3754676
user3754676

Reputation: 321

Average color of an image of selected region giving wrong image

I am trying to find the average color of some part of the image and then setting it as a background. I am using this color to find the selected region average code.

JSFiddle code to find average image color.

This is my image

I want to extract that part from the image and find the average color then set it to the background image

Average color of the grass region from the image

This is the code i am using

<img id="i" src="bg_300x250_landscape.jpg"/>

<script type="text/javascript">
    var rgb = getAverageRGB(document.getElementById('i'));
    document.body.style.backgroundColor = 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')';

   function getAverageRGB(img) {
var canvas = document.createElement('canvas'),
context = canvas.getContext && canvas.getContext('2d'),
rgb = {r:102,g:102,b:102}, // Set a base colour as a fallback for non-compliant browsers
pixelInterval = 5, // Rather than inspect every single pixel in the image inspect every 5th pixel
count = 0,
i = -4,
data, length;

// return the base colour for non-compliant browsers
if (!context) { return rgb; }



 context.drawImage(img, 146, 214);

try {
data = context.getImageData(146, 214, 70, 20);
} catch(e) {
// catch errors - usually due to cross domain security issues
alert(e);
return rgb;
}

data = data.data;
length = data.length;
while ((i += pixelInterval * 4) < length) {
count++;
rgb.r += data[i];
rgb.g += data[i+1];
rgb.b += data[i+2];
}
// floor the average values to give correct rgb values (ie: round number values)
rgb.r = Math.floor(rgb.r/count);
rgb.g = Math.floor(rgb.g/count);
rgb.b = Math.floor(rgb.b/count);

return rgb;
}


</script>

I have used MeasureIT Firefox AddOn to get the cordinates and i found

x:146
y:214
width:70
height:20

which i have used here.

context.drawImage(img, 146, 214);
 ...
data = context.getImageData(146, 214, 70, 20);

So the average color of that region should be green but i am getting the color of the sky.

Upvotes: 1

Views: 1716

Answers (1)

Cinn
Cinn

Reputation: 4517

I wrote an example on jsfiddle : http://jsfiddle.net/w86mu4bz

Here is the code : html :

<img src="http://publicdomainarchive.com/wp-content/uploads/2014/02/public-domain-images-free-high-resolution-quality-photos-unsplash-0079.jpg" title="Photo from publicdomainarchive.com" id="image" crossOrigin="anonymous"/>

<h1 id="h1">My amazing title</h1>

css :

img, h1 {
    margin : 0;
    padding : 0;
}
img {
    width : 500px;
    position : absolute;
    top : 0;
    left : 0;
    z-index : 1;
}
h1 {
    font-family : 'Open Sans', Arial;
    font-size : 2em;
    position : absolute;
    top : 20px;
    left : 0;
    color : white;
    z-index : 2;
    padding : 3px 5px 3px 25px; /* attention this causes a margin of error !! */
}

And javascript :

var average_color_background = function(image, title) {
    var treat_properties = function(elmt_propertie) {
        return parseInt(elmt_propertie.replace(/px/, ''));
    }
    var image_width = treat_properties(getComputedStyle(image, null).width),
        image_height = treat_properties(getComputedStyle(image, null).height),
        title_width = treat_properties(getComputedStyle(title, null).width),
        title_height = treat_properties(getComputedStyle(title, null).height),
        title_top = treat_properties(getComputedStyle(title, null).top),
        title_left = treat_properties(getComputedStyle(title, null).left);

    var c = document.createElement('canvas');
        c.width = image_width;
        c.height = image_height;
        c.style.position = "absolute";
        c.style.top = 0;
        c.style.left = 0;
        c.style.zIndex = 0; // invisible calculation

    document.getElementsByTagName('body')[0].appendChild(c);

    var ctx = c.getContext("2d");

    var image_bis = new Image();
    image_bis.crossOrigin = 'anonymous'; // avoid security error

    image_bis.onload = function(){
        ctx.drawImage(image_bis,0,0,image_width,image_height);
        var imageData = ctx.getImageData(title_left, title_top, title_width, title_height),
            mapPixel = imageData.data;

        var red = 0,
            green = 0,
            blue = 0,
            length = 4 * title_width * title_height;
        for(var i=0;i<length;i+=4) {
            red += mapPixel[i];
            green += mapPixel[i+1];
            blue += mapPixel[i+2];
        }
        length = length / 4;
        red = Math.round(red/length);
        green = Math.round(green/length);
        blue = Math.round(blue/length);

        // display result, can easily be improved for something more beautiful (e.g. using complementary color):
        title.style.backgroundColor = 'rgb('+red+','+green+','+blue+')';

        c.parentNode.removeChild(c);
        return true;        
    }
    image_bis.src = image.src;
}
average_color_background(document.getElementById('image'),document.getElementById('h1'));

It uses canvas, so don't forget to add a default color for browsers that don't support it (using modernizr for example)

Upvotes: 1

Related Questions