Flash8 est sorti, et c’est l’occasion de voir ce qu’il a de nouveau sous le capot.
Commençons donc par la classe ColorMatrixFilter.
Unique prérequis, qui facilitera la compréhension des exemples AS 2.0: Vous vous êtes déjà familiarisés quelque peu avec l’utilisation du package flash.filters.
- ColorMatrixFilter, de quoi s’agit-il ?
Ce filtre applique une matrice de transformation sur les valeurs de couleur et alpha RGBA de chaque pixel d’une image en entrée pour produire une image résultat avec un nouveau jeu de valeurs.
- Mais qu’est ce qu’une matrice pour commencer ?
Une matrice, c’est un tableau bi-dimensionnel de réels constitué de lignes et colonnes.
Une matrice 4×5 est donc ni plus ni moins un tableau contenant 4 lignes et 5 colonnes.
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ]
- Voici maintenant la formule de base qui permet de recalculer le RGBA d’une image à partir d’une matrice 4×5 de valeurs, c’est à dire en pratique, à partir d’un Array composé de 20 réels indexés de 0 à 19 (comme ci-dessus).
Red = (a[0]*Red) + (a[1]*Green) + (a[2]*Blue) + (a[3]*Alpha) + a[4] Green = (a[5]*Red) + (a[6]*Green) + (a[7]*Blue) + (a[8]*Alpha) + a[9] Blue = (a[10]*Red) + (a[11]*Green) + (a[12]*Blue) + (a[13]*Alpha) + a[14] Alpha = (a[15]*Red) + (a[16]*Green) + (a[17]*Blue) + (a[18]*Alpha) + a[19]
Comme vous pouvez le remarquer, pour calculer la valeur finale de chacun des 4 canaux, on multiplie la valeur d’origine de chaque pixel de l’image par la valeur correspondante de la matrice de transformation et on ajoute au total (si stipulée, c’est à dire non nulle) une valeur offset (située entre -255 et 255), respectivement les valeurs indexées 4, 9, 14 et 19.
- Voici maintenant une matrice d’identité, c’est à dire une matrice carrée, dont tous les composants sont nuls sauf les éléments de la première diagonale qui valent un (on fait ici abstraction de la 5ème colonne, les valeurs offsets).
[1,0,0,0,0,
0,1,0,0,0,
0,0,1,0,0,
0,0,0,1,0];
Faisons le calcul du résultat :
Red = (1*Red) + (0*Green) + (0*Blue) + (0*Alpha) + 0 Green = (0*Red) + (1*Green) + (0*Blue) + (0*Alpha) + 0 Blue = (0*Red) + (0*Green) + (1*Blue) + (0*Alpha) + 0 Alpha = (0*Red) + (0*Green) + (0*Blue) + (1*Alpha) + 0
On obtient au final: Red = (1*Red)
Green = (1*Green)
Blue = (1*Blue)
Alpha = (1*Alpha)
Autrement dit:
Red = Red
Green = Green
Blue = Blue
Alpha = Alpha
Cette matrice a donc pour particularité d’appliquer aucune transformation sur les valeurs RGBA d’une image. Elle map chacun des composants à sa valeur initiale.
Elle constitue donc en définitive un bon point de départ pour toutes vos expérimentations.
- Nous allons maintenant créer le négatif d’une image. On affecte à chacun des canaux (RGB) sa valeur maximale à laquelle on retranche la valeur initiale de l’image.
[ -1, 0, 0, 0, 255, 0, -1, 0, 0, 255, 0, 0, -1, 0, 255, 0, 0, 0, 1, 0]
C’est à dire:
Red = 255 – Red
Green = 255 – Green
Blue = 255 – Blue
Alpha = Alpha
import flash.filters.*; var negativeTransform:ColorMatrixFilter = new ColorMatrixFilter( new Array ( -1, 0, 0, 0, 255, 0, -1, 0, 0, 255, 0, 0, -1, 0, 255, 0, 0, 0, 1, 0 )); // On applique le filtre à une occurrence en le passant en argument // à l'intérieur d'un tableau. // Ce tableau représente la liste des filtres à appliquer. // Le MovieClip sera mis automatiquement en cache bitmap // (cacheAsBitmap == true) afin d'être traité comme une image. mc.filters = [ negativeTransform ];
NB: Si l’array contient plusieurs filtres, l’indexage de ceux-ci n’est pas anecdotique. Il s’agit de l’ordre dans lequel vont être appliqués les différents traitements sur le clip cible.
Après cette entrée en matière, vous disposez maintenant des outils nécessaires pour aborder les différents algorithmes disponibles sur le sujet.
Pour constituer des exemples pratiques en AS 2.0, nous allons partir d’un article qui fait référence dans le domaine:
Matrix Operations for Image Processing par Paul Haeberli.
-Premier exemple:
Converting to Luminance
Pour convertir une image en noir et blanc, on utilise cette matrice:
float mat[4][4] = { rwgt, rwgt, rwgt, 0.0, gwgt, gwgt, gwgt, 0.0, bwgt, bwgt, bwgt, 0.0, 0.0, 0.0, 0.0, 1.0, };
Où rwgt vaut 0.3086, gwgt 0.6094, et bwgt is 0.0820. This is the luminance vector.
Ce qui nous donne en ActionScript:
import flash.filters.*; // La luminance, c'est la partie du signal vidéo qui contient les informations // concernant l'intensité lumineuse, ou brillance, de chaque point. // En clair, il s'agit de la trame noire et blanc de l'image. // Voici les constantes pour la conversion. // Certaines personnes utilisent les valeurs .299, .587, et .114 du modèle colorimétrique YIQ. // Mais Paul Haeberli spécifie bien que les valeurs ci-dessous sont meilleures pour du RGB linéaire. var rwgt:Number = .3086; var gwgt:Number = .6094; var bwgt:Number = .0820; // Charles A. Poynton conseille (dans le faq colorspace) d'utiliser .212671, .715160 et .072169. var luminanceTransform:ColorMatrixFilter = new ColorMatrixFilter( new Array ( rwgt, gwgt, bwgt, 0.0, 0.0, rwgt, gwgt, bwgt, 0.0, 0.0, rwgt, gwgt, bwgt, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 )); mc.filters = [ luminanceTransform ];
-Deuxième exemple à partir de l’étude d’Haeberli:
Changing Brightness
To scale RGB colors a matrix like this is used:
float mat[4][4] = { rscale, 0.0, 0.0, 0.0, 0.0, gscale, 0.0, 0.0, 0.0, 0.0, bscale, 0.0, 0.0, 0.0, 0.0, 1.0, };
Où rscale, gscale, et bscale specifient les valeurs offset à appliquer sur les valeurs RGB. On peut utiliser cette matrice pour modifier la balance des couleurs d’une image.
Ce qui nous donne en ActionScript:
import flash.filters.*; // On utilise directement des valeurs offsets pour ajuster de manière uniforme les valeurs RGB. function getBrightnessTransform( scale:Number ) : Array { return new Array ( 1.0, 0.0, 0.0, 0.0, scale, 0.0, 1.0, 0.0, 0.0, scale, 0.0, 0.0, 1.0, 0.0, scale, 0.0, 0.0, 0.0, 1.0, 0 ); } mc.filters = [ new ColorMatrixFilter( getBrightnessTransform( 100 ) ) ];
-Un dernier exemple pour finir, toujours à partir de l’étude d’Haeberli:
Modifying Saturation
Pour saturer les couleurs RGB, on utilise cette matrice:
float mat[4][4] = { a, b, c, 0.0, d, e, f, 0.0, g, h, i, 0.0, 0.0, 0.0, 0.0, 1.0, };
Où les constantes de luminances sont dérivées à partir de la valeur de saturation comme montré ci-dessous:
a = (1.0-s)*rwgt + s; b = (1.0-s)*rwgt; c = (1.0-s)*rwgt; d = (1.0-s)*gwgt; e = (1.0-s)*gwgt + s; f = (1.0-s)*gwgt; g = (1.0-s)*bwgt; h = (1.0-s)*bwgt; i = (1.0-s)*bwgt + s;
Ce qui nous donne en ActionScript:
import flash.filters.*; var rwgt:Number = .3086; var gwgt:Number = .6094; var bwgt:Number = .0820; function getSaturationTransform ( sat:Number ) : Array { var rl:Number = rwgt * (1 - sat); var gl:Number = gwgt * (1 - sat); var bl:Number = bwgt * (1 - sat); return new Array ( rl+sat, gl, bl, 0, 0, rl, gl+sat, bl, 0, 0, rl, gl, bl+sat, 0, 0, 0, 0, 0, 1, 0 ); } mc.filters = [ new ColorMatrixFilter( getSaturationTransform( 3 ) ) ];
Pour finir, voici quelques liens:
- Colorspace-faq — FAQ about Color and Gamma par Charles A. Poynton.
- Matrix Operations for Image Processing par Paul Haeberli
- Using Flash Player 8 filters for good par Tinic Uro.
- Flash8 source color matrix par Grant Skinner.
- Flash 8: ColorMatrix par Mario Klingemann.
J’espère que ces explications et quelques liens vous donneront envie de passer à l’action, coder vos propres classes et vous lancer dans des expérimentations graphiques inédites.
Merci pour cette instant de détente
Il me tente de pouvoir essayer tout ça, vite des vacances !
Posted by ali_o_kan | 21 septembre 2005, 0 h 47 minon imprime ça demain,
cool du boulot !
Posted by Clément Hussenot | 21 septembre 2005, 0 h 50 min:-/
T’es trops fort Petepx.
Merci :love
PS :
On pourrait peut-être regrouper tous ces effets en tant que
méthodes statiques d’une classe qui hériterait de ColorMatrixFilter…
Posted by Tonio | 21 septembre 2005, 1 h 51 minRe moi pour une ptite précision :
Dans quel interval sont compris les valeurs de la matrice ?
M[4], M[9], M[14] et M[19], sont compris entre -255 et 255 je crois ?
Et les autre je crois entre -1 et 1 ?
Ou est-ce qu’on peut dépasser 1 ou -1 ?
Sinon est-ce qu’on utilise vraiment toutes les valeurs ?
:hot
Nottament celle concernant l’alpha ?
Fait chaud jvais m’coucher
Posted by Tonio | 21 septembre 2005, 2 h 22 minMerci infiniment pour cette excellent tutorial Pete
Grâce à toi c’est beaucoup plus clair.
Merci encore !
Posted by jeanphilippe | 21 septembre 2005, 6 h 37 minNe serait ce pas plutot :
function getBrightnessTransform( scale:Number ) : Array
{
var s:Number = 0.01 * scale;
return new Array (
s, 0.0, 0.0, 0.0, 0,
0.0, s, 0.0, 0.0, 0,
0.0, 0.0, s, 0.0, 0,
0.0, 0.0, 0.0, 1.0, 0
);
}
Posted by zemax | 21 septembre 2005, 9 h 51 minTonio : je crois que Lalex vient de terminer sa classe XColor, ca devrait répondre à ta demande.
Merci encore pour cet excellent article Francis, qui tend à prouver une chose : Flash8 a gagné en richesse autant qu’en complexité. Ce qui pour moi est une excellente chose :cat
Posted by Aggelos | 21 septembre 2005, 10 h 41 mintonio,
M[4], M[9], M[14] et M[19] sont compris entre -255 et 255.
Dans la majorité des cas, pour les autres valeurs, on utilisera des valeurs entre -1 et 1 pour préserver la luminosité de l’image.
Mais rien n’interdit d’utiliser d’autres valeurs pour créer des effets hors norme. Contrairement à ce que l’on pourrait croire, n’y a aucune règle établie à ce sujet.
Sinon, les valeurs alpha sont utiles aussi.
Tu peux reprendre la matrice d’identité et changer juste la valeur du composant alpha. Comme stipulé dans la doc, tu gagneras en performance par rapport à une transformation classique.
[1, 0, 0, 0,
0, 0, 1, 0,
0, 0, 0, 0,
1, 0, 0, 0,
0, 0, A, 0]
Il est possible aussi de créer une alpha map comme ci-dessous:
[0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,1,0,0]
Ici, on passe la valeur du canal bleu en alpha et on vire le reste de l’information.
zemax,
Si on reprend la formule d’Haeberli, on part du postulat :
tr = r*rscale;
tg = g*gscale;
tb = b*bscale;
Au final donc, utiliser une matrice d’identité et jouer sur les valeurs offsets revient au même au niveau du résultat (on fait varier le RGB de manière symétrique) et permet d’optimiser les calculs.
aggelos,
la classe de LAlex utilise ColorTransform, ce qui ne répond pas tout à fait à la demande de tonio
par contre tonio tu trouveras ton bonheur dans les liens postés ci-dessus (cf: Grant Skinner et Mario Klingemann)
Posted by Francis Bourre | 21 septembre 2005, 11 h 36 minIl est possible aussi de créer une alpha map comme ci-dessous:
[0,0,0,0,0,
0,0,0,0,0,
0,0,0,0,0,
0,0,1,0,0]
Ici, on passe la valeur du canal bleu en alpha et on vire le reste de l’information.
Pourquoi la valeur bleu ?
Arff… je comprends pas bien ce passage
merci
Posted by jeanphilippe | 21 septembre 2005, 12 h 06 minjeanphilippe,
le bleu c’était juste pour l’exemple.
Une alpha map est une image en niveaux de gris, où le noir est transparent, et le blanc solide.
Si tu appliques la transformation ci-dessus, tu obtiendras une alpha map de ton image où le canal bleu est considéré comme invisible.
Posted by Francis Bourre | 21 septembre 2005, 13 h 42 minmerci pour l’expli Francis
c’est nikel ça marche !
Posted by jeanphilippe | 21 septembre 2005, 13 h 51 minPlus exactement pour obtenir un brightness identique à celui que l’on a dans l’IDE de Flash, il faut utiliser cette transformation (avec scale compris entre 0 et 100) :
function getBrightnessTransform2( scale:Number ) : Array {
var s = 1 – 0.01 * scale;
var o = 2.55 * scale;
return new Array (
s, 0.0, 0.0, 0.0, o,
0.0, s, 0.0, 0.0, o,
0.0, 0.0, s, 0.0, o,
0.0, 0.0, 0.0, 1.0, 0
);
}
Posted by zemax | 22 septembre 2005, 11 h 22 minRien à voir avec l’article, mais je ne sais pas si il y a encore de la peinture un peu fraiche sur le design de ce blog, donc je te propose de rajouter cette régle css :
pre {
font-size:0.9em;
margin:0.5em;
width:90%;
padding:0.5em;
overflow:auto;
}
Sinon, ça casse un peu la mise en page
Y a aussi un plug-ins geshi pour actionscript
avec lien vers la doc du wiki de média-box :
media-box.net/index.php/2…
Cordialement,
Posted by [ NikO ] | 22 septembre 2005, 17 h 08 minDis moi pete,
c’est quoi la police que tu utilise pour tes titre :
http://www.tweenpix.net/blog/the...
Merci
Posted by Mark | 24 septembre 2005, 12 h 32 minNiko, effectivement il y a de la peinture fraiche partout. Merci pour ton feedback.
Sinon pour la version Geshi/Mediabox, je ne suis pas super chaud, et ce pour plusieurs raisons. La doc est assez incomplète, j’aime pas le look syntaxe en hyperlien et quitte à linker une doc, je préfèrerais que cela soit les livedocs de MM et leurs commentaires constructifs.
Merci en tout cas pour la suggestion!
Mark, pour les fonts :
HelveticaNeue UltraLigExt, Frutiger LT 87 ExtraBlackCn et Arial.
Posted by Francis Bourre | 26 septembre 2005, 22 h 14 minMerci
Posted by Mark | 28 septembre 2005, 21 h 25 minTu pourrais pas me l’envoyé sur msn ou hotmail, parceque j’ai pas 22€ pour la payé :s
Posted by Mark | 28 septembre 2005, 21 h 55 minBen Mark non mais ça va pas bien? Tu te crois sur un site warez? :non
Posted by rosyflower | 29 septembre 2005, 21 h 03 minSi dans la vie on peu plus rire.
M’enfin je l’ais, c’est le principal
Posted by Mark | 30 septembre 2005, 17 h 08 minbonjour bonjour,
Je viens juste d’installer flash8 (on peut pas dire qu’ils ont chomer) et je suis un peu perdu avec tout ces package en plus. Donc vu que moi et les maths on peut pas dire qu’on soit super pote la class ColorMatrixFilter me perturbe un peu (d’ailleurs l’ensemble des filtre est obscure pour moi là lol). Si j’ai bien comprit pour faire simple, on peut directecment agir sur les couches de l’image et notemment l’alpha, mais quel est vraiment la difference entre cette class et la class Color (ou l’on pouvait deja agir sur les couches). De plus ‘jai du mal a voir comment on peut modifier ses valeurs grave a des tweens.
C’est pas brillant je sais mais là i’m totally largued :hot
En tout cas felicitation pour tout ces pitits billets :frog
Posted by Gauthier | 4 octobre 2005, 11 h 12 mindemandes à rosy, elle maîtrise bien tout ça.
Posted by patrouscou | 4 octobre 2005, 17 h 36 minI’m not french, I don’t speak french, only learnt a little at school, but with your examples I can still work out what’s going on – great article mate!
Posted by Jon B | 18 octobre 2005, 17 h 32 minJe te remercie pas seulement pour l’article mais du fait que tu proposes le CSS convenable à l’impression!
Posted by Alan Shaw | 18 octobre 2005, 20 h 59 minGreat article – Superbe article!!
Do you have a Matrix to convert a color image to SEPIA tone (old-color images)?
As-tu une matrix pour transformer une image en color `a SEPIA tone(c’est comme le vieille images en couleur)
Merci d’avance
Posted by alanfox70 | 27 octobre 2005, 16 h 07 minTu peux essayer une matrice dans ce genre :
[code]
import flash.filters.ColorMatrixFilter ;
function getSepia( r, g, b ) {
var r = 2.83 ;
var sepia:Array = [
r * 0.393 , g * 0.749 , b * 0.189 , 0.0 , 0.0 ,
r * 0.349 , g * 0.686 , b * 0.168 , 0.0 , 0.0 ,
r * 0.272 , g * 0.534 , b * 0.131 , 0.0 , 0.0 ,
0.0 , 0.0 , 0.0 , 1.0 , 1.0 ,
0.0 , 0.0 , 0.0 , 0.0 , 1.0
]
return new ColorMatrixFilter( sepia ) ;
}
var r = 2.83 ;
var g = 2.83 ;
var b = 2.83 ;
mc.filters = [ getSepia( r, v, b) ];
[/code]
En cherchant un peu sur google tu peux trouver des liens comme :
msdn.microsoft.com/msdnma…
intéressant à ce sujet aussi
Posted by ekameleon | 28 octobre 2005, 0 h 16 min
Posted by sipion | 30 novembre 2005, 17 h 01 minTu trouveras surment plus d’infos sur flash.media-box.net
Posted by ali_o_kan | 30 novembre 2005, 19 h 09 min