2011-04-17 4 views
7

J'ai essayé de faire un script qui compare deux images en HTML5 et Javascript. Mais pour une raison étrange, il revient toujours que les images sont complètement les mêmes.getImageData retourne toujours 0

Et en regardant ce que le problème pourrait être, j'ai découvert que chaque valeur de données de chaque pixel retourné, pour une raison étrange, "0".

Donc, une idée de ce que j'ai mal fait? :)

Pour une raison quelconque, j'ai l'impression que c'est quelque chose de très simple, mais je viens d'apprendre à propos de l'élément de toile, alors oui.

Ceci est mon code:

function compareImg() { 
    var c1 = document.getElementById("c"); 
    var ctx1 = c1.getContext("2d"); 
    var c2 = document.getElementById("c2"); 
    var ctx2 = c2.getContext("2d"); 

    var match = 0; 

    var img1 = new Image(); 
    img1.src = "cat.jpg"; 
    img1.onload = function() { 
     ctx1.drawImage(img1, 0, 0); 
    } 
    var img2 = new Image(); 
    img2.src = "bird.jpg"; 
    img2.onload = function() { 
     ctx2.drawImage(img2, 0, 0); 
    } 


    for(var x = 0; x<c1.width; x++) { // For each x value 
     for(var y = 0; y<c1.height; y++) { // For each y value 
      var data1 = ctx1.getImageData(x, y, 1, 1); 
      var data2 = ctx2.getImageData(x, y, 1, 1); 
      if (data1.data[0] == data2.data[0] && data1.data[1] == data2.data[1] && data1.data[2] == data2.data[2]) { 
       match++; 
      } 
     } 
    } 
    var pixels = c1.width*c1.height; 
    match = match/pixels*100; 
    document.getElementById("match").innerHTML = match + "%"; 
} 

Répondre

5

Vous n'attendez pas que vos images soient chargées et dessinées avant d'effectuer votre comparaison. Essayez ceci:

var img = new Image; 
img.onload = function(){ 
    ctx1.drawImage(img,0,0); 
    var img = new Image; 
    img.onload = function(){ 
    ctx2.drawImage(img,0,0); 
    // diff them here 
    }; 
    img.src = 'cat.jpg'; 
}; 
img.src = 'cat.jpg'; 

Comme indiqué ci-dessus, vous devriez toujours set your srcafter your onload.

+0

Merci d'avoir fait écho à ma superstition sur l'ordre d'assigner" src "et" onload ". :-) Peut-être que ce n'est pas une superstition après tout! – Pointy

+0

@Pointy [Non, ce n'est pas juste de la superstition.] (Http://stackoverflow.com/questions/4776670/should-setting-an-image-src-to-dataurl-be-available-immédiatement) – Phrogz

+0

Fascinant, @ Phrogz! Je me sens justifié pour toutes ces années à dire aux gens de faire ça :-) – Pointy

1

Je pense que le problème est que vos données d'image est probablement pas prêt au moment où vous essayez de l'utiliser pour la toile. Si vous différez ce code aux gestionnaires onload, qui sera (probablement) aide:

var img1 = new Image(), count = 2; 
img1.src = "cat.jpg"; 
img1.onload = function() { 
    ctx1.drawImage(img1, 0, 0); 
    checkReadiness(); 
} 
var img2 = new Image(); 
img2.src = "bird.jpg"; 
img2.onload = function() { 
    ctx2.drawImage(img2, 0, 0); 
    checkReadiness(); 
} 

function checkReadiness() { 
    if (--count !== 0) return; 

    for(var x = 0; x<c1.width; x++) { // For each x value 
    for(var y = 0; y<c1.height; y++) { // For each y value 
     var data1 = ctx1.getImageData(x, y, 1, 1); 
     var data2 = ctx2.getImageData(x, y, 1, 1); 
     if (data1.data[0] == data2.data[0] && data1.data[1] == data2.data[1] && data1.data[2] == data2.data[2]) { 
      match++; 
     } 
    } 
    } 
    var pixels = c1.width*c1.height; 
    match = match/pixels*100; 
    document.getElementById("match").innerHTML = match + "%"; 
} 

Tout ce que je l'ai fait était d'ajouter une enveloppe de fonction autour de votre code. Cette fonction vérifie la variable de comptage d'images que j'ai ajoutée, et seulement quand elle est nulle (c'est-à-dire, seulement après que les deux images ont été chargées) fera le travail.

(Ce peut être la superstition, mais j'attribue toujours le « onload » gestionnaire avant je définir l'attribut « src ». Je cette idée que, peut-être que dans le passé, les navigateurs pourraient ne pas exécuter le gestionnaire si l'image est déjà dans la mémoire cache.)

Maintenant une autre chose: vous devriez probablement obtenir les données d'image une seule fois, puis parcourir les données retournées. Appeler "getImageData()" pour chaque pixel va demander beaucoup de travail au navigateur.

+0

Maintenant, je reçois une "erreur de sécurité" sur la première ligne où le script obtient les données d'image ... Chrome dit "SECURITY_ERR: DOM exception 18" et Firefox dit "Erreur: exception non interceptée: [Exception ... "Erreur de sécurité" code: "1000" nsresult: "0x805303e8 (NS_ERROR_DOM_SECURITY_ERR) ...]" – iamarcel

+1

Est-ce que vous récupérez les images d'un autre domaine? Si oui, alors c'est une erreur de sécurité :-) C'est le même genre de problème que essayer de jouer avec un '