2013-01-31 8 views
6

Also die Herausforderung, die ich für mich selbst erstellt habe, ist als solche.Javascript - Bilddatenverarbeitung und Div-Rendering

Ich habe eine Quelle Foto:

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

Dass ich Farbwerte am Mapping und eine pixelig Darstellung davon mit divs

Hier ist das Ergebnis der Erstellung:

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

Der Code, mit dem ich das bewerkstellige, lautet:

'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'); 

Die Variable pixelDensity steuert, wie nahe die Farbmuster sind. Je kleiner die Zahl ist, desto weniger Proben werden benötigt, um weniger Zeit für das Ergebnis zu haben. Wenn Sie die Zahl erhöhen, werden die Samples erhöht und die Funktion verlangsamt sich erheblich.

Ich bin neugierig zu wissen, was dieses Ding so lange braucht. Ich habe mir etwas ähnliche Projekte angeschaut - vor allem Jscii - die die Bilddaten viel schneller verarbeiten, aber ich kann nicht herausfinden, was der Unterschied ist, der die zusätzliche Leistung bietet.

Danke für Ihre Hilfe!

+0

Berühren Sie das DOM nicht, es sei denn, Sie müssen es tun. Erstellen Sie Ihr Offscreen-Objektmodell und hängen Sie es dann einmal an. Je mehr Samples, je mehr Divs, desto mehr Edits. Also, alles auf dem Bildschirm aufgebaut, alles auf einmal anhängen. –

+0

Das war, was ich ursprünglich tat, aber ich fand, dass das Ziehen der Bilddaten das war, was die meiste Zeit nahm. Ich werde es nochmal versuchen, wenn ich den folgenden Ratschlag gebe. Danke für die Hilfe! – tylerdavis

+0

Eine andere Sache. Wenn Sie versuchen, jede mögliche Leistung zu erzielen, hilft jede Kleinigkeit. Zwischenspeichern Sie Ihre for-Schleife-Bedingungen. 'für (var j = pixelDensity/2; j

Antwort

1

Das Hauptproblem ist, dass Sie DOM-Elemente auf einer Seite direkt in einer Schleife anhängen. Dies würde viel schneller laufen, wenn Sie ein Wrapper-Element mit all Ihren Daten erstellen, bevor Sie es der Seite hinzufügen.

Edit: ich Sie rufen context.getImageData für jedes Pixel auch bemerkt haben, ist das, was die meiste Zeit dauert. Stattdessen sollten Sie Bilddaten in Variablen zwischenspeichern und daraus Farbwerte erhalten.Sie müssen auch Schleifenbedingungen Cache als @Travis J erwähnt und um sie herum:

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); 

Diese Zeit von 6 bis 9 Sekunden 600-1000 Millisekunden reduzieren würde. Sie können auch einfaches Javascript verwenden, um DOM-Elemente anstelle von jquery zu manipulieren, um es noch schneller zu machen.

+0

Das war das Problem. Vielen Dank für die Antwort! – tylerdavis

1

Warum denkst du nicht darüber nach, das Ergebnis auf die Leinwand zu zeichnen, anstatt so viele divs zu erstellen? In der Theorie sollte es viel schneller sein ...

0

Ich hatte ähnliche Geschwindigkeitsprobleme vorher - Der Grund, der so lange dauert, ist, weil Sie die Elemente hinzufügen, indem Sie ihm den HTML in Form von Text geben, der bedeutet, dass der Text jedes Mal analysiert werden muss. Wenn Sie das JavaScript-DOM zum Anhängen neuer Elemente verwenden, werden Sie eine deutliche Geschwindigkeitssteigerung bemerken.

EDIT: Falls Sie mit dem Erstellen von neuen Elementen auf diese Weise nicht vertraut sind, sieht die Syntax wie folgt:

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

Sie etwas durch die Reduzierung der Anzahl von jquery Lookups beschleunigen könnte. Zum Beispiel vor dem ersten Loop-Start, dies zu tun:

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

Jetzt haben Sie nicht auf die Behälter jedes Mal nachschlagen.

Auch wenn Sie eine Zeile erstellen, verwenden Sie den gleichen Trick das zu vermeiden ‚Reihe: letzte‘ Nachschlag:

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