通过文件检测图像颜色,并更改背景颜色

时间:2017-07-22 16:01:21

标签: javascript jquery

代码很简单: 我在jsfiddle上编辑图像的链接,然后背景的颜色变为图像的颜色。

现在我想将jsfiddle上传到我的localhost,但问题是我需要调试 该页面,如果我想更改图像网址。

我测试它并且它不起作用,

图像折叠但背景颜色没有。

我需要的是通过文件输入上传图像的选项,

因此背景颜色会随着图像负载或图像变化而改变。

onload()/ change或类似的东西。

的jsfiddle:

jsfiddle.net/xLF38/2735/


<img id="i" src="data:image/png;base64,....." />

    var rgb = getAverageRGB(document.getElementById('i'));
document.body.style.backgroundColor = 'rgb('+rgb.r+','+rgb.g+','+rgb.b+')';

function getAverageRGB(imgEl) {

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.naturalHeight || imgEl.offsetHeight || imgEl.height;
width = canvas.width = imgEl.naturalWidth || imgEl.offsetWidth || imgEl.width;

context.drawImage(imgEl, 0, 0);

try {
    data = context.getImageData(0, 0, width, height);
} catch(e) {
    /* security error, img on diff domain */alert('x');
    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;

}

3 个答案:

答案 0 :(得分:0)

运行:

&#13;
&#13;
$(function(){
    $('#i').on('load change',function(){
        var rgb = getAverageRGB(this);
        $('body').css('backgroundColor',"rgb("+rgb.r+","+rgb.g+","+rgb.b+")");
    });

    $('#upload').on('change',function(){
        var $file = this.files[0];
        if($file!=null){
            var $src = URL.createObjectURL($file);
            $('#i').attr('src',$src);
        }
    });
});




function getAverageRGB(imgEl) {
	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.naturalHeight || imgEl.offsetHeight || imgEl.height;
	width = canvas.width = imgEl.naturalWidth || imgEl.offsetWidth || imgEl.width;

	context.drawImage(imgEl, 0, 0);

	try {
		data = context.getImageData(0, 0, width, height);
	}catch(e) {
		/* security error, img on diff domain */
		alert('x');
		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;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>



<img id="i" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALkAAABQCAYAAABF5tQWAAAENUlEQVR4nO2UWY7cMAxEff9LJz89gGGYEpeiKNFFoJCxW+JSfM51Xdc/iuqiZ/ze1zdGUSgRcqq9CDnVXoScai9CTrUXIafai5A31MtCPy1C3lCEXPaDkDcRIZf9IORNRMhlPwh5ExFy2Q9C3kSEXPaDkDcRIZf9IORNRMhlPwh5ExFy2Q9C3kSEXPaDkDcRIZf9IORNRMhlPwh5ExFy2Q9C3kSEXPaDkDcRIZf9IOQHS4rqvqReK735vY8Za4lqwztpd3+r+iqHfIeoXj5ymYOllvdW1Y/gR10DX44sL3cBvLr+o49aU6pN6Bae+dG+7rTflpB7AUBBhOgzEtG60Vl22//vfT2YmUNqF/B2NgqB9+4sRmcQuT0zVu994nl9Y5lDaheojaz7VhC9+RH9PfNY97Ny/xch90PqDRSE2fkRgGviM5AjjfDmWBkIH6y5EdBZe3me99Y9GnKvKSshz/oAPF5kQ474QKScmvdZTJVAPjN49PvIlFFEPjhrr9Y89+doTe2c9w9ndjcyG3JHx0OuGXR2PmqgJlAQ3PPd/9XUtPZn6dlTZ1ZbGy0gtww5ezf6fXbO8yHN8mSFtRYCcm9fz7ufhNxiyAzet7MRAzV5oh+xNaz1LF6/PWvnQAKIyLs15DPYtAZF4Xx+MNE8COA9sHgh9/SlrbsS8GMgjxjlNfB+DrmEjH5R96z9eeGO9Pw5yGdGvf2tMVIbqN5ndb0+RPxDzJjRMyGfmLXL8q2RAUz2jJ6aKznZEnJrZC4/uhDPLKshr9gXITca5jUzcyHeOA3yrDkJ+cMor5FZy7jftQYa8oz5ooAjah8Nucccj4nZS7jn0NZA9F0xozX+7hJyw2K057ywIGfL7tsSFYAjezgWco2J2ZBH+x2B/Tw/+jsTMNRuZv7Pnj8NubT8N4Osi9SG11RNrkhtRCB2E+3rSMi1g1mG1BhkMdIbUdg8PqE+MGveBMhef2sLuWVQ7T1UoD6IUU5t7izPqyBf1YdQP7+I13TtPUSshgmRA5kHtfvqnoRatZCPBn6eGd2JBno+RK6I/5baI2A9kGfNtg3kHuC05o3ueCNzrll+ZG9ZO/LmHdVYPdcWkEsGjMxa8XF58s7O7wK6ZR5PzvaQR0HXmLVygdZ+NXe7QY7OdwTkaNgtZkXvZy7w7Syqz6y9nAJ4GeRZoHtrZvWe6dNJe1k9wzaQe4DZwbDVkEu1TwP6LT4DOQr0Hfv9amg8qt7XcsgJUK942+no+RjIGedF5k7fcuz0HychD0TVIlfBcaI3Qi/1hsxiF7Mq+9lh7t13BoV8VZN/z/ffis36hE4DW7G3+sakZncxqtqLHTwg5M2009J20QmAS31e1U1R52hHqEc9EnKqpQg51V6EnGovQk61FyGn2ouQU+1FyKn2IuRUexFyqr0IOdVehJxqL0JOtRchpz6p/04AcdQFWWI+AAAAAElFTkSuQmCC" width="100" height="75"/>
<br>
<input type="file" id="upload">
&#13;
&#13;
&#13;

答案 1 :(得分:0)

你想要做的是设置一个文件上传字段并在其上设置一个事件监听器,它将触发一个函数通过File API获取文件并获取其数据uri,更新图像元素src,然后调用你的在图像加载时起作用。

HTML:

<img id="i" src="">
<input type="file" id="upload">

监听器:

var $upload = document.getElementById('upload');
$upload.addEventListener('change', updateImage);

更新图片功能:

// Will get data url via File API, update image src, then pass image element to setBackground
function updateImage(evt) {
    var $image = document.getElementById('i');
    var files = evt.target.files;
    var file = files[0];
    var reader = new FileReader();

    reader.onload = function (e) {
        $image.src = e.target.result;
    };

    $image.onload = function(e) {
        setBackground($image);
    };

    reader.readAsDataURL(file);
}

设置背景(将一些初始代码放入函数中):

// Will pass image element to getAverageRGB then set background equal to result
function setBackground($image) {
    var rgb = getAverageRGB($image);
    document.body.style.backgroundColor = 'rgb('+rgb.r+','+rgb.g+','+rgb.b+')';
}

获取RGB(您的功能):

function getAverageRGB(imgEl) {
    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.naturalHeight || imgEl.offsetHeight || imgEl.height;
    width = canvas.width = imgEl.naturalWidth || imgEl.offsetWidth || imgEl.width;

    context.drawImage(imgEl, 0, 0);

    try {
        data = context.getImageData(0, 0, width, height);
    } catch(e) {
        /* security error, img on diff domain */
        alert('x');
        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;
}

小提琴:http://jsfiddle.net/2mw6r8Ls/

答案 2 :(得分:0)

你有一个错误,你的代码可能更具可读性。您以i而不是-4开始-4 * blockSize。但是,我相信如果从零开始并使用for循环,它会更简单。此外,defaultRBG值是多余的。您可以返回rgb,因为它们在循环像素之前是相同的。更令人困惑的是你使用~~。您的代码应该是自我记录的。如果您需要撰写评论,请问自己是否有更易读的方式来编写代码。

如果要上传图像,则需要input[type="file"]元素,并附加一些处理程序和逻辑以加载和读取图像。 MDN文章经历了一个彻底的例子。我建议在获取对象URL并设置img.src后,在加载事件监听器中调用下面的函数,获取rgb对象并更改正文的背景颜色。

function getAverageRGB(imgEl) {
  const BLOCK_SIZE = 5; // only visit every 5 pixels
  const rgb = {r: 0, g: 0, b: 0};
  const canvas = document.createElement('canvas'),
  const context = canvas.getContext && canvas.getContext('2d'),
  let data, width, height, length;
  let count = 0;

  if (!context) {
    return rgb;
  }

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

  context.drawImage(imgEl, 0, 0);

  try {
    data = context.getImageData(0, 0, width, height).data;
  } catch(e) {
    // security error, img on diff domain
    return rgb;
  }

  length = data.length;

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

  rgb.r = Math.floor(rgb.r / count);
  rgb.g = Math.floor(rgb.g / count);
  rgb.b = Math.floor(rgb.b / count);
  return rgb;
}