=== Ten&Two IMG Processor ===
Contributors: tenandtwo
Donate link:
Tags: image, resize, cache, shortcode
Requires at least: 5.2
Tested up to: 6.5
Requires PHP: 7.4
Stable tag: 0.0.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html


Transform and cache images from local and remote sources using PHP's GD or ImageMagick extensions.


== Description ==

The Ten&Two Systems IMG Processor brings the power of PHP’s GD and ImageMagick libraries to WordPress. Once enabled, the plugin creates a suite of WordPress Shortcodes, API functions, and WP-CLI Commands which can be used separately or in tandem to optimize the production and delivery of your site’s images.

Source images may be local or remote. Processed images are created on-demand and then cached.  Later visitors receive the pre-processed images immediately.  When the cache expires or the source is changed, a new version of the processed image is created automatically.

As a developer, the IMG Processor allows you to maintain just one (1) version of each site image. Creating new versions for new display contexts is simply a matter of adjusting shortcode parameters and reloading the page.  Because caching depends on access dates, popular images are always ready-to-serve.  Rarely visited versions, on the other hand, are periodically swept. For sites with a large number of images and/or versions of those images, the IMG Processor can save significant disk space.

Detailed documentation and sample code can be found at
 - https://plugins.tenandtwo.com/img-processor/


### TL;DR

Resize a local image proportionally to a height of 300 pixels; output the new URL.

 - `[img_fit output="url" height="300" source="/wp-content/uploads/image.jpg" /]`

Resize; cache the result in WebP format and 72 DPI max; output an `<img/>` tag.

 - `[img_fit output="img" output_type="webp" output_dpi="72" height="300"]/wp-content/uploads/image.jpg[/img_fit]`

Resize; then, trim 10 pixels from each edge; output an `<img/>` tag.

 - `[img_trim output="img" top="10" left="10" bottom="10" right="10"]
    [img_fit output="url" height="320"]/wp-content/uploads/image.jpg[/img_fit]
    [/img_trim]`

Use the API to resize and display (no shortcode) with optional `output_nocache=1` argument.

 - `<img src="/wp-content/plugins/tenandtwo-img-processor/api.php?transform=fit&height=300&output_nocache=1&source=/wp-content/uploads/image.jpg" />`

Use the WP-CLI to pre-cache.

 - `wp img_process fit --height=300 /wp-content/uploads/image.jpg`
 - `wp img_process crop --output=info --top=10 --left=10 --bottom=10 --right=10 \
    $(wp img_process fit --height=320 /wp-content/uploads/image.jpg)`


## Shortcodes

The IMG Processor plugin provides twelve (12) shortcodes.

 - `[img_process transform="{info|fit|fill|resize|crop|trip|border|flip|rotate|scale|zoom}" /]`
 - `[img_info/]`
 - `[img_fit/]`
 - `[img_fill/]`
 - `[img_resize/]`
 - `[img_crop/]`
 - `[img_trim/]`
 - `[img_border/]`
 - `[img_flip/]`
 - `[img_rotate/]`
 - `[img_scale/]`
 - `[img_zoom/]`

In the sections below, two (2) parameters which are shared by every IMG Processor shortcode are described first - `source` and `output`.  Three (3) shared output options are described next - `output_dpi`, `output_type`, and `output_file`.  And finally, unique options and behaviors are described with the individual transform types.


### Attribute : `source`

All IMG Processor shortcodes require a source image to function.  The location of that image can be specified either in the shortcode's `source` attribute, or in the shortcode's body. The following statements are equivalent.

 - `[img_info source="{file|url}" /]`
 - `[img_info]{file|url}[/img_info]`

The source image can be located on your Wordpress server (local) or on any other accessible server (remote).  Local paths can be absolute or relative.  Given a relative path (3rd example below), the plugin will search for the file using the location(s) specified in *IMG Processor Settings* > *Local Image Search Paths*.

 - remote : `http://abc.de/remote/image.jpg`
 - local  : `/var/www/html/wp-content/uploads/image.jpg`
 - local  : `wp-content/uploads/image.jpg`

If the source image is not found, a placeholder is used.  The default is a simple grey box.  It can be changed in *IMG Processor Settings* > *Placeholder Image*.


### Attribute : `output`

All IMG Processor shortcodes accept the `output` attribute to select and tailor results.  If omitted, the default is `output="info"` for `[img_info/]`, and `output="img"` otherwise.

The first output option - `output="info"` - is a development and debugging aid.  It returns details for the result image formated as an HTML list.  Any single value from that list can be returned by using its name.  For instance, `output="bytes"` will return the image's file size; `output="datetime"` will return it's modification date; etc.  The most-used `output` options are listed here, in order of complexity.

 - `output="file"`   : cached image path, absolute
 - `output="url"`    : cached image path, relative
 - `output="img"`    : default `<img/>` tag
 - `output="html"`   : customizable `<img/>` tag
 - `output="figure"` : customizable `<figure/>`, `<img/>`, and `<figcaption/>` tags

`output="html"` allows the default `<img/>` tag to be customized by adding any of the following shortcode attributes.  If set, a corresponding `<img/>` attribute is added to the HTML result.

 - `img-id="{css-name}"`
 - `alt="{image-description}"`      (default: source image name)
 - `title="{image-title}"`
 - `style="{css-styles}"`
 - `decoding="{auto|async|sync}"`   (default: async)
 - `loading="{eager|lazy}"`

`output="figure"` extends `output="html"` further, wrapping the `<img/>` in `<figure>..</figure>` tags and, optionally, adding `<figcaption>..</figcaption>` tags.

 - `figure-id="{css-name}"`
 - `figure-class="{css-classnames}"`
 - `caption="{image-caption}"`
 - `caption-class="{css-classnames}"`

The final option - `output="json"` - is similar to `output="info"`, except the image details are encoded as JSON.  The result can be passed to Javascript by parsing that JSON string.

 - `var $info = JSON.parse('[img_info output="json" source="image.jpg" /]');`

Tip: For debugging shortcode outputs - especially the `html`, `figure`, and `json` formats - add `htmlentities="yes"` or just `htmlentities` to the shortcode.  You can inspect the raw output in your browser console, of course, but this is often quicker.


### Attribute : `output_dpi`

The resolution for processed images is configured in *IMG Processor Settings* > *Cache File Resolution*.  Images can be cached with the original resolution, or automatically reduced to a maximum of 72 DPI.  Individual shortcodes can override the setting.

 - `output_dpi="72"`   : max resolution
 - `output_dpi="0"`    : no max


### Attribute : `output_type`

The format for processed images is configured in *IMG Processor Settings* > *Cache File Type*.  Images can be cached in the original format, or in a common format.  Individual shortcodes can override the setting.

 - `output_type="{jpg,gif,png,webp}"`


### Attribute : `output_file`

Normally, the name and location for cached image is determined automatically.  The starting location is specified in *IMG Processor Settings* > *Cache Directory*, and then the final path depends on the `source`, `transform` type, and applied options.  Individual shortcodes can override the setting.

 - `output_file="{/full/path/to/image.type}"`

Note: The result of this option is similar to the normal cache.  The `output_file` is written as needed and read if available.  But, the file is not cleared or deleted with other IMG Processor cache files.  The "Cache Lifetime" is effectively forever, unless deleted by some other process.


### Shortcode : [img_process/]

`[img_process/]` provides general access to all the other IMG Processor transformations.  For other shortcodes, the transformation is implied in the shortcode name.  Here, the transformation is specified in the shortcode's `transform` attribute.  The following statements are equivalent.

 - `[img_process transform="{type}" /]`
 - `[img_{type} /]`

Note: WP does not support nested shortcodes with identical names.  Substituting `[img_process/]` for one of the duplicates allows the same type of transformation to be run twice on the same source image.  The following statements are equivalent.

 - `[img_fit output="img"][img_process transform="fit" output="file" /][/img_fit]`
 - `[img_process transform="fit" output="img"][img_fit output="file" /][/img_process]`


### Shortcode : [img_info/]

Unlike other IMG Processor shortcodes, `[img_info/]` has no extra parameters and performs no transformation.  Instead of returning information for a transformed and cached image, it returns information for the `source` image in the requested `output` format.

 - `[img_info output="{format}"]{source}[/img_info]`


### Shortcode : [img_fit/]

`[img_fit/]` shrinks or expands the `source` image proportionally to fit within the given `width` and/or `height` without cropping.  Both values are positive integers, and specify the maximum for each dimension.  Setting `width="0"` or `height="0"`, or simply omitting one of the attributes is interpreted as 'no maximum'.

 - `[img_fit width="{int}" height="{int}"]{source}[/img_fit]`


### Shortcode : [img_fill/]

`[img_fill/]` resizes the `source` image proportionally to exactly cover the given `width` and `height`, cropping the image as necessary.  If either dimension is omitted, the behaviour of this shortcode is identical to `[img_fit/]`.

 - `[img_fill width="{int}" height="{int}"]{source}[/img_fill]`


### Shortcode : [img_resize/]

`[img_resize/]` stretches the `source` image (non-proportionally) to cover the given `width` and `height`. Both values are positive integers, and specify exact dimensions.  If either parameter is omitted, the behaviour of this shortcode is identical to `[img_fit/]`.

 - `[img_resize width="{int}" height="{int}"]{source}[/img_resize]`


### Shortcode : [img_crop/]

`[img_crop/]` extracts a `width` x `height` portion of the `source` image, starting at the given `top`,`left` position.  Values should be positive integers.  At least one of the four (4) parameters is required.  Setting `top="0"`, for instance, is the same as omitting the attribute.

 - `[img_crop top="{int}" left="{int}" width="{int}" height="{int}"]{source}[/img_crop]`


### Shortcode : [img_trim/]

`[img_trim/]` resizes the `source` image by removing pixels from the edges.  Values should be positive integers.  At least one of the four (4) parameters is required.  Setting `top="0"`, for instance, is the same as omitting the attribute.

 - `[img_trim top="{int}" left="{int}" bottom="{int}" right="{int}"]{source}[/img_trim]`


### Shortcode : [img_border/]

`[img_border/]` resizes the `source` image by adding pixels to the edges.  Width values should be positive integers.  The color of the border is specified as RGB values in the parameters `color_r`, `color_g`, and `color_b`.  If Imagick is available, border opacity can be adjusted using `color_a`, setting a value between 0.0 (transparent) and 1.0 (opaque).

 - `[img_border top="{int}" left="{int}" bottom="{int}" right="{int}"
    color_r="{0-255}" color_g="{0-255}" color_b="{0-255}" color_a="{0.0-1.0}"
    ]{source}[/img_border]`


### Shortcode : [img_flip/]

`[img_flip/]` flips the `source` image horizontally (x-axis) or vertically (y-axis).

 - `[img_flip axis="{x|y}"]{source}[/img_flip]`


### Shortcode : [img_rotate/]

`[img_rotate/]` rotates the `source` image clockwise by the specified number of `degrees`.  Positive or negative values are accepted.  Empty triangles created by the rotation are filled with the given RGB background color.  If Imagick is available, the background opacity can be adjusted using `color_a`.  The value is a floating number between 0.0 (transparent) and 1.0 (opaque).

 - `[img_rotate degrees="{int}"
    color_r="{0-255}" color_g="{0-255}" color_b="{0-255}" color_a="{0.0-1.0}"
    ]{source}[/img_rotate]`


### Shortcode : [img_scale/]

`[img_scale/]` resizes the `source` image proportionally to some `percent` of it's original dimensions.  The value should be a positive integer; `percent="100"` is fullsize; `percent="50"` is halfsize; etc.

 - `[img_scale percent="{int}"]{source}[/img_scale]`


### Shortcode : [img_zoom/]

`[img_zoom/]` resizes the `source` image proportionally to some `percent`, then crops the image to the requested `width` and `height`.  The default output dimensions are the same as the input.  The `focus` parameter specifies one of nine (9) positions.  The default crops the result from the center of the image.  The values 'NE|NW|SE|SW' select the corners; the values 'N|S|E|W' select the sides.

 - `[img_zoom percent="{int}" focus="{focus}" width="{int}" height="{int}"]{source}[/img_zoom]`


## API Requests

Shortcodes are not the only method for accessing IMG Processor functions and results.  The plugin also provides an API that functions directly within the `src` attribute of any `<img/>` tag.  The following statements are equivalent.

 - `<img src="image.jpg" />`
 - `<img src="/wp-content/plugins/tenandtwo-img-processor/api.php?source=image.jpg" />`

Normally, the `src` attribute of an `<img/>` specifies a URL for an image file.  Using the IMG Processor API, that URL is passed as the `source` parameter instead.   If the source image is missing or can't be found, the configured "Placeholder Image" is shown, not a broken link.

After the required `file` parameter, `api.php` accepts the same arguments as the `[img_process/]` shortcode. For instance, an image can be resized by appending `&transform=fit&height=200` to the request.

Note: API requests are sent by users as pages are loaded into their browsers.  To work properly, `api.php` must be public.  A malicious actor, however, could use this to overwhelm the site with API transform requests.  If you are not using this plugin feature - ie, not serving images to other sites, and not serving images to non-Wordpress sections of your own site - it should be disabled in *IMG Processor Settings* > *Activate API*.

There is one (1) option that is unique to the IMG Processor API: `output_nocache`. Because the API streams image data directly to the page, there is an option to bypass the usual cache process. The image can be transformed and returned immediately, without creating a new image file.  Simply append `&output_nocache=1` to the URL.

 - `<img src="/wp-content/plugins/tenandtwo-img-processor/api.php?source=image.jpg&transform=fit&height=200&output_nocache=1" />`


## WP-CLI Commands

The Ten&Two IMG Processor enables fourteen (14) WP-CLI subcommands. The first three (3) are primarily for debugging and maintenance purposes. Then, there are command equivalents for eleven (11) IMG Processor shortcodes.  For in-context details, use `wp img_process --help` or `wp img_process <subcommand> --help`.

The `version` subcommand provides information about the plugin's PHP environment, specifically, the status of the GD and Imagick image libraries.  The optional `--types` argument adds a list of supported image formats to the output.

 - `wp img_process version [--types]`

The `cache_clean` and `cache_delete` subcommands facilitate cache management outside of Wordpress.  The three (3) optional arguments `--expire_type`, `--expire_value`, and `--cache_path` override the selected IMG Processor Settings.  If `--cache_path` is set, the command requires confirmation.

 - `wp img_process cache_delete [--cache_path={dirpath}]`
 - `wp img_process cache_clean [--expire_type={atime|amin|ctime|cmin|mtime|mmin}] [--expire_value={int}] [--cache_path={dirpath}]`

Like their shortcode counterparts, most IMG Processor subcommands share several arguments. The location of the source image is the only required argument; it is specified by the first positional (unlabeled) argument, `<source>`. The name and location of the output image can be overridden using the second positional argument, `<output_file>`. The defaults for `--output_type` and `--output_dpi` are configured in the IMG Processor Settings. For the `info` subcommand, `--output=info` is the default; for all other subcommands, `--output=file` is the default result format.

 - `<source>`               : REQUIRED source image path or URL
 - `<output_file>`          : optional output image path (cache override)
 - `--output_type={type}`   : image format      (gif|jpg|png|webp|...)
 - `--output_dpi={dpi}`     : max resolution    (0|72|int)
 - `--output={format}`      : result format     (info|file|url|img|...)

The remaining arguments for each subcommand match the corresponding shortcode's attributes.

 - `wp img_process info`
 - `wp img_process fit --width={int} --height={int}`
 - `wp img_process fill --width={int} --height={int}`
 - `wp img_process resize --width={int} --height={int}`
 - `wp img_process crop --top={int} --left={int} --width={int} --height={int}`
 - `wp img_process trim --top={int} --left={int} --bottom={int} --right={int}`
 - `wp img_process border --top={int} --left={int} --bottom={int} --right={int} --color_r={0-255} --color_g={0-255} --color_b={0-255} --color_a={0-1.0}`
 - `wp img_process flip --axis={x|y}`
 - `wp img_process rotate --degrees={int} --color_r={0-255} --color_g={0-255} --color_b={0-255} --color_a={0-1.0}`
 - `wp img_process scale --percent={int}`
 - `wp img_process zoom --percent={int} --focus={X|N|S|E|W|NE|NW|SE|SW} --width={int} --height={int}`


== Installation ==

### WordPress installation

1. Go to *Plugins* > *Add New* > *Search* for "tenandtwo-img-processor"
2. Press "Install Now" for the "Ten&Two IMG Processor" plugin
3. Press "Activate Plugin"

### WP-CLI installation

1. `wp plugin install tenandtwo-img-processor --activate`

### Manual installation

1. Download the latest archive from the Plugin Homepage : https://wordpress.org/plugins/tenandtwo-img-processor
2. Upload the `tenandtwo-img-processor` directory to your `/wp-content/plugins/` directory
3. Activate the plugin through the "Plugins" menu in WordPress

For more details on installation options, see Manage Plugins at wordpress.org - https://wordpress.org/documentation/article/manage-plugins/

## Requirements

The Ten&Two IMG Processor plugin uses PHP's Imagick extension, if it is available.  Otherwise, PHP's GD extension is used.  Shortcode and CLI parameters are the same in either case.

If GD is installed, the *IMG Processor Settings* screen will display a message similar to the first message below.  If the extension is missing, all plugin options are disabled automatically and the second message is displayed.

 - `PHP's GD extension is available : GD v2.0.35`
 - `PHP's GD extension is NOT available`

If Imagick is installed, the *IMG Processor Settings* screen will display a message similar to the first message below.  Otherwise, the second message is displayed.

 - `PHP's Imagick extension is available : Imagick v6.9.11`
 - `PHP's Imagick extension is NOT available`


The GD extension's requirements are detailed at php.net - https://www.php.net/manual/en/image.requirements.php

The Imagick extension's requirements are detailed at php.net - https://www.php.net/manual/en/imagick.requirements.php


== Frequently Asked Questions ==


### Where are the plugin options?

In WordPress, go to *Settings* > *IMG Processor Settings*.  There are nine (9) sections.

 - Activate Shortcodes
 - Activate API
 - Activate CLI
 - Local Image Search Paths
 - Placeholder Image
 - Cache Directory
 - Cache Lifetime
 - Cache File Type
 - Cache File Resolution


### Where is the documentation?

For a quick reference to the shortcodes and their main parameters, go to *IMG Processor Settings*.  If you have the WP-CLI enabled, use `wp img_process <subcommand> --help`.

Full documentation and working examples are available at https://plugins.tenandtwo.com/img-processor/.  There are XXX (x) main sections.

 - Getting Started : https://plugins.tenandtwo.com/img-processor/getting-started
 - Methods         : https://plugins.tenandtwo.com/img-processor/methods
 - Shortcodes      : https://plugins.tenandtwo.com/img-processor/shortcodes
 - How To          : https://plugins.tenandtwo.com/img-processor/how-to


== Screenshots ==


1. IMG Processor Settings


== Changelog ==

= 1.0.x =
* Initial Release
