Convertir image avec palette de couleur donnée

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Convertir image avec palette de couleur donnée

Re: Convertir image avec palette de couleur donnée

par ndkdesign » 14 mars 2012, 15:51

Salut, je viens de tomber sur cette fonction qui semble tout à fait répondre à mon besoin : Modifier les couleurs d'une image avec une palette définie.
Etant novice en php, pourrais tu me dire comment utiliser cette fonction, pour que lui envoyant mon image source, elle me retourne l'image modifiée?

Merci beaucoup.

par matique » 11 févr. 2006, 18:32

Bonjour,

Voici la version finale de mon algo, revue et corrigée :
	private function setCouleurs(){
		$netb = true;
		$niveauxGris = true;
		$palette = Array(Array(0,0,0),	//noir
					Array(128,128,128),  //gris
					Array(128,0,0),		//marron
					Array(255,0,0),		//rouge
					Array(0,128,0),		//vert fonce
					Array(0,255,0),		//vert
					Array(128,128,0),     //olive
					Array(255,255,0),     //jaune
					Array(0,0,128),		//marine
					Array(0,0,255),		//bleu
					Array(128,0,128),     //violet
					Array(255,0,255),     //fuchsia
					Array(0,128,128),     //cobalt
					Array(0,255,255),     //aqua
					Array(192,192,192), //argent
					Array(255,255,255), //blanc
					Array(255,128,0)     //orange
		);
		//palette pondérée et initialisée à 0
		$paletteDom = Array(17);
		for ($i = 0 ; $i < 17 ; $i++)$paletteDom[$i]=0;

		$xMini = (int)ImageSX($this->miniature);
		$yMini = (int)ImageSY($this->miniature);
		// on parcours chaque pixel de la miniature pour regarder sa couleur 
		for ($i=0 ; $i < $xMini; $i++) {
			for ($j=0 ; $j < $yMini ; $j++) {
				$pixel = ImageColorAt($this->miniature,$i,$j);
				if ($pixel != 0 || $pixel != 16777215) $netb = false;
				$r = ($pixel >> 16) & 0xFF;
				$v = ($pixel >> 8) & 0xFF;
				$b = $pixel & 0xFF;
				if ($r != $v || $v != $b || $r != $b) $niveauxGris = false;

				$distMin = 1000000000; $indCoulProche = 0;
				//on determine quelle couleur de la palette est la plus proche de celle du pixel
				//en evaluant leur distance
				for ($k=0 ; $k < count($palette) && $distMin != 0 ; $k++) {
					$distance = pow($palette[$k][0] - $r,2) + pow($palette[$k][1] - $v,2) + pow($palette[$k][2] - $b,2);
					if ($distance < $distMin){
						$distMin = $distance;
						$indCoulProche = $k;
					}
				}
				//on incremente la pondération de a couleur la plus proche
				$paletteDom[$indCoulProche]++;
			}
		}
		print_r($paletteDom);
		$max = 0;
		foreach ($paletteDom as $key => $val)if ($val > $max){$max = $val;$indDom = $key;}
		$this->couleurDominante = hexdec(dechex($palette[$indDom][0]).dechex($palette[$indDom][1]).dechex($palette[$indDom][2]));

		if ($netb)$this->coloration = 1;			//noir et blanc
		else if ($niveauxGris)$this->coloration = 2;//niveaux de gris
		else $this->coloration = 3;					//couleur
	}

par albat » 08 févr. 2006, 20:31

Pas grave. Tu seras fouetté... :twisted:

par matique » 08 févr. 2006, 18:57

Oups désolé je ne m'était pas connecté !
Dommage je ne peux plus rééditer maintenant !

par Invité » 08 févr. 2006, 18:53

Bonjour,

Voici ma methode complete pour ceux que ca interessent.

Elle realise le calcul de couleur dominante a partir d'un palette, dit si l'image est en couleur, noir et blanc ou niveaux de gris.

