/[drupal]/contributions/modules/watermark/watermark.module
ViewVC logotype

Contents of /contributions/modules/watermark/watermark.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.10 - (show annotations) (download) (as text)
Mon Jun 23 23:20:38 2008 UTC (17 months ago) by kbahey
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-6--1
Changes since 1.9: +55 -60 lines
File MIME type: text/x-php
#242231 by sto, Port to Drupal 6.
1 <?php
2
3 // $Id: watermark.module,v 1.5.2.6 2008/05/17 20:38:05 kbahey Exp $
4 // Author: Khalid Baheyeldin of http://2bits.com
5 // Additional features by schnizZzla for http://BerlinerStrassen.com
6
7 define('WATERMARK_ENABLE', 'watermark_enable');
8 define('WATERMARK_PATH', 'watermark_path');
9 define('WATERMARK_LOCATION', 'watermark_location');
10 define('WATERMARK_SCALING', 'watermark_scaling');
11 define('WATERMARK_SCALING_PERCENTAGE', 'watermark_scaling_percentage');
12 define('WATERMARK_MIN_WIDTH', 'watermark_min_width');
13 define('WATERMARK_EXCLUDE', 'watermark_exclude');
14 define('WATERMARK_EXCLUDE_TERMS', 'watermark_exclude_terms');
15 define('WATERMARK_WATCHDOG', 'watermark');
16 define('WATERMARK', 'watermark_');
17 define('WATERMARK_POS_MIDDLE', 0);
18 define('WATERMARK_POS_MIDDLERIGHT', 1);
19 define('WATERMARK_POS_MIDDLELEFT', 2);
20 define('WATERMARK_POS_TOPMIDDLE', 3);
21 define('WATERMARK_POS_TOPLEFT', 4);
22 define('WATERMARK_POS_TOPRIGHT', 5);
23 define('WATERMARK_POS_BOTTOMMIDDLE', 6);
24 define('WATERMARK_POS_BOTTOMRIGHT', 7);
25 define('WATERMARK_POS_BOTTOMLEFT', 8);
26
27 define('WATERMARK_PERM_MANAGE', 'manage watermarks');
28
29 function watermark_help($path, $arg) {
30 switch ($path) {
31 case 'admin/help#description':
32 return t('Adds watermark to image.module. Requires image.module');
33 }
34 }
35
36 function watermark_menu() {
37 $items = array();
38 $items['admin/settings/image_watermark'] = array(
39 'title' => 'Image Watermark',
40 'description' => 'Configure image watermark settings.',
41 'page callback' => 'drupal_get_form',
42 'page arguments' => array('watermark_admin_settings'),
43 'access arguments' => array('administer images'),
44 'type' => MENU_NORMAL_ITEM,
45 );
46 return $items;
47 }
48
49 function watermark_perm() {
50 return array(WATERMARK_PERM_MANAGE);
51 }
52
53 function watermark_admin_settings() {
54 if (!watermark_check_functions()) {
55 return;
56 }
57
58 $form['watermark'] = array(
59 '#type' => 'fieldset',
60 '#title' => t('Watermark'),
61 '#collapsible' => TRUE,
62 '#weight' => -1,
63 );
64
65 $form['watermark'][WATERMARK_ENABLE] = array(
66 '#type' => 'checkbox',
67 '#title' => t('Enable watermarking of new images?'),
68 '#default_value' => variable_get(WATERMARK_ENABLE, FALSE),
69 '#description' => t('Check this box to enable watermarking of new images.'),
70 );
71
72 $form['watermark'][WATERMARK_PATH] = array(
73 '#type' => 'textfield',
74 '#title' => t('Watermark overlay image'),
75 '#size' => 70,
76 '#maxlength' => 255,
77 '#required' => TRUE,
78 '#default_value' => variable_get(WATERMARK_PATH, ''),
79 '#description' => t('Path of the image that should be used as the watermark image, relative to the Drupal root. This should be a truecolor (32 bit) PNG file with an alpha channel, but other formats may work.'),
80 );
81
82 $locations = array(
83 WATERMARK_POS_MIDDLE => t('Middle'),
84 WATERMARK_POS_MIDDLERIGHT => t('Middle right'),
85 WATERMARK_POS_MIDDLELEFT => t('Middle left'),
86 WATERMARK_POS_TOPMIDDLE => t('Top middle'),
87 WATERMARK_POS_TOPLEFT => t('Top left'),
88 WATERMARK_POS_TOPRIGHT => t('Top right'),
89 WATERMARK_POS_BOTTOMMIDDLE => t('Bottom middle'),
90 WATERMARK_POS_BOTTOMRIGHT => t('Bottom right'),
91 WATERMARK_POS_BOTTOMLEFT => t('Bottom left'),
92 );
93
94 $form['watermark'][WATERMARK_LOCATION] = array(
95 '#type' => 'select',
96 '#title' => t('Location'),
97 '#options' => $locations,
98 '#default_value' => variable_get(WATERMARK_LOCATION, WATERMARK_POS_MIDDLE),
99 '#description' => t('Location on the final image where the watermark will be placed.'),
100 );
101
102 $form['watermark']['scaling'] = array(
103 '#type' => 'fieldset',
104 '#title' => t('Watermark scaling'),
105 '#collapsible' => TRUE,
106 '#collapsed' => TRUE,
107 );
108
109 $form['watermark']['scaling'][WATERMARK_SCALING] = array(
110 '#type' => 'checkbox',
111 '#title' => t('Scale watermark'),
112 '#description' => t('Use scaling, if you want the watermark to be proportional to the image width. Please note that the watermark is scaled only, when it is too big.'),
113 '#default_value' => variable_get(WATERMARK_SCALING, FALSE),
114 );
115
116 $form['watermark']['scaling'][WATERMARK_SCALING_PERCENTAGE] = array(
117 '#type' => 'textfield',
118 '#title' => t('Percentage'),
119 '#description' => t('Percentage to apply the watermark to the image.'),
120 '#size' => 3,
121 '#default_value' => variable_get(WATERMARK_SCALING_PERCENTAGE, 50),
122 );
123
124 $form['watermark']['scaling'][WATERMARK_MIN_WIDTH] = array(
125 '#type' => 'textfield',
126 '#title' => t('Minimum width'),
127 '#description' => t('The mimimum of the watermark in pixels. Type 0 to turn this option off.'),
128 '#size' => 3,
129 '#default_value' => variable_get(WATERMARK_MIN_WIDTH, 0),
130 );
131
132 $form['watermark']['labels'] = array(
133 '#type' => 'fieldset',
134 '#title' => t('Apply watermark to the following images'),
135 '#collapsible' => FALSE,
136 '#description' => t('Check which images you want to apply watermarks for.'),
137 );
138
139 foreach (_image_get_sizes() as $id => $size) {
140 $label_var = WATERMARK . $id;
141 $form['watermark']['labels'][$label_var] = array(
142 '#type' => 'checkbox',
143 '#title' => $size['label'] ." ($id)",
144 '#default_value' => variable_get($label_var, FALSE),
145 );
146 }
147
148 $gallery_enabled = module_exists('image_gallery');
149 $exclude_terms_description = t('Exclude image nodes with specific gallery terms from watermark process.');
150 $exclude_terms_description .= $gallery_enabled ? '' : ' '. t('Note: <strong>This option is disabled</strong> because Image Gallery module must be enabled first.');
151
152 $form['watermark']['toggles'] = array(
153 '#type' => 'fieldset',
154 '#title' => t('Toggles'),
155 '#collapsible' => TRUE,
156 '#collapsed' => TRUE,
157 );
158
159 $form['watermark']['toggles'][WATERMARK_EXCLUDE_TERMS] = array(
160 '#type' => 'select',
161 '#disabled' => !$gallery_enabled,
162 '#title' => t('Exclude terms'),
163 '#description' => $exclude_terms_description,
164 '#default_value' => variable_get(WATERMARK_EXCLUDE_TERMS, array()),
165 '#options' => _watermark_get_gallery_terms(),
166 '#multiple' => TRUE,
167 );
168
169 return system_settings_form($form);
170 }
171
172 function watermark_admin_settings_validate($form, &$form_state) {
173 if (!is_numeric($form_state['values'][WATERMARK_SCALING_PERCENTAGE]) || $form_state['values'][WATERMARK_SCALING_PERCENTAGE] <= 0 || $form_state['values'][WATERMARK_SCALING_PERCENTAGE] >= 100) {
174 form_set_error(WATERMARK_SCALING_PERCENTAGE, t('Please enter a number between 1 and 100 for scaling percentage.'));
175 }
176 else if ($form_state['values'][WATERMARK_SCALING_PERCENTAGE] < 10 || $form_state['values'][WATERMARK_MIN_WIDTH] < 50) {
177 // we do not disable scaling for low values, e.g. if the user chooses to scale down to 1%, we just warn
178 drupal_set_message(t('Warning: Scaling is set to @percentage%, minimum width is only @min_width px. This may result in very small or almost invisible watermarks. It is recommended to check twice that an adequate minimum width has been set.',
179 array('@percentage' => $form_state['values'][WATERMARK_SCALING_PERCENTAGE], '@min_width' => $form_state['values'][WATERMARK_MIN_WIDTH])));
180 }
181
182 if (intval($form_state['values'][WATERMARK_MIN_WIDTH]) < 0) {
183 form_set_error(WATERMARK_MIN_WIDTH, t('Please enter a positive number for minimum width.'));
184 }
185 }
186
187 function watermark_check_functions() {
188 $errors = array();
189
190 $function_list = array();
191
192 $function_list[] = 'exif_imagetype';
193 $function_list[] = 'imagecopy';
194 $function_list[] = 'imagecopyresampled';
195 $function_list[] = 'imagedestroy';
196 $types = array('gif', 'jpeg', 'png', 'wbmp');
197 foreach ($types as $type) {
198 $function_list[] = 'image'. $type;
199 $function_list[] = 'imagecreatefrom'. $type;
200 }
201
202 foreach ($function_list as $function) {
203 if (!function_exists($function)) {
204 drupal_set_message('Function $function does not exist. Watermarking cannot be done. Please make sure that you are running PHP 4.3 or higher, or that you (or your hosting provider) manually compile the GD library into your PHP installation. You also need PHP to be compiled with --enable-exif.', 'error');
205 $errors[] = 1;
206 }
207 }
208
209 if (!empty($errors)) {
210 return FALSE;
211 }
212
213 return TRUE;
214 }
215
216 function watermark_nodeapi(&$node, $op, $teaser = null, $page = null) {
217 if ($node->type != 'image') {
218 return;
219 }
220
221 if (!variable_get(WATERMARK_ENABLE, FALSE)) {
222 return;
223 }
224
225 // excluding node depends on the toggled options
226 if (_watermark_is_node_excluded($node)) {
227 return;
228 }
229
230 // We hook into node validation to be able to have a watermark on all uploads, also in previews!
231 if ($op == 'validate') {
232 // Was a new file uploaded?
233 $is_new_file = $node->new_file && is_array($node->images);
234 // Has this node already an image?
235 $has_image = !empty($node->images['_original']);
236 // for users with "manage watermarks" permission bypass automatic watermark process
237 if (user_access(WATERMARK_PERM_MANAGE)) {
238 if ($node->wm_apply) {
239 // do we need a watermark, is there any image?
240 if (!$has_image && !$is_new_file) {
241 return;
242 }
243 _watermark_apply($node);
244 }
245 }
246 // normal user, automatic watermark process
247 else if ($is_new_file) {
248 _watermark_apply($node);
249 }
250 }
251 }
252
253 function watermark_form_alter(&$form, &$form_state, $form_id) {
254 // additional option to toggle watermark process when a user has "manage watermarks" permission
255 if ($form_id == 'image_node_form' && user_access(WATERMARK_PERM_MANAGE)) {
256 $apply_watermark = TRUE;
257
258 if (preg_match('/^\/node\/[0-9]+\/edit$/i', $form['#action'])) {
259 $apply_watermark = FALSE;
260 }
261 else if ($form['#action'] != '/node/add/image') {
262 return;
263 }
264
265 $form['watermark'] = array(
266 '#type' => 'fieldset',
267 '#title' => t('Watermark settings'),
268 '#collapsible' => TRUE,
269 '#collapsed' => FALSE,
270 );
271 $form['watermark']['wm_apply'] = array(
272 '#title' => t('Apply watermark'),
273 '#type' => 'checkbox',
274 '#description' => t('<strong>Automatic watermark process bypass:</strong> Please decide yourself if a watermark needs to be applied. <strong>Be careful, do not apply watermarks twice!</strong>'),
275 '#default_value' => $apply_watermark,
276 );
277 }
278 }
279
280 function _watermark_apply($node) {
281 $watermark = variable_get(WATERMARK_PATH, '');
282 $location = variable_get(WATERMARK_LOCATION, 0);
283 $sizes = _image_get_sizes();
284 foreach ($node->images as $size => $filepath) {
285 if (variable_get(WATERMARK . $size, FALSE)) {
286 if (_watermark_process($filepath, $watermark, $location)) {
287 drupal_set_message(t('Watermark applied to image: %file', array('%file' => $sizes[$size]['label'])));
288 }
289 else {
290 drupal_set_message(t('Error adding watermark.'), 'error');
291 watchdog('error', 'Error adding watermark');
292 }
293 }
294 }
295 }
296
297 function _watermark_process($image_path, $watermark_path, $location) {
298 // init return status
299 $status = FALSE;
300
301 $scaling = variable_get(WATERMARK_SCALING, FALSE);
302
303 if (!$wm_info = _watermark_make_image($watermark_path)) {
304 return FALSE;
305 }
306 $wm = $wm_info['handle'];
307
308 if (!$im_info = _watermark_make_image($image_path)) {
309 return FALSE;
310 }
311 $im = $im_info['handle'];
312
313 if (!$im_info['truecolor']) {
314 // create truecolor image for alpha blending and better resampling
315 $new_im = imagecreatetruecolor($im_info['width'], $im_info['height']);
316 imagecopy($new_im, $im, 0, 0, 0, 0, $im_info['width'], $im_info['height']);
317 imagedestroy($im);
318 $im = $new_im;
319 }
320 imagealphablending($im, TRUE);
321
322 $im_x = $im_info['width'];
323 $im_y = $im_info['height'];
324
325 if ($scaling) {
326 // rescale wm image to desired percentage of dest image WIDTH
327 $percentage = variable_get(WATERMARK_SCALING_PERCENTAGE, 50) / 100;
328 $min_width = intval(variable_get(WATERMARK_MIN_WIDTH, 0));
329 $desired_width = $im_x * $percentage;
330 if ($desired_width < $min_width) {
331 $desired_width = $min_width;
332 }
333 $scale_ratio = $desired_width / $wm_info['width'];
334
335 // new size
336 $wm_x = $wm_info['width'] * $scale_ratio;
337 $wm_y = $wm_info['height'] * $scale_ratio;
338 }
339 else {
340 $wm_x = $wm_info['width'];
341 $wm_y = $wm_info['height'];
342 }
343
344 switch ($location) {
345 case WATERMARK_POS_MIDDLE:
346 //middle
347 $dest_x = ($im_x / 2) - ($wm_x / 2);
348 $dest_y = ($im_y / 2) - ($wm_y / 2);
349 break;
350 case WATERMARK_POS_MIDDLERIGHT:
351 //middle right
352 $dest_x = $im_x - $wm_x;
353 $dest_y = ($im_y / 2) - ($wm_y / 2);
354 break;
355 case WATERMARK_POS_MIDDLELEFT:
356 //middle left
357 $dest_x = 0;
358 $dest_y = ($im_y / 2) - ($wm_y / 2);
359 break;
360 case WATERMARK_POS_TOPMIDDLE:
361 //top middle
362 $dest_x = (($im_x - $wm_x) / 2);
363 $dest_y = 0;
364 break;
365 case WATERMARK_POS_TOPLEFT:
366 //top left
367 $dest_x = 0;
368 $dest_y = 0;
369 break;
370 case WATERMARK_POS_TOPRIGHT:
371 //top right
372 $dest_x = $im_x - $wm_x;
373 $dest_y = 0;
374 break;
375 case WATERMARK_POS_BOTTOMMIDDLE:
376 //bottom middle
377 $dest_x = (($im_x - $wm_x) / 2);
378 $dest_y = $im_y - $wm_y;
379 break;
380 case WATERMARK_POS_BOTTOMRIGHT:
381 //bottom right
382 $dest_x = $im_x - $wm_x;
383 $dest_y = $im_y - $wm_y;
384 break;
385 case WATERMARK_POS_BOTTOMLEFT:
386 //bottom left
387 $dest_x = 0;
388 $dest_y = $im_y - $wm_y;
389 break;
390 }
391
392 // image create function according to original image type
393 $img_create_func = 'image'. $im_info['type'];
394
395 // scaling on - resampling image
396 if ($scaling &&
397 !imagecopyresampled($im, $wm, $dest_x, $dest_y, 0, 0, $wm_x, $wm_y, $wm_info['width'], $wm_info['height'])) {
398 $msg = t('Failed to merge image with watermark.');
399 drupal_set_message($msg, 'error');
400 watchdog(WATERMARK_WATCHDOG, $msg, WATCHDOG_ERROR);
401 }
402 // scaling off
403 else if (!$scaling &&
404 !imagecopy($im, $wm, $dest_x, $dest_y, 0, 0, $wm_x, $wm_y)) {
405 $msg = t('Failed to merge image with watermark.');
406 drupal_set_message($msg, 'error');
407 watchdog(WATERMARK_WATCHDOG, $msg, WATCHDOG_ERROR);
408 }
409 // create an image of the same type!
410 else if (!$img_create_func($im, $image_path)) {
411 $msg = t('Failed to save merged image.');
412 drupal_set_message($msg, 'error');
413 watchdog(WATERMARK_WATCHDOG, $msg, WATCHDOG_ERROR);
414 }
415 else {
416 $status = TRUE;
417 }
418
419 imagedestroy($im);
420 imagedestroy($wm);
421
422 return $status;
423 }
424
425 function _watermark_make_image($file) {
426
427 if (!file_exists($file)) {
428 drupal_set_message(t('Image file %file not found.', array('%file' => $file ) ), 'error');
429 return FALSE;
430 }
431
432 $type = exif_imagetype($file);
433
434 switch ($type) {
435 case IMAGETYPE_GIF:
436 $type = 'gif';
437 break;
438 case IMAGETYPE_JPEG:
439 $type = 'jpeg';
440 break;
441 case IMAGETYPE_PNG:
442 $type = 'png';
443 break;
444 case IMAGETYPE_WBMP:
445 $type = 'wbmp';
446 break;
447 default:
448 // Unsupported type
449 drupal_set_message(t('Image file %file is an unsupported format type=%type.', array( '%file' => $file, '%type' => $type ) ), 'error');
450 return FALSE;
451 }
452
453 $function = 'imagecreatefrom'. $type;
454 $handle = $function($file);
455
456 if (!$handle) {
457 drupal_set_message(t('Failed to create handle for image file %file via function %function.', array( '%file' => $file, '%function' => $function )), 'error');
458 return FALSE;
459 }
460
461 // create image info
462 $img_info = array(
463 'type' => $type,
464 'truecolor' => imageistruecolor($handle),
465 'colors' => imagecolorstotal($handle),
466 'handle' => $handle,
467 'width' => imagesx($handle),
468 'height' => imagesy($handle),
469 );
470
471 return $img_info;
472 }
473
474 function _watermark_get_gallery_terms() {
475 $gallery_terms = array();
476
477 $vid = _watermark_get_gallery_vid();
478 $term_data = db_query('SELECT tid, name FROM {term_data} WHERE vid=%d', $vid);
479 while ($row = db_fetch_array($term_data)) {
480 $gallery_terms[$row['tid']] = $row['name'];
481 }
482
483 return $gallery_terms;
484 }
485
486 function _watermark_get_excluded_tids() {
487 $excluded_tids = array();
488 foreach (variable_get(WATERMARK_EXCLUDE_TERMS, array()) as $tid => $term) {
489 $excluded_tids[] = $tid;
490 }
491 return $excluded_tids;
492 }
493
494 function _watermark_get_gallery_vid() {
495
496 // code from image gallery module
497
498 $vid = variable_get('image_gallery_nav_vocabulary', '');
499 if (empty($vid) || !taxonomy_vocabulary_load($vid)) {
500 // Check to see if an image gallery vocabulary exists
501 $vid = db_result(db_query("SELECT vid FROM {vocabulary} WHERE module='image_gallery'"));
502 if (!$vid) {
503
504 // change: we don't want to create any vocabulary here
505 return FALSE;
506 }
507 variable_set('image_gallery_nav_vocabulary', $vid);
508 }
509
510 return $vid;
511 }
512
513 function _watermark_is_node_excluded($node) {
514 // for now we have only one toggle:
515 // - exclude nodes with specified vocabulary terms from watermark process
516
517 if (!empty($node->taxonomy)) {
518 $excluded_tids = _watermark_get_excluded_tids();
519 $gallery_vid = _watermark_get_gallery_vid();
520
521 foreach ($node->taxonomy as $vid => $tids) {
522 // taxonomy is an nested array when multiple selection
523 // of terms in the gallery vocabulary is allowed
524 if (is_array($tids) && $vid == $gallery_vid) {
525 foreach ($tids as $tid => $status) {
526 if ($status!=0 && in_array($tid, $excluded_tids)) {
527 // at least one term matches excluded terms
528 return TRUE;
529 }
530 }
531 }
532 // it's not a multiple select vocabulary
533 else if (!empty($tids) && $vid == $gallery_vid && in_array($tids, $excluded_tids)) {
534 // excluded term found
535 return TRUE;
536 }
537 }
538 }
539 return FALSE;
540 }

  ViewVC Help
Powered by ViewVC 1.1.2