Bild von RGB in HSL, dann Änderungen und wieder zurück

nhoj

Mitglied
Ich möchte Benutzern die Möglichkeit geben, die Farbe von Bildern online zu ändern. Da das auf RGB-Basis nur schwer nachvollziehbar ist, möchte ich die Bilder zunächst in den HSL-Farbraum umwandeln, dann die entsprechenden Werte ändern und das Bild wieder in den RGB-Farbraum zurückkonvertieren.

Im Moment gehe ich so vor, dass ich den RGB-Wert für jedes einzelne Pixel auslese und in den entsprechenden HSL-Wert umwandle, dann die Änderungen hinzufüge und das Bild wieder zurückkonvertiere. Allerdings ergeben sich dadurch unschöne "Pixelflecken" im Bild (Originalbild/ Geändertes Bild). Außerdem scheint die Umwandlung nur bei jpeg Bildern zu funktionieren, bei gif wird abgesehen von Grautönen nur weiß angezeigt.

Mein Code sieht bis jetzt wie folgt aus und ist größtenteils eine Umsetzung von folgender Seite (http://accessibility.kde.org/hsl-adjusted.php):
PHP:
$img = imagecreatefromjpeg('bild.jpeg');
$width = imagesx($img);
$height = imagesy($img);
$hue_shift = 60;

// Feste Werte
$fr = 0.2126;
$fg = 0.7152;
$fb = 0.0722;
$f0 = $fr;
$f1 = $fg;

for ($x=0;$x<$width;$x++) {
	for ($y=0;$y<$height;$y++) {
		$rgb = imagecolorat($img,$x,$y);
		$R = ($rgb >> 16) & 0xFF;
		$G = ($rgb >> 8) & 0xFF;
		$B = $rgb & 0xFF;
		
		$Nr = pow(($R/255),2.2);
		$Ng = pow(($G/255),2.2);
		$Nb = pow(($B/255),2.2);
		$N1 = max($Nr,$Ng,$Nb);
		$Nm1 = min($Nr,$Ng,$Nb);		
		$N0 = $Nr; 
		if (($N0 > $Ng && $N0 > $Nb) || ($N0 < $Ng && $N0 < $Nb)) $N0 = $Ng;
		if (($N0 > $Nr && $N0 > $Nb) || ($N0 < $Nr && $N0 < $Nb)) $N0 = $Nb;
		
		// Es handelt sich um einen Grauton, die Farbe kann nicht geandert werden
		if ($N1 == $Nm1)
			continue;
		
		$L = $fr * $Nr + $fg * $Ng + $fb * $Nb;
		$m = $f1 + $f0 * ($N0-$Nm1) / ($N1-$Nm1);
		$D = min($L/$m,(1-$L) / (1-$m));
		
		$_h = 1 - abs($hue_shift%120/60 - 1);
		$_m = $f1 + $f0 * $_h;
		$_D = min($L / $_m, (1-$L) / (1-$_m));
		
		$_N1 = $L + (1-$_m)*($N1-$Nm1) * $_D/$D;
		$_N0 = $L + ($_h-$_m)*($N1-$Nm1) * $_D/$D;
		$_Nm1 = $L + $_m*($N1-$Nm1) * $_D/$D;		
		$_Nr = ($Nr==$N1?$_N1:($Nr==$N0?$_N0:$_Nm1));
		$_Ng = ($Ng==$N1?$_N1:($Ng==$N0?$_N0:$_Nm1));
		$_Nb = ($Nb==$N1?$_N1:($Nb==$N0?$_N0:$_Nm1));
		
		$_R = 255*pow($_Nr,1/2.2);
		$_G = 255*pow($_Ng,1/2.2);
		$_B = 255*pow($_Nb,1/2.2);
		
		$img_color = imagecolorallocate($img,$_R,$_G,$_B);
		imagesetpixel($img,$x,$y,$img_color);
	}
}


header('Content-Type: image/jpeg');
imagejpeg($img,'',100);
 
Zuletzt bearbeitet:
Weil das einfacher und intuitiver zu bedienen ist als RGB. Der Farbton lässt sich z.B. unabhängig von der Helligkeit ändern.
 
Ok, das stimmt.

Deine Pixelflecken sehen aus, als wenn der RGB-Wert ausserhalb von 0-255 liegt.
Mal überprüft, ob die einzelnen RGB-Kanäle saubere RGB-Werte liefern ?

Teilweise sieht es auch fast so aus, als wenn die RGB-Werte gerundet werden.
Ok, kann mich irren, ist nur so ein Vermutung.
 
Mittlerweile habe ich dieses Problem gelöst und das Script funktioniert, allerdings liegt die Ausführungszeit im Bereich von 30 Sekunden. Hat jemand eine Idee wie man das noch verkürzen könnte?
 
Aha, wie haste das denn nun gelöst ?

Naja, an der Ausführungszeit kann man nicht viel machen, wenn das Bild Pixelweise bearbeitet wird.
 
Zurück