2012-10-08 4 views
1

Bon, alors disons que je veux comparer deux BitmapDatas. L'une est une image d'un arrière-plan (pas solide, il a différents pixels), et l'autre est de quelque chose (comme un sprite) sur le même fond. Maintenant, ce que je veux faire est de supprimer l'arrière-plan de la deuxième image, en comparant les deux images, et en supprimant tous les pixels de l'arrière-plan qui sont présents dans la deuxième image. Pour plus de clarté, fondamentalement, je veux faire this en AS3.AS3 - Comparer BitmapDatas, méthode la plus rapide?

Maintenant, j'ai trouvé deux façons de le faire, et ils fonctionnent parfaitement. L'un compare les pixels directement, tandis que l'autre utilise d'abord la méthode BitmapData.compare(), puis copie les pixels appropriés dans le résultat. Ce que je veux savoir, c'est quel chemin est le plus rapide.

Voici mes deux façons de le faire:

Méthode 1

for (var j:int = 0; j < layer1.height; j++) 
{ 
    for (var i:int = 0; i < layer1.width; i++) 
    { 
     if (layer1.getPixel32(i, j) != layer2.getPixel32(i, j)) 
     { 
      result.setPixel32(i, j, layer2.getPixel32(i, j)); 
     } 
    } 
} 

Méthode 2

result = layer1.compare(layer2) as BitmapData; 

for (var j:int = 0; j < layer1.height; j++) 
{ 
    for (var i:int = 0; i < layer1.width; i++) 
    { 
     if (result.getPixel32(i, j) != 0x00000000) 
     { 
      result.setPixel32(i, j, layer2.getPixel32(i, j)); 
     } 
    } 
} 

layer1 est l'arrière-plan, layer2 est l'image l'arrière-plan sera retiré de, et result est juste un BitmapData que le résultat sortira sur.

Ce sont très similaires, et personnellement, je n'ai pas remarqué de différence de vitesse, mais je me demandais si quelqu'un sait ce qui serait le plus rapide. Je vais probablement utiliser la méthode 1 de toute façon, car BitmapData.compare() ne compare pas les pixels alpha, sauf si les couleurs sont identiques, mais je pensais toujours que cela ne ferait pas de mal à demander.

Répondre

2

Cela pourrait ne pas être 100% applicable à votre situation, mais FWIW je fait quelques recherches dans ce un certain temps, voici ce que je l'ai écrit à l'époque:

Je voulais essayer subvention Skinners test de performance chose pendant un moment, donc c'était mon opportunité.

J'ai testé la comparaison native, la comparaison itérative, une comparaison itérative inverse (parce que je sais qu'ils sont un peu plus rapides) et enfin une comparaison en utilisant blendmode DIFFERENCE.

L'inverse itératif comparer ressemble à ceci:

for (var bx:int = _base.width - 1; bx >= 0; --bx) { 
for (var by:int = _base.height - 1; by >= 0; --by) { 
    if (_base.getPixel32(bx, by) != compareTo.getPixel32(bx, by)) { 
    return false; 
    } 
} 
} 
return true; 

Le blendmode comparer ressemble à ceci:

var test:BitmapData = _base.clone(); 
test.draw(compareTo, null, null, BlendMode.DIFFERENCE); 
var rect:Rectangle = test.getColorBoundsRect(0xffffff, 0x000000, false); 
return (rect.toString() != _base.rect.toString()); 

Je ne suis pas 100% sûr que ce soit tout à fait fiable, mais il semblait travailler . J'ai effectué chaque test pour 50 itérations sur des images 500 x 500.

Malheureusement, mon toolkit de pixel bender est borked, donc je n'ai pas pu essayer cette méthode.

Chaque test a été exécuté dans les deux lecteurs de débogage et de relâchement pour comparaison, notez les différences massives!

Code complet est ici: http://webbfarbror.se/dump/bitmapdata-compare.zip

graph

+0

Huh, intéressant. On dirait que blendmode est la meilleure option, la comparaison native est plutôt bonne mais pour un très différent c'est un changement. La vitesse n'est pas vraiment le plus gros problème pour moi, mais je vais voir comment fonctionnent les BlendModes. Je ne marquerai pas ceci comme réponse encore au cas où je verrais ce que les autres ont à dire, mais merci! – puggsoy

1

Vous pouvez essayer un shader qui vérifierait si deux images sont assorties, et sinon, sauf un du point de l'image en sortie. Comme ceci:

kernel NewFilter 
< namespace : "Your Namespace"; 
    vendor : "Your Vendor"; 
    version : 1; 
    description : "your description"; 
> 
{ 
    input image4 srcOne; 
    input image4 srcTwo; 
    output pixel4 dst; 

    void evaluatePixel() 
    { 
     float2 positionHere = outCoord(); 
     pixel4 fromOne = sampleNearest(srcOne, positionHere); 
     pixel4 fromTwo = sampleNearest(srcTwo, positionHere); 
     float4 difference=fromOne-fromTwo; 
     if (abs(difference.r)<0.01&&abs(difference.g)<0.01&&abs(difference.b)<0.01) dst=pixel4(0,0,0,1); 
     else dst = fromOne; 
    } 
} 

Ceci retournera le pixel noir s'il est apparié et le pixel de la première image s'il n'y a pas de correspondance. Utilisez Pixel Bender pour le faire fonctionner dans Flash. Certains tutoriel est here. Les shaders sont généralement un facteur plus rapide que le code AS3 ordinaire.

Questions connexes