This program 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 3 of the License, or (at your option) any later version. This program 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 this program. If not, see . */ if(version_compare($wp_version, '2.9', '>=')) // integration check begin { // Sorry, WordPress 2.9 and newer are not supported! // Please check out the integrated image editor I was invited to // contribute to ... // Stephan, December 2009 } else { function scissors_set_memory_limit() { @ini_set('memory_limit', '256M'); //@ini_set('memory_limit', WP_MEMORY_LIMIT); } $scissors_dirname = plugin_basename(dirname(__FILE__)); $scissors_locale_dir = PLUGINDIR . '/' . $scissors_dirname . '/languages'; load_plugin_textdomain('scissors', $scissors_locale_dir); function scissors_create_image($width, $height) { if($width <= 0 || $height <= 0) return FALSE; $image = imagecreatetruecolor($width, $height); if(is_resource($image)) { // set default alpha-blending mode imagealphablending($image, false); imagesavealpha($image, true); } return $image; } function scissors_get_file_mime_type($filename) { if(!file_exists($filename)) return ''; $size = getimagesize($filename); return isset($size['mime']) ? $size['mime'] : ''; } function scissors_supports_imagetype($mime_type) { if(function_exists('imagetypes')) { switch($mime_type) { case 'image/jpeg': return (imagetypes() & IMG_JPG) != 0; case 'image/png': return (imagetypes() & IMG_PNG) != 0; case 'image/gif': return (imagetypes() & IMG_GIF) != 0; default: return FALSE; } } else { switch($mime_type) { case 'image/jpeg': return function_exists('imagecreatefromjpeg'); case 'image/png': return function_exists('imagecreatefrompng'); case 'image/gif': return function_exists('imagecreatefromgif'); default: return FALSE; } } } function scissors_load_image($filename, $mime_type) { if(!file_exists($filename)) return FALSE; if(!scissors_supports_imagetype($mime_type)) return FALSE; switch($mime_type) { case 'image/jpeg': $image = imagecreatefromjpeg($filename); break; case 'image/png': $image = imagecreatefrompng($filename); break; case 'image/gif': $image = imagecreatefromgif($filename); break; default: $image = FALSE; break; } if(is_resource($image)) { // set default alpha-blending mode imagealphablending($image, false); imagesavealpha($image, true); } return $image; } function scissors_save_image($image, $filename, $mime_type) { if(!scissors_supports_imagetype($mime_type)) return FALSE; // set default alpha-blending mode imagealphablending($image, false); imagesavealpha($image, true); switch($mime_type) { case 'image/jpeg': return imagejpeg($image, $filename, 90); case 'image/png': return imagepng($image, $filename); case 'image/gif': return imagegif($image, $filename); default: return FALSE; } } // Automatic resizing functionality ------------------------------------------- function scissors_get_fullpath_from_metadata($metadata) { $upload_path = trim(get_option('upload_path')); if(empty($upload_path)) $upload_path = WP_CONTENT_DIR . '/uploads'; $upload_path = path_join(ABSPATH, $upload_path); $filename = path_join($upload_path, $metadata['file']); return file_exists($filename) ? $filename : FALSE; } function scissors_resize_auto($metadata) { $srcW = intval($metadata['width']); $srcH = intval($metadata['height']); if($srcW <= 0 || $srcH <= 0) return $metadata; // image dimensions are fishy ... // skip full if temporarily disabled if(array_key_exists('scissorsSkipFullResize', $_REQUEST) && intval($_REQUEST['scissorsSkipFullResize']) != 0) $sizes = array('large', 'medium'); else $sizes = array('full', 'large', 'medium'); $filename = FALSE; $src = NULL; $src_mime_type = ''; foreach($sizes as $size) { $adaptive = (get_option("{$size}_adaptive") == '1'); if($size != 'full') { if(!$adaptive) continue; // skip, standard intermediate images have already been created ... if(!is_array($metadata) || !isset($metadata['sizes']) || !isset($metadata['sizes'][$size])) continue; // not available } // calculate scaled image dimensions $dstW = $srcW; $dstH = $srcH; $maxW = intval(get_option("{$size}_size_w")); $maxH = intval(get_option("{$size}_size_h")); $scaleW = (!$adaptive || $srcW >= $srcH); $scaleH = (!$adaptive || $srcH >= $srcW); if($scaleW && $maxW > 0 && $dstW > $maxW) { $dstH = $dstH * ($maxW / $dstW); $dstW = $maxW; } if($scaleH && $maxH > 0 && $dstH > $maxH) { $dstW = $dstW * ($maxH / $dstH); $dstH = $maxH; } if($dstW == $srcW && $dstH == $srcH) continue; // no need to resize the image if(!$filename) { $filename = scissors_get_fullpath_from_metadata($metadata); if(!$filename) return $metadata; // failed to locate the file scissors_set_memory_limit(); // load the full size image $src_mime_type = scissors_get_file_mime_type($filename); $src = scissors_load_image($filename, $src_mime_type); if(!is_resource($src)) return $metadata; // failed to load the file } // create a resized copy, overwrite the intermediate file and update the metadata $dst = scissors_create_image($dstW, $dstH); if(is_resource($dst)) { if(imagecopyresampled($dst, $src, 0, 0, 0, 0, $dstW, $dstH, $srcW, $srcH)) { if($size == 'full') { if(scissors_save_image($dst, $filename, $src_mime_type)) { $metadata['width'] = $dstW; $metadata['height'] = $dstH; list($uwidth, $uheight) = wp_shrink_dimensions($metadata['width'], $metadata['height']); $metadata['hwstring_small'] = "height='$uheight' width='$uwidth'"; } } else { $fname = path_join(dirname($filename), $metadata['sizes'][$size]['file']); if(scissors_save_image($dst, $fname, $src_mime_type)) { $metadata['sizes'][$size]['width'] = $dstW; $metadata['sizes'][$size]['height'] = $dstH; } } } imagedestroy($dst); } } if(is_resource($src)) imagedestroy($src); return $metadata; } add_filter('wp_generate_attachment_metadata', 'scissors_resize_auto'); function scissors_fullsize_fields() { ?>

/>

/>
/> :"; echo sprintf(__('Lock aspect ratio to %s.', 'scissors'), $field); ?>
/>
/>
[?]", 'scissors_cropping_reir', 'media', 'cropping'); } add_action('admin_init', 'scissors_cropping_add_settings'); register_activation_hook(__FILE__, 'scissors_cropping_activation'); // Watermarking support ------------------------------------------------------- function scissors_get_global_watermarking_path() { if(is_dir(WP_CONTENT_DIR . '/mu-plugins')) { $upload_path = trim(get_option('upload_path')); if(empty($upload_path)) $upload_path = WP_CONTENT_DIR . '/uploads'; $upload_path = path_join(ABSPATH, $upload_path); return path_join($upload_path, get_option('scissors_watermark_path')); } else return path_join(ABSPATH, get_option('scissors_watermark_path')); } function scissors_get_watermark_configuration() { $filename = scissors_get_global_watermarking_path(); list($ww, $wh) = file_exists($filename) ? getimagesize($filename) : array(0, 0); return array('ver' => 1, // NOTE: increment this if features are added and add appropriate checks to load_configuration 'ww' => $ww, 'wh' => $wh, 'doscale' => get_option('scissors_watermark_size'), 'scale' => get_option('scissors_watermark_size_relative'), 'horz' => get_option('scissors_watermark_halign'), 'vert' => get_option('scissors_watermark_valign')); } function scissors_get_relative_filepath($filename) { $upload_path = trim(get_option('upload_path')); if(empty($upload_path)) $upload_path = WP_CONTENT_DIR . '/uploads'; $upload_path = path_join(ABSPATH, $upload_path); return str_replace($upload_path . '/', '', $filename); } function scissors_get_absolute_filepath($filename) { $upload_path = trim(get_option('upload_path')); if(empty($upload_path)) $upload_path = WP_CONTENT_DIR . '/uploads'; $upload_path = path_join(ABSPATH, $upload_path); return path_join($upload_path, $filename); } function scissors_get_postid_from_fullfilename($filename) { global $wpdb; $relfile = scissors_get_relative_filepath($filename); $post = $wpdb->get_row($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_value = %s LIMIT 1", $relfile)); return ($post != null) ? $post->post_id : FALSE; } function scissors_save_watermark_configuration($filename, $rectfilename) { $postId = scissors_get_postid_from_fullfilename($filename); if(!$postId) return FALSE; $config = scissors_get_watermark_configuration(); $config['rectfilename'] = addslashes(scissors_get_relative_filepath($rectfilename)); return add_post_meta($postId, "_scissors_watermarking", $config, true) or update_post_meta($postId, "_scissors_watermarking", $config); } function scissors_load_watermark_configuration($postId) { $config = get_post_meta($postId, '_scissors_watermarking', true); if($config == '') return FALSE; $config['rectfilename'] = scissors_get_absolute_filepath($config['rectfilename']); return $config; } function scissors_get_watermarking_state($postId = '') { if($postId != '') { $state = get_post_meta($postId, '_scissors_watermarking_state', true); if($state == 'disabled') $state = '0'; // legacy value handling if($state != '') return $state; } return get_option('scissors_watermark_enabled'); // global configuration } function scissors_set_watermarking_state($postId, $state) { return add_post_meta($postId, '_scissors_watermarking_state', $state, true) or update_post_meta($postId, '_scissors_watermarking_state', $state); } function scissors_is_watermarking_enabled($size = '*', $postId = '', $checkFile = FALSE) { if($size == '*' || $size == '+') { if($postId != '') { $sizes = array(); $metadata = wp_get_attachment_metadata($postId); if(is_array($metadata) && isset($metadata['sizes']) && count($metadata['sizes']) > 0) { foreach($metadata['sizes'] as $s => $value) $sizes[] = $s; } } else $sizes = apply_filters('intermediate_image_sizes', array('large', 'medium', 'thumbnail')); $sizes[] = 'full'; if($size == '*') $sizes[] = 'custom'; // '+' ignores custom foreach($sizes as $s) { if(scissors_is_watermarking_enabled($s, $postId, $checkFile)) return TRUE; } return FALSE; } $str = scissors_get_watermarking_state($postId); $enabled = (strlen($str) > 0 && $str[0] == '1'); // legacy value handling (was 0 for none, 1 for all). $enabled |= strstr($str, "+$size") != FALSE; // size added? $enabled &= strstr($str, "-$size") == FALSE; // size not removed? if(!$enabled || !$checkFile) return $enabled; $filename = scissors_get_global_watermarking_path(); list($ww, $wh) = file_exists($filename) ? getimagesize($filename) : array(0, 0); return ($ww > 0 && $wh > 0); // make sure the watermark image is valid! } function scissors_find_rect_filename($filename) { $rectfilename = FALSE; if(file_exists($filename)) { $path_parts = pathinfo($filename); $sansext = substr($path_parts['basename'], 0, -(strlen($path_parts['extension']) + 1)); // +1 for the dot $pattern = '!' . preg_quote($sansext) . '-[0-9]+-rect' . preg_quote('.' . $path_parts['extension']) . '$!'; $dir = opendir($path_parts['dirname']); while($file = readdir($dir)) { if(preg_match($pattern, $file) == 1) { $rectfilename = $path_parts['dirname'] . '/' . $file; break; } } closedir($dir); } return $rectfilename; } function scissors_delete_watermark_meta($filename) { $postId = scissors_get_postid_from_fullfilename($filename); $config = $postId ? get_post_meta($postId, '_scissors_watermarking', true) : ''; if($config != '') @unlink(scissors_get_absolute_filepath($config['rectfilename'])); if($postId) delete_post_meta($postId, '_scissors_watermarking'); if($config == '') { // try to find the file manually ... it seems that the // metadata in the db is already gone when delete_file is invoked $rectfilename = scissors_find_rect_filename($filename); if($rectfilename) @unlink($rectfilename); } return $filename; // needs this to support WP filter chain } function scissors_place_watermark($image, $config = '') { if($config == '') $config = scissors_get_watermark_configuration(); $iw = imagesx($image); $ih = imagesy($image); $ww = $config['ww']; $wh = $config['wh']; // scale down the watermark to occupy the desired area if requested if($config['doscale'] == 1) { $desiredarea = $iw * $ih * ($config['scale'] / 100.0); // ($ww * $s) * ($wh * $s) = $desiredArea; $s = sqrt($desiredarea / ($ww * $wh)); if($s < 1) { $ww = $ww * $s; $wh = $wh * $s; } } // make sure that the watermark fits onto the original image, scale it down if necessary if($ww > $iw) { $wh = $wh * ($iw / $ww); $ww = $iw; } if($wh > $ih) { $ww = $ww * ($ih / $wh); $wh = $ih; } switch($config['horz']) { default: case 0: $l = 0; break; // left case 1: $l = ($iw - $ww) / 2; break; // center case 2: $l = $iw - $ww; break; // right } switch($config['vert']) { default: case 0: $t = 0; break; // top case 1: $t = ($ih - $wh) / 2; break; // middle case 2: $t = $ih - $wh; break; // bottom } return array($l, $t, $ww, $wh); } function scissors_build_rect_filename($filename) { $path_parts = pathinfo($filename); $sansext = substr($path_parts['basename'], 0, -(strlen($path_parts['extension']) + 1)); // +1 for the dot $randid = time(); // add a random number to make access to the rect more difficult (would allow watermark-removal) $path_parts['basename'] = "{$sansext}-{$randid}-rect." . $path_parts['extension']; return $path_parts["dirname"] . '/' . $path_parts['basename']; } // the following functions are referenced by the resampling and resizing/cropping functionality --- function scissors_remove_watermark($image, $postId) { $config = scissors_load_watermark_configuration($postId); if($config) { $mime_type = scissors_get_file_mime_type($config['rectfilename']); $rect = scissors_load_image($config['rectfilename'], $mime_type); if(is_resource($rect)) { imagealphablending($image, false); imagesavealpha($image, true); list($left, $top, $width, $height) = scissors_place_watermark($image, $config); imagecopy($image, $rect, $left, $top, 0, 0, $width, $height); imagedestroy($rect); } } } function scissors_watermark_image($image) { $result = FALSE; $watermark_path = scissors_get_global_watermarking_path(); $watermark_mime_type = scissors_get_file_mime_type($watermark_path); $watermark = scissors_load_image($watermark_path, $watermark_mime_type); if(is_resource($watermark)) { imagesavealpha($image, false); imagealphablending($image, true); list($l, $t, $ww, $wh) = scissors_place_watermark($image); $result = imagecopyresampled($image, $watermark, $l, $t, 0, 0, $ww, $wh, imagesx($watermark), imagesy($watermark)); imagedestroy($watermark); } return $result; } function scissors_watermark_file($filename) { $result = FALSE; $mime_type = scissors_get_file_mime_type($filename); $image = scissors_load_image($filename, $mime_type); if(is_resource($image)) { if(scissors_watermark_image($image)) $result = scissors_save_image($image, $filename, $mime_type); imagedestroy($image); } return $result; } function scissors_rebuild_watermark_meta($image, $mime_type, $postId) { $fullfilename = get_attached_file($postId); $done = FALSE; if(scissors_is_watermarking_enabled('full', $postId, TRUE)) // only need meta if full image is modified, because all image operations use it as the base { // determine the place and the size of the watermark if applied to this image list($left, $top, $width, $height) = scissors_place_watermark($image); // back up the part of the image that will be overlaid with the watermark $rect = scissors_create_image($width, $height); if(is_resource($rect)) { if(imagecopy($rect, $image, 0, 0, $left, $top, $width, $height)) { $oldconfig = scissors_load_watermark_configuration($postId); $rectfilename = ($oldconfig == FALSE) ? scissors_build_rect_filename($fullfilename) : $oldconfig['rectfilename']; if(scissors_save_image($rect, $rectfilename, $mime_type)) $done = scissors_save_watermark_configuration($fullfilename, $rectfilename); } imagedestroy($rect); } } if(!$done) scissors_delete_watermark_meta($fullfilename); } // ------------------------------------------------------------------------------------------------ function scissors_get_postid_from_metadata($metadata) { global $wpdb; $post = $wpdb->get_row($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_value = %s LIMIT 1", $metadata['file'])); return ($post != null) ? $post->post_id : FALSE; } function scissors_apply_initial_watermarks($metadata) { // skip if temporarily disabled if(array_key_exists('scissorsSkipWatermarking', $_REQUEST) && intval($_REQUEST['scissorsSkipWatermarking']) != 0) return $metadata; $postId = scissors_get_postid_from_metadata($metadata); if($postId) { $fullfilename = get_attached_file($postId); if($fullfilename && file_exists($fullfilename)) { scissors_set_watermarking_state($postId, scissors_get_watermarking_state()); // initialize local watermarking state if(scissors_is_watermarking_enabled('*', $postId, TRUE)) { // load the full size image scissors_set_memory_limit(); $mime_type = scissors_get_file_mime_type($fullfilename); $image = scissors_load_image($fullfilename, $mime_type); if(is_resource($image)) { scissors_rebuild_watermark_meta($image, $mime_type, $postId); // apply the watermark to the full size image if(scissors_is_watermarking_enabled('full', $postId, TRUE)) { if(scissors_watermark_image($image)) scissors_save_image($image, $fullfilename, $mime_type); } imagedestroy($image); // apply the watermark to the intermediate images if(is_array($metadata) && isset($metadata['sizes']) && count($metadata['sizes']) > 0) { foreach($metadata['sizes'] as $size => $data) { if(scissors_is_watermarking_enabled($size, $postId, TRUE)) { $filename = path_join(dirname($fullfilename), $data['file']); $mime_type = scissors_get_file_mime_type($filename); $image = scissors_load_image($filename, $mime_type); if(is_resource($image)) { if(scissors_watermark_image($image)) scissors_save_image($image, $filename, $mime_type); imagedestroy($image); } } } } } } } } return $metadata; } add_filter('wp_generate_attachment_metadata', 'scissors_apply_initial_watermarks'); add_filter('wp_delete_file', 'scissors_delete_watermark_meta'); function scissors_watermarking() { ?>

"; $sizes = apply_filters('intermediate_image_sizes', array('large', 'medium', 'thumbnail')); $sizes[] = 'full'; $sizes[] = 'custom'; foreach($sizes as $size) { $checked = scissors_is_watermarking_enabled($size) ? "checked" : ""; echo " "; } } function scissors_watermarking_path() { ?>

/>
/> '; echo sprintf(__('Limit the watermark to %s percent of the destination image area.', 'scissors'), $field); ?>
/> /> />
/> /> /> \n"; echo "\n"; echo "\n"; wp_enqueue_script('thickbox'); wp_enqueue_script('scissors_watermark_select_js', '/' . PLUGINDIR . '/'.$scissors_dirname.'/js/watermark-select.js', array('jquery') ); } } function scissors_watermarking_activation() { add_option('scissors_watermark_enabled', '0'); add_option('scissors_watermark_path', ''); add_option('scissors_watermark_size', '1'); add_option('scissors_watermark_size_relative', '20'); add_option('scissors_watermark_halign', '2'); add_option('scissors_watermark_valign', '2'); } function scissors_watermarking_add_settings() { register_setting('media', 'scissors_watermark_enabled'); register_setting('media', 'scissors_watermark_path', 'trim'); register_setting('media', 'scissors_watermark_size'); register_setting('media', 'scissors_watermark_size_relative', 'intval'); register_setting('media', 'scissors_watermark_halign'); register_setting('media', 'scissors_watermark_valign'); add_settings_section('watermarking', __('Watermarking', 'scissors'), 'scissors_watermarking', 'media'); add_settings_field('scissors_watermarking_switch', __('Enable', 'scissors'), 'scissors_watermarking_switch', 'media', 'watermarking'); add_settings_field('scissors_watermarking_path', __('Image', 'scissors'), 'scissors_watermarking_path', 'media', 'watermarking'); add_settings_field('scissors_watermarking_size', __('Size', 'scissors'), 'scissors_watermarking_size', 'media', 'watermarking'); add_settings_field('scissors_watermarking_halign', __('Horizontal alignment', 'scissors'), 'scissors_watermarking_halign', 'media', 'watermarking'); add_settings_field('scissors_watermarking_valign', __('Vertical alignment', 'scissors'), 'scissors_watermarking_valign', 'media', 'watermarking'); } add_action('admin_print_scripts', 'scissors_admin_head_watermark'); add_action('admin_init', 'scissors_watermarking_add_settings'); register_activation_hook(__FILE__, 'scissors_watermarking_activation'); function scissors_plugin_settings_link($links) { $settings_link = '' . __('Settings') . ''; array_unshift($links, $settings_link); return $links; } $plugin = plugin_basename(__FILE__); add_filter("plugin_action_links_$plugin", 'scissors_plugin_settings_link' ); function scissors_post_upload_ui() { $watermarking = scissors_is_watermarking_enabled('+'); $fullresizing = (intval(get_option("full_size_w")) > 0 || intval(get_option("full_size_h")) > 0); if(!$watermarking && !$fullresizing) return; echo '
'; if($watermarking) { ?> "; if($fullresizing) { ?> "; } add_action('post-flash-upload-ui', 'scissors_post_upload_ui'); add_action('post-html-upload-ui', 'scissors_post_upload_ui'); // Manual cropping and resizing functionality --------------------------------- function scissors_admin_head() { if(strstr($_SERVER['REQUEST_URI'], 'media')) { global $scissors_dirname; wp_enqueue_script('scissors_crop', '/' . PLUGINDIR . '/'.$scissors_dirname.'/js/jquery.Jcrop.js', array('jquery') ); wp_enqueue_script('scissors_js', '/' . PLUGINDIR . '/'.$scissors_dirname.'/js/scissors.js' ); $thisUrl = admin_url('admin-ajax.php'); echo "\n"; echo "\n"; echo "\n"; } } function scissors_styles() { global $scissors_dirname; wp_register_style('jcrop_style', '/' .PLUGINDIR . "/$scissors_dirname/css/jquery.Jcrop.css"); wp_register_style('scissors_style', '/' .PLUGINDIR . "/$scissors_dirname/css/scissors.css"); wp_enqueue_style('jcrop_style'); wp_enqueue_style('scissors_style'); wp_enqueue_style('thickbox'); } function gcd($a, $b) { if ($a == 0 || $b == 0) return 0; else if ($a == $b) return $a; else { do { $r = $a % $b; $a = $b; $b = $r; } while($r != 0); return $a; } } function scissors_media_meta($string, $post) { $errstr = ""; if(!scissors_supports_imagetype($post->post_mime_type)) $errstr = sprintf(__('Failed to load image. Image type %s not supported.', 'scissors'), $post->post_mime_type); { $postId = $post->ID; $filename = get_attached_file($postId); if(!$filename || !file_exists($filename)) $errstr = __('Failed to load image. File not found.', 'scissors'); else { list($width, $height) = getimagesize($filename); if($width <= 0 || $height <= 0) $errstr = __('Failed to load image. Invalid image dimensions.', 'scissors'); } } if($errstr != "") { $string .= "\n\t\t"; $string .= ""; $string .= "

$errstr

"; } else { $text_crop = __('Crop', 'scissors'); $text_resize = __('Resize', 'scissors'); $text_rotate = __('Rotate', 'scissors'); $text_watermarks = __('Watermarks', 'scissors'); $text_apply = __('Apply', 'scissors'); $text_abort = __('Abort', 'scissors'); $text_crop2 = __('Crop %s.', 'scissors'); $text_crop3 = __('Lock aspect ratio to %s.', 'scissors'); $text_width = __('width', 'scissors'); $text_height = __('height', 'scissors'); $text_longside = __('long side', 'scissors'); $text_shortside = __('short side', 'scissors'); $text_reir = __('Use automatic relevance-enhanced image reduction.', 'scissors'); $image_url = wp_get_attachment_url($post->ID); $nonce = wp_create_nonce("scissors-$postId"); $img_size = $width . ' × ' . $height; $string .= "$img_size\n\t\t"; $string .= ""; $string .= "
"; $string .= " "; $string .= " "; if(function_exists('imagerotate')) $string .= " "; $string .= ""; $string .= "
"; $cropTargets = ""; $aspectMode = get_option('scissors_crop_defaultaspect'); $aspectChecked = ($aspectMode != 2) ? "checked='checked'" : ""; if($aspectMode == 1) { $aspectX = intval(get_option('scissors_crop_useraspectx')); $aspectY = intval(get_option('scissors_crop_useraspecty')); } if($aspectMode != 1 || $aspectX <= 0 || $aspectY <= 0) { $aspectX = $width; $aspectY = $height; while(($g = gcd($aspectX, $aspectY)) > 1) { $aspectX = intval($aspectX / $g); $aspectY = intval($aspectY / $g); } } $cropAspect = ":"; $cropAspect .= ""; $reirChecked = get_option('scissors_crop_defaultreir') ? "checked='checked'" : ""; $string .= "
"; $string .= sprintf($text_crop2, $cropTargets); $string .= " "; $string .= " "; $string .= "
"; $string .= ""; $string .= ""; $string .= ""; $string .= "
 "; $string .= sprintf($text_crop3, $cropAspect); $string .= " "; $string .= "
 $text_reir [?]
"; $string .= "
"; $fields = " × "; $fields .= ""; $string .= "
"; $string .= sprintf(__('Resize to %s pixels.', 'scissors'), $fields); $string .= " "; $string .= " 
"; $string .= ""; $string .= ""; $string .= ""; $string .= ""; $string .= ""; $string .= "
"; $text_rotate2 = __('Rotate by', 'scissors'); $text_left90 = __('90 degrees left', 'scissors'); $text_right90 = __('90 degrees right', 'scissors'); $text_180 = __('180 degrees', 'scissors'); if(function_exists('imagerotate')) { $string .= "
"; $string .= "$text_rotate2 ."; $string .= " "; $string .= " "; $string .= "
"; } $string .= "
"; $wstate = scissors_get_watermarking_state($postId); $string .= ""; $sizes = (is_array($metadata) && isset($metadata['sizes']) && count($metadata['sizes']) > 0) ? array_keys($metadata['sizes']) : array(); $sizes[] = 'full'; $sizes[] = 'custom'; foreach($sizes as $size) { $checked = scissors_is_watermarking_enabled($size, $postId, TRUE) ? "checked" : ""; $string .= " "; } $string .= " "; $string .= " "; $string .= "
"; $string .= "
"; } return $string; } function scissors_image_make_intermediate_size($file, $width, $height, $crop=false, $adaptive=false) { if($adaptive == '1') { $fullsize = getimagesize($file); $width = ($fullsize[0] >= $fullsize[1]) ? $width : 0; $height = ($fullsize[1] >= $fullsize[0]) ? $height : 0; } $intermediate_result = image_make_intermediate_size($file, $width, $height, $crop); if(!$intermediate_result) { // simply use the specified file as the new intermediate albeit with smaller dimensions $suffix = "{$width}x{$height}"; $info = pathinfo($file); $dir = $info['dirname']; $ext = $info['extension']; $name = basename($file, ".{$ext}"); $destfilename = "{$dir}/{$name}-{$suffix}.{$ext}"; copy($file, $destfilename); list($realW, $realH) = getimagesize($file); $intermediate_result = array('file' => basename($destfilename), 'width' => $realW, 'height' => $realH); } return $intermediate_result; } function scissors_has_thumbnail($metadata) { return is_array($metadata) && isset($metadata['sizes']) && count($metadata['sizes']) > 0 && isset($metadata['sizes']['thumbnail']) && isset($metadata['sizes']['thumbnail']); } function scissors_crop($post, $srcfile, $src) { $x = intval($_POST['x']); $y = intval($_POST['y']); $w = intval($_POST['w']); $h = intval($_POST['h']); if($x >= 0 && $y >= 0 && $w > 0 && $h > 0) { $fullfile = get_attached_file($post->ID); if($_POST['target'] == 'chain' || $_POST['target'] == 'full') $dstfile = $fullfile; else if($intermediate = image_get_intermediate_size($post->ID, $_POST['target'])) $dstfile = tempnam(dirname($fullfile), 'scissors'); else return __('Invalid target.', 'scissors'); // TODO: respect auto-size settings for full-sized image? cropping is no problem, but rotation ... $dst = scissors_create_image($w, $h); if(is_resource($dst)) { if(imagecopy($dst, $src, 0, 0, $x, $y, $w, $h)) { if(scissors_save_image($dst, $dstfile, $post->post_mime_type)) { if($dstfile == $fullfile) scissors_rebuild_watermark_meta($dst, $post->post_mime_type, $post->ID); $metadata = wp_get_attachment_metadata($post->ID); if($_POST['target'] == 'chain' || $_POST['target'] == 'full') { // update meta data for the full-size image $metadata['width'] = $w; $metadata['height'] = $h; list($uwidth, $uheight) = wp_shrink_dimensions($metadata['width'], $metadata['height']); $metadata['hwstring_small'] = "height='$uheight' width='$uwidth'"; $msg = "done;full,{$w},{$h}"; // signal change of the full-size image if(!scissors_has_thumbnail($metadata)) $msg .= "+thumbnail,{$w},{$h}"; // full size image is used as thumbnail, force GUI updated // update existing intermediate images if requested if($_POST['target'] == 'chain' && is_array($metadata) && isset($metadata['sizes']) && count($metadata['sizes']) > 0) { foreach($metadata['sizes'] as $size => $data) { $srcfile = $fullfile; $w2 = get_option("{$size}_size_w"); $h2 = get_option("{$size}_size_h"); if($_POST['reir'] == '1') { $fx = $w2 / $w; $fy = $h2 / $h; $factor = sqrt($fx > $fy ? $fx : $fy); $cw = ceil($w * $factor); $ch = ceil($h * $factor); if($cw != $w || $ch != $h) { $cx = floor(($w - $cw) / 2); $cy = floor(($h - $ch) / 2); $interfile = tempnam(dirname($fullfile), 'scissors'); // crop $fullfile to ($cx,$cy) [$cw,$ch] and store to $interfile $tmp = scissors_create_image($cw, $ch); if(is_resource($tmp)) { if(imagecopy($tmp, $dst, 0, 0, $cx, $cy, $cw, $ch)) { if(scissors_save_image($tmp, $interfile, $post->post_mime_type)) $srcfile = $interfile; } imagedestroy($tmp); } if($srcfile != $interfile) unlink($interfile); } } $resized = scissors_image_make_intermediate_size($srcfile, $w2, $h2, get_option("{$size}_crop"), get_option("{$size}_adaptive")); if($resized) { $oldfile = path_join(dirname($fullfile), $data['file']); if($resized['file'] != $data['file']) { // overwrite the old file with the newly created image $resizedfile = path_join(dirname($srcfile), $resized['file']); copy($resizedfile, $oldfile); unlink($resizedfile); $resized['file'] = $data['file']; } $metadata['sizes'][$size] = $resized; $msg .= "+$size," . $resized['width'] . ',' . $resized['height']; // signal change if(scissors_is_watermarking_enabled($size, $post->ID, TRUE)) scissors_watermark_file($oldfile); } if($srcfile != $fullfile) unlink($srcfile); // clean up reir temporary } } wp_update_attachment_metadata($post->ID, $metadata); if(scissors_is_watermarking_enabled('full', $post->ID, TRUE)) scissors_watermark_file($dstfile); } else { $size = $_POST['target']; $resized = scissors_image_make_intermediate_size($dstfile, get_option("{$size}_size_w"), get_option("{$size}_size_h"), get_option("{$size}_crop"), get_option("{$size}_adaptive")); if($resized) { // overwrite the specified destination $resizedfile = path_join(dirname($dstfile), $resized['file']); $oldfile = path_join(dirname($fullfile), $intermediate['file']); if(copy($resizedfile, $oldfile)) { $resized['file'] = $intermediate['file']; $metadata['sizes'][$size] = $resized; $msg = "done;$size," . $resized['width'] . ',' . $resized['height']; // signal change if(scissors_is_watermarking_enabled($size, $post->ID, TRUE)) scissors_watermark_file($oldfile); } else $msg = __('Failed to save new image.', 'scissors'); unlink($resizedfile); } else $msg = __('Failed to save new image.', 'scissors'); wp_update_attachment_metadata($post->ID, $metadata); } } else $msg = __('Failed to save new image.', 'scissors'); } else $msg = __('Failed to crop image.', 'scissors'); imagedestroy($dst); } else $msg = __('Failed to allocate memory.', 'scissors'); // cleanup temporary file if($intermediate) unlink($dstfile); return $msg; } else return __('Invalid selection.', 'scissors'); } function scissors_resize($post, $filename, $src) { $w = intval($_POST['width']); $h = intval($_POST['height']); if($w > 0 && $h > 0) { $srcW = imagesx($src); $srcH = imagesy($src); if($w != $srcW || $h != $srcH) { $dst = scissors_create_image($w, $h); if(is_resource($dst)) { if(imagecopyresampled($dst, $src, 0, 0, 0, 0, $w, $h, $srcW, $srcH)) { scissors_rebuild_watermark_meta($dst, $post->post_mime_type, $post->ID); if(scissors_is_watermarking_enabled('full', $post->ID, TRUE)) scissors_watermark_image($dst); if(scissors_save_image($dst, $filename, $post->post_mime_type)) { // update meta data, no need to rebuild intermediate images because the aspect ratio always stays the same $metadata = wp_get_attachment_metadata($post->ID); $metadata['width'] = $w; $metadata['height'] = $h; list($uwidth, $uheight) = wp_shrink_dimensions($metadata['width'], $metadata['height']); $metadata['hwstring_small'] = "height='$uheight' width='$uwidth'"; wp_update_attachment_metadata($post->ID, $metadata); $msg = "done;full,{$w},{$h}"; // signal change of the full-size image if(!scissors_has_thumbnail($metadata)) $msg .= "+thumbnail,{$w},{$h}"; // full size image is used as thumbnail, force GUI updated } else $msg = __('Failed to save new image.', 'scissors'); } else $msg = __('Failed to resize image.', 'scissors'); imagedestroy($dst); return $msg; } else return __('Failed to allocate memory.', 'scissors'); } else return 'done;*'; // signal no change } else return __('Invalid destination dimensions.', 'scissors'); } function scissors_per_image_watermarks($post, $srcfile, $src) { scissors_set_watermarking_state($post->ID, $_POST['state']); // reuse the cropping functionality to rebuild the image chain with/without watermarking // TODO: this does a lot more work than what is necessary ... OPTIMIZE ME! $_POST['x'] = 0; $_POST['y'] = 0; $_POST['w'] = imagesx($src); $_POST['h'] = imagesy($src); $_POST['target'] = 'chain'; $_POST['reir'] = 0; return scissors_crop($post, $srcfile, $src); } function scissors_rotate($post, $srcfile, $src) { $angle = intval($_POST['angle']); switch($angle) { case -90: case 90: case 180: $rotated = imagerotate($src, $angle, 0); break; default: return __('Invalid query.', 'scissors'); } // reuse the cropping functionality to rebuild the image chain after rotation $_POST['x'] = 0; $_POST['y'] = 0; $_POST['w'] = imagesx($rotated); $_POST['h'] = imagesy($rotated); $_POST['target'] = 'chain'; $_POST['reir'] = 0; return scissors_crop($post, $srcfile, $rotated); } function scissors_action() { $postId = intval($_POST['post_id']); // perform security checks if (wp_verify_nonce($_POST['_wpnonce'], "scissors-$postId") && current_user_can('upload_files')) { // retrieve post data and load the full-size image $post = get_post($postId); $filename = get_attached_file($postId); if($post && $filename && file_exists($filename)) { scissors_set_memory_limit(); $src = scissors_load_image($filename, $post->post_mime_type); // load the source image if(is_resource($src)) { // if the full image contains a watermark we have to remove it first ... scissors_remove_watermark($src, $postId); if($_POST['action'] == 'scissorsCrop') $msg = scissors_crop($post, $filename, $src); else if($_POST['action'] == 'scissorsResize') $msg = scissors_resize($post, $filename, $src); else if($_POST['action'] == 'scissorsRotate') $msg = scissors_rotate($post, $filename, $src); else if($_POST['action'] == 'scissorsWatermark') $msg = scissors_per_image_watermarks($post, $filename, $src); else $msg = __('Invalid query.', 'scissors'); imagedestroy($src); } else $msg = __('Failed to load image.', 'scissors'); } else $msg = __('Invalid post-id.', 'scissors'); } else $msg = __('Unauthorized query.', 'scissors'); die($msg); } add_filter('media_meta', 'scissors_media_meta', 99, 2); add_action('admin_print_scripts', 'scissors_admin_head'); add_action('admin_print_styles', 'scissors_styles'); add_action('wp_ajax_scissorsCrop', 'scissors_action'); add_action('wp_ajax_scissorsResize', 'scissors_action'); add_action('wp_ajax_scissorsRotate', 'scissors_action'); add_action('wp_ajax_scissorsWatermark', 'scissors_action'); // On-the-fly image resampling functionality ---------------------------------- class Scissors { function Scissors() { add_filter('mce_external_plugins', array(&$this, 'mce_external_plugins')); add_filter('content_save_pre', array(&$this, 'content_save_pre')); add_action('save_post', array(&$this, 'save_post')); add_action('delete_post', array(&$this, 'delete_post')); global $wp_version; if(version_compare($wp_version, '2.8', '>=')) add_action('delete_attachment', array(&$this, 'delete_attachment')); else { // NOTE: We cannot use the delete_attachment-action because at the time it is invoked the metadata // associated with the attachment is already gone. add_filter('wp_delete_file', array(&$this, 'wp_delete_file')); } } function mce_external_plugins($plugins) { $plugins['scissors'] = plugins_url('/scissors/mce/editor_plugin.js'); return $plugins; } function _getImagePostIdFromUrl($url) { $wud = wp_upload_dir(); // remove the base url $url = str_replace($wud['baseurl'] . '/', '', $url); // remove -(width)x(height) and -custom if(preg_match('!(-[0-9]+x[0-9]+(-custom)?)([^/\\\]+)$!', $url, $match) == 1) $url = str_replace($match[1], '', $url); global $wpdb; $post = $wpdb->get_row($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_value = %s LIMIT 1", $url)); return ($post != null) ? $post->post_id : FALSE; } function _createResampledImage($imgurl, $destWidth, $destHeight) { $retval = FALSE; $postId = $this->_getImagePostIdFromUrl($imgurl); if($postId != FALSE) { // retrieve post data and load the full-size image $post = get_post($postId); $filename = get_attached_file($postId); if($post && $filename && file_exists($filename)) { $url = wp_get_attachment_url($postId); list($fullWidth, $fullHeight) = getimagesize($filename); if($destWidth < $fullWidth || $destHeight < $fullHeight) { $path_parts = pathinfo($filename); $sansext = substr($path_parts['basename'], 0, -(strlen($path_parts['extension']) + 1)); // +1 for the dot $path_parts['basename'] = "{$sansext}-{$destWidth}x{$destHeight}-custom." . $path_parts['extension']; $url = str_replace(basename($url), $path_parts['basename'], $url); $destfilename = $path_parts["dirname"] . '/' . $path_parts['basename']; if(!file_exists($destfilename)) { scissors_set_memory_limit(); $src = scissors_load_image($filename, $post->post_mime_type); // load the source image if(is_resource($src)) { $dst = scissors_create_image($destWidth, $destHeight); if(is_resource($dst)) { // if the full image contains a watermark we have to remove it first ... scissors_remove_watermark($src, $postId); if(imagecopyresampled($dst, $src, 0, 0, 0, 0, $destWidth, $destHeight, imagesx($src), imagesy($src))) { // add the watermark to the resampled image if(scissors_is_watermarking_enabled('custom', $postId, TRUE)) scissors_watermark_image($dst); if(scissors_save_image($dst, $destfilename, $post->post_mime_type)) { $key = basename($url); add_post_meta($postId, "_scissors_custom_images", array(), true); // initialize if non-existant $meta = get_post_meta($postId, '_scissors_custom_images', true); $meta[$key] = array('ref' => ''); update_post_meta($postId, "_scissors_custom_images", $meta); $retval = $url; } } imagedestroy($dst); } imagedestroy($src); } } else $retval = $url; } else $retval = $url; } } return $retval; } function content_save_pre($content) { // find images with class 'scissors-resample' and resample the image to the specified size $pattern = '!(<)img[^>]+class=\\\"[^">]*scissors-resample[^">]*\\\"[^>]*(>)!is'; $count = preg_match_all($pattern, $content, $matches, PREG_OFFSET_CAPTURE | PREG_PATTERN_ORDER); if($count > 0) { $newcontent = ''; $last = 0; for($i = 0; $i < $count; $i++) { $tagStart = $matches[1][$i][1]; $tagEnd = $matches[2][$i][1]; $newcontent .= substr($content, $last, $tagStart - $last); // append the content up to the tag $last = $tagEnd + 1; // skip over the tag itself $tag = substr($content, $tagStart, $tagEnd - $tagStart + 1); $tag = str_replace('scissors-resample', '', str_replace(' scissors-resample', '', $tag)); // remove the class $width = -1; $height = -1; $url = ''; if(preg_match('!width=\\\"([0-9]+)\\\"!is', $tag, $widthmatch) == 1) $width = ($widthmatch[1]); if(preg_match('!height=\\\"([0-9]+)\\\"!is', $tag, $heightmatch) == 1) $height = ($heightmatch[1]); if(preg_match('!src=\\\"([^">]*)\\\"!is', $tag, $urlmatch, PREG_OFFSET_CAPTURE) == 1) $url = $urlmatch[1][0]; if($width > 0 && $height > 0 && $url != '') { $newurl = $this->_createResampledImage($url, $width, $height); if($newurl != FALSE) $tag = str_replace($url, $newurl, $tag); } $newcontent .= $tag; // append the modified tag } $newcontent .= substr($content, $last); return $newcontent; } else return $content; } function _deleteReferenceToCustomImage($imgPostId, $key, $postId) { $meta = get_post_meta($imgPostId, '_scissors_custom_images', true); if($meta != FALSE) { if(strstr($meta[$key]['ref'], "[$postId]") != FALSE) { $meta[$key]['ref'] = str_replace("[$postId]", '', $meta[$key]['ref']); if($meta[$key]['ref'] == '') { $filename = get_attached_file($imgPostId); $filename = str_replace(basename($filename), $key, $filename); @unlink($filename); unset($meta[$key]); } if(count($meta) > 0) update_post_meta($imgPostId, "_scissors_custom_images", $meta); else delete_post_meta($imgPostId, "_scissors_custom_images"); } } } function save_post($postId) { $post = get_post($postId); $newimglist = array(); // find references to custom images $pattern = '!]+src="([^">]+-[0-9]+x[0-9]+-custom[^">/\\\]+)"[^>]*>!is'; $count = preg_match_all($pattern, $post->post_content, $matches, PREG_PATTERN_ORDER); foreach($matches[1] as $url) { $imgPostId = $this->_getImagePostIdFromUrl($url); if($imgPostId != FALSE) { $meta = get_post_meta($imgPostId, '_scissors_custom_images', true); if($meta != FALSE) { $key = basename($url); $newimglist[] = "$imgPostId:$key"; if(strstr($meta[$key]['ref'], "[$postId]") == FALSE) { $meta[$key]['ref'] .= "[$postId]"; update_post_meta($imgPostId, "_scissors_custom_images", $meta); } } } } $newimglist = array_unique($newimglist); // if this post gets edited, make sure to remove references to images // that are no longer present in the new version $oldimglist = get_post_meta($postId, '_scissors_custom_images', true); if(is_array($oldimglist)) { $oldimglist = array_diff($oldimglist, $newimglist); foreach($oldimglist as $elem) { list($imgPostId, $key) = explode(':', $elem); $this->_deleteReferenceToCustomImage($imgPostId, $key, $postId); } } if(count($newimglist) > 0) { add_post_meta($postId, "_scissors_custom_images", $newimglist, true) or update_post_meta($postId, "_scissors_custom_images", $newimglist); } else delete_post_meta($postId, "_scissors_custom_images"); } function delete_post($postId) { $post = get_post($postId); // find references to custom images $pattern = '!]+src="([^">]+-[0-9]+x[0-9]+-custom[^">/\\\]+)"[^>]*>!is'; $count = preg_match_all($pattern, $post->post_content, $matches, PREG_PATTERN_ORDER); foreach($matches[1] as $url) { $imgPostId = $this->_getImagePostIdFromUrl($url); if($imgPostId != FALSE) { $key = basename($url); $this->_deleteReferenceToCustomImage($imgPostId, $key, $postId); } } } function delete_attachment($postId) // proper semantics in WP >= 2.8 { $meta = get_post_meta($postId, '_scissors_custom_images', true); if($meta != FALSE) { $filename = get_attached_file($postId); $path_parts = pathinfo($filename); foreach($meta as $key => $value) @unlink($path_parts["dirname"] . '/' . $key); } } function wp_delete_file($filename) { if(file_exists($filename)) { $path_parts = pathinfo($filename); $sansext = substr($path_parts['basename'], 0, -(strlen($path_parts['extension']) + 1)); // +1 for the dot $pattern = '!' . preg_quote($sansext) . '-[0-9]+x[0-9]+-custom' . preg_quote('.' . $path_parts['extension']) . '$!'; $dir = opendir($path_parts['dirname']); while($file = readdir($dir)) { if(preg_match($pattern, $file) == 1) @unlink($path_parts['dirname'] . '/' . $file); } closedir($dir); } return $filename; } } $ScissorsInstance = new Scissors(); } // integration check end ?>