Alex Chamberlain schreef:
Hi,

I need to generate an online proof for vinyl lettering. Customers specify
the text, font, colour, maximum frame size (mm) (ie the width and height it
must fit into), and whether or not they want to keep aspect ratio (ie not
distort the lettering).

I want to represent all this on a single image. So it would display a border
with their width and height on, and inside this would be the text in the
appropriate colour and font – if they decide to keep aspect ratio the text
would not be distorted. If they do not, it would be. The image would always
be 300px wide by 150px high (these would need to be constants that I could
change from time to time).

I’ve got a very basic proof working using a GD wrapper, but I don’t think GD
is powerful enough to do it all, nor do I recon my programming skills are up
for it. Has anybody got any advice on how to tackle this, even if it is just
bits of the problem??

GD can do all this, although I hear said that ImageMagick does more and has 
somewhat
better output.

you'll only be able to offer fonts that you have installed on the server, also
image generation works in pixels so you'll have to come up with a way to 
'convert'
millimeters to a pixel value for display purposes.

I offer you a class that you might be able to use, at least for inspiration ...
the pertinent functions used are ImageColorAllocate(), ImageTTFBBox() and 
ImageTTFText()

<?

/*
 * Example:

$renderer = new RenderTTFText( 81, 756 );
$renderer->setOffset( 28, 40 );
$renderer->setBgImage( '/images/headerbase-lightblue.jpg' );
// $renderer->setBgColor( ??? );
$renderer->setLifetime( 10000000 );
// $renderer->setMaxLines( 1 )
$renderer->render(
    array( 'THESE', 'ARE', 'strings' ),
    array( 10, 14, 18 ),
    array( '/fonts/arial.ttf', '/fonts/verdana.ttf', '/fonts/symbol.ttf' ),
);

 *
 */

class RenderTTFText
{
    var $xsize,     $ysize;
    var $xoffset,   $yoffset,   $margin;
    var $bgimage,   $bgimagetype;
    var $bgcolor,   $fgcolor;

    var $lifetime;
    var $maxLines;

    var $transparent;

    // nasty little hack :-)
    var $stringSpacingOffsetTweak;

    var $im; // reference to the image resource.

    function RenderTTFText($xsize = null, $ysize = null)
    {
        $this->xsize        = (is_integer($xsize) && $xsize) ? 100: $xsize;
        $this->ysize        = (is_integer($ysize) && $ysize) ? 100: $ysize;
        $this->xoffset      = 0;
        $this->yoffset      = 0;
        $this->margin       = 0;
        $this->bgcolor      = array(0,0,0);
        $this->fgcolor      = array(255,255,255);
        $this->lifetime     = 0;
        $this->maxLines     = 1;
        $this->transparent  = false;

        $this->stringSpacingOffsetTweak = 0;
    }

    function setOffset($x,$y,$m = 0)
    {
        $this->xoffset = intval($x);
        $this->yoffset = intval($y);
        $this->margin  = intval($y);
    }

    function setBgImage($img_file)
    {
        $this->bgimage = $img_file;
        list($this->xsize, $this->ysize, $this->bgimagetype) = 
GetImageSize($this->bgimage);
    }

    function setBgColor($color)
    {
        $this->bgcolor = $this->convColor($color);
    }

    function setLifetime($t)
    {
        $this->lifetime = intval($t);
    }

    function setMaxLines($l)
    {
        if (($l = intval($l)) > 0) {
            $this->maxLines = $l;
        }
    }

    function setTransparent($b = true)
    {
        $this->transparent = (boolean)$b;
    }

    function setStringSpacingOffsetTweak($v)
    {
        if (is_numeric($v)) {
            $this->stringSpacingOffsetTweak = $v;
        }
    }

