Javascript - 图像数据处理和div渲染

时间:2013-01-31 19:07:41

标签: javascript jquery canvas

因此,我为自己创造的挑战就是这样。

我有一张来源照片:

Source Photo http://f.cl.ly/items/012t1M250f0T101F2L0n/unicorn.jpg

我正在使用divs

映射颜色值并创建它的像素化表示

结果如下:

Result Photo http://f.cl.ly/items/2t1F2Q0Y2w0K250L0t0v/Screen%20Shot%202013-01-31%20at%2010.52.19%20AM.png

我正在实现的代码是:

'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 - 它可以更快地处理图像数据,但我无法弄清楚提供增加性能的区别是什么。

感谢您的帮助!

4 个答案:

答案 0 :(得分:1)

为什么不考虑在画布上绘制结果而不是创建这么多div?理论上它应该快得多......

答案 1 :(得分:1)

主要问题是您将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来操作DOM元素而不是jquery来使它更快。

答案 2 :(得分:0)

之前我遇到过类似的速度问题 - 它需要这么长时间的原因是因为你通过以文本形式提供HTML来添加元素,这意味着它必须每次都解析该文本。如果您使用JavaScript DOM附加新元素,您会发现速度显着提高。

编辑:如果您不熟悉以这种方式创建新元素,语法如下所示:

var newPixel = document.createElement('div');
newPixel.style.height = 3;
newPixel.style.backgroundColor = 'black';
// etc...
parentElement.appendChild(newPixel);

答案 3 :(得分:0)

您可以通过减少jquery查找次数来加快速度。例如,在第一次循环开始之前,请执行以下操作:

var $container = $('.container');

现在您不必每次都查找容器。

此外,当您创建一行时,使用相同的技巧来避免'row:last'查找:

var $row = $('<div class="row">');
$container.append($row);
...
$row.append($('<div class="block">')...