[image processing] More image processing options [5.3.0-B1]
Currently the ImageHelper
class we're using to process user-uploaded images offers several post processing options, like:
- resizing to given dimensions
- cropping, with piece to crop take from user-specified location (e.g. center, one of a corners, absolute margins)
- filling in black bars added during cropping with any color
- watermarking
However there is always a place for improvements. I'm proposing to add following options:
Option Name | Possible Values | What it does |
---|---|---|
orientation |
| Right now attempt to resize 768x1024 (portrait) image to the 1024x768 (landscape) size would result in too small image. This behavior is kept with "manual" option. However when you specify "auto" option, then given resize dimensions are inverted (only when needed) to match portrait/landscape setting of user uploaded image. |
output_format |
| Right now the format of user uploaded image is preserved after resize. This option would allow to force resized image to have given format. |
quality |
| Right now we're setting maximal quality (based on image format) to reduce distortion in resized images. With this new setting (in combination with "output_format") it will be possible to have images of desired quality. |
Examples
- <inp2:u_Field name="PrimaryImage" format="resize:800x600;orientation:auto"/> - will adjust resize dimensions based on source image orientation
- <inp2:u_Field name="PrimaryImage" format="resize:800x600;output_format:jpg"/> - will convert image to jpg preserving maximal image quality
- <inp2:u_Field name="PrimaryImage" format="resize:800x600;output_format:jpg;quality:70"/> - will convert image to jpg with 70% image quality (default setting in Photoshop when saving jpg files)
- <inp2:u_Field name="PrimaryImage" format="resize:800x600;quality:70"/> - will convert image, but will apply 70 number as-is to the quality parameter, which will result in broken png image (when png is uploaded)
Solution
Plan (part 1 - support for "quality" option)
- in "ImageHelper::parseFormat" method parse "quality:X" format: - 0.5h
- the "X" is a number between 0 and 100
- when "X" happens to be something else throw an exception
- the "$res" array would initially contain array('quality' => 100)
- add protected "ImageHelper::convertQualityToCompression($quality)" method after "ImageHelper::ScaleImage" method that will: - 0.5h
- subtract value from 100 (when 60 is given it will become 40)
- divide by 10 and round it (the (100-65)/10 becomes 4)
- return the result
- in "ImageHelper::ScaleImage" method where "$write_function" is used to save file on disk: - 0.5h
- where "0" is used now (the PNG files) use result of "ImageHelper::convertQualityToCompression" method on "quality" parameter parsed before
- where "100" is used (everything else) use "quality" parameter parsed before
Plan (part 2 - support for "output_format" option):
- in "ImageHelper::parseFormat" method parse "output_format:X" format: - 0.5h
- the "X" is a string from this list: jpg, png, gif, bmp, auto
- when "X" happens to be something else throw an exception
- the "$res" array would initially contain array('output_format' => 'auto')
- in "ImageHelper::ScaleImage" method: - 0.5h
- after "$write_function" variable was defined create "$output_format_map" array, where:
- key is value for "output_format" option, except "auto"
- value is 2 last matching elements (also separated by colon) from $resize_map" array (e.g. "imagejpeg:jpg" value for "jpg" key and so on)
- if "output_format" option isn't "auto", then change "$write_function" and "$file_extension" variables to values extracted from "$output_format_map" array based on used "output_format" option value
- after "$write_function" variable was defined create "$output_format_map" array, where:
Plan (part 3 - support for "orientation" option):
- in "ImageHelper::parseFormat" method parse "orientation:X" format: - 0.5h
- the "X" is a string from this list: auto, manual, portrait, landscape
- when "X" happens to be something else throw an exception
- the "$res" array would initially contain array('orientation' => 'manual')
- add protected "ImageHelper::shouldRotateDimensions($src_image, $dst_width, $dst_height, array $params)" method, that will: - 0.5h
- store $params['orientation'] into $orientation variable
- if $orientation is "manual", then return "false"
- if $orientation is "auto", but only one of $dst_width/$dst_height is a number, then throw an exception
- if $orientation is "auto", then set $resized_orientation variable to orientation ("portrait" or "landscape") based on $dst_width and $dst_height variable values
- otherwise set $resized_orientation variable to value of $orientation variable (at this point it could be only "portrait" or "landscape")
- get image dimensions of "$src_image" image using "\ImageHelper::getImageInfo" method
- set $src_image_orientation variable to orientation ("portrait" or "landscape") of $src_image based on above retrieved image dimensions and store it into
- return true, when $src_image_orientation doesn't match $resized_orientation
- return false otherwise
- in "ImageHelper::ResizeImage" method, when "orientation" is "auto" AND we're inside if ( !$this->isSVG($src_image) && ($params['max_width'] > 0 || $params['max_height'] > 0) ) { logic branch (as 1st thing): - 0.5h
- if "ImageHelper::shouldRotateDimensions" returns thrusy value, then:
- swap "$params['max_width']" and "$params['max_height']" values
- swap "$params['crop_x']" and "$params['crop_y']" values, but only when such keys exist
- if "ImageHelper::shouldRotateDimensions" returns thrusy value, then:
Quote: 4h*1.4 = 6h
Related Discussions
- Center crop without resize changes the image [5.2.2-B1]
- [uploader] Incorrect uploaded image extension, when "storage_format" is used [5.2.2-B1]
- [image processing] Add support for webp images [5.2.2-B2]