Désolé je n'est pas encore eu trop le temps de la commenté ni vraiment de la tester !
private function setCouleurs()
{
$netb = true;
$niveaugris = true;
$palette = Array([0]=>Array(0,0,0), //noir
[1]=>Array(128,128,128), //gris
[2]=>Array(128,0,0), //marron
[3]=>Array(255,0,0), //rouge
[4]=>Array(0,128,0), //vertfoncé
[5]=>Array(0,255,0), //vert
[6]=>Array(128,128,0), //olive
[7]=>Array(255,255,0), //jaune
[8]=>Array(0,0,128), //marine
[9]=>Array(0,0,255), //bleu
[10]=>Array(128,0,128), //violet
[11]=>Array(255,0,255), //fuchsia
[12]=>Array(0,128,128), //cobalt
[13]=>Array(0,255,255), //aqua
[14]=>Array(192,192,192),//argent
[15]=>Array(255,255,255),//blanc
[16]=>Array(255,128,0) //orange
);


for ($i=1 ; $i < ImageSX($this->miniatureNonReechantillonnee) ; $i++) {
for ($j=1 ; $j < ImageSX($this->miniatureNonReechantillonnee) ; $j++) {

$pixel = ImageColorAt($miniatureNonReechantillonnee,$i,$j);

if ($pixel != 0 || $pixel != 255255255) $netb = false;

$r = ($pixel >> 16) & 0xFF;
$v = ($pixel >> 8) & 0xFF;
$b = $pixel & 0xFF;

if ($r != $v || $v != $b || $r != $b) $niveaugris = false;
$distMin = 1000;
for ($k=0 ; $k < count($palette) && $disMin != 0 ; $k++) {
$distance = pow($palette[$k][0] - $r,2) + pow($palette[$k][1] - $v,2) + pow($palette[$k][2] - $b,2);
if ($distance < $distMin){$disMin = $distance;$indCoulProche = $k;}
}
$paletteDom[$indCoulProche]++;
}
}

$max = 0;
foreach ($paletteDom as $key => $val)if ($val > $max)$this->couleurDominante = $key);
$this->couleurDominante = $this->couleurDominante[0].$this->couleurDominante[1].$this->couleurDominante[2];

if ($netb)$this->coloration = 1;
else if ($niveaugris)$this->coloration = 2;
else $this->coloration = 3;
}

par matique » 07 févr. 2006, 19:00

Oui bien sur que celui la marche car 55 est très proche de 66.
Mais le probleme est de savoir si l'algo marche pour 55 et DD qui eux sont relativement éloignés alors que DDDDDD reste du gris !

De toutes facons j'ai une idée dans la tete pour calculer la distance entre deux couleurs !
Je vais d'ailleurs m'inspirer du fameux algo de math intégré a levenstein qui sert a calculer la distance entre deux mots !
J'espere avoir des resultats convainquants !

Je posterais l'algo par la suite si les résultats sont fiables !

Encore merci pour votre aide !

par albat » 07 févr. 2006, 18:36

#555555 devrait être très proche de #DDDDDD
:shock:

Selon l'exemple que je t'ai donné, #555555 :arrow: #666666
Ça reste un gris, à peine plus clair.

par matique » 07 févr. 2006, 18:27

Merci pour ta réponse.

Toutefois je ne suis pas sur que le rendu de cette méthode soit vraiment fiable. Je pense notamment au gris ou R = V = B ou par exemple #555555 devrait être très proche de #DDDDDD.

Enfin, peut être que je me trompe...

par albat » 07 févr. 2006, 15:47

Mathématiquement parlant, je pense qu'il te faut concevoir un algorithme
qui attribue la valeur standard pour chacune des composantes R, V et B.

Supposons que pour chacune de ces 3 composantes, tu aies 6 valeurs : 00, 33, 66, 99, CC et FF
ce qui te permet de définir ta palette de couleurs "standard" : 33CC00, FF6699, etc.

Ton algorithme récupère la couleur proposée : E42F88, par exemple
et en isole les 3 composantes : E4, puis 2F, puis 88

Il les compare individuellement aux valeurs standard : 00, 33, 66, ...
et les remplace par la valeur standard la plus proche.

E4 est plus proche de CC que de FF
2F est plus proche de 33 que de 00
88 est plus proche de 99 que de 66
E42F88 :arrow: CC3399

Convertir image avec palette de couleur donnée

par matique » 07 févr. 2006, 14:35

Bonjour,

Je souaiterais convertir une image en restreignant sa palette de couleurs à une palette de couleurs que j'ai definit.

Par exemple : j'ai une image en couleur vraie et je veux qu'elle soit recalculée en utilisant les couleur bleu vert et rouge.
Pour chaque pixel cette fonction chercherait ainsi si la couleur du pixel est plus proche du rouge, du bleu ou du vert !

C'est en fait la meme chose que de convertir une image en 256 couleurs (cas du gif par exemple) sauf que c'est moi qui donne les couleurs !

Je pense a un algo mais je ne sais pas s'il est possible de calculer la distance entre une couleur et une autre ? (en code hexa par exemple)

Merci beaucoup pour cette aide precieuse qui va me servir a calculer la couleur dominante d'une image de maniere fiable.