因此,我为自己创造的挑战就是这样。
我有原始照片:
我正在映射颜色值并使用div创建它的像素化表示
结果如下:
我完成此操作的代码是:
'use strict';
var imageSource = 'images/unicorn.jpg';
var img = new Image();
img.src = imageSource;
var canvas = $('<canvas/>')[0];
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);
var context = canvas.getContext('2d');
console.log('img height: ' + img.height);
console.log('img width: ' + img.width);
var pixelDensity = 70;
var timerStart = new Date();
for (var i = pixelDensity/2; i < img.height; i += (img.height/pixelDensity) ) {
$('.container').append($('<div class="row">'));
for(var j = pixelDensity/2; j < img.width; j += img.height/pixelDensity) {
var value = context.getImageData(j, i, 1, 1).data;
var colorValue = 'rgb(' + value[0] + ', ' + value[1] + ', ' + value[2] + ')';
$('.row:last').append($('<div class="block">').css({'background-color' : colorValue}));
}
}
var timerStop = new Date();
console.log(timerStop - timerStart + ' ms');
pixelDensity变量控制颜色样本的紧密程度。数量越少,样本越少,产生结果所需的时间就越少。随着数量的增加,采样数会增加,功能会大大降低。我很想知道是什么使这件事花了这么长时间。我看过稍微相似的项目-最著名的是Jscii-它可以更快地处理图像数据,但是我不知道提供额外性能的区别是什么。
谢谢你的帮助!
最佳答案
主要问题是您将DOM元素直接循环添加到页面。如果将所有数据创建包装器元素,然后再将其实际添加到页面,则运行起来会更快。
编辑:
我还注意到您为每个像素调用context.getImageData
,这是大多数时间所需要的。相反,您应该将图像数据缓存在变量中并从中获取颜色值。您还需要缓存@Travis J提到的循环条件并将其四舍五入:
var wrapper = $('<div class="container">');
var imgData = context.getImageData(0, 0, img.width, img.height).data;
var getRGB = function(i) { return [imgData[i], imgData[i+1], imgData[i+2]]; };
var start = Math.round(pixelDensity/2),
inc = Math.round(img.height/pixelDensity);
for (var i = start; i < img.height; i += inc) {
var row = $('<div class="row">');
for(var j = start; j < img.width; j += inc) {
var colorValue = getRGB((i * (img.width*4)) + (j*4));
row.append($('<div class="block">').css({'background-color' : 'rgb('+(colorValue.join(','))+')'}));
}
wrapper.append(row);
}
$('body').append(wrapper);
这会将时间从6-9秒减少到600-1000毫秒。您还可以使用普通的javascript而不是jquery来操纵DOM元素,从而使其变得更快。