    /*
     * $text, a string or array of strings. - strings to display in order.
     * $size, a float or an array of floats - which size to display the related 
text at.
     * $font, a fontfilename or an array of fontfilenames - which font to use 
for the related text string
     * $br,   a boolean, or an array of bools - whether to follow the related 
$text string with a line break
     */
    function render($text, $size, $font, $color, $br = false)
    {
        /* our text items to render (each item can have a seperate size, font 
and linebreak(true/false) */
        foreach (array('text','size','font','color','br') as $arg) {
            if (!is_array(${$arg})) $$arg = array(${$arg});
            if ($arg == 'text') {
                $tcount = count($text);
                $text   = array_map('trim', $text);
            } else {
                while (($c = count(${$arg})) < $tcount) {
                    if (!isset(${$arg}[$c - 1])) {
                        return false;
                    }
                    ${$arg}[$c] = ($arg == 'br')
                              ? false
                              : ${$arg}[$c - 1];
                }
            }

            ${$arg} = array_values(${$arg});
        }

        /* create the background/base image */
        if (! empty($this->bgimage)) {
            switch ($this->bgimagetype) {
                case 3:
                    $this->im = ImageCreateFromPNG($this->bgimage);
                    break;
                case 2:
                    $this->im = ImageCreateFromJPEG($this->bgimage);
                    break;
            }
        }
        if (! $this->im) $this->im = 
ImageCreateTrueColor($this->xsize,$this->ysize);

        /* allocate colors */
        $bgColor    = 
ImageColorAllocate($this->im,$this->bgcolor[0],$this->bgcolor[1],$this->bgcolor[2]);
        $colorsHad  = $colorsAlloc = array();
        foreach ($color as $k => $v) {
            if (($prevKey = array_search($v, $colorsHad)) !== false) {
                $color[$k]  = $colorsAlloc[ $prevKey ];
                continue;
            }
            $colorsHad[$k]  = $v;
            $color[$k]      = $this->convColor($v);
            $colorsAlloc[$k]=
            $color[$k]      = 
ImageColorAllocate($this->im,$color[$k][0],$color[$k][1],$color[$k][2]);
        }

        $transXoffset = $this->xoffset;
        $lineCount    = 0;
        foreach ($text as $k => $str) {
            $lines      = array();
            $words      = explode(" ",$str);
            $wordCount  = count($words);

            //var_dump($k, $str, $words, $wordCount, $lineCount, $this->maxLines); echo '<br 
/><br /><br />';

            $i = $minCount = 0;
            for ($j = 0; $j < $this->maxLines; ++$j) {
                $lines[$j] = $words[$i];
                ++$i;
                while($i < $wordCount) {
                    $newText = $lines[$j]." ".$words[$i++];
                    list($x1,$y1,,,$x2,$y2) = ImageTTFBBox($size[$k], 0, 
$font[$k],$newText);
                    if (($x2 - $x1) > $this->xsize - ($transXoffset + 
($this->margin*2))) break;
                    $lines[$j] = $newText;
                }
                if ($i >= count($words)) break;
            }

            /* we resize the image if it doesn't have a background.
             *
             * THIS DOES NOT WORK WITH THE CHANGES MADE REGARDING PASSING IN 
MULTIPLE STRINGS (each with its own size/font/etc)
             */
            // if (!$this->im) $this->im = 
ImageCreate($this->xsize,max($this->ysize,1 + $size[$k]*count($lines)));

            $lines      = array_values($lines);
            $minCount   = 0;
            for ($maxCount = $lineCount + count($lines), $i = 0;
                 $lineCount < $maxCount;
                 ++$i. ++$lineCount)
            {
                if ($transXoffset !== $this->xoffset) {
                    if ($minCount > 0) {
                        $transXoffset = $this->xoffset;
                    } else {
                        $transXoffset -= $this->stringSpacingOffsetTweak;
                    }
                }

                list(,,,,$transXoffset) = ImageTTFText($this->im,
                                                       $size[$k],
                                                       0,
                                                       $transXoffset + 
$this->margin,
                                                       ($lineCount*$size[$k]) + 
$this->yoffset + $this->margin,
                                                       $color[$k],
                                                       $font[$k],
                                                       $lines[$i]);
                if ($transXoffset !== $this->xoffset) {
                    $minCount = 1;
                }

                /*
                var_dump(   $str,
                            $size[$k],
                            0,
                            $transXoffset + $this->margin,
                            ($lineCount*$size[$k]) + $this->yoffset + 
$this->margin,
                            $color[$k],
                            $font[$k],
                            $lines[$i]); echo '<br />';
                  //*/
            }

            /* force a new line at the end of this string?
             * if not then we must take account of the x-axis position of the 
end of the
             * last line of the last rendered string of the given $text (array)
             */
            //var_dump($transXoffset,$this->xoffset,$lines,$lineCount); echo '<br 
/>----';
            if (@$br[$k] || ($transXoffset == $this->xoffset)) {
                $transXoffset = $this->xoffset;
                ++$lineCount;
            } else {
                $lineCount -= $minCount;
            }
            //var_dump($transXoffset,$this->xoffset,$lines,$lineCount); echo '<br 
/>----<hr />';
        }


        if ($this->transparent) imagecolortransparent($this->im, $bgColor);
    }

    function showImage($type = 'png', $quality = 100)
    {
        if (is_resource($this->im)) {
            if ($this->lifetime) {
                header("Cache-Control: public max-age={$this->lifetime}");
            }

            header("Content-Type: image/png"); //update by mark
            ImagePNG($this->im);
            ImageDestroy($this->im);
        }
    }

    function saveImage($filename, $quality = 100)
    {
        if ($this->im == null) {
            return false;
        }

        $ext = strtolower($this->_getExtension($filename));
        $func = "image$ext";

        if ([EMAIL PROTECTED]($func)) {
            return false;
        }

        $saved = ($ext == 'png') ? $func($this->im, $filename) : 
$func($this->im, $filename, $quality);
        if ($saved == false) {
            return false;
        }

        return true;
    }

    function _getExtension($filename)
    {
$ext = @strtolower(@substr($filename, (@strrpos($filename, ".") ? @strrpos($filename, ".") + 1 : @strlen($filename)), @strlen($filename)));
        return ($ext == 'jpg') ? 'jpeg' : $ext;
    }

    function convColor($color)
    {
        $i = hexdec($color);
        return array(($i >> 16),(($i >>8) & 255),($i & 255));
    }
}

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to