Index: branches/RC/core/units/images/image_tag_processor.php =================================================================== diff -u -N -r11892 -r11920 --- branches/RC/core/units/images/image_tag_processor.php (.../image_tag_processor.php) (revision 11892) +++ branches/RC/core/units/images/image_tag_processor.php (.../image_tag_processor.php) (revision 11920) @@ -1,6 +1,6 @@ getObject($params); + /* @var $object kDBItem */ + $this->makeRelativePaths($object); // show "noimage.gif" when requested image is missing OR was not uploaded @@ -221,6 +223,17 @@ $image_helper =& $this->Application->recallObject('ImageHelper'); /* @var $image_helper ImageHelper */ + $crop = $this->SelectParam($params, 'Crop,crop'); + if ($crop) { + $crop = $params['crop']; + if (strpos($crop, ';') === false) { + $crop = 'c|c'; + } + + $max_width = 'resize:' . $max_width . 'x' . $max_height . ';crop:' . $crop; + $max_height = null; + } + return $image_helper->ResizeImage($src_image, $max_width, $max_height); } elseif ($use_default_image) { @@ -323,7 +336,7 @@ $max_width = $this->getImageDimension('Width', $params); $max_height = $this->getImageDimension('Height', $params); - $image_dimensions = $image_helper->GetImageDimensions($img_path, $max_width, $max_height); + $image_dimensions = $image_helper->GetImageDimensions($img_path, $max_width, $max_height, $params); if (!$image_dimensions) { return false; } Index: branches/RC/core/units/general/helpers/image_helper.php =================================================================== diff -u -N -r11892 -r11920 --- branches/RC/core/units/general/helpers/image_helper.php (.../image_helper.php) (revision 11892) +++ branches/RC/core/units/general/helpers/image_helper.php (.../image_helper.php) (revision 11920) @@ -1,6 +1,6 @@ 0 || $params['max_height'] > 0) { - list ($params['max_width'], $params['max_height'], $needs_resize) = $this->GetImageDimensions($src_image, $params['max_width'], $params['max_height']); + list ($params['target_width'], $params['target_height'], $needs_resize) = $this->GetImageDimensions($src_image, $params['max_width'], $params['max_height'], $params); $src_path = dirname($src_image); @@ -117,7 +121,7 @@ return false; } -/* list ($params['max_width'], $params['max_height'], $resized) = $this->GetImageDimensions($src_image, $params['max_width'], $params['max_height']); + /*list ($params['max_width'], $params['max_height'], $resized) = $this->GetImageDimensions($src_image, $params['max_width'], $params['max_height'], $params); if (!$resized) { // image dimensions are smaller or equals to required dimensions return false; @@ -140,71 +144,140 @@ $src_image_rs = @$read_function($src_image); if ($src_image_rs) { - $dst_image_rs = imagecreatetruecolor($params['max_width'], $params['max_height']); + // when source image has large dimensions (over 1MB filesize), then 16M is not enough + set_time_limit(0); + ini_set('memory_limit', -1); + $dst_image_rs = imagecreatetruecolor($params['target_width'], $params['target_height']); // resize target size + if ($file_extension == 'png') { // preserve transparency of PNG images $transparent_color = imagecolorallocate($dst_image_rs, 0, 0, 0); imagecolortransparent($dst_image_rs, $transparent_color); } - imagecopyresampled($dst_image_rs, $src_image_rs, 0, 0, 0, 0, $params['max_width'], $params['max_height'], $image_info[0], $image_info[1]); + // 1. resize + imagecopyresampled($dst_image_rs, $src_image_rs, 0, 0, 0, 0, $params['target_width'], $params['target_height'], $image_info[0], $image_info[1]); - if(array_key_exists('wm_filename', $params) && $params['wm_filename'] && file_exists($params['wm_filename'])) - { - $logo_img = imagecreatefrompng($params['wm_filename']); - list($logo_width, $logo_height) = getimagesize($params['wm_filename']); + // 2. crop + if (array_key_exists('crop_x', $params) || array_key_exists('crop_y', $params)) { + $dst_image_rs =& $this->_cropImage($dst_image_rs, $params); - //if(($params['max_width'] > $logo_width * 2) && ($params['max_height'] > $logo_height * 2)) - //{ - imagealphablending($dst_image_rs, true); - //imagecopy($dst_image_rs, $logo_img, $params['max_width'] - $logo_width - $right_margin, $params['max_height'] - $logo_height - $bottom_margin, 0, 0, $logo_width, $logo_height); - - if ($params['h_margin'] == 'c') { - $x_position = round($params['max_width']/2 - $logo_width/2); - } - elseif ($params['h_margin'] >= 0) { - $x_position = $params['h_margin']; - } - else { - $x_position = $params['max_width'] - (-$params['h_margin'] + $logo_width); - } - - if ($params['v_margin'] == 'c') { - $y_position = round($params['max_height']/2 - $logo_height/2); - } - elseif ($params['v_margin'] >= 0) { - $y_position = $params['v_margin']; - } - else { - $y_position = $params['max_height'] - (-$params['v_margin'] + $logo_height); - } - - imagecopy($dst_image_rs, $logo_img, $x_position, $y_position, 0, 0, $logo_width, $logo_height); - //} + // 3. apply watermark + $dst_image_rs =& $this->_applyWatermark($dst_image_rs, $params['max_width'], $params['max_height'], $params); } + else { + // 3. apply watermark + $dst_image_rs =& $this->_applyWatermark($dst_image_rs, $params['target_width'], $params['target_height'], $params); + } return @$write_function($dst_image_rs, $params['dst_image'], 100); } } else { // try to resize using ImageMagick - exec('/usr/bin/convert '.$src_image.' -resize '.$params['max_width'].'x'.$params['max_height'].' '.$params['dst_image'], $shell_output, $exec_status); + // TODO: implement crop and watermarking using imagemagick + exec('/usr/bin/convert '.$src_image.' -resize '.$params['target_width'].'x'.$params['target_height'].' '.$params['dst_image'], $shell_output, $exec_status); return $exec_status == 0; } return false; } /** + * Crop given image resource using given params and return resulting image resource + * + * @param resource $src_image_rs resized image resource + * @param Array $params crop parameters + * @return resource + */ + function &_cropImage(&$src_image_rs, $params) + { + if ($params['crop_x'] == 'c') { + $x_position = round($params['target_width'] / 2 - $params['max_width'] / 2); // center + } + elseif ($params['crop_x'] >= 0) { + $x_position = $params['crop_x']; // margin from left + } + else { + $x_position = $params['target_width'] - ($params['max_width'] - $params['crop_x']); // margin from right + } + + if ($params['crop_y'] == 'c') { + $y_position = round($params['target_height'] / 2 - $params['max_height'] / 2); // center + } + elseif ($params['crop_y'] >= 0) { + $y_position = $params['crop_y']; // margin from top + } + else { + $y_position = $params['target_height'] - ($params['max_height'] - $params['crop_y']); // margin from bottom + } + + // crop resized image + $crop_image_rs = imagecreatetruecolor($params['max_width'], $params['max_height']); + imagecopyresampled($crop_image_rs, $src_image_rs, 0, 0, $x_position, $y_position, $params['target_width'], $params['target_height'], $params['target_width'], $params['target_height']); + + return $crop_image_rs; + } + + /** + * Apply watermark (transparent PNG image) to given resized image resource + * + * @param resource $src_image_rs + * @param int $max_width + * @param int $max_height + * @param Array $params + * @return resource + */ + function &_applyWatermark(&$src_image_rs, $max_width, $max_height, $params) + { + $watermark_file = array_key_exists('wm_filename', $params) ? $params['wm_filename'] : false; + + if (!$watermark_file || !file_exists($watermark_file)) { + // no watermark required, or provided watermark image is missing + return $src_image_rs; + } + + $watermark_img_rs = imagecreatefrompng($watermark_file); + list ($watermark_width, $watermark_height) = $this->getImageInfo($watermark_file); + + imagealphablending($src_image_rs, true); + + if ($params['h_margin'] == 'c') { + $x_position = round($max_width / 2 - $watermark_width / 2); // center + } + elseif ($params['h_margin'] >= 0) { + $x_position = $params['h_margin']; // margin from left + } + else { + $x_position = $max_width - ($watermark_width - $params['h_margin']); // margin from right + } + + if ($params['v_margin'] == 'c') { + $y_position = round($max_height / 2 - $watermark_height / 2); // center + } + elseif ($params['v_margin'] >= 0) { + $y_position = $params['v_margin']; // margin from top + } + else { + $y_position = $max_height - ($watermark_height - $params['v_margin']); // margin from bottom + } + + imagecopy($src_image_rs, $watermark_img_rs, $x_position, $y_position, 0, 0, $watermark_width, $watermark_height); + + return $src_image_rs; + } + + /** * Returns destination image size without actual resizing (useful for HTML tag) * * @param string $src_image full path to source image (already existing) * @param int $dst_width destination image width (in pixels) * @param int $dst_height destination image height (in pixels) + * @param Array $params * @return Array resized image dimensions (0 - width, 1 - height) */ - function GetImageDimensions($src_image, $dst_width, $dst_height) + function GetImageDimensions($src_image, $dst_width, $dst_height, $params) { $image_info = $this->getImageInfo($src_image); if (!$image_info) { @@ -220,8 +293,16 @@ if ($too_large) { $width_ratio = $dst_width ? $dst_width / $orig_width : 1; $height_ratio = $dst_height ? $dst_height / $orig_height : 1; - $ratio = min($width_ratio, $height_ratio); + if (array_key_exists('crop_x', $params) || array_key_exists('crop_y', $params)) { + // resize by smallest inverted radio + $resize_by = $this->_getCropImageMinRatio($image_info, $dst_width, $dst_height); + $ratio = $resize_by == 'width' ? $width_ratio : $height_ratio; + } + else { + $ratio = min($width_ratio, $height_ratio); + } + $width = ceil($orig_width * $ratio); $height = ceil($orig_height * $ratio); } @@ -234,6 +315,22 @@ } /** + * Returns ratio type with smaller relation of original size to target size + * + * @param Array $image_info image information from "ImageHelper::getImageInfo" + * @param int $dst_width destination image width (in pixels) + * @param int $dst_height destination image height (in pixels) + * @return Array + */ + function _getCropImageMinRatio($image_info, $dst_width, $dst_height) + { + $width_ratio = $dst_width ? $image_info[0] / $dst_width : 1; + $height_ratio = $dst_height ? $image_info[1] / $dst_height : 1; + + return $width_ratio < $height_ratio ? 'width' : 'height'; + } + + /** * Returns image dimensions + checks if given file is existing image * * @param string $src_image full path to source image (already existing)