Page MenuHomeIn-Portal Phabricator

D368.id912.diff
No OneTemporary

File Metadata

Created
Wed, Feb 26, 12:35 AM

D368.id912.diff

Index: core/units/helpers/image_helper.php
===================================================================
--- core/units/helpers/image_helper.php
+++ core/units/helpers/image_helper.php
@@ -35,11 +35,15 @@
* Parses format string into array
*
* @param string $format sample format: "resize:300x500;wm:inc/wm.png|c|-20"
- * @return Array sample result: Array('max_width' => 300, 'max_height' => 500, 'wm_filename' => 'inc/wm.png', 'h_margin' => 'c', 'v_margin' => -20)
+ * @return Array sample result: Array('max_width' => 300, 'max_height' => 500, 'wm_filename' => 'inc/wm.png', 'h_margin' => 'c', 'v_margin' => -20, 'quality' => 100, output_format => 'auto', orientation => 'manual')
+ *
+ * @throws InvalidArgumentException When requested quality is out of 0..100 range.
+ * @throws InvalidArgumentException When requested output_format is out of [jpg,png,gif,bmp,auto] range.
+ * @throws InvalidArgumentException When requested orientation is out of [auto,manual,portrait,landscape] range.
*/
function parseFormat($format)
{
- $res = Array ();
+ $res = array('quality' => 100, 'output_format' => 'auto', 'orientation' => 'manual');
$format_parts = explode(';', $format);
foreach ($format_parts as $format_part) {
@@ -47,6 +51,35 @@
$res['max_width'] = $regs[1];
$res['max_height'] = $regs[2];
}
+ elseif ( preg_match('/^quality:(.*)$/', $format_part, $regs) ) {
+ $quality = (int)$regs[1];
+
+ if ( $quality > 100 || $quality < 0 || (string)$quality !== $regs[1] ) {
+ throw new InvalidArgumentException(
+ 'Quality value "' . $regs[1] . '" is out of 0..100 integer range.'
+ );
+ }
+
+ $res['quality'] = $quality;
+ }
+ elseif ( preg_match('/^output_format:(.*)$/', $format_part, $regs) ) {
+ if ( !in_array($regs[1], array('jpg', 'png', 'gif', 'bmp', 'auto')) ) {
+ throw new InvalidArgumentException(
+ 'Output format value "' . $regs[1] . '" is out of [jpg,png,gif,bmp,auto] range.'
+ );
+ }
+
+ $res['output_format'] = $regs[1];
+ }
+ elseif ( preg_match('/^orientation:(.*)$/', $format_part, $regs) ) {
+ if ( !in_array($regs[1], array('auto', 'manual', 'portrait', 'landscape')) ) {
+ throw new InvalidArgumentException(
+ 'Orientation value "' . $regs[1] . '" is out of [auto,manual,portrait,landscape] range.'
+ );
+ }
+
+ $res['orientation'] = $regs[1];
+ }
elseif (preg_match('/^wm:([^\|]*)\|([^\|]*)\|([^\|]*)$/', $format_part, $regs)) {
$res['wm_filename'] = FULL_PATH.THEMES_PATH.'/'.$regs[1];
$res['h_margin'] = strtolower($regs[2]);
@@ -113,6 +146,16 @@
}
if ( !$this->isSVG($src_image) && ($params['max_width'] > 0 || $params['max_height'] > 0) ) {
+ if ( $this->shouldRotateDimensions($src_image, $params['max_width'], $params['max_height'], $params) ) {
+ list ($params['max_width'], $params['max_height']) = array(
+ $params['max_height'], $params['max_width'],
+ );
+
+ if ( isset($params['crop_x']) && isset($params['crop_y']) ) {
+ list ($params['crop_x'], $params['crop_y']) = array($params['crop_y'], $params['crop_x']);
+ }
+ }
+
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'])) {
@@ -140,9 +183,10 @@
// Escape replacement patterns, like "\<number>".
$src_path_escaped = preg_replace('/(\\\[\d]+)/', '\\\\\1', $src_path);
$params_hash = kUtil::crc32(serialize($this->fileHelper->makeRelative($params)));
+ $file_extension = $params['output_format'] === 'auto' ? '\\2' : $params['output_format'];
$dst_image = preg_replace(
'/^' . preg_quote($src_path, '/') . '(.*)\.(.*)$/',
- $src_path_escaped . '\\1_' . $params_hash . '.\\2',
+ $src_path_escaped . '\\1_' . $params_hash . '.' . $file_extension,
$src_image
);
@@ -217,6 +261,18 @@
list ($read_function, $write_function, $file_extension) = explode(':', $resize_map[$mime_type]);
+ $output_format_map = array(
+ 'jpg' => 'imagejpeg:jpg',
+ 'png' => 'imagepng:png',
+ 'gif' => 'imagegif:gif',
+ 'bmp' => 'imagejpeg:bmp',
+ );
+ $output_format = $params['output_format'];
+
+ if ( isset($output_format_map[$output_format]) ) {
+ list ($write_function, $file_extension) = explode(':', $output_format_map[$output_format]);
+ }
+
// when source image has large dimensions (over 1MB filesize), then 16M is not enough
kUtil::setResourceLimit();
@@ -253,7 +309,11 @@
return @$write_function($dst_image_rs, $params['dst_image']);
}
- return @$write_function($dst_image_rs, $params['dst_image'], $write_function == 'imagepng' ? 0 : 100);
+ if ( $write_function == 'imagepng' ) {
+ $params['quality'] = $this->convertQualityToCompression($params['quality']);
+ }
+
+ return @$write_function($dst_image_rs, $params['dst_image'], $params['quality']);
}
}
else {
@@ -267,6 +327,18 @@
}
/**
+ * Converts quality to compression
+ *
+ * @param integer $quality Quality.
+ *
+ * @return integer
+ */
+ protected function convertQualityToCompression($quality)
+ {
+ return round((100 - $quality) / 10);
+ }
+
+ /**
* Preserve transparency for GIF and PNG images
*
* @param resource $src_image_rs
@@ -557,6 +629,43 @@
}
/**
+ * Determines when dimensions must be rotated
+ *
+ * @param string $src_image Source image path.
+ * @param integer $dst_width Destination width.
+ * @param integer $dst_height Destination height.
+ * @param array $params Parameters.
+ *
+ * @return boolean
+ * @throws InvalidArgumentException When orientation is "auto", but some of $dst_width/$dst_height is empty.
+ */
+ protected function shouldRotateDimensions($src_image, $dst_width, $dst_height, array $params)
+ {
+ $orientation = $params['orientation'];
+
+ if ( $orientation === 'manual' ) {
+ return false;
+ }
+
+ if ( $orientation === 'auto' ) {
+ if ( $dst_width === '' || $dst_height === '' ) {
+ throw new InvalidArgumentException('Both width & height parameters must be specified.');
+ }
+
+ $resized_orientation = $dst_width > $dst_height ? 'landscape' : 'portrait';
+ }
+ else {
+ $resized_orientation = $orientation;
+ }
+
+ list ($src_width, $src_height) = $this->getImageInfo($src_image);
+
+ $src_image_orientation = $src_width > $src_height ? 'landscape' : 'portrait';
+
+ return $src_image_orientation != $resized_orientation;
+ }
+
+ /**
* Returns maximal image size (width & height) among fields specified
*
* @param kDBItem $object

Event Timeline