Changeset 12851


Ignore:
Timestamp:
01/05/12 22:35:25 (8 years ago)
Author:
rvelices
Message:

feature 2548 multisize - sharpen + watermarks (partially implemented / no test with imagick extension)

Location:
trunk
Files:
3 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/admin/derivatives.php

    r12820 r12851  
    2929{ 
    3030  $pderivatives = $_POST['d']; 
     31  $pwatermark = $_POST['w']; 
    3132 
    3233  // step 1 - sanitize HTML input 
     
    8788      $prev_h = intval($pderivative['h']); 
    8889    } 
    89   } 
     90     
     91    $v = intval($pderivative['sharpen']); 
     92    if ($v<0 || $v>100) 
     93    { 
     94      $errors[$type]['sharpen'] = '[0..100]'; 
     95    } 
     96    $v = intval($pderivative['quality']); 
     97    if ($v<=0 || $v>100) 
     98    { 
     99      $errors[$type]['quality'] = '(0..100]'; 
     100    } 
     101  } 
     102  $v = intval($pwatermark['xpos']); 
     103  if ($v<0 || $v>100) 
     104  { 
     105    $errors['watermark']['xpos'] = '[0..100]'; 
     106  } 
     107  $v = intval($pwatermark['ypos']); 
     108  if ($v<0 || $v>100) 
     109  { 
     110    $errors['watermark']['ypos'] = '[0..100]'; 
     111  } 
     112  $v = intval($pwatermark['opacity']); 
     113  if ($v<=0 || $v>100) 
     114  { 
     115    $errors['watermark']['opacity'] = '(0..100]'; 
     116  } 
     117 
     118 
    90119  // step 3 - save data 
    91120  if (count($errors)==0) 
    92121  { 
     122    $watermark = new WatermarkParams(); 
     123    $watermark->file = $pwatermark['file']; 
     124    $watermark->xpos = intval($pwatermark['xpos']); 
     125    $watermark->ypos = intval($pwatermark['ypos']); 
     126    $watermark->xrepeat = intval($pwatermark['xrepeat']); 
     127    $watermark->opacity = intval($pwatermark['opacity']); 
     128    $watermark->min_size = array(intval($pwatermark['minw']),intval($pwatermark['minh'])); 
     129     
     130    $old_watermark = ImageStdParams::get_watermark(); 
     131    $watermark_changed =  
     132      $watermark->file != $old_watermark->file 
     133      || $watermark->xpos != $old_watermark->xpos 
     134      || $watermark->ypos != $old_watermark->ypos 
     135      || $watermark->xrepeat != $old_watermark->xrepeat 
     136      || $watermark->opacity != $old_watermark->opacity; 
     137    ImageStdParams::set_watermark($watermark); 
     138     
    93139    $enabled = ImageStdParams::get_defined_type_map(); 
    94140    $disabled = @unserialize( @$conf['disabled_derivatives'] ); 
     
    107153        $new_params = new DerivativeParams( 
    108154            new SizingParams(  
    109               array($pderivative['w'],$pderivative['h']), 
     155              array(intval($pderivative['w']), intval($pderivative['h'])), 
    110156              round($pderivative['crop'] / 100, 2), 
    111               array($pderivative['minw'],$pderivative['minh']) 
     157              array(intval($pderivative['minw']), intval($pderivative['minh'])) 
    112158              )  
    113159          ); 
     160        $new_params->sharpen = intval($pderivative['sharpen']); 
     161        $new_params->quality = intval($pderivative['quality']); 
     162        ImageStdParams::apply_global($new_params); 
     163         
    114164        if (isset($enabled[$type])) 
    115165        { 
     
    124174          if ( $same && $new_params->sizing->max_crop != 0  
    125175              && !size_equals($old_params->sizing->min_size, $new_params->sizing->min_size) ) 
     176          { 
     177            $same = false; 
     178          } 
     179 
     180          if ( $same &&  
     181              ( $new_params->sharpen != $old_params->sharpen 
     182              || $new_params->quality > $old_params->quality) 
     183             ) 
     184          { 
     185            $same = false; 
     186          } 
     187           
     188          if ($same && 
     189            ( $new_params->use_watermark != $old_params->use_watermark  
     190             || $new_params->use_watermark && $watermark_changed ) 
     191            ) 
    126192          { 
    127193            $same = false; 
     
    183249  { 
    184250    $template->assign('derivatives', $pderivatives); 
     251    $template->assign('watermark', $pwatermark); 
    185252    $template->assign('ferrors', $errors); 
    186253  } 
     
    225292        $tpl_var['minw'] = $tpl_var['minh'] = ""; 
    226293      } 
     294      $tpl_var['sharpen'] = $params->sharpen; 
     295      $tpl_var['quality'] = $params->quality; 
    227296    } 
    228297    $tpl_vars[$type]=$tpl_var; 
    229298  } 
    230299  $template->assign('derivatives', $tpl_vars); 
     300   
     301  $wm = ImageStdParams::get_watermark(); 
     302  $template->assign('watermark', array( 
     303      'file' => $wm->file, 
     304      'minw' => $wm->min_size[0], 
     305      'minh' => $wm->min_size[1], 
     306      'xpos' => $wm->xpos, 
     307      'ypos' => $wm->ypos, 
     308      'xrepeat' => $wm->xrepeat, 
     309      'opacity' => $wm->opacity, 
     310    )); 
    231311} 
     312 
     313$watermark_files = array(); 
     314foreach (glob(PHPWG_ROOT_PATH.'themes/default/watermarks/*.png') as $file) 
     315{ 
     316  $watermark_files[] = substr($file, strlen(PHPWG_ROOT_PATH)); 
     317} 
     318$watermark_filemap = array( '' => '---' ); 
     319foreach( $watermark_files as $file) 
     320{ 
     321  $display = basename($file); 
     322  $watermark_filemap[$file] = $display; 
     323} 
     324$template->assign('watermark_files', $watermark_filemap); 
    232325 
    233326$template->set_filename('derivatives', 'derivatives.tpl'); 
  • trunk/admin/include/image.class.php

    r12756 r12851  
    4242 
    4343  function resize($width, $height); 
     44   
     45  function sharpen($amount); 
     46   
     47  function compose($overlay, $x, $y, $opacity); 
    4448 
    4549  function write($destination_filepath); 
     
    257261 
    258262    return $rotation; 
     263  } 
     264 
     265  /** Returns a normalized convolution kernel for sharpening*/ 
     266  static function get_sharpen_matrix($amount) 
     267  { 
     268                // Amount should be in the range of 18-10 
     269                $amount = round(abs(-18 + ($amount * 0.08)), 2); 
     270 
     271                $matrix = array 
     272                ( 
     273                        array(-1,   -1,    -1), 
     274                        array(-1, $amount, -1), 
     275                        array(-1,   -1,    -1), 
     276                ); 
     277     
     278    $norm = array_sum(array_map('array_sum', $matrix)); 
     279 
     280    for ($i=0; $i<3; $i++) 
     281    { 
     282      $line = & $matrix[$i]; 
     283      for ($j=0; $j<3; $j++) 
     284        $line[$j] /= $norm; 
     285    } 
     286 
     287                return $matrix; 
    259288  } 
    260289 
     
    398427  } 
    399428 
     429  function sharpen($amount) 
     430  { 
     431    $m = pwg_image::get_sharpen_matrix($amount); 
     432                return  $this->image->convolveImage($m); 
     433  } 
     434   
     435  function compose($overlay, $x, $y, $opacity) 
     436  { 
     437    // todo 
     438    return false; 
     439  } 
     440 
    400441  function write($destination_filepath) 
    401442  { 
     
    416457  var $commands = array(); 
    417458 
    418   function __construct($source_filepath, $imagickdir='') 
    419   { 
     459  function __construct($source_filepath) 
     460  { 
     461    global $conf; 
    420462    $this->source_filepath = $source_filepath; 
    421     $this->imagickdir = $imagickdir; 
    422  
    423     $command = $imagickdir.'identify -format "%wx%h" "'.realpath($source_filepath).'"'; 
     463    $this->imagickdir = $conf['ext_imagick_dir']; 
     464 
     465    $command = $this->imagickdir.'identify -format "%wx%h" "'.realpath($source_filepath).'"'; 
    424466    @exec($command, $returnarray); 
    425467    if(!is_array($returnarray) or empty($returnarray[0]) or !preg_match('/^(\d+)x(\d+)$/', $returnarray[0], $match)) 
    426468    { 
    427       die("[External ImageMagick] Corrupt image"); 
     469      die("[External ImageMagick] Corrupt image\n" . var_export($returnarray, true)); 
    428470    } 
    429471 
     
    477519    $this->add_command('filter', 'Lanczos'); 
    478520    $this->add_command('resize', $width.'x'.$height.'!'); 
     521    return true; 
     522  } 
     523 
     524  function sharpen($amount) 
     525  { 
     526    $m = pwg_image::get_sharpen_matrix($amount); 
     527     
     528    $param ='convolve "'.count($m).':'; 
     529    foreach ($m as $line) 
     530    { 
     531      $param .= ' '; 
     532      $param .= implode(',', $line); 
     533    } 
     534    $param .= '"'; 
     535    $this->add_command('morphology', $param); 
     536    return true; 
     537  } 
     538   
     539  function compose($overlay, $x, $y, $opacity) 
     540  { 
     541    $param = 'compose dissolve -define compose:args='.$opacity; 
     542    $param .= ' '.escapeshellarg(realpath($overlay->image->source_filepath)); 
     543    $param .= ' -gravity NorthWest -geometry +'.$x.'+'.$y; 
     544    $param .= ' -composite'; 
     545    $this->add_command($param); 
    479546    return true; 
    480547  } 
     
    497564    $exec .= ' "'.realpath($dest['dirname']).'/'.$dest['basename'].'"'; 
    498565    @exec($exec, $returnarray); 
     566     
     567    //echo($exec); 
    499568    return is_array($returnarray); 
    500569  } 
     
    612681  } 
    613682 
     683  function sharpen($amount) 
     684  { 
     685    $m = pwg_image::get_sharpen_matrix($amount); 
     686                return imageconvolution($this->image, $m, 1, 0); 
     687  } 
     688   
     689  function compose($overlay, $x, $y, $opacity) 
     690  { 
     691    $ioverlay = $overlay->image->image; 
     692    /* A replacement for php's imagecopymerge() function that supports the alpha channel 
     693    See php bug #23815:  http://bugs.php.net/bug.php?id=23815 */ 
     694 
     695    $ow = imagesx($ioverlay); 
     696    $oh = imagesy($ioverlay); 
     697       
     698                // Create a new blank image the site of our source image 
     699                $cut = imagecreatetruecolor($ow, $oh); 
     700 
     701                // Copy the blank image into the destination image where the source goes 
     702                imagecopy($cut, $this->image, 0, 0, $x, $y, $ow, $oh); 
     703 
     704                // Place the source image in the destination image 
     705                imagecopy($cut, $ioverlay, 0, 0, 0, 0, $ow, $oh); 
     706                imagecopymerge($this->image, $cut, $x, $y, 0, 0, $ow, $oh, $opacity); 
     707    return true; 
     708  } 
     709 
    614710  function write($destination_filepath) 
    615711  { 
  • trunk/admin/themes/default/template/derivatives.tpl

    r12829 r12851  
    2424 
    2525<form method="post" id="derviativesForm"> 
     26<fieldset> 
     27<legend>{'Watermark'|@translate}</legend> 
     28 
     29 
     30<select name="w[file]" id="wSelect"> 
     31        {html_options options=$watermark_files selected=$watermark.file} 
     32</select> 
     33 
     34<p><img id="wImg"></img></p> 
     35 
     36<label>{'Min Width'|@translate} 
     37        <input type="text" name="w[minw]" value="{$watermark.minw}"{if isset($ferrors.watermark.minw)}class="dError"{/if}>  
     38</label> 
     39 
     40<label>{'Min Height'|@translate} 
     41        <input type="text" name="w[minh]" value="{$watermark.minh}"{if isset($ferrors.watermark.minh)}class="dError"{/if}>  
     42</label> 
     43 
     44<label>{'X Position'|@translate} 
     45        <input type="text" name="w[xpos]" value="{$watermark.xpos}"{if isset($ferrors.watermark.xpos)}class="dError"{/if}>  
     46%</label> 
     47 
     48<label>{'Y Position'|@translate} 
     49        <input type="text" name="w[ypos]" value="{$watermark.ypos}"{if isset($ferrors.watermark.ypos)}class="dError"{/if}>  
     50%</label> 
     51 
     52<label>{'X Repeat'|@translate} 
     53        <input type="text" name="w[xrepeat]" value="{$watermark.xrepeat}"{if isset($ferrors.watermark.xrepeat)}class="dError"{/if}>  
     54</label> 
     55 
     56<label>{'Opacity'|@translate} 
     57        <input type="text" name="w[opacity]" value="{$watermark.opacity}"{if isset($ferrors.watermark.opacity)}class="dError"{/if}>  
     58</label> 
     59 
     60</fieldset> 
     61 
    2662<table class="table2"> 
    2763        <thead> 
     
    3470                <td>{'Min Width'|@translate}</td> 
    3571                <td>{'Min Height'|@translate}</td> 
     72                <td>{'Sharpen'|@translate} (%)</td> 
     73                <td>{'Quality'|@translate} (%)</td> 
    3674        </tr> 
    3775        </thead> 
     
    66104                        {if isset($ferrors.$type.minh)}<span class="dErrorDesc" title="{$ferrors.$type.minh}">!</span>{/if} 
    67105                {/if}</td> 
    68  
     106                <td> 
     107                        <input type="text" name="d[{$type}][sharpen]" value="{$d.sharpen}"{if isset($ferrors.$type.sharpen)}class="dError"{/if}> 
     108                        {if isset($ferrors.$type.sharpen)}<span class="dErrorDesc" title="{$ferrors.$type.sharpen}">!</span>{/if} 
     109                </td> 
     110                <td> 
     111                        <input type="text" name="d[{$type}][quality]" value="{$d.quality}"{if isset($ferrors.$type.quality)}class="dError"{/if}> 
     112                        {if isset($ferrors.$type.quality)}<span class="dErrorDesc" title="{$ferrors.$type.quality}">!</span>{/if} 
     113                </td> 
    69114        </tr> 
    70115        {/foreach} 
     
    77122        jQuery(this).removeClass("dError"); 
    78123} ); 
     124 
     125function onWatermarkChange() 
     126{ 
     127        var val = jQuery("#wSelect").val(); 
     128        if (val.length) { 
     129                jQuery("#wImg").attr('src', {/literal}'{$ROOT_URL}'{literal}+val).show(); 
     130        } 
     131        else { 
     132                jQuery("#wImg").hide(); 
     133        } 
     134} 
     135 
     136onWatermarkChange(); 
     137jQuery("#wSelect").bind("change", onWatermarkChange ); 
    79138{/literal}{/footer_script} 
  • trunk/i.php

    r12820 r12851  
    270270 
    271271include_once(PHPWG_ROOT_PATH . 'admin/include/image.class.php'); 
     272 
     273ignore_user_abort(true); 
     274set_time_limit(0); 
     275 
    272276$image = new pwg_image($page['src_path']); 
    273277 
     
    282286 
    283287// Crop & scale 
    284 $params->sizing->compute( array($image->get_width(),$image->get_height()), $page['coi'], $crop_rect, $scale_width ); 
     288$o_size = $d_size = array($image->get_width(),$image->get_height()); 
     289$params->sizing->compute($o_size , $page['coi'], $crop_rect, $scaled_size ); 
    285290if ($crop_rect) 
    286291{ 
     
    289294} 
    290295 
    291 if ($scale_width) 
     296if ($scaled_size) 
    292297{ 
    293298  $changes++; 
    294   $image->resize( $scale_width[0], $scale_width[1] ); 
     299  $image->resize( $scaled_size[0], $scaled_size[1] ); 
     300  $d_size = $scaled_size; 
     301} 
     302 
     303if ($params->sharpen) 
     304{ 
     305  $changes += $image->sharpen( $params->sharpen ); 
     306} 
     307 
     308if ($params->use_watermark) 
     309{ 
     310  $wm = ImageStdParams::get_watermark(); 
     311  $wm_image = new pwg_image(PHPWG_ROOT_PATH.$wm->file); 
     312  $wm_size = array($wm_image->get_width(),$wm_image->get_height()); 
     313  if ($d_size[0]<$wm_size[0] or $d_size[1]<$wm_size[1]) 
     314  { 
     315    $wm_scaling_params = SizingParams::classic($d_size[0], $d_size[1]); 
     316    $wm_scaling_params->compute($wm_size, null, $tmp, $wm_scaled_size); 
     317    $wm_size = $wm_scaled_size; 
     318    $wm_image->resize( $wm_scaled_size[0], $wm_scaled_size[1] ); 
     319  } 
     320  $x = round( ($wm->xpos/100)*($d_size[0]-$wm_size[0]) ); 
     321  $y = round( ($wm->ypos/100)*($d_size[1]-$wm_size[1]) ); 
     322  if ($image->compose($wm_image, $x, $y, $wm->opacity)) 
     323  { 
     324    $changes++; 
     325    if ($wm->xrepeat) 
     326    { 
     327      // todo 
     328    } 
     329  } 
     330  $wm_image->destroy(); 
    295331} 
    296332 
     
    302338} 
    303339 
     340$image->set_compression_quality( $params->quality ); 
    304341$image->write( $page['derivative_path'] ); 
    305342$image->destroy(); 
  • trunk/include/derivative_params.inc.php

    r12820 r12851  
    283283  public $type = IMG_CUSTOM; 
    284284  public $last_mod_time = 0; // used for non-custom images to regenerate the cached files 
     285  public $use_watermark = false; 
    285286  public $sizing; 
     287  public $sharpen = 0; 
     288  public $quality = 85; 
    286289 
    287290  function __construct($sizing) 
     
    292295  public function __sleep() 
    293296  { 
    294       return array('last_mod_time', 'sizing'); 
     297      return array('last_mod_time', 'sizing', 'sharpen', 'quality'); 
    295298  } 
    296299     
  • trunk/include/derivative_std_params.inc.php

    r12820 r12851  
    2929define('IMG_CUSTOM', 'custom'); 
    3030 
     31final class WatermarkParams 
     32{ 
     33  public $file = ''; 
     34  public $min_size = array(500,500); 
     35  public $xpos = 50; 
     36  public $ypos = 50; 
     37  public $xrepeat = 0; 
     38  public $opacity = 100; 
     39} 
     40 
     41 
    3142final class ImageStdParams 
    3243{ 
     
    3546  private static $type_map = array(); 
    3647  private static $undefined_type_map = array(); 
     48  private static $watermark; 
    3749 
    3850  static function get_all_types() 
     
    6173  } 
    6274 
     75  static function get_watermark() 
     76  { 
     77    return self::$watermark; 
     78  } 
     79 
    6380  static function load_from_db() 
    6481  { 
     
    6885    { 
    6986      self::$type_map = $arr['d']; 
     87      self::$watermark = @$arr['w']; 
     88      if (!self::$watermark) self::$watermark = new WatermarkParams(); 
    7089    } 
    7190    else 
     
    83102    { 
    84103      self::$type_map = $arr['d']; 
     104      self::$watermark = @$arr['w']; 
     105      if (!self::$watermark) self::$watermark = new WatermarkParams(); 
    85106    } 
    86107    else 
     
    91112  } 
    92113 
     114  static function set_watermark($watermark) 
     115  { 
     116    self::$watermark = $watermark; 
     117  } 
     118   
    93119  static function set_and_save($map) 
    94120  { 
     
    97123 
    98124    $ser = serialize( array( 
    99       'd' => self::$type_map 
     125      'd' => self::$type_map, 
     126      'w' => self::$watermark, 
    100127      ) ); 
    101128    conf_update_param('derivatives', addslashes($ser) ); 
     
    104131  } 
    105132 
    106   static function make_default() 
     133  private static function make_default() 
    107134  { 
     135    self::$watermark = new WatermarkParams(); 
    108136    self::$type_map[IMG_SQUARE] = new DerivativeParams( SizingParams::square(100,100) ); 
    109137    self::$type_map[IMG_THUMB] = new DerivativeParams( SizingParams::classic(144,144) ); 
     
    115143  } 
    116144 
     145  public static function apply_global($params) 
     146  { 
     147    if (!empty(self::$watermark->file) && 
     148        (self::$watermark->min_size[0]<=$params->sizing->ideal_size[0] 
     149        && self::$watermark->min_size[1]<=$params->sizing->ideal_size[1] ) ) 
     150    { 
     151      $params->use_watermark = true; 
     152    } 
     153  } 
     154   
    117155  private static function build_maps() 
    118156  { 
     
    120158    { 
    121159      $params->type = $type; 
     160      self::apply_global($params); 
    122161    } 
    123162    self::$all_type_map = self::$type_map; 
Note: See TracChangeset for help on using the changeset viewer.