Index: branches/RC/core/units/general/helpers/image_helper.php
===================================================================
diff -u -N
--- branches/RC/core/units/general/helpers/image_helper.php (revision 11939)
+++ branches/RC/core/units/general/helpers/image_helper.php (revision 0)
@@ -1,593 +0,0 @@
- 300, 'max_height' => 500, 'wm_filename' => 'inc/wm.png', 'h_margin' => 'c', 'v_margin' => -20)
- */
- function parseFormat($format)
- {
- $res = Array ();
-
- $format_parts = explode(';', $format);
- foreach ($format_parts as $format_part) {
- if (preg_match('/resize:(\d*)x(\d*)/', $format_part, $regs)) {
- $res['max_width'] = $regs[1];
- $res['max_height'] = $regs[2];
- }
- elseif (preg_match('/wm:([^\|]*)\|([^\|]*)\|([^\|]*)/', $format_part, $regs)) {
- $res['wm_filename'] = FULL_PATH.THEMES_PATH.'/'.$regs[1];
- $res['h_margin'] = strtolower($regs[2]);
- $res['v_margin'] = strtolower($regs[3]);
- }
- elseif (preg_match('/crop:([^\|]*)\|([^\|]*)/', $format_part, $regs)) {
- $res['crop_x'] = strtolower($regs[1]);
- $res['crop_y'] = strtolower($regs[2]);
- }
- elseif ($format_part == 'img_size' || $format_part == 'img_sizes') {
- $res['image_size'] = true;
- }
- elseif (preg_match('/fill:(.*)/', $format_part, $regs)) {
- $res['fill'] = $regs[1];
- }
- }
-
- return $res;
- }
-
- /**
- * Resized given image to required dimensions & saves resized image to "resized" subfolder in source image folder
- *
- * @param string $src_image full path to image (on server)
- * @param mixed $max_width maximal allowed resized image width or false if no limit
- * @param mixed $max_height maximal allowed resized image height or false if no limit
- * @return string direct url to resized image
- */
- function ResizeImage($src_image, $max_width, $max_height = null)
- {
- $image_size = false;
-
- if(isset($max_height)) {
- $params['max_height'] = $max_height;
- $params['max_width'] = $max_width;
- }
- else {
- $params = $this->parseFormat($max_width);
-
- if (array_key_exists('image_size', $params)) {
- // image_size param shouldn't affect resized file name (crc part)
- $image_size = $params['image_size'];
- unset($params['image_size']);
- }
- }
-
- if ($params['max_width'] > 0 || $params['max_height'] > 0) {
- list ($params['target_width'], $params['target_height'], $needs_resize) = $this->GetImageDimensions($src_image, $params['max_width'], $params['max_height'], $params);
-
- if (!is_numeric($params['max_width'])) {
- $params['max_width'] = $params['target_width'];
- }
-
- if (!is_numeric($params['max_height'])) {
- $params['max_height'] = $params['target_height'];
- }
-
- $src_path = dirname($src_image);
-
- if ($needs_resize || array_key_exists('wm_filename', $params) && $params['wm_filename']) {
- // resize required OR watermarking required -> change resulting image name !
- $dst_image = preg_replace('/^'.preg_quote($src_path, '/').'(.*)\.(.*)$/', $src_path . DIRECTORY_SEPARATOR . 'resized\\1_' . crc32(serialize($params)) . '.\\2', $src_image);
- if (!file_exists($dst_image) || filemtime($src_image) > filemtime($dst_image)) {
- // resized image not available OR should be recreated due source image change
- $params['dst_image'] = $dst_image;
- $image_resized = $this->ScaleImage($src_image, $params);
- if (!$image_resized) {
- // resize failed, because of server error
- $dst_image = $src_image;
- }
- }
-
- // resize/watermarking ok
- $src_image = $dst_image;
- }
- }
-
- if ($image_size) {
- // return only image size (resized or not)
- $image_info = $this->getImageInfo($src_image);
- return $image_info ? $image_info[3] : '';
- }
-
- $base_url = rtrim($this->Application->BaseURL(), '/');
- return str_replace(DIRECTORY_SEPARATOR, '/', preg_replace('/^'.preg_quote(FULL_PATH, '/').'(.*)/', $base_url.'\\1', $src_image));
- }
-
- /**
- * Proportionally resizes given image to destination dimensions
- *
- * @param string $src_image full path to source image (already existing)
- * @param string $dst_image full path to destination image (will be created)
- * @param int $dst_width destination image width (in pixels)
- * @param int $dst_height destination image height (in pixels)
- */
- function ScaleImage($src_image, $params)
- {
- $image_info = $this->getImageInfo($src_image);
- if (!$image_info) {
- return false;
- }
-
- /*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;
- }*/
-
- if (!$this->Application->ConfigValue('ForceImageMagickResize') && function_exists('imagecreatefromjpeg')) {
- // try to resize using GD
- $resize_map = Array (
- 'image/jpeg' => 'imagecreatefromjpeg:imagejpeg:jpg',
- 'image/gif' => 'imagecreatefromgif:imagegif:gif',
- 'image/png' => 'imagecreatefrompng:imagepng:png',
- 'image/bmp' => 'imagecreatefrombmp:imagejpeg:bmp',
- );
-
- $mime_type = $image_info['mime'];
- if (!isset($resize_map[$mime_type])) {
- return false;
- }
-
- list ($read_function, $write_function, $file_extension) = explode(':', $resize_map[$mime_type]);
-
- $src_image_rs = @$read_function($src_image);
- if ($src_image_rs) {
- // 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);
- }
-
- // 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]);
-
- $watermark_size = 'target';
-
- if (array_key_exists('crop_x', $params) || array_key_exists('crop_y', $params)) {
- // 2.1. crop image to given size
- $dst_image_rs =& $this->_cropImage($dst_image_rs, $params);
- $watermark_size = 'max';
- } elseif (array_key_exists('fill', $params)) {
- // 2.2. fill image margins from resize with given color
- $dst_image_rs =& $this->_applyFill($dst_image_rs, $params);
- $watermark_size = 'max';
- }
-
- // 3. apply watermark
- $dst_image_rs =& $this->_applyWatermark($dst_image_rs, $params[$watermark_size . '_width'], $params[$watermark_size . '_height'], $params);
-
- return @$write_function($dst_image_rs, $params['dst_image'], 100);
- }
- }
- else {
- // try to resize using ImageMagick
- // 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;
- }
-
- /**
- * Fills margins (if any) of resized are with given color
- *
- * @param resource $src_image_rs resized image resource
- * @param Array $params crop parameters
- * @return resource
- */
- function &_applyFill(&$src_image_rs, $params)
- {
- $x_position = round(($params['max_width'] - $params['target_width']) / 2); // center
- $y_position = round(($params['max_height'] - $params['target_height']) / 2); // center
-
- // crop resized image
- $fill_image_rs = imagecreatetruecolor($params['max_width'], $params['max_height']);
-
- $fill = $params['fill'];
-
- if (substr($fill, 0, 1) == '#') {
- // hexdecimal color
- $color = imagecolorallocate($fill_image_rs, hexdec( substr($fill, 1, 2) ), hexdec( substr($fill, 3, 2) ), hexdec( substr($fill, 5, 2) ));
- }
- else {
- // for now we don't support color names, but we will in future
- return $src_image_rs;
- }
-
- imagefill($fill_image_rs, 0, 0, $color);
- imagecopy($fill_image_rs, $src_image_rs, $x_position, $y_position, 0, 0, $params['target_width'], $params['target_height']);
-
- return $fill_image_rs;
- }
-
- /**
- * 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['max_width'] - $params['target_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['max_height'] - $params['target_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']);
- $crop_image_rs =& $this->_applyFill($crop_image_rs, $params);
-
- imagecopy($crop_image_rs, $src_image_rs, $x_position, $y_position, 0, 0, $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, $params)
- {
- $image_info = $this->getImageInfo($src_image);
- if (!$image_info) {
- return false;
- }
-
- $orig_width = $image_info[0];
- $orig_height = $image_info[1];
-
- $too_large = is_numeric($dst_width) ? ($orig_width > $dst_width) : false;
- $too_large = $too_large || (is_numeric($dst_height) ? ($orig_height > $dst_height) : false);
-
- if ($too_large) {
- $width_ratio = $dst_width ? $dst_width / $orig_width : 1;
- $height_ratio = $dst_height ? $dst_height / $orig_height : 1;
-
- 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);
- }
- else {
- $width = $orig_width;
- $height = $orig_height;
- }
-
- return Array ($width, $height, $too_large);
- }
-
- /**
- * 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)
- * @return mixed
- */
- function getImageInfo($src_image)
- {
- if (!file_exists($src_image)) {
- return false;
- }
-
- $image_info = @getimagesize($src_image);
- if (!$image_info) {
- trigger_error('Image '.$src_image.' missing or invalid', E_USER_WARNING);
- return false;
- }
-
- return $image_info;
- }
-
- /**
- * Returns maximal image size (width & height) among fields specified
- *
- * @param kDBItem $object
- * @param string $fields
- * @param string $format any format, that returns full url (e.g. files_resized:WxH, resize:WxH, full_url, full_urls)
- * @return string
- */
- function MaxImageSize(&$object, $fields, $format = null)
- {
- static $cached_sizes = Array ();
-
- $cache_key = $object->getPrefixSpecial().'_'.$object->GetID();
- if (!isset($cached_sizes[$cache_key])) {
- $images = Array ();
-
- $fields = explode(',', $fields);
- foreach ($fields as $field) {
- $image_data = $object->GetField($field, $format);
- if (!$image_data) {
- continue;
- }
-
- $images = array_merge($images, explode('|', $image_data));
- }
-
- $max_width = 0;
- $max_height = 0;
- $base_url = rtrim($this->Application->BaseURL(), '/');
-
- foreach ($images as $image_url) {
- $image_path = preg_replace('/^'.preg_quote($base_url, '/').'(.*)/', FULL_PATH.'\\1', $image_url);
- $image_info = $this->getImageInfo($image_path);
- $max_width = max($max_width, $image_info[0]);
- $max_height = max($max_height, $image_info[1]);
- }
-
- $cached_sizes[$cache_key] = Array ($max_width, $max_height);
- }
-
- return $cached_sizes[$cache_key];
- }
-
- /**
- * Puts existing item images (from subitem) to virtual fields (in main item)
- *
- * @param kCatDBItem $object
- */
- function LoadItemImages(&$object)
- {
- if (!$this->Application->prefixRegistred($object->Prefix.'-img')) {
- return ;
- }
-
- $max_image_count = $this->Application->ConfigValue($object->Prefix.'_MaxImageCount');
-
- $sql = 'SELECT *
- FROM '.TABLE_PREFIX.'Images
- WHERE ResourceId = '.$object->GetDBField('ResourceId').'
- ORDER BY Priority DESC
- LIMIT 0, ' . (int)$max_image_count;
- $item_images = $this->Conn->Query($sql);
-
- $image_counter = 1;
- foreach ($item_images as $item_image) {
- $image_path = $item_image['ThumbPath'];
- if ($item_image['DefaultImg'] == 1 || $item_image['Name'] == 'main') {
- // process primary image separately
- if (array_key_exists('PrimaryImage', $object->Fields)) {
- $object->SetDBField('PrimaryImage', $image_path);
- $object->SetOriginalField('PrimaryImage', $image_path);
- $object->Fields['PrimaryImage']['original_field'] = $item_image['Name'];
-
- $this->_loadCustomFields($object, $item_image, 0);
- }
- continue;
- }
-
- if (abs($item_image['Priority'])) {
- // use Priority as image counter, when specified
- $image_counter = abs($item_image['Priority']);
- }
-
- if (array_key_exists('Image'.$image_counter, $object->Fields)) {
- $object->SetDBField('Image'.$image_counter, $image_path);
- $object->SetOriginalField('Image'.$image_counter, $image_path);
- $object->Fields['Image'.$image_counter]['original_field'] = $item_image['Name'];
-
- $this->_loadCustomFields($object, $item_image, $image_counter);
- }
- $image_counter++;
- }
- }
-
- /**
- * Saves newly uploaded images to external image table
- *
- * @param kCatDBItem $object
- */
- function SaveItemImages(&$object)
- {
- if (!$this->Application->prefixRegistred($object->Prefix.'-img')) {
- return ;
- }
-
- $table_name = $this->Application->getUnitOption('img', 'TableName');
- $max_image_count = $this->Application->getUnitOption($object->Prefix, 'ImageCount'); // $this->Application->ConfigValue($object->Prefix.'_MaxImageCount');
-
- $i = 0;
- while ($i < $max_image_count) {
- $field = $i ? 'Image'.$i : 'PrimaryImage';
- $field_options = $object->GetFieldOptions($field);
-
- $image_src = $object->GetDBField($field);
- if ($image_src) {
- if (isset($field_options['original_field'])) {
- $key_clause = 'Name = '.$this->Conn->qstr($field_options['original_field']).' AND ResourceId = '.$object->GetDBField('ResourceId');
-
- if ($object->GetDBField('Delete'.$field)) {
- // if item was cloned, then new filename is in db (not in $image_src)
- $sql = 'SELECT ThumbPath
- FROM '.$table_name.'
- WHERE '.$key_clause;
- $image_src = $this->Conn->GetOne($sql);
- if (@unlink(FULL_PATH.$image_src)) {
- $sql = 'DELETE FROM '.$table_name.'
- WHERE '.$key_clause;
- $this->Conn->Query($sql);
- }
- }
- else {
- // image record found -> update
- $fields_hash = Array (
- 'ThumbPath' => $image_src,
- );
- $this->_saveCustomFields($object, $fields_hash, $i);
-
- $this->Conn->doUpdate($fields_hash, $table_name, $key_clause);
- }
- }
- else {
- // image record not found -> create
- $fields_hash = Array (
- 'ResourceId' => $object->GetDBField('ResourceId'),
- 'Name' => $field,
- 'AltName' => $field,
- 'Enabled' => STATUS_ACTIVE,
- 'DefaultImg' => $i ? 0 : 1, // first image is primary, others not primary
- 'ThumbPath' => $image_src,
- );
- $this->_saveCustomFields($object, $fields_hash, $i);
-
- $this->Conn->doInsert($fields_hash, $table_name);
- $field_options['original_field'] = $field;
- $object->SetFieldOptions($field, $field_options);
- }
- }
- $i++;
- }
- }
-
- /**
- * Adds ability to load custom fields along with main image field
- *
- * @param kCatDBItem $object
- * @param Array $fields_hash
- * @param int $counter 0 - primary image, other number - additional image number
- */
- function _loadCustomFields(&$object, $fields_hash, $counter)
- {
- $field_name = $counter ? 'Image' . $counter . 'Alt' : 'PrimaryImageAlt';
-
- $object->SetDBField($field_name, (string)$fields_hash['AltName']);
- }
-
- /**
- * Adds ability to save custom field along with main image save
- *
- * @param kCatDBItem $object
- * @param Array $fields_hash
- * @param int $counter 0 - primary image, other number - additional image number
- */
- function _saveCustomFields(&$object, &$fields_hash, $counter)
- {
- $field_name = $counter ? 'Image' . $counter . 'Alt' : 'PrimaryImageAlt';
-
- $fields_hash['AltName'] = (string)$object->GetDBField($field_name);
- }
- }
-
-?>
\ No newline at end of file