Created
May 10, 2012 14:41
-
-
Save xpathr/2653540 to your computer and use it in GitHub Desktop.
Magical JIT Resizer by tmslnz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" xmlns:dyn="http://exslt.org/dynamic" extension-element-prefixes="exsl dyn"> | |
| <!-- | |
| //////////////////////////// Magical Image Resize Utility | |
| // /////////////// /// ============================ | |
| /// ///////////// //// | |
| //// ///// ///// ///// | |
| ///// /// /// ////// | |
| ////// / / /////// | |
| /////// //////// | |
| //////// // ///////// | |
| ///////// //// ////////// | |
| //////////////////////////// | |
| Copyright® The Workers Ltd. | |
| --> | |
| <!-- | |
| Magical Image Resize Utility | |
| ============================ | |
| By The Workers London Ltd. | |
| # Overview | |
| Magical image resizer and <img/> tag generator, with fallback to DummyImage extension. | |
| Suitable for call-template as well as apply-templates. Buyah. | |
| ## Params: | |
| - upload: takes an Result Tree Fragment of Symphony's <upload> or a URI to a local file. | |
| - external: takes an URL of a remote image without the "http://" part. If both $upload and $external are present, $external takes precedence. | |
| - w: the desired width | |
| - h: the desired height | |
| - value-only: if set to either 'w' or 'h' will return only the resulting dimension not the whole <img/> tag. | |
| - mode: 'normal', 'fit', 'max', 'trim'. | |
| 'normal' (default). No value: original size. One value: proportional scaling. Two values: force scale. (none, w or h, w + h) | |
| 'fit' uses w and h to define a bouding box to which images will fit proportionally. (w + h) | |
| 'max' shrinks the image only if an original dimension tops the desired max w or h (w or h, w + h) | |
| 'trim' floors any derived value to a set grid interval. (w or h) | |
| - gridsize: the size of the grid. When in 'normal' (default) mode, w and h are to be considered as grid multipliers. | |
| - JITmode: JIT modes 0 to 3 (see docs on Symphony-CMS.com) | |
| - JITcenter: JIT center 1 to 9 | |
| - Standard <img/> attributes: class, id, title, name, longdesc, etc. | |
| See README for usage examples. | |
| --> | |
| <xsl:variable name="maxsize" select="2000"/> | |
| <!-- TMEPLATE ///////////////////////////////////////////////////////// --> | |
| <!-- Controller (use it NAMED or MATCHED)--> | |
| <xsl:template name="img" match="*" mode="img"> | |
| <xsl:param name="upload" select="."/><!-- Must be a Result Tree Fragment (RTF). If empty falls back to DummyImage extension --> | |
| <xsl:param name="external"/><!-- takes an URL string of the desired image --> | |
| <xsl:param name="value-only"/><!-- Require either w or h and it will only return the numeric value, not the whole <img/> tag --> | |
| <xsl:param name="mode" select="'normal'"/><!-- string: normal, fit, max --> | |
| <xsl:param name="gridsize"/> | |
| <xsl:param name="JITmode" select="2"/> | |
| <xsl:param name="JITcenter" select="5"/> | |
| <!-- <img/> attributes --> | |
| <xsl:param name="id"/> | |
| <xsl:param name="class"/> | |
| <xsl:param name="alt"> | |
| <xsl:choose> | |
| <xsl:when test="$upload/filename"> | |
| <xsl:value-of select="$upload/filename"/> | |
| </xsl:when> | |
| <xsl:otherwise><xsl:value-of select="'undefined'"/></xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:param> | |
| <xsl:param name="name"/> | |
| <xsl:param name="title"/> | |
| <xsl:param name="longdesc"/> | |
| <xsl:param name="align"/> | |
| <xsl:param name="style"/> | |
| <xsl:param name="ismap"/> | |
| <xsl:param name="usemap"/> | |
| <!-- Requested w and/or h. Will either be used to force specific dims | |
| or as a bounding box in which to fit the resulting dims --> | |
| <xsl:param name="w"/> | |
| <xsl:param name="h"/> | |
| <!-- Original W/H. Can either be passed directly or fall-back to the following defaults. Never go without it.--> | |
| <xsl:param name="source-w"/> | |
| <xsl:param name="source-h"/> | |
| <!-- Symphony Root prefix (i.e. /cms/image/2/200...)--> | |
| <xsl:param name="root_prefix" select="substring-after(substring-after($root, 'http://'), '/')"/> | |
| <xsl:variable name="root"><!-- let's prepend the $root in case symphony is installed in a subdirectory --> | |
| <xsl:if test="$root_prefix != ''"> | |
| <xsl:value-of select="concat('/', $root_prefix)"/> | |
| </xsl:if> | |
| </xsl:variable> | |
| <xsl:variable name="non-standard-upload"> | |
| <!-- TODO: implement check for leading slash. | |
| If not found, add it. --> | |
| </xsl:variable> | |
| <xsl:variable name="original-w"> | |
| <xsl:choose> | |
| <xsl:when test="not($source-w)"> | |
| <xsl:choose> | |
| <xsl:when test="$upload/meta/@width"> | |
| <xsl:value-of select="$upload/meta/@width"/> | |
| </xsl:when> | |
| <xsl:when test="$w"> | |
| <xsl:value-of select="$w"/> | |
| </xsl:when> | |
| </xsl:choose> | |
| </xsl:when> | |
| <xsl:otherwise> | |
| <xsl:value-of select="$source-w"/> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:variable> | |
| <xsl:variable name="original-h"> | |
| <xsl:choose> | |
| <xsl:when test="not($source-h)"> | |
| <xsl:choose> | |
| <xsl:when test="$upload/meta/@height"> | |
| <xsl:value-of select="$upload/meta/@height"/> | |
| </xsl:when> | |
| <xsl:when test="$h"> | |
| <xsl:value-of select="$h"/> | |
| </xsl:when> | |
| </xsl:choose> | |
| </xsl:when> | |
| <xsl:otherwise> | |
| <xsl:value-of select="$source-h"/> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:variable> | |
| <!-- Minimal error checking --> | |
| <xsl:choose> | |
| <xsl:when test="$mode = 'trim' and $gridsize = ''"> | |
| <xsl:message>When using <![CDATA[<xsl:with-param name="mode" select="trim">]]> you also need to specify a grid size. Eg: <![CDATA[<xsl:with-param name="gridsize" select="50">]]> </xsl:message> | |
| </xsl:when> | |
| <xsl:when test="$mode = 'max' and ($w = '' and $h = '')"> | |
| <xsl:message>When using 'max' mode you need to specify either width, height or both. For instance: <![CDATA[<xsl:with-param name="w" select="400">]]></xsl:message> | |
| </xsl:when> | |
| </xsl:choose> | |
| <xsl:choose> | |
| <!-- If neither $upload or $external are there, then we default to Dummy Image but we need the following: --> | |
| <xsl:when test="$upload = '' and $external = '' and (($original-w = '' and $w = '') or ($original-h = '' and $h=''))"> | |
| <xsl:message>Dummy Image mode needs both W and H params if original-W and original-H are not passed</xsl:message> | |
| </xsl:when> | |
| <!-- If $external is set then we also need some sizing info --> | |
| <xsl:when test="$external != '' and (($original-w = '' and $w = '') or ($original-h = '' and $h = ''))"> | |
| <xsl:message>When using external images, we need the original dims passed or both the desired width and height.</xsl:message> | |
| </xsl:when> | |
| <!-- If non of these are set it and the previous tests have passed, then $upload has data, but it's non-standard and we need--> | |
| <xsl:when test="$upload != '' and (($original-w = '' and $w = '') or ($original-h = '' and $h = ''))"> | |
| <xsl:message>Cannot automatically determine original-w or original-h, please pass both explicitly if you are using a non-standard upload field</xsl:message> | |
| </xsl:when> | |
| <!-- Using non-standard upload field we also need to make sure we have a file path in $upload --> | |
| <xsl:when test=" | |
| $upload != '' | |
| and | |
| not($upload/meta/@width) and not($upload/meta/@height) | |
| and not | |
| ( | |
| (substring(normalize-space($upload), string-length(normalize-space($upload))-3) = '.jpg') | |
| or | |
| (substring(normalize-space($upload), string-length(normalize-space($upload))-3) = '.png') | |
| ) | |
| "> | |
| <xsl:message>The upload file path doesn't seem valid. It should end with .jpg or .png</xsl:message> | |
| </xsl:when> | |
| </xsl:choose> | |
| <!-- end possible cases --> | |
| <xsl:variable name="img_w"> | |
| <xsl:call-template name="core-logic"> | |
| <xsl:with-param name="return" select="'w'"/> | |
| <xsl:with-param name="mode" select="$mode"/> | |
| <xsl:with-param name="w" select="$w"/> | |
| <xsl:with-param name="h" select="$h"/> | |
| <xsl:with-param name="original-w" select="$original-w"/> | |
| <xsl:with-param name="original-h" select="$original-h"/> | |
| <xsl:with-param name="gridsize" select="$gridsize"/> | |
| </xsl:call-template> | |
| </xsl:variable> | |
| <xsl:variable name="img_h"> | |
| <xsl:call-template name="core-logic"> | |
| <xsl:with-param name="return" select="'h'"/> | |
| <xsl:with-param name="mode" select="$mode"/> | |
| <xsl:with-param name="w" select="$w"/> | |
| <xsl:with-param name="h" select="$h"/> | |
| <xsl:with-param name="original-w" select="$original-w"/> | |
| <xsl:with-param name="original-h" select="$original-h"/> | |
| <xsl:with-param name="gridsize" select="$gridsize"/> | |
| </xsl:call-template> | |
| </xsl:variable> | |
| <xsl:variable name="img_src"> | |
| <xsl:choose> | |
| <xsl:when test="$external != ''"> | |
| <xsl:value-of select="concat($root, '/image/', $JITmode, '/', $img_w, '/', $img_h, '/', $JITcenter, '/1/', $external)"/> | |
| </xsl:when> | |
| <xsl:when test="$upload/@path and $upload/filename"> | |
| <xsl:value-of select="concat($root, '/image/', $JITmode, '/', $img_w, '/', $img_h, '/', $JITcenter, '/0', $upload/@path, '/', $upload/filename)"/> | |
| </xsl:when> | |
| <xsl:when test="$upload != ''"> | |
| <xsl:value-of select="concat($root, '/image/', $JITmode, '/', $img_w, '/', $img_h, '/', $JITcenter, '/0', $upload)"/> | |
| </xsl:when> | |
| <xsl:when test="$upload = ''"> | |
| <xsl:value-of select="concat('/dummyimage/', $img_w, 'x', $img_h)"/> | |
| </xsl:when> | |
| </xsl:choose> | |
| </xsl:variable> | |
| <xsl:if test="$value-only = 'w'"> | |
| <xsl:value-of select="$img_w"/> | |
| </xsl:if> | |
| <xsl:if test="$value-only = 'h'"> | |
| <xsl:value-of select="$img_h"/> | |
| </xsl:if> | |
| <xsl:if test="$value-only = ''"> | |
| <xsl:call-template name="return-full-tag-with-attributes"> | |
| <xsl:with-param name="src" select="$img_src"/> | |
| <xsl:with-param name="width" select="$img_w"/> | |
| <xsl:with-param name="height" select="$img_h"/> | |
| <xsl:with-param name="id" select="$id"/> | |
| <xsl:with-param name="class" select="$class"/> | |
| <xsl:with-param name="alt" select="$alt"/> | |
| <xsl:with-param name="name" select="$name"/> | |
| <xsl:with-param name="longdesc" select="$longdesc"/> | |
| <xsl:with-param name="align" select="$align"/> | |
| <xsl:with-param name="style" select="$style"/> | |
| <xsl:with-param name="ismap" select="$ismap"/> | |
| <xsl:with-param name="usemap" select="$usemap"/> | |
| </xsl:call-template> | |
| </xsl:if> | |
| </xsl:template> | |
| <!-- TMEPLATE ///////////////////////////////////////////////////////// --> | |
| <!-- Width and Height Controller | |
| Checks what mode we're in and passes/retrieves the right values for it --> | |
| <xsl:template name="core-logic"> | |
| <xsl:param name="return"/> | |
| <xsl:param name="mode"/> | |
| <xsl:param name="w"/> | |
| <xsl:param name="h"/> | |
| <xsl:param name="original-w"/> | |
| <xsl:param name="original-h"/> | |
| <xsl:param name="gridsize"/> | |
| <!-- the dimension currently being processed --> | |
| <xsl:variable name="current-dim"> | |
| <xsl:choose> | |
| <xsl:when test="$return = 'w'"> | |
| <xsl:value-of select="$w"/> | |
| </xsl:when> | |
| <xsl:when test="$return = 'h'"> | |
| <xsl:value-of select="$h"/> | |
| </xsl:when> | |
| </xsl:choose> | |
| </xsl:variable> | |
| <!-- the original width or height of the image --> | |
| <xsl:variable name="original-dim"> | |
| <xsl:choose> | |
| <xsl:when test="$return = 'w'"> | |
| <xsl:value-of select="$original-w"/> | |
| </xsl:when> | |
| <xsl:when test="$return = 'h'"> | |
| <xsl:value-of select="$original-h"/> | |
| </xsl:when> | |
| </xsl:choose> | |
| </xsl:variable> | |
| <!-- Figure out ratio of original and compare to ratio of container if in 'fit' mode --> | |
| <xsl:variable name="original-ratio" select="$original-w div $original-h"/> | |
| <xsl:variable name="fit-ratio"> | |
| <xsl:if test="$w and $h"> | |
| <xsl:value-of select="$w div $h"/> | |
| </xsl:if> | |
| </xsl:variable> | |
| <!-- Modes --> | |
| <xsl:variable name="result"> | |
| <xsl:choose> | |
| <xsl:when test="$mode = 'max'"> | |
| <xsl:choose> | |
| <xsl:when test="(($original-w > $w) and ($w != '')) or (($original-h > $h) and ($h != ''))"> | |
| <xsl:call-template name="rescale"> | |
| <xsl:with-param name="return" select="$return"/> | |
| <xsl:with-param name="w" select="$w"/> | |
| <xsl:with-param name="h" select="$h"/> | |
| <xsl:with-param name="original-w" select="$original-w"/> | |
| <xsl:with-param name="original-h" select="$original-h"/> | |
| </xsl:call-template> | |
| </xsl:when> | |
| <xsl:otherwise><!-- Used to be test="(($original-w < $w) and ($w != '')) or (($original-h < $h) and ($h != ''))" --> | |
| <xsl:value-of select="$original-dim"/> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:when> | |
| <xsl:when test="$mode = 'fit'"> | |
| <xsl:if test="$original-ratio >= $fit-ratio"> | |
| <xsl:call-template name="rescale"> | |
| <xsl:with-param name="return" select="$return"/> | |
| <xsl:with-param name="w" select="$w"/> | |
| <xsl:with-param name="original-w" select="$original-w"/> | |
| <xsl:with-param name="original-h" select="$original-h"/> | |
| </xsl:call-template> | |
| </xsl:if> | |
| <xsl:if test="$original-ratio < $fit-ratio"> | |
| <xsl:call-template name="rescale"> | |
| <xsl:with-param name="return" select="$return"/> | |
| <xsl:with-param name="h" select="$h"/> | |
| <xsl:with-param name="original-w" select="$original-w"/> | |
| <xsl:with-param name="original-h" select="$original-h"/> | |
| </xsl:call-template> | |
| </xsl:if> | |
| </xsl:when> | |
| <xsl:otherwise> | |
| <xsl:call-template name="rescale"> | |
| <xsl:with-param name="return" select="$return"/> | |
| <xsl:with-param name="w" select="$w"/> | |
| <xsl:with-param name="h" select="$h"/> | |
| <xsl:with-param name="original-w" select="$original-w"/> | |
| <xsl:with-param name="original-h" select="$original-h"/> | |
| </xsl:call-template> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:variable> | |
| <!-- before returning the final value, we check if there's any griddy settings --> | |
| <xsl:variable name="value"> | |
| <xsl:choose> | |
| <xsl:when test="$mode = 'trim'"> | |
| <xsl:choose> | |
| <xsl:when test="$current-dim != ''"> | |
| <xsl:value-of select="$current-dim"/> | |
| </xsl:when> | |
| <xsl:otherwise> | |
| <xsl:value-of select="round($result div $gridsize) * $gridsize"/> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:when> | |
| <xsl:when test="$gridsize and not($mode = 'fit' or $mode = 'max')"> | |
| <xsl:value-of select="round($result) * $gridsize"/> | |
| </xsl:when> | |
| <xsl:otherwise> | |
| <xsl:value-of select="$result"/> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:variable> | |
| <!-- last sanity check to avoid massive memory swapping and crashing PHP --> | |
| <xsl:variable name="final"> | |
| <xsl:choose> | |
| <xsl:when test="$value and ($value <= $maxsize)"> | |
| <xsl:value-of select="$value"/> | |
| </xsl:when> | |
| <xsl:when test="$value = ''"> | |
| <xsl:choose> | |
| <xsl:when test="$return = 'w'"> | |
| <xsl:message>Width has not been calculated</xsl:message> | |
| </xsl:when> | |
| <xsl:when test="$return = 'h'"> | |
| <xsl:message>Height has not been calculated</xsl:message> | |
| </xsl:when> | |
| </xsl:choose> | |
| </xsl:when> | |
| </xsl:choose> | |
| </xsl:variable> | |
| <xsl:value-of select="$final"/> | |
| </xsl:template> | |
| <!-- TMEPLATE ///////////////////////////////////////////////////////// --> | |
| <!-- Calculates the missing dimension, retaining proportions. | |
| If both w and h values are empty it returns the original image size --> | |
| <xsl:template name="rescale"> | |
| <xsl:param name="return"/><!-- Required. Takes 'w' or 'h' --> | |
| <!-- if none specified the original dims are returned --> | |
| <xsl:param name="h"/> | |
| <xsl:param name="w"/> | |
| <xsl:param name="original-h"/> | |
| <xsl:param name="original-w"/> | |
| <xsl:variable name="derived-dim"> | |
| <xsl:choose> | |
| <xsl:when test="$w"> | |
| <xsl:value-of select="($w div $original-w)* $original-h"/> | |
| </xsl:when> | |
| <xsl:when test="$h"> | |
| <xsl:value-of select="($h div $original-h)* $original-w"/> | |
| </xsl:when> | |
| </xsl:choose> | |
| </xsl:variable> | |
| <xsl:variable name="result"> | |
| <xsl:choose> | |
| <xsl:when test="$return = 'w'"> | |
| <xsl:choose> | |
| <xsl:when test="$w"> | |
| <xsl:value-of select="$w"/> | |
| </xsl:when> | |
| <xsl:when test="$h"> | |
| <xsl:value-of select="$derived-dim"/> | |
| </xsl:when> | |
| <xsl:otherwise> | |
| <xsl:value-of select="$original-w"/> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:when> | |
| <xsl:when test="$return = 'h'"> | |
| <xsl:choose> | |
| <xsl:when test="$h"> | |
| <xsl:value-of select="$h"/> | |
| </xsl:when> | |
| <xsl:when test="$w"> | |
| <xsl:value-of select="$derived-dim"/> | |
| </xsl:when> | |
| <xsl:otherwise> | |
| <xsl:value-of select="$original-h"/> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:when> | |
| </xsl:choose> | |
| </xsl:variable> | |
| <xsl:value-of select="round($result)"/> | |
| </xsl:template> | |
| <!-- TMEPLATE ///////////////////////////////////////////////////////// --> | |
| <!-- Iterates through all defined attributes and returns the full <img/> tag to the calling template --> | |
| <xsl:template name="return-full-tag-with-attributes"> | |
| <xsl:param name="src"/> | |
| <xsl:param name="width"/> | |
| <xsl:param name="height"/> | |
| <xsl:param name="id"/> | |
| <xsl:param name="class"/> | |
| <xsl:param name="alt"/> | |
| <xsl:param name="name"/> | |
| <xsl:param name="title"/> | |
| <xsl:param name="longdesc"/> | |
| <xsl:param name="align"/> | |
| <xsl:param name="style"/> | |
| <xsl:param name="ismap"/> | |
| <xsl:param name="usemap"/> | |
| <xsl:variable name="nodeset"> | |
| <attr name="src" value="{$src}"/> | |
| <attr name="width" value="{$width}"/> | |
| <attr name="height" value="{$height}"/> | |
| <attr name="id" value="{$id}"/> | |
| <attr name="class" value="{$class}"/> | |
| <attr name="alt" value="{$alt}"/> | |
| <attr name="name" value="{$name}"/> | |
| <attr name="title" value="{$title}"/> | |
| <attr name="longdesc" value="{$longdesc}"/> | |
| <attr name="align" value="{$align}"/> | |
| <attr name="style" value="{$style}"/> | |
| <attr name="ismap" value="{$ismap}"/> | |
| <attr name="usemap" value="{$usemap}"/> | |
| </xsl:variable> | |
| <img> | |
| <xsl:for-each select="exsl:node-set($nodeset)/attr[@value != '']"> | |
| <xsl:attribute name="{@name}"><xsl:value-of select="@value"/></xsl:attribute> | |
| </xsl:for-each> | |
| </img> | |
| </xsl:template> | |
| </xsl:stylesheet> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment