PHP Starkes Aliasing bei rotate

Kagee

Lt. Junior Grade Pro
Registriert
Feb. 2005
Beiträge
446
Hallo! Ich habe ein Problem.

Ich habe ein Uploadskript, welches die Grafik auch noch bearbeiten soll. Ziel ist es, das Bild in einen Polaroid-Stil zu bekommen. Dazu muss ich die Grafik skalieren, beschneiden und drehen.

Nun zu meinem Problem:
Ich bin gezwungen im ersten Schritt die Grafik zu skalieren, da sonst beim Drehen zu große Dateien enstehen.

Ich gehe also wie folgt vor:

- Skalieren
- Beschneiden
- Drehen
- In Polaroid-Master einsetzen

Nun entsteht das Problem, dass beim Drehen ein starkes Aliasing entsteht. Ich Drehe mit Hintergrundfarbe weiß und setze das dann in die polariod-vorlage ein

Ein Beispiel:
340.jpg


Hier seht man sehr schöne den Treppeneffekt. Kann ich es irgendwie hinbekommen, dass das besser berechnet wird beim drehen? Es gibt ja die Antialiasing-Einstellung für Bilder in PHP, jedoch bin ich nicht sicher, wie ich die einsetzen soll, da das Bild beim Drehen ja erst erzeugt wird:

bool imageantialias ( resource $image , bool $enabled )

Hier ist das momentane Skript (Speicherfreigaben sind noch nicht drin)

mein Skript:
PHP:
// File and rotation
								$degrees = -3.3;
								
								// laden des Bilds
								$source = imagecreatefromjpeg($path.$img_ordner.$filename);
								$resized = imagecreatetruecolor(220,165);
								$cropped = imagecreatetruecolor(220,165);
								
								//berechne den Beschneidungsteil
								$percW = imagesx($source)/220;
								$percH = imagesy($source)/165;
								
								//Breite-Koeffizient kleiner -> auf Breite skalieren und Höhe zuschneiden
								if($percW < $percH)
								{
									//skalieren
									$resized = imagecreatetruecolor(220,imagesy($source)/$percW);
									imagecopyresampled($resized,$source,0,0,0,0,220,imagesy($source)/$percW ,imagesx($source),imagesy($source));
									imageCopy($cropped,$resized,0,0,0,(imagesy($resized)-165)/2,220,165);
									
									$ausgabe.=  'Ursprung: '.imagesx($source).'x'.imagesy($source).'<br />';
									$ausgabe.= 'Skaliert auf: '.imagesx($resized).'x'.imagesy($resized).'<br />';
									$ausgabe.=  'Beschnitten auf: '.imagesx($cropped).'x'.imagesy($cropped).'<br />';
									
								}
								//Höhen-Koeffizient kleiner --> auf Höhe skalieren und Breite zuschneiden
								else
								{
									$resized = imagecreatetruecolor(imagesx($source)/$percH,165);
									imagecopyresampled($resized,$source,0,0,0,0,imagesx($source)/$percH,165 ,imagesx($source),imagesy($source));
									imageCopy($cropped,$resized,0,0,(imagesx($resized)-220)/2,0,220,165);
									
									$ausgabe.= 'Ursprung: '.imagesx($source).'x'.imagesy($source).'<br />';
									$ausgabe.= 'Skaliert auf: '.imagesx($resized).'x'.imagesy($resized).'<br />';
									$ausgabe.=  'Beschnitten auf: '.imagesx($cropped).'x'.imagesy($cropped).'<br />';
								}
								
								
								
								//drehen
								$weiss = imagecolorallocate($cropped ,0xFF,0xFF,0xFF);
								imageantialias($cropped ,true);   //!scheint keinen Effekt zu haben!
								imagealphablending($cropped ,true);   //!scheint keinen Effekt zu haben!
								$rotated = imagerotate($cropped , $degrees, $weiss ,1);
								$ausgabe.=  'Gedreht um: '.$degrees.' Grad<br />';
								
								
								//laden des masters
								$master = imagecreatefromjpeg($path.'photoMaster.jpg');
								

								ImageCopy($master,$rotated,21,20,0,0, imagesx($rotated),imagesy($rotated));
								
								// Output
								imagejpeg($master,$path.$img_ordner.$filename,90);
 
Kagee schrieb:
Kann ich es irgendwie hinbekommen, dass das besser berechnet wird beim drehen? Es gibt ja die Antialiasing-Einstellung für Bilder in PHP, jedoch bin ich nicht sicher, wie ich die einsetzen soll, da das Bild beim Drehen ja erst erzeugt wird:
genau dort greift doch aber das aliasing - beim verarbeiten. du setzt mit der funktion wahrscheinlich einfach nur ein flag innerhalb des moduls und daraufhin wird bei jeder veränderung anti aliasing angewandt. das beispiel zeigts auch schön auf: bild erstellen, funktion aufrufen, bild bearbeiten, bild anzeigen/speichern. an deiner stelle würde ich nun (falls du es so machst), das bild laden und danach erst die aliasing funktion aufrufen.

ggf. solltest du auch mal nach lanczos oder spline resampling algorithmen suchen. sind zwar ein wenig rechenaufwändig, aber das ergebnis ist das beste beim resampling.
 
Das einfachste ist hier FSAA.. kannst du erreichen, indem du das zu drehende Bild z.B. auf die doppelte Größe bringst (jede Seite verdoppelt), es dann drehst und das Ergebnis auf die Hälfte der Größe schrumpfst (ggf. mit bikubischem Filter). Das reduziert dir die Aliasing-Effekte schon ganz enorm.

imageantialias hat nur Effekte auf Linien und Polygone. Nicht auf Bilder!
 
Alternative ist, das du das Bild nach allen Aktionen durch ein Imagemagick das auf dem Server installiert ist jagst. Das hat ohnehin einen viel besseren AntiAliasing Filter wie die GD Lib und müsste auch auf Bilder funzen.
 
danke für die Antworten!

Ich hatte schon die Befürchtung, dass es ohne zusätzliche Mittel nicht geht.

Ich habe es nun tatsächlich mit der GD-Library hinbekommen.

Falls jemand auf ein ähnliches Problem stößt:

Offensichtlich arbeitet die imagerotate-Funktion der GD Library beim Erweitern der Grafik etwas unsauber. Wie oben am Bild zu sehen ist, sind diese starken Treppeneffekt nur am unteren, linken und rechten Rand zu sehen, nicht aber am oberen.
Lösung war hier, bevor man dreht 2 Pixel an jeder Kante eine Linie in der Hintergrundfarbe des Drehvorgangs zu zeichnen - in meinem Fall weiß. Ich habe also das gesamt Bild mit einem 2 Pixel starken Rahmen versehen - und sie da, jede Kante ist korrekt Anti-aliased. (Was nicht heißen soll, dass die o.g. Möglichkeiten das nicht noch besser hinbekommen).

(Wenn die Grafik die vorgeschriebenen Maße haben soll, einfach vor dem Drehen eine um 4 Pixel in jeder Achse größere Grafik erstellen und dann die zu drehende Grafik einfügen.

PHP:
$weiss = imagecolorallocate($cropped ,0xFF,0xFF,0xFF);
//2 Weiße Rechtecke für einen 2-Pixel-Rahmen
imagerectangle  ($cropped,0,0, imagesx($cropped)-1,imagesy($cropped)-1,$weiss);
imagerectangle  ($cropped,1,1, imagesx($cropped)-2,imagesy($cropped)-2,$weiss);
//drehen
$rotated = imagerotate($cropped , $degrees, $weiss);
 

Ähnliche Themen

R
Antworten
13
Aufrufe
2.093
Zurück
Oben