We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 9102 ☆ A M B ☆
    • 318 Posts
    So this is the first snippet I’ve considered sharing -- the question is, do you think anyone would find it useful?

    It’s a very simple little snippet that calls phpThumbOf to create an image with dynamic text generated from a GET paramater.

    Demo here:

    http://www.kpaonline.com/magic-images/to-do.jpg?text=I%20love%20MODx

    Why do it this way, instead of just calling phpThumbOf normally within a page? Because this makes an image that is dynamic externally, in particular it could be sent in email using a merge field to fill in, for example, the recipient’s first name.

    Because it outputs the image directly to the browser, the snippet has to be called in a completely blank template.

    Any feedback would be appreciated.

    <?php
    /**
     * magicImage
     *
     * version 0.1.0 (beta)
     *
     * Copyright 2011 by Eli Snyder <[email protected]>
     *
     * magicImage is free software; you can redistribute it and/or modify it
     * under the terms of the GNU General Public License as published by the Free
     * Software Foundation; either version 2 of the License, or (at your option) any
     * later version.
     *
     * magicImage is distributed in the hope that it will be useful, but WITHOUT ANY
     * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License along with
     * magicImage; if not, write to the Free Software Foundation, Inc., 59 Temple
     * Place, Suite 330, Boston, MA 02111-1307 USA
     *
     */
    /**
     * A MODx snippet that outputs a customized image with overlaid text
     * as specified in the URL GET parameter "text"
     *
     * Requires Sean McCormick's phpThumbOf snippet 
     * documentation here: http://rtfm.modx.com/display/ADDON/phpThumbOf
     *
     * Notes on parameters:
     * text - from GET parameter ?text=my-random-text 
     *	       can contain word characters and URL character codes
     * defaultText - displayed if text is empty or fails validation
     * font - this is the name of a .ttf file (without extension) 
     * fontDir - by default, fonts are in /assets/fonts/
     * maxChars - soft max number of characters after which font size is reduced
     * additionalOptions - any phpThumb options
     *
     * The remaining parameters are pretty self-explanatory 
     * standard phpThumb options for watermark filter:
     * size - font size (point)
     * myImage - background image URL
     * hOff - horizontal offset from left side of image to left side of text
     * vOff - vertical offset from top of image to top of text
     * color - hex color of text
     * opacity - 0 to 100 opacity of text
     * margin - margin from edge of background image
     * angle - rotation angle of text
     * bgColor - color of text overlay background
     * bgOpacity - opacity of text background, transparent by default
     * bgExtend - direction to extend text background - x, y or both
     * additionalOptions - any other desired phpThumb options
     *
     * Output: this snippet does not return a value - it outputs the image
     * directly to the browser. It should be placed in an otherwise blank template.
     *
     */
    
    /* get text from URL parameter */
    /* validate text, set to default if it fails */
    
    if(!filter_has_var(INPUT_GET, 'text')) {
        $text=$modx->getOption('defaultText', $scriptProperties, '');
    }else{
        if (!filter_input(INPUT_GET, 'text', FILTER_VALIDATE_REGEXP, array('options'=>array('regexp'=>'/^[\w\s%]+$/')))) {
            $text=$modx->getOption('defaultText', $scriptProperties, '');
        } else {
            $text = $_GET['text'];
        }
    }
    
    $text = urldecode($text);
    
    /* get all other script options */
    $size=$modx->getOption('size', $scriptProperties, 12);
    $maxChars=$modx->getOption('maxChars', $scriptProperties, 20);
    $myImage=$modx->getOption('myImage', $scriptProperties, 'assets/images/magic-images/to-do.jpg');
    $hOff=$modx->getOption('hOff', $scriptProperties, 0);
    $vOff=$modx->getOption('vOff', $scriptProperties, 0);
    $color=$modx->getOption('color', $scriptProperties, '000000');
    $font=$modx->getOption('font', $scriptProperties, 'angelina');
    $opacity=$modx->getOption('opacity', $scriptProperties, 100);
    $margin=$modx->getOption('margin', $scriptProperties, 0);
    $angle=$modx->getOption('angle', $scriptProperties, 0);
    $bgColor=$modx->getOption('bgColor', $scriptProperties, 'FFFFFF');
    $bgOpacity=$modx->getOption('bgOpacity', $scriptProperties, 0);
    $bgExtend=$modx->getOption('bgExtend', $scriptProperties, 'x');
    $fontDir=$modx->getOption('fontDir', $scriptProperties, 'assets/fonts/');
    $basePath = $modx->getOption('base_path',null,MODX_BASE_PATH);
    
    /* allow extension with any other phpThumb options not explicitly specified */
    $additionalOptions=$modx->getOption('additionalOptions', $scriptProperties, '');
    
    /* reduce font size if text is longer than maxChars */
    $length = strlen($text);
    if ($length > $maxChars){
        $size = intval($size*$maxChars/$length);
    }
    
    /* call phpThumbOf to generate the image file */
    $image = $modx->runSnippet('phpThumbOf',array(
        'input' => $myImage,
        'options' => $additionalOptions.'&fltr[]=wmt|'.$text.'|'.$size.'|'.$hOff.'x'.$vOff.'|'.$color.'|'.$basePath.$fontDir.$font.'.ttf'.'|'.$opacity.'|'.$margin.'|'.$angle.'|'.$bgColor.'|'.$bgOpacity.'|'.$bgExtend
    ));
    
    $imagePath = $basePath.$image;
    
    /* output the image directly as a jpg */
    if (file_exists($imagePath)){
        header('Content-Description: File Transfer');
        header('Content-Type: image/jpeg');
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: ' . filesize($imagePath));
        ob_clean();
        flush();
        readfile($imagePath);
        die();
    }else{
        return false;
    }
    
      • 35291
      • 21 Posts
      i’m trying to work something similar (adding overlaying text) and it seems that it always displays some image code instead of the actual image, if you could take a look at my script, i’d be more then happy to mail it to you. thankx
        • 9102 ☆ A M B ☆
        • 318 Posts
        Sure, I’d be happy to have a look at it. As my sig says, I’m freejung on gmail, you can mail me there.

        Or you could just post the code here - that has the added advantage that others far more skilled than I may also look at it and provide feedback.

        Also, you are welcome to use the code I posted, it works well for me. If you don’t want the text to come from a GET parameter you could easily substitute a variable, or just call phpThumbOf normally in your template with the appropriate wmt options.
          • 35291
          • 21 Posts
          thing is, i am building a "geochecker" similar to the ones found on the internet (google-it)

          basically, my registered member enters some informations about a mystery thing, then my website give him a link to display an image on his "mystery" thing page.

          that image is dynamic and needs to show 2 numbers, #of correct answers - and #of incorrect answers

          so then future "mystery" thing users have an idead of what to expect in terms of dgree of difficulty.

          -------

          that beein said, i can successfully render my image, using GD, in full php. Since it’s supposed to load on request from another webpage, it only displays a png header thaat you can call directly with the php name or via an <img src"php-source">

          -------

          my problem is - inside of MODX, i can’t seem to get the whole thing working as a snippet. (it must have something to do with headers already sent) -- i found a way to ajust this, but i must say i’d rather have only ONE snippet that would either display outside of modx and inside.

          so here’s the code.

          this is my PHP source that works outside of MODX.
          <?php
          
          // Check for input values and check if file exists (txt) on server
          if (isset($_GET['gid']) && file_exists("../test/data/". ($_GET['gid']) . ".txt")) {
          $fileName = "../test/data/". ($_GET['gid']) . ".txt";
          		displayImg($fileName);}
          	else {
          		displayErrorImg();
          }
          
          // Checked, OK! Display image...
          function displayImg($tmpfileName) {
          
          $values = explode("\n",file_get_contents($tmpfileName));
          $rightAmnt = $values[0];
          $wrongAmnt = $values[1];
          
          $image = imagecreatefrompng("../test/checker1_default.png");
          // Set Font Size
          $font_size = 20;
          
          // Set The Color Of The Outline
          $shadow_color = imagecolorallocate($image, 0,0,0);
          
          // Set The Color Of The RIGHT and WRONG Front TEXT
          $shadow_right = imagecolorallocate($image, 193,226,61);
          $shadow_wrong = imagecolorallocate($image, 255,88,43);
          
          //--------------------------------------------------------------
          // Text Outline RIGHT
          //--------------------------------------------------------------
          
          ImageTTFText ($image, $font_size, 35, 93, 103, $shadow_color, "../test/arial.ttf",$rightAmnt);
          ImageTTFText ($image, $font_size, 35, 93, 105, $shadow_color, "../test/arial.ttf",$rightAmnt);
          ImageTTFText ($image, $font_size, 35, 92, 104, $shadow_color, "../test/arial.ttf",$rightAmnt);
          ImageTTFText ($image, $font_size, 35, 94, 104, $shadow_color, "../test/arial.ttf",$rightAmnt);
          
          // Front Text Generation RIGHT
          ImageTTFText ($image, $font_size, 35, 93, 104, $shadow_right, "../test/arial.ttf",$rightAmnt);
          
          //--------------------------------------------------------------
          // Text Outline WRONG
          //--------------------------------------------------------------
          
          ImageTTFText ($image, $font_size, 327, 270, 44, $shadow_color, "../test/arial.ttf",$wrongAmnt);
          ImageTTFText ($image, $font_size, 327, 270, 46, $shadow_color, "../test/arial.ttf",$wrongAmnt);
          ImageTTFText ($image, $font_size, 327, 269, 45, $shadow_color, "../test/arial.ttf",$wrongAmnt);
          ImageTTFText ($image, $font_size, 327, 271, 45, $shadow_color, "../test/arial.ttf",$wrongAmnt);
          
          // Front Text Generation WRONG
          ImageTTFText ($image, $font_size, 327, 270, 45, $shadow_wrong, "../test/arial.ttf",$wrongAmnt);
          
          //--------------------------------------------------------------
          
          header("Content-type: image/png");
          imagepng($image);
          return $image;
          }
          
          // Checked, BAD! Display BAD image...
          function displayErrorImg(){
          $image = imagecreatefrompng("../test/checker1_BadUrl.png");
          header("Content-type: image/png");
          imagepng($image);
          return $image;
          }
          
          imagedestroy($image);
          ?>
          

          ---------------------------------------------------

          If i want to display that image in modx, crazy PNG header characters appear instead of the actual image.

          looking around at some modx problems and solutions, i found this fix wich enables me to display my dynamic image inside of modx with the previous script as a snippet. But it’s only good for one thing, prevewing the image result in modx (for the front-end user while setting up the data per example)
          <?php
          // displays in MODX only
          ImagePNG($image,"image.png");
          ImageDestroy($image);
          $output = '<img src="image.png" border=2>  ' . $fileName;
          return $output;
          ?>
          

          So. Essentially... id love to have a modx snippet that can output to browsers outside of modx environment AND use the same snippet, no extra parameters required, to preview the image in modx (just like the fix does so wonderfully)

          say you wanted to display that picture on your site... just add [img]http://myModXSite/friendlyUrltoSnippet[/img]
          and use the equivalent to display inside of modx ; <img src="[[!snippetCallForImg]]"/>

          [EDIT] The previous has been partially dealt with - read on other posts for explanation;

          am i crazy? confusing? please tell me... also remember, i have only been coding php for a couple months.

          Maybe your script does exactly that, but i don’t seem to understand it properly :/

          [EDIT] I understand your script, now;

          Thanks!
            • 16702 ☆ A M B ☆
            • 536 Posts
            cool idea smiley
              palma non sine pulvere
              • 28042 ☆ A M B ☆
              • 24,524 Posts
              If the snippet is in a resource with no template, similar to an AJAX request processor snippet?
                Studying MODX in the desert - http://sottwell.com
                Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
                Join the Slack Community - http://modx.org
                • 35291
                • 21 Posts
                If the snippet is in a resource with no template, similar to an AJAX request processor snippet?

                Unfortunately, even in an empty template, it seems that modx still sends some header information before my script is beeing executed resulting in crazy image code.

                i’ll make sure to try again - and again not to say - later on today and keep you informed.

                thanks for the reply

                [EDIT] Read on, i found another ’half’ solution to my problem
                  • 35291
                  • 21 Posts
                  Ok, i have re-tested my affirmations.

                  It seems that, i can load the image into modx using the include snippet [[!include? &file=`../test/checkerDisplayImagePublic.php`]] into a ressource without modification to my source code.

                  Then, to load it into an <img> container anywhere on the site, i simply use;
                  <img src="[[~11]]?gid=testcache"/>
                  where 11 is the ressource wich contains my include snippet call to php file (the previous call in BOLD). That ressource file MUST have a blank template since image headers have to be send from PHP. The remainder url parameter is a test parameter passed on to the snippet - it’s fixed at ’testcache’ for now because i’m testing the snippet with a file called testcache.txt - will be dynamic once everything is in order.

                  I can also display the image on another page outside of modx by referencing a link to the ressource (in this case, ressource #11, with friendly url alias set to ’display’) By simply calling
                  <img src="http://localhost/site/gc/display?gid=testcache"/>
                  i get what i was looking for - well, partially.

                  As for creating a REAL MODX SNIPPET - i’m encountering loads of error when i simply paste my code into a snippet in the manager. Per example (not well defined examples i must say);

                  call to unreferenced function displayErrorImg() - why??
                  unexpected T string on line XX - seriously?

                  Why would it work as an [[!Include]] snippet and not as a modx internal snippet?

                  Is it me or i find modx more complicated than actual php (snippets-wise i mean)? Do i just don’t get it?

                  Could someone actually help me translate my current source code (php) to a working modx snippet so i don’t have loose PHP files on my site? --- or just point me towards the right direction.

                  Thank you!
                    • 9102 ☆ A M B ☆
                    • 318 Posts
                    I’m not sure if it’s relevant to your problem, but I found that the die() statement at the end was crucial. I don’t know for sure, but I’m guessing that it’s because normally MODx expects a snippet to return a value that it can insert back into the document where the snippet was called. So if you don’t kill your process, MODx will continue doing stuff after the snippet runs -- in my case, I think I was getting HTML code in the file instead of the actual image code.

                    That’s one thing I was hoping for feedback on, actually. I know that killing the process without returning a value is not proper form for a MODx snippet. Snippets are supposed to return something, even if it’s just "false." Is it wrong to die() at the end of a snippet? Will this mess up other processes? It appears to work fine for me, and it’s the only way I can get it to work.

                    Maybe it would be better for me to use the Include snippet for my code, instead of trying to run it as an actual snippet.
                      • 35291
                      • 21 Posts
                      Not to pretend anything here, but just my point of view.

                      Normally, in php, a return acts almost as a die().

                      In your case, since you never use return to return an image to the browser, you need to have that die() function pr else, from what i understand about modx so far, modx is looking for something to output, more specifically a return statement.

                      <?php
                      // ALL CHECKS OUT so output the image by sending headers.
                      if (file_exists($imagePath)){
                          header('Content-Description: File Transfer');
                          header('Content-Type: image/jpeg');
                          header('Content-Transfer-Encoding: binary');
                          header('Expires: 0');
                          header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
                          header('Pragma: public');
                          header('Content-Length: ' . filesize($imagePath));
                          ob_clean();
                          flush();
                          readfile($imagePath);
                      // Huh? no return statement? Fine, just kill it works :)
                          die();
                      // Huho! ERROR then RETURN false
                      }else{
                          return false;
                      ?>
                      }


                      You seem to be using return only in case of ’error’. Hence the need for die();

                      If you look closely to my snippet code, you’ll see that i actually use a return so i don’t need the die()

                      Maybe some1 could correct my affirmations here, i’m all ok with that!

                      [EDIT] The only inconvenient, if i can say so, with your snippet is that it needs phpthumof snippet to function. Using the GD Library eliminates this