Overview

Classes

  • Meme_generator
  • Overview
  • Class
  • Tree
  1: <?php 
  2: /**
  3:  * Meme generator class:
  4:  * - Generates image file with two lines of text - top & bottom
  5:  * - Is very customizable
  6:  * - Works well with different frameworks (tested on CodeIgniter)
  7:  * - Supports watermarking
  8:  *
  9:  * @author http://neart.eu/
 10:  * @copyright Copyright &copy; 2013 Neart Interactive Agency, Libera Solutions Ltd.
 11:  * @version 1.0
 12:  * @example ./example.php Class usage examples
 13:  */
 14: class Meme_generator
 15: {
 16:     public $config;
 17: 
 18:     public function __construct()
 19:     {
 20:         $this->clear(); // DEFAULT BASIC SETTING 
 21:     }
 22: 
 23:     /**
 24:     * Bulk config load - instead of setters
 25:     * @param Array class configuration array, possible keys: 
 26:     * meme_font / meme_output_dir / meme_font_to_image_ratio / meme_margins_to_image_ratio / meme_image_path / meme_top_text / 
 27:     * meme_bottom_text / meme_font
 28:     * meme_watermark_file / meme_watermark_margins / meme_watermark_opacity
 29:     */
 30:     public function load_config ($config)
 31:     {
 32:         $this->config = $config;
 33:     }
 34:     /**
 35:     * Sets image file path
 36:     * @param String image file path
 37:     */ 
 38:     public function set_image ( $image_path ) 
 39:     {
 40:         $this->config['meme_image_path'] = $image_path;
 41:     }
 42: 
 43:     /**
 44:     * Sets TOP text on image
 45:     * @param String
 46:     */ 
 47:     public function set_top_text( $txt ) 
 48:     {
 49:         $this->config['meme_top_text'] = $txt;
 50:     }
 51:     
 52:     /**
 53:     * Sets BOTTOM text on image
 54:     * @param String 
 55:     */ 
 56:     public function set_bottom_text( $txt ) 
 57:     {
 58:         $this->config['meme_bottom_text'] = $txt;
 59:     }
 60: 
 61:     /**
 62:     * Sets font for texts (TTF)
 63:     * @param String font file path
 64:     */ 
 65:     public function set_font ( $file ) 
 66:     {
 67:         $this->config['meme_font'] = $file ;
 68:     }
 69: 
 70:     /**
 71:     * Sets output path for generated image (default to ./)
 72:     * @param String path
 73:     */ 
 74:     public function set_output_dir( $path ) 
 75:     {
 76:         $this->config['meme_output_dir'] = $path;
 77:     }
 78: 
 79:     /**
 80:     * If You know what You're doing - You can change font size to image ratio (default to 0.04)
 81:     * Recommended values: 0.01 - 0.05
 82:     * @param float 
 83:     */
 84:     public function set_font_ratio( $ratio )
 85:     {
 86:         $this->config['meme_font_to_image_ratio'] = $ratio;
 87:     }
 88:     /**
 89:     * Sets output image quality - default to 90
 90:     */
 91:     public function set_quality( $q )
 92:     {
 93:         $this->config['meme_quality'] = $q;
 94:     }
 95: 
 96:     /**
 97:     * If You know what You're doing - You can change margins to image ratio (default to 0.02)
 98:     * Recommended values: 0.01 - 0.05
 99:     * @param float 
100:     */
101:     public function set_margins_ratio( $ratio )
102:     {
103:         $this->config['meme_margins_to_image_ratio'] = $ratio;
104:     }
105: 
106: 
107:     /**
108:     * Set watermark PNG image file path
109:     * @param String PNG file path
110:     */
111:     public function set_watermark( $path )
112:     {
113:         $this->config['meme_watermark_file'] = $path;
114:     }
115: 
116:     /**
117:     * Sets watermark margins - right & bottom, defaults to 10 px
118:     * @param integer margins in pixels
119:     */
120:     public function set_watermark_margins( $margins = 10 )
121:     {
122:          $this->config['meme_watermark_margins'] = $margins;
123:     }
124: 
125:     /**
126:     * Sets watermark opacity - default to 50 
127:     * @param integer opacity 0 - 100
128:     */
129:     public function set_watemark_opacity( $opacity = 50)
130:     {
131:          $this->config['meme_watermark_opacity'] = $opacity;
132:     }
133: 
134:     /**
135:     * Resets all of the values used when processing an image. You will want to call this if you are processing images in a loop.
136:     */
137:     public function clear()
138:     {
139:         $this->config['meme_image_path'] = null;
140:         $this->config['meme_top_text'] = '';
141:         $this->config['meme_bottom_text'] = '';
142:         $this->config['meme_watermark_file'] = null;
143:         $this->config['meme_font'] = './fonts/DejaVuSansMono-Bold.ttf';
144:         $this->config['meme_output_dir'] = './';
145:         $this->config['meme_font_to_image_ratio'] = 0.04;
146:         $this->config['meme_margins_to_image_ratio'] = 0.02;
147:         $this->config['meme_quality'] = 90;
148:         $this->config['meme_watermark_margins'] = 10;
149:         $this->config['meme_watermark_opacity'] = 50;
150:         $this->config['meme_prefix'] = 'meme_';
151:         $this->config['debug'] = array();
152:     }
153: 
154:     public function debug()
155:     {
156:         return $this->config['debug'];
157:     }
158: 
159:     /**
160:      * Generate meme on image file
161:      * @return String newly created image file name (stored in $this->config['meme_output_dir'] )
162:      */
163:     public function generate()
164:     {
165:         if ( ! isset( $this->config['meme_image_path'] ) || ! strlen( $this->config['meme_image_path'] ) ) {
166:             die ( 'Meme_generator Class ERROR : Trying to generate meme without image file specified');
167:         }
168:         $tmp_sizes = getimagesize( $this->config['meme_image_path'] );
169:         $image_width = $tmp_sizes[0];
170:         $image_height= $tmp_sizes[1];
171:         $this->config['debug'] = array_merge ($this->config['debug'], $this->config);
172:         $this->config['debug'] = array_merge ($this->config['debug'], $tmp_sizes );
173:         
174:         $text1 = preg_replace('/\s\s+/', ' ',  $this->config['meme_top_text'] );
175:         $text2 = preg_replace('/\s\s+/', ' ', $this->config['meme_bottom_text'] );
176: 
177:         $font = $this->config['meme_font'];
178:         $font_size = round($this->config['meme_font_to_image_ratio'] * $image_width );
179:         $margin = round($this->config['meme_margins_to_image_ratio'] * $image_width );
180:         
181:         $text1_params = $this->get_text_params($text1,$image_width,$margin,$font,$font_size);
182:         $text2_params = $this->get_text_params($text2,$image_width,$margin,$font,$font_size);
183:         // Some extra debug info
184:         $this->config['debug']['font_size'] = $font_size;
185:         $this->config['debug']['margin'] = $margin;
186:         $this->config['debug']['text1_params'] = $text1_params;
187:         $this->config['debug']['text2_params'] = $text2_params;
188:         
189:         $im = @imagecreatefromstring(file_get_contents( $this->config['meme_image_path'] ));
190:         $white = imagecolorallocate($im, 255, 255, 255);
191:         $black = imagecolorallocate($im, 0, 0, 0);
192: 
193:         if ( isset ( $this->config['meme_watermark_file'] ) && strlen( $this->config['meme_watermark_file'] ) ) { 
194:             // watermark file selected - watermarking...
195:             //$overlay_gd_image = imagecreatefrompng($this->config['meme_watermark_file']);
196:             $overlay_gd_image = @imagecreatefromstring(file_get_contents  ($this->config['meme_watermark_file'] ) );
197:             $overlay_width = imagesx($overlay_gd_image);
198:             $overlay_height = imagesy($overlay_gd_image);
199: 
200:             $merge_result = imagecopymerge(
201:                 $im,
202:                 $overlay_gd_image,
203:                 $image_width - $overlay_width - $this->config['meme_watermark_margins'] ,
204:                 $image_height - $overlay_height - $this->config['meme_watermark_margins'],
205:                 0,
206:                 0,
207:                 $overlay_width,
208:                 $overlay_height,
209:                 $this->config['meme_watermark_opacity']
210:             );
211:             $this->config['debug']['meme_watermark_file'] = $this->config['meme_watermark_file'];
212:             $this->config['debug']['meme_watermark_margins'] = $this->config['meme_watermark_margins'];
213:             $this->config['debug']['meme_watermark_opacity'] = $this->config['meme_watermark_opacity'];
214:             imagedestroy($overlay_gd_image);
215:         } 
216: 
217:         // top text
218:         imagettftext($im, $font_size, 0,
219:             $text1_params['centered_start'],
220:             $font_size+$margin,
221:             $black, $font, $text1_params['text']
222:         );
223:         imagettftext($im, $font_size, 0,
224:             $text1_params['centered_start']-2,
225:             $font_size+$margin-2,
226:             $white, $font, $text1_params['text']
227:         );
228:         // bottom text
229:         imagettftext($im, $font_size, 0,
230:             $text2_params['centered_start'] ,
231:             $image_height-$text2_params['height']+$font_size+$margin,
232:             $black, $font, $text2_params['text']
233:         );
234:         imagettftext($im, $font_size, 0,
235:             $text2_params['centered_start']-2,
236:             $image_height-$text2_params['height']+$font_size+$margin-2,
237:             $white, $font, $text2_params['text']
238:         );
239:         $fname = $this->config['debug']['meme_recent_file_name'] 
240:             = $this->config['meme_prefix'] . md5(serialize( $this->config )) .time() . '.jpg'; // serialize is hack for cleared obejcts in loop
241:         $cache_file_name =  $this->config['meme_output_dir'] . $fname;
242:         $this->config['debug']['cache_file_name'] = $cache_file_name;
243:         imagejpeg($im, $cache_file_name, $this->config['meme_quality']);
244:         imagedestroy($im);
245:         return $fname;
246:     }
247:     
248:     /**
249:     * Positioning texts
250:     */
251:     private function get_text_params($text,$width,$margin,$font,$font_size)
252:     {
253:         $rv = array();
254:         $text_a = explode(' ', $text);
255:         $text_new = '';
256:         foreach($text_a as $word){
257:             $box = imagettfbbox($font_size, 0, $font, $text_new.' '.$word);
258:             if($box[2] > $width - $margin*2){
259:                 $text_new .= "\n".$word;
260:             } else {
261:                 $text_new .= " ".$word;
262:             }
263:         }
264:     
265:         $text_new = $this->align_center_img_txt($text_new);
266:         $box = imagettfbbox($font_size, 0, $font, $text_new);
267:         $rv['text'] = $text_new;
268:         $rv['height'] = $box[1] + $font_size + $margin * 2;
269:         $rv['centered_start'] = ceil(($width-$box[2]) / 2);
270:         return $rv;
271:     }
272:     
273:     /**
274:     * Some text centering and text padding with spaces
275:     */
276:     private function align_center_img_txt ($text_new)
277:     {
278:         $text_new = trim($text_new);
279:         $text_a_tmp = explode("\n", $text_new);
280:         $max_line_length1 = 0;
281:         foreach($text_a_tmp as $line){
282:             if ( mb_strlen($line) > $max_line_length1) $max_line_length1 = mb_strlen($line);
283:         }
284:         $text_new = ''; // reset
285:         foreach($text_a_tmp as $line){
286:             $text_new .= $this->mb_str_pad($line, $max_line_length1, ' ', STR_PAD_BOTH) . "\n";
287:         }
288:         return $text_new;
289:     }
290:     
291:     private function mb_str_pad ($input, $pad_length, $pad_string, $pad_style, $encoding="UTF-8") {
292:         return str_pad (
293:             $input,
294:             strlen($input)-mb_strlen($input,$encoding)+$pad_length, $pad_string, $pad_style
295:             );
296:     }
297:     
298: }
299: 
Meme Generator PHP Class API documentation generated by ApiGen 2.8.0