peter nack: Bild mit dynamischen Text generieren

Guten Abend allerseits,

ich habe eine Liste von Orten. Fuer jeden Ort muss ich ein eigenes Bild generieren. Dies muss nicht zur Laufzeit geschehen, sondern soll einmalig durchgefuehrt werden.
Als Hintergrundbild dient ein "abgerundeter" Button. Sprich, das zu erstellende Bild setzt sich aus drei Einzelteilen zusammen
1. linker Rand
2. Inhalt (dynamische Laenge, abhaengig von dem Text)
3. rechter Rand

Nun meine Frage: Kann ich so was mit PHP realisieren?

Oder eventuell gibt es hierfuer ja auch ein schoenes Tool (also kein PHP, sondern Windows), welches ich zb mit einer csv-Datei fuettern kann. Anhand dieser werden dann die Bilder generiert... Irgendwelche Vorschlaege?

Vielen Dank!
Peter

  1. Hi,

    Als Hintergrundbild dient ein "abgerundeter" Button. Sprich, das zu erstellende Bild setzt sich aus drei Einzelteilen zusammen

    1. linker Rand
    2. Inhalt (dynamische Laenge, abhaengig von dem Text)
    3. rechter Rand

    Nun meine Frage: Kann ich so was mit PHP realisieren?

    Klar, bspw. mit den Funktionen der GD-Lib.

    imagettfbbox verrät dir, wie viel Platz den Text brauchen wird [1], mit imagettftext kannst du ihn ins Bild zeichnen.
    Die imagecopy*-Funktionen helfen dir, deine bestehenden Rahmen-/Hintergrundbilder ins neue Bild zu kopieren.

    [1] Wobei imagettfbbox nicht die präzisesten Ergebnisse liefert. Modifizierte Berechnungsmethoden findest du im Netz.

    MfG ChrisB

    --
    “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
    1. Hi,

      imagettfbbox verrät dir, wie viel Platz den Text brauchen wird [1]

      Hm, also mit den besagten Funktionen habe ich bereits die ganzen Buttons erstellt. Allerdings bin ich dabei nicht auf die Loesung gestoszen, wie ich drei Bilder damit vereinen kann.

      Aber nun gut, dann lese ich mich noch mal naeher dazu ein.

      Besten Dank!

      Peter Nack

  2. Hallo peter,

    ich habe eine Liste von Orten. Fuer jeden Ort muss ich ein eigenes Bild generieren. Dies muss nicht zur Laufzeit geschehen, sondern soll einmalig durchgefuehrt werden.

    Nun meine Frage: Kann ich so was mit PHP realisieren?

    Natürlich, nur mußt Du evtl. gar nicht. Du könntest das wohl auch rein mit HTML und CSS so hinbekommen, daß es wie ein Bild aussieht.

    Aber falls Du es unbedingt mit PHP machen willst, helfen Dir folgende Links wohl weiter:
    * (PHP) mehrere Bilder zusammenfügen, Antwort von Sven Rautenberg, 30. 05. 2003
    * (PHP) PHP GD Lib - Bilder zusammenfügen, Ergebnis unscharf von Denny, 03. 12. 2008
    * usw.

    Grüße aus Heilbronn,
    Götz

    --
    (neue Signatur gesucht - oder auch nicht)
  3. @@peter nack:

    nuqneH

    ich habe eine Liste von Orten. Fuer jeden Ort muss ich ein eigenes Bild generieren.

    Musst du??

    Ich glaube, Schiebetüren wären was für dich: Sliding Doors of CSS Part I, Part II

    Qapla'

    --
    Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
    (Mark Twain)
  4. Hallo allerseits,

    ich habe das jetzt so weit hinbekommen, dass es meinen Anspruechen genuegt.
    Vielleicht kann ja der eine oder andere hier auch etwas damit anfangen.

    Die Funktion arbeitet mit drei PNG-Grafiken, wobei zwei davon den Raendern entsprechen (link und rechts). Die mittlere Grafik wird mit Text befuellt (und sollte die maximale Textlaenge abdecken). Die Hoehe der Grafiken ist egal und wird bei der Kalkulation automatisch beruecksichtigt.

    Des weiteren muss arial.ttf im selben Ordner wie das Script liegen (auszer es wird speziell als Parameter mit angegeben).

      
    <?php  
      
      
    // Call the Generator  
    GenerateButton(  
    	'bg_left.png',  
    	'bg_center.png',  
    	'bg_right.png',  
    	'Hello World'  
    );  
      
      
      
    /**  
     * Generates a dynamic Button with Text.  
     *  
     * @example GenerateButton( 'left.png', 'center.png', 'right.png', 'Hello World', 'test.png', 'arial.ttf', 10, 0 );  
     *  
     * @param String $fileImgLeft Link of the left Part  
     * @param String $fileImgCenter link to the middle Part. Gets filled with Text.  
     * @param String $fileImgRight link of the right Part  
     * @param String $strText The Text to write  
     * @param String $filename Link for saving the Image. If null -> Browser-Output  
     * @param String $fontFile Link to the Font to use  
     * @param Integer $fontSize Size of the Font  
     * @param Integer $fontAngle The Angle used for writing the Text  
     *  
     * @return  
     */  
    function GenerateButton( $fileImgLeft, $fileImgCenter, $fileImgRight, $strText, $filename=null, $fontFile='arial.ttf', $fontSize=10, $fontAngle=0 )  
    {  
      
    	/*  
    	 * GET IMAGE RESOURCES AND CALCULATE DIMENSIONS  
    	 ************************************************************/  
      
    	// Get all Image-Resources  
    	$imgLeft = imagecreatefrompng( $fileImgLeft );  
    	$imgCenter = imagecreatefrompng( $fileImgCenter );  
    	$imgRight = imagecreatefrompng( $fileImgRight );  
      
    	// Calculate the Height and Width for the Image-Resources (0:width, 1:height)  
    	$arrSizeLeft = getimagesize( $fileImgLeft );  
    	$arrSizeCenter = getimagesize( $fileImgCenter );  
    	$arrSizeRight = getimagesize( $fileImgRight );  
      
    	// Calculate the needed Space for the dynamic Text  
    	$arrTextbox = CalculateTextBox( $fontSize, $fontAngle, $fontFile, $strText );  
      
      
    	/*  
    	 * CREATE NEW IMAGE  
    	 ************************************************************/  
      
    	$newWidth = $arrSizeLeft[0] + $arrTextbox['width'] + $arrSizeRight[0];  
    	$newHeight = max( $arrSizeLeft[1], $arrTextbox['height'], $arrSizeRight[1] );  
    	$imgTarget = imagecreate( $newWidth, $newHeight );  
      
      
    	/*  
    	 * DEFINE COLORS  
    	 ************************************************************/  
    	$clrRed = imagecolorallocate( $imgTarget, 0xFF, 0x00, 0x00);  
    	$clrBlack = imagecolorallocate( $imgTarget, 0x00, 0x00, 0x00);  
      
      
    	/*  
    	 * WRITE TEXT TO IMAGE  
    	 ************************************************************/  
      
    	imagefttext(  
    		// the image resource  
    		$imgCenter,  
    		// the font size to use in points  
    		$fontSize,  
    		// the angle in degrees  
    		$fontAngle,  
    		// the x-coordinate  
    		$arrTextbox['left'],  
    		// the y-coordinate. TODO: donna whats the real algorithm here?  
    		$arrTextbox['top'] + ($arrSizeCenter[1] / 3),  
    		// the index of the desired color for the text  
    		$clrBlack,  
    		// the path to the TrueType font  
    		$fontFile,  
    		// text to be inserted into image  
    		$strText  
    	);  
      
      
    	/*  
    	 * COPY NEW IMAGE  
    	 ************************************************************/  
      
    	// Copy the left Part into the new Image  
    	imagecopy( 	  
    	  
    		// destination image resource  
    		$imgTarget,  
    		  
    		// source image resource  
    		$imgLeft,  
    		  
    		// x-coordinate of destination point		  
    		0,  
    		  
    		// y-coordinate of destination point  
    		0,	  
    		  
    		// x-coordinate of source point		  
    		0,  
    		  
    		// y-coordinate of source point  
    		0, 		  
    		  
    		// width of source  
    		$arrSizeLeft[0],  
    		  
    		// height of source  
    		$arrSizeLeft[1]			  
    	);  
      
    	// Copy the center Part into the new Image  
    	imagecopy( 	  
    	  
    		// destination image resource  
    		$imgTarget, 	  
    		  
    		// source image resource  
    		$imgCenter,  
    		  
    		// x-coordinate of destination point  
    		$arrSizeLeft[0],	  
    		  
    		// y-coordinate of destination point  
    		0,  
    		  
    		// x-coordinate of source point  
    		0,  
    		  
    		// y-coordinate of source point  
    		0, 			  
    		  
    		// width of source  
    		$arrTextbox['width'],  
    		  
    		// height of source  
    		$arrSizeCenter[1]		  
    	);  
      
    	// Copy the right Part into the new Image  
    	imagecopy( 	  
    	  
    		// destination image resource  
    		$imgTarget,  
    		  
    		// source image resource  
    		$imgRight,  
    		  
    		// x-coordinate of destination point  
    		$arrSizeLeft[0] + $arrTextbox['width'],  
    		  
    		// y-coordinate of destination point  
    		0,			  
    		  
    		// x-coordinate of source point  
    		0, 		  
    		  
    		// y-coordinate of source point  
    		0, 		  
    		  
    		// width of source  
    		$arrSizeRight[0], 	  
    		  
    		// height of source  
    		$arrSizeRight[1]		  
    	);  
      
      
      
    	/*  
    	 * OUTPUT IMAGE  
    	 ************************************************************/  
    	if( !isset( $filename ) )  
    		header('Content-type: image/png');  
      
    	// Output created Image  
    	imagepng( $imgTarget, $filename );  
      
    	// Destroy Image  
    	imagedestroy( $imgTarget );  
    	imagedestroy( $imgLeft );  
    	imagedestroy( $imgRight );  
    	imagedestroy( $imgCenter );  
    }  
      
      
      
      
    /**  
     * Calculates the required Space for a Textbox inside an Image.  
     *  
     * @author blackbart at simail dot it  
     * @see http://php.net/manual/en/function.imagettfbbox.php  
     *  
     * @param Integer $font_size The Size of the Font  
     * @param Integer $font_angle The Angle of the Text  
     * @param String $font_file Link to the Font  
     * @param String $text The desired Text  
     *  
     * @return Array (left|top|width|height)  
     */  
      
    function CalculateTextBox( $font_size, $font_angle, $font_file, $text )  
    {  
    	$box   = imagettfbbox($font_size, $font_angle, $font_file, $text);  
    	if( !$box )  
    		return false;  
      
    	$min_x = min( array($box[0], $box[2], $box[4], $box[6]) );  
    	$max_x = max( array($box[0], $box[2], $box[4], $box[6]) );  
    	$min_y = min( array($box[1], $box[3], $box[5], $box[7]) );  
    	$max_y = max( array($box[1], $box[3], $box[5], $box[7]) );  
    	$width  = ( $max_x - $min_x );  
    	$height = ( $max_y - $min_y );  
    	$left   = abs( $min_x ) + $width;  
    	$top    = abs( $min_y ) + $height;  
      
      
    	/**  
    	 * to calculate the exact bounding box i write the text in a large image  
    	 ************************************************************/  
    	$img     = @imagecreatetruecolor( $width << 2, $height << 2 );  
    	$white   =  imagecolorallocate( $img, 255, 255, 255 );  
    	$black   =  imagecolorallocate( $img, 0, 0, 0 );  
    	imagefilledrectangle($img, 0, 0, imagesx($img), imagesy($img), $black);  
      
      
    	/**  
    	 * for sure the text is completely in the image!  
    	 ************************************************************/  
    	imagettftext( $img, $font_size,  
    	              $font_angle, $left, $top,  
    	              $white, $font_file, $text);  
      
      
    	/**  
    	 * start scanning (0=> black => empty)  
    	 ************************************************************/  
    	$rleft  = $w4 = $width<<2;  
    	$rright = 0;  
    	$rbottom   = 0;  
    	$rtop = $h4 = $height<<2;  
    	for( $x = 0; $x < $w4; $x++ )  
    	{  
    		for( $y = 0; $y < $h4; $y++ )  
    		{  
    			if( imagecolorat( $img, $x, $y ) )  
    			{  
    		        $rleft   = min( $rleft, $x );  
    		        $rright  = max( $rright, $x );  
    		        $rtop    = min( $rtop, $y );  
    		        $rbottom = max( $rbottom, $y );  
    			}  
    		}  
    	}  
      
      
    	/**  
    	 * destroy img and serve the result  
    	 ************************************************************/  
    	imagedestroy( $img );  
      	return array( "left"   => $left - $rleft,  
        	          "top"    => $top  - $rtop,  
            	      "width"  => $rright - $rleft + 1,  
                	  "height" => $rbottom - $rtop + 1 );  
    }  
      
    ?>