/home/altere25/highwoodoutdoorpool.com/wp-includes
NameSizeModeActions
assets/-0755rm
blocks/-0755rm
certificates/-0755rm
css/-0755rm
customize/-0755rm
fonts/-0755rm
ID3/-0755rm
images/-0755rm
IXR/-0755rm
js/-0755rm
pomo/-0755rm
random_compat/-0755rm
Requests/-0755rm
rest-api/-0755rm
SimplePie/-0755rm
sodium_compat/-0755rm
Text/-0755rm
theme-compat/-0755rm
widgets/-0755rm
.htaccess1780644editdlrm
admin-bar.php313150644editdlrm
atomlib.php118400644editdlrm
author-template.php170370644editdlrm
blocks.php192620644editdlrm
bookmark-template.php125030644editdlrm
bookmark.php150140644editdlrm
cache.php88010644editdlrm
canonical.php296280644editdlrm
capabilities.php346850644editdlrm
category-template.php530880644editdlrm
category.php122020644editdlrm
class-feed.php5290644editdlrm
class-http.php391080644editdlrm
class-IXR.php25430644editdlrm
class-json.php434470644editdlrm
class-oembed.php4070644editdlrm
class-phpass.php73190644editdlrm
class-phpmailer.php1485890644editdlrm
class-pop3.php209190644editdlrm
class-requests.php298040644editdlrm
class-simplepie.php892610644editdlrm
class-smtp.php409190644editdlrm
class-snoopy.php377850644editdlrm
class-walker-category-dropdown.php21270644editdlrm
class-walker-category.php78740644editdlrm
class-walker-comment.php136830644editdlrm
class-walker-nav-menu.php86500644editdlrm
class-walker-page-dropdown.php22990644editdlrm
class-walker-page.php70330644editdlrm
class-wp-admin-bar.php171850644editdlrm
class-wp-ajax-response.php52360644editdlrm
class-wp-block-parser.php152150644editdlrm
class-wp-block-styles-registry.php47280644editdlrm
class-wp-block-type-registry.php50910644editdlrm
class-wp-block-type.php48150644editdlrm
class-wp-comment-query.php445220644editdlrm
class-wp-comment.php89680644editdlrm
class-wp-customize-control.php255050644editdlrm
class-wp-customize-manager.php2001560644editdlrm
class-wp-customize-nav-menus.php549650644editdlrm
class-wp-customize-panel.php104060644editdlrm
class-wp-customize-section.php109740644editdlrm
class-wp-customize-setting.php296800644editdlrm
class-wp-customize-widgets.php669740644editdlrm
class-wp-date-query.php352800644editdlrm
class-wp-dependency.php25000644editdlrm
class-wp-editor.php706650644editdlrm
class-wp-embed.php148020644editdlrm
class-wp-error.php49230644editdlrm
class-wp-fatal-error-handler.php74160644editdlrm
class-wp-feed-cache-transient.php25600644editdlrm
class-wp-feed-cache.php7490644editdlrm
class-wp-hook.php140510644editdlrm
class-wp-http-cookie.php71460644editdlrm
class-wp-http-curl.php123300644editdlrm
class-wp-http-encoding.php65100644editdlrm
class-wp-http-ixr-client.php33390644editdlrm
class-wp-http-proxy.php60770644editdlrm
class-wp-http-requests-hooks.php19500644editdlrm
class-wp-http-requests-response.php43430644editdlrm
class-wp-http-response.php29510644editdlrm
class-wp-http-streams.php160790644editdlrm
class-wp-image-editor-gd.php141040644editdlrm
class-wp-image-editor-imagick.php290520644editdlrm
class-wp-image-editor.php140160644editdlrm
class-wp-list-util.php64070644editdlrm
class-wp-locale-switcher.php50220644editdlrm
class-wp-locale.php139140644editdlrm
class-wp-matchesmapregex.php18050644editdlrm
class-wp-meta-query.php278550644editdlrm
class-wp-metadata-lazyloader.php53860644editdlrm
class-wp-network-query.php183720644editdlrm
class-wp-network.php123760644editdlrm
class-wp-object-cache.php128480644editdlrm
class-wp-oembed-controller.php60270644editdlrm
class-wp-oembed.php304760644editdlrm
class-wp-paused-extensions-storage.php49310644editdlrm
class-wp-post-type.php195330644editdlrm
class-wp-post.php64410644editdlrm
class-wp-query.php1327830644editdlrm
class-wp-recovery-mode-cookie-service.php64570644editdlrm
class-wp-recovery-mode-email-service.php101210644editdlrm
class-wp-recovery-mode-key-service.php42820644editdlrm
class-wp-recovery-mode-link-service.php33680644editdlrm
class-wp-recovery-mode.php113560644editdlrm
class-wp-rewrite.php608310644editdlrm
class-wp-role.php27920644editdlrm
class-wp-roles.php84060644editdlrm
class-wp-session-tokens.php74310644editdlrm
class-wp-simplepie-file.php23280644editdlrm
class-wp-simplepie-sanitize-kses.php17750644editdlrm
class-wp-site-query.php285320644editdlrm
class-wp-site.php73670644editdlrm
class-wp-tax-query.php194420644editdlrm
class-wp-taxonomy.php108420644editdlrm
class-wp-term-query.php355270644editdlrm
class-wp-term.php52650644editdlrm
class-wp-text-diff-renderer-inline.php7160644editdlrm
class-wp-text-diff-renderer-table.php168310644editdlrm
class-wp-theme.php517040644editdlrm
class-wp-user-meta-session-tokens.php29900644editdlrm
class-wp-user-query.php313020644editdlrm
class-wp-user-request.php19960644editdlrm
class-wp-user.php218720644editdlrm
class-wp-walker.php127220644editdlrm
class-wp-widget-factory.php26200644editdlrm
class-wp-widget.php179020644editdlrm
class-wp-xmlrpc-server.php2103170644editdlrm
class-wp.php246880644editdlrm
class.wp-dependencies.php126740644editdlrm
class.wp-scripts.php181500644editdlrm
class.wp-styles.php106820644editdlrm
comment-template.php929920644editdlrm
comment.php1176410644editdlrm
compat.php129890644editdlrm
cron.php326670644editdlrm
date.php4060644editdlrm
default-constants.php101570644editdlrm
default-filters.php261100644editdlrm
default-widgets.php21230644editdlrm
deprecated.php1149450644editdlrm
embed-template.php3410644editdlrm
embed.php476260644editdlrm
error-protection.php33850644editdlrm
feed-atom-comments.php54440644editdlrm
feed-atom.php31020644editdlrm
feed-rdf.php26680644editdlrm
feed-rss.php11890644editdlrm
feed-rss2-comments.php40880644editdlrm
feed-rss2.php37990644editdlrm
feed.php220600644editdlrm
formatting.php2990060644editdlrm
functions.php2317760644editdlrm
functions.wp-scripts.php128420644editdlrm
functions.wp-styles.php82450644editdlrm
general-template.php1529290644editdlrm
http.php243170644editdlrm
kses.php590040644editdlrm
l10n.php538290644editdlrm
link-template.php1437950644editdlrm
load.php439550644editdlrm
locale.php1620644editdlrm
media-template.php581040644editdlrm
media.php1513450644editdlrm
meta.php504930644editdlrm
ms-blogs.php249860644editdlrm
ms-default-constants.php47870644editdlrm
ms-default-filters.php64280644editdlrm
ms-deprecated.php211220644editdlrm
ms-files.php26410644editdlrm
ms-functions.php894380644editdlrm
ms-load.php197970644editdlrm
ms-network.php36580644editdlrm
ms-settings.php41220644editdlrm
ms-site.php430330644editdlrm
nav-menu-template.php221500644editdlrm
nav-menu.php417450644editdlrm
option.php708900644editdlrm
pluggable-deprecated.php62630644editdlrm
pluggable.php1013050644editdlrm
plugin.php322010644editdlrm
post-formats.php70690644editdlrm
post-template.php631600644editdlrm
post-thumbnail-template.php90210644editdlrm
post.php2465730644editdlrm
query.php342180644editdlrm
registration-functions.php2020644editdlrm
registration.php2020644editdlrm
rest-api.php473600644editdlrm
revision.php217100644editdlrm
rewrite.php180480644editdlrm
rss-functions.php2110644editdlrm
rss.php232080644editdlrm
script-loader.php1049150644editdlrm
session.php2580644editdlrm
shortcodes.php223550644editdlrm
spl-autoload-compat.php4430644editdlrm
taxonomy.php1583470644editdlrm
template-loader.php33520644editdlrm
template.php210460644editdlrm
theme.php1049460644editdlrm
update.php256890644editdlrm
user.php1325800644editdlrm
vars.php58200644editdlrm
version.php7660644editdlrm
widgets.php587850644editdlrm
wlwmanifest.xml10450644editdlrm
wp-db.php1039120644editdlrm
wp-diff.php6470644editdlrm
Edit: /home/altere25/highwoodoutdoorpool.com/wp-includes/class-wp-image-editor-imagick.php (29052B)
image instanceof Imagick ) { // We don't need the original in memory anymore. $this->image->clear(); $this->image->destroy(); } } /** * Checks to see if current environment supports Imagick. * * We require Imagick 2.2.0 or greater, based on whether the queryFormats() * method can be called statically. * * @since 3.5.0 * * @param array $args * @return bool */ public static function test( $args = array() ) { // First, test Imagick's extension and classes. if ( ! extension_loaded( 'imagick' ) || ! class_exists( 'Imagick', false ) || ! class_exists( 'ImagickPixel', false ) ) { return false; } if ( version_compare( phpversion( 'imagick' ), '2.2.0', '<' ) ) { return false; } $required_methods = array( 'clear', 'destroy', 'valid', 'getimage', 'writeimage', 'getimageblob', 'getimagegeometry', 'getimageformat', 'setimageformat', 'setimagecompression', 'setimagecompressionquality', 'setimagepage', 'setoption', 'scaleimage', 'cropimage', 'rotateimage', 'flipimage', 'flopimage', 'readimage', 'readimageblob', ); // Now, test for deep requirements within Imagick. if ( ! defined( 'imagick::COMPRESSION_JPEG' ) ) { return false; } $class_methods = array_map( 'strtolower', get_class_methods( 'Imagick' ) ); if ( array_diff( $required_methods, $class_methods ) ) { return false; } return true; } /** * Checks to see if editor supports the mime-type specified. * * @since 3.5.0 * * @param string $mime_type * @return bool */ public static function supports_mime_type( $mime_type ) { $imagick_extension = strtoupper( self::get_extension( $mime_type ) ); if ( ! $imagick_extension ) { return false; } // setIteratorIndex is optional unless mime is an animated format. // Here, we just say no if you are missing it and aren't loading a jpeg. if ( ! method_exists( 'Imagick', 'setIteratorIndex' ) && 'image/jpeg' !== $mime_type ) { return false; } try { // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged return ( (bool) @Imagick::queryFormats( $imagick_extension ) ); } catch ( Exception $e ) { return false; } } /** * Loads image from $this->file into new Imagick Object. * * @since 3.5.0 * * @return true|WP_Error True if loaded; WP_Error on failure. */ public function load() { if ( $this->image instanceof Imagick ) { return true; } $is_stream = preg_match( '|^https?://|', $this->file ); $is_file = ! $is_stream && is_file( $this->file ); // Only allow loading files or HTTP streams. if ( ! $is_file && ! $is_stream ) { return new WP_Error( 'error_loading_image', __( 'File doesn’t exist?' ), $this->file ); } // Establish the provided filename based on the kind of resource being loaded. $given_filename = $this->file; if ( 0 === strncasecmp( $given_filename, 'file://', 7 ) ) { $given_filename = basename( substr( $given_filename, 7 ) ); // 7 is the strlen of 'file://'. } elseif ( 1 === preg_match( '~^https?://~i', $this->file ) ) { /* * For URLs, it will be the final path segment. * * Example: * * https://wordpress.org/i/happy.png?size=40px * ╰───────╯ * this is the given filename * * If the stream returns a `Content-Disposition` header it would * provide an alternative name, but this is used as a reasonable * proxy to avoid adding the additional complexity of reading and * parsing the returned HTTP headers. */ $url_path = wp_parse_url( $this->file, PHP_URL_PATH ); // This URL can not be parsed, so it is not a valid image resource. if ( false === $url_path ) { return new WP_Error( 'error_loading_image', __( 'File is not an image.' ), $this->file ); } /** * The URL has an empty path, so continue with an empty string. * * This is the case with a URL such as `https://example.com?file_id=123` */ if ( null === $url_path ) { $url_path = ''; } $last_path_at = strrpos( $url_path, '/' ); $given_filename = is_int( $last_path_at ) ? substr( $url_path, $last_path_at + 1 ) : $url_path; $given_filename = rawurldecode( $given_filename ); } /* * Strip off any potential `Imagick` format specifiers. * * If a real file exists with the identified format specifier, then * `Imagick` may not treat it as a format, but WordPress will reject * it anyway to avoid adding more complexity into this detection. * * `Imagick` reads only the first `FORMAT:` specifier on a name, but * stripping a segment would promote a second specifier to the front * of the name handed to `Imagick`, which would then honor it. * * Loop to capture all format specifiers for comparison. * * Exclude Windows drive-letter prefixes from here. */ $imagick_formats = array(); while ( false !== ( $format_ends_at = strpos( $given_filename, ':' ) ) && 1 !== preg_match( '~^[a-z]:~i', $given_filename ) ) { $imagick_formats[] = strtoupper( substr( $given_filename, 0, $format_ends_at ) ); $given_filename = substr( $given_filename, $format_ends_at + 1 ); } $file_extension = strtolower( pathinfo( $given_filename, PATHINFO_EXTENSION ) ); /* * Even though Imagick uses less PHP memory than GD, set higher limit * for users that have low PHP.ini limits. */ wp_raise_memory_limit( 'image' ); /** * Read the resource header for MIME sniffing. * * For files, which will be passed into Imagick by their file names, avoid * eagerly loading the entire contents into PHP memory. For streams, however, * it’s more important to avoid validating a separate copy of the file data * than is later fetched by Imagick, so go ahead and load the entire payload, * then pass it to Imagick as the data blob itself. * * @link https://mimesniff.spec.whatwg.org/#reading-the-resource-header */ try { if ( $is_file ) { $file_data = file_get_contents( $this->file, false, null, 0, 1445 ); } else { $file_data = file_get_contents( $this->file ); } } catch ( Exception $e ) { $file_data = false; } if ( false === $file_data ) { return new WP_Error( 'error_loading_image', __( 'File doesn’t exist?' ), $this->file ); } $pdf_extensions = array( 'ai', 'epdf', 'pdf', 'pdfa', 'pocketmod', ); // Reject files claiming to be PDFs which lack the required signature. $has_pdf_extension = in_array( $file_extension, $pdf_extensions, true ); $has_pdf_signature = 0 === strncmp( $file_data, '%PDF-', 5 ); if ( $has_pdf_extension && ! $has_pdf_signature ) { return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file ); } $ps_formats = array( 'DPS', 'EPI', 'EPS', 'EPSF', 'EPSI', 'PS', 'WPG', ); $ps_extensions = array( 'dps', 'epi', 'eps', 'eps2', 'eps3', 'epsf', 'epsi', 'ept', 'ept2', 'ept3', 'ps', 'ps2', 'ps3', 'wpg', ); // Reject files which Imagick will parse as PostScript. if ( array() !== array_intersect( $imagick_formats, $ps_formats ) || in_array( $file_extension, $ps_extensions, true ) || 0 === strncmp( $file_data, '%!', 2 ) || 0 === strncmp( $file_data, "\x04%!", 3 ) || 0 === strncmp( $file_data, "\xC5\xD0\xD3\xC6", 4 ) || 0 === strncmp( $file_data, "\xFFWPC", 3 ) ) { return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file ); } $compressed_extensions = array( 'gz', 'bz2', 'svgz', 'z', 'wmz', ); // Reject compressed archives that Imagick will transparently decompress. if ( in_array( $file_extension, $compressed_extensions, true ) || 0 === strncmp( $file_data, "\x1F\x8B\x08", 3 ) || // gzip 0 === strncmp( $file_data, 'BZh', 3 ) || // bzip2 0 === strncmp( $file_data, "\x1F\x9D", 2 ) // compress ) { return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file ); } try { $this->image = new Imagick(); $filename = $this->file; if ( $has_pdf_signature ) { $filename = $this->pdf_setup(); } if ( $is_file ) { $this->image->readImage( $filename ); } else { $this->image->readImageBlob( $file_data, $given_filename ); } if ( ! $this->image->valid() ) { return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file ); } // Select the first frame to handle animated images properly. if ( is_callable( array( $this->image, 'setIteratorIndex' ) ) ) { $this->image->setIteratorIndex( 0 ); } $this->mime_type = $this->get_mime_type( $this->image->getImageFormat() ); } catch ( Exception $e ) { return new WP_Error( 'invalid_image', $e->getMessage(), $this->file ); } $updated_size = $this->update_size(); if ( is_wp_error( $updated_size ) ) { return $updated_size; } return $this->set_quality(); } /** * Sets Image Compression quality on a 1-100% scale. * * @since 3.5.0 * * @param int $quality Compression Quality. Range: [1,100] * @return true|WP_Error True if set successfully; WP_Error on failure. */ public function set_quality( $quality = null ) { $quality_result = parent::set_quality( $quality ); if ( is_wp_error( $quality_result ) ) { return $quality_result; } else { $quality = $this->get_quality(); } try { if ( 'image/jpeg' === $this->mime_type ) { $this->image->setImageCompressionQuality( $quality ); $this->image->setImageCompression( imagick::COMPRESSION_JPEG ); } else { $this->image->setImageCompressionQuality( $quality ); } } catch ( Exception $e ) { return new WP_Error( 'image_quality_error', $e->getMessage() ); } return true; } /** * Sets or updates current image size. * * @since 3.5.0 * * @param int $width * @param int $height * * @return true|WP_Error */ protected function update_size( $width = null, $height = null ) { $size = null; if ( ! $width || ! $height ) { try { $size = $this->image->getImageGeometry(); } catch ( Exception $e ) { return new WP_Error( 'invalid_image', __( 'Could not read image size.' ), $this->file ); } } if ( ! $width ) { $width = $size['width']; } if ( ! $height ) { $height = $size['height']; } return parent::update_size( $width, $height ); } /** * Resizes current image. * * At minimum, either a height or width must be provided. * If one of the two is set to null, the resize will * maintain aspect ratio according to the provided dimension. * * @since 3.5.0 * * @param int|null $max_w Image width. * @param int|null $max_h Image height. * @param bool $crop * @return bool|WP_Error */ public function resize( $max_w, $max_h, $crop = false ) { if ( ( $this->size['width'] == $max_w ) && ( $this->size['height'] == $max_h ) ) { return true; } $dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop ); if ( ! $dims ) { return new WP_Error( 'error_getting_dimensions', __( 'Could not calculate resized image dimensions' ) ); } list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims; if ( $crop ) { return $this->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h ); } // Execute the resize. $thumb_result = $this->thumbnail_image( $dst_w, $dst_h ); if ( is_wp_error( $thumb_result ) ) { return $thumb_result; } return $this->update_size( $dst_w, $dst_h ); } /** * Efficiently resize the current image * * This is a WordPress specific implementation of Imagick::thumbnailImage(), * which resizes an image to given dimensions and removes any associated profiles. * * @since 4.5.0 * * @param int $dst_w The destination width. * @param int $dst_h The destination height. * @param string $filter_name Optional. The Imagick filter to use when resizing. Default 'FILTER_TRIANGLE'. * @param bool $strip_meta Optional. Strip all profiles, excluding color profiles, from the image. Default true. * @return bool|WP_Error */ protected function thumbnail_image( $dst_w, $dst_h, $filter_name = 'FILTER_TRIANGLE', $strip_meta = true ) { $allowed_filters = array( 'FILTER_POINT', 'FILTER_BOX', 'FILTER_TRIANGLE', 'FILTER_HERMITE', 'FILTER_HANNING', 'FILTER_HAMMING', 'FILTER_BLACKMAN', 'FILTER_GAUSSIAN', 'FILTER_QUADRATIC', 'FILTER_CUBIC', 'FILTER_CATROM', 'FILTER_MITCHELL', 'FILTER_LANCZOS', 'FILTER_BESSEL', 'FILTER_SINC', ); /** * Set the filter value if '$filter_name' name is in our whitelist and the related * Imagick constant is defined or fall back to our default filter. */ if ( in_array( $filter_name, $allowed_filters, true ) && defined( 'Imagick::' . $filter_name ) ) { $filter = constant( 'Imagick::' . $filter_name ); } else { $filter = defined( 'Imagick::FILTER_TRIANGLE' ) ? Imagick::FILTER_TRIANGLE : false; } /** * Filters whether to strip metadata from images when they're resized. * * This filter only applies when resizing using the Imagick editor since GD * always strips profiles by default. * * @since 4.5.0 * * @param bool $strip_meta Whether to strip image metadata during resizing. Default true. */ if ( apply_filters( 'image_strip_meta', $strip_meta ) ) { $this->strip_meta(); // Fail silently if not supported. } try { /* * To be more efficient, resample large images to 5x the destination size before resizing * whenever the output size is less that 1/3 of the original image size (1/3^2 ~= .111), * unless we would be resampling to a scale smaller than 128x128. */ if ( is_callable( array( $this->image, 'sampleImage' ) ) ) { $resize_ratio = ( $dst_w / $this->size['width'] ) * ( $dst_h / $this->size['height'] ); $sample_factor = 5; if ( $resize_ratio < .111 && ( $dst_w * $sample_factor > 128 && $dst_h * $sample_factor > 128 ) ) { $this->image->sampleImage( $dst_w * $sample_factor, $dst_h * $sample_factor ); } } /* * Use resizeImage() when it's available and a valid filter value is set. * Otherwise, fall back to the scaleImage() method for resizing, which * results in better image quality over resizeImage() with default filter * settings and retains backward compatibility with pre 4.5 functionality. */ if ( is_callable( array( $this->image, 'resizeImage' ) ) && $filter ) { $this->image->setOption( 'filter:support', '2.0' ); $this->image->resizeImage( $dst_w, $dst_h, $filter, 1 ); } else { $this->image->scaleImage( $dst_w, $dst_h ); } // Set appropriate quality settings after resizing. if ( 'image/jpeg' === $this->mime_type ) { if ( is_callable( array( $this->image, 'unsharpMaskImage' ) ) ) { $this->image->unsharpMaskImage( 0.25, 0.25, 8, 0.065 ); } $this->image->setOption( 'jpeg:fancy-upsampling', 'off' ); } if ( 'image/png' === $this->mime_type ) { $this->image->setOption( 'png:compression-filter', '5' ); $this->image->setOption( 'png:compression-level', '9' ); $this->image->setOption( 'png:compression-strategy', '1' ); $this->image->setOption( 'png:exclude-chunk', 'all' ); } /* * If alpha channel is not defined, set it opaque. * * Note that Imagick::getImageAlphaChannel() is only available if Imagick * has been compiled against ImageMagick version 6.4.0 or newer. */ if ( is_callable( array( $this->image, 'getImageAlphaChannel' ) ) && is_callable( array( $this->image, 'setImageAlphaChannel' ) ) && defined( 'Imagick::ALPHACHANNEL_UNDEFINED' ) && defined( 'Imagick::ALPHACHANNEL_OPAQUE' ) ) { if ( $this->image->getImageAlphaChannel() === Imagick::ALPHACHANNEL_UNDEFINED ) { $this->image->setImageAlphaChannel( Imagick::ALPHACHANNEL_OPAQUE ); } } // Limit the bit depth of resized images to 8 bits per channel. if ( is_callable( array( $this->image, 'getImageDepth' ) ) && is_callable( array( $this->image, 'setImageDepth' ) ) ) { if ( 8 < $this->image->getImageDepth() ) { $this->image->setImageDepth( 8 ); } } if ( is_callable( array( $this->image, 'setInterlaceScheme' ) ) && defined( 'Imagick::INTERLACE_NO' ) ) { $this->image->setInterlaceScheme( Imagick::INTERLACE_NO ); } } catch ( Exception $e ) { return new WP_Error( 'image_resize_error', $e->getMessage() ); } } /** * Create multiple smaller images from a single source. * * Attempts to create all sub-sizes and returns the meta data at the end. This * may result in the server running out of resources. When it fails there may be few * "orphaned" images left over as the meta data is never returned and saved. * * As of 5.3.0 the preferred way to do this is with `make_subsize()`. It creates * the new images one at a time and allows for the meta data to be saved after * each new image is created. * * @since 3.5.0 * * @param array $sizes { * An array of image size data arrays. * * Either a height or width must be provided. * If one of the two is set to null, the resize will * maintain aspect ratio according to the provided dimension. * * @type array $size { * Array of height, width values, and whether to crop. * * @type int $width Image width. Optional if `$height` is specified. * @type int $height Image height. Optional if `$width` is specified. * @type bool $crop Optional. Whether to crop the image. Default false. * } * } * @return array An array of resized images' metadata by size. */ public function multi_resize( $sizes ) { $metadata = array(); foreach ( $sizes as $size => $size_data ) { $meta = $this->make_subsize( $size_data ); if ( ! is_wp_error( $meta ) ) { $metadata[ $size ] = $meta; } } return $metadata; } /** * Create an image sub-size and return the image meta data value for it. * * @since 5.3.0 * * @param array $size_data { * Array of size data. * * @type int $width The maximum width in pixels. * @type int $height The maximum height in pixels. * @type bool $crop Whether to crop the image to exact dimensions. * } * @return array|WP_Error The image data array for inclusion in the `sizes` array in the image meta, * WP_Error object on error. */ public function make_subsize( $size_data ) { if ( ! isset( $size_data['width'] ) && ! isset( $size_data['height'] ) ) { return new WP_Error( 'image_subsize_create_error', __( 'Cannot resize the image. Both width and height are not set.' ) ); } $orig_size = $this->size; $orig_image = $this->image->getImage(); if ( ! isset( $size_data['width'] ) ) { $size_data['width'] = null; } if ( ! isset( $size_data['height'] ) ) { $size_data['height'] = null; } if ( ! isset( $size_data['crop'] ) ) { $size_data['crop'] = false; } $resized = $this->resize( $size_data['width'], $size_data['height'], $size_data['crop'] ); if ( is_wp_error( $resized ) ) { $saved = $resized; } else { $saved = $this->_save( $this->image ); $this->image->clear(); $this->image->destroy(); $this->image = null; } $this->size = $orig_size; $this->image = $orig_image; if ( ! is_wp_error( $saved ) ) { unset( $saved['path'] ); } return $saved; } /** * Crops Image. * * @since 3.5.0 * * @param int $src_x The start x position to crop from. * @param int $src_y The start y position to crop from. * @param int $src_w The width to crop. * @param int $src_h The height to crop. * @param int $dst_w Optional. The destination width. * @param int $dst_h Optional. The destination height. * @param bool $src_abs Optional. If the source crop points are absolute. * @return bool|WP_Error */ public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) { if ( $src_abs ) { $src_w -= $src_x; $src_h -= $src_y; } try { $this->image->cropImage( $src_w, $src_h, $src_x, $src_y ); $this->image->setImagePage( $src_w, $src_h, 0, 0 ); if ( $dst_w || $dst_h ) { // If destination width/height isn't specified, // use same as width/height from source. if ( ! $dst_w ) { $dst_w = $src_w; } if ( ! $dst_h ) { $dst_h = $src_h; } $thumb_result = $this->thumbnail_image( $dst_w, $dst_h ); if ( is_wp_error( $thumb_result ) ) { return $thumb_result; } return $this->update_size(); } } catch ( Exception $e ) { return new WP_Error( 'image_crop_error', $e->getMessage() ); } return $this->update_size(); } /** * Rotates current image counter-clockwise by $angle. * * @since 3.5.0 * * @param float $angle * @return true|WP_Error */ public function rotate( $angle ) { /** * $angle is 360-$angle because Imagick rotates clockwise * (GD rotates counter-clockwise) */ try { $this->image->rotateImage( new ImagickPixel( 'none' ), 360 - $angle ); // Normalise EXIF orientation data so that display is consistent across devices. if ( is_callable( array( $this->image, 'setImageOrientation' ) ) && defined( 'Imagick::ORIENTATION_TOPLEFT' ) ) { $this->image->setImageOrientation( Imagick::ORIENTATION_TOPLEFT ); } // Since this changes the dimensions of the image, update the size. $result = $this->update_size(); if ( is_wp_error( $result ) ) { return $result; } $this->image->setImagePage( $this->size['width'], $this->size['height'], 0, 0 ); } catch ( Exception $e ) { return new WP_Error( 'image_rotate_error', $e->getMessage() ); } return true; } /** * Flips current image. * * @since 3.5.0 * * @param bool $horz Flip along Horizontal Axis * @param bool $vert Flip along Vertical Axis * @return true|WP_Error */ public function flip( $horz, $vert ) { try { if ( $horz ) { $this->image->flipImage(); } if ( $vert ) { $this->image->flopImage(); } // Normalise EXIF orientation data so that display is consistent across devices. if ( is_callable( array( $this->image, 'setImageOrientation' ) ) && defined( 'Imagick::ORIENTATION_TOPLEFT' ) ) { $this->image->setImageOrientation( Imagick::ORIENTATION_TOPLEFT ); } } catch ( Exception $e ) { return new WP_Error( 'image_flip_error', $e->getMessage() ); } return true; } /** * Check if a JPEG image has EXIF Orientation tag and rotate it if needed. * * As ImageMagick copies the EXIF data to the flipped/rotated image, proceed only * if EXIF Orientation can be reset afterwards. * * @since 5.3.0 * * @return bool|WP_Error True if the image was rotated. False if no EXIF data or if the image doesn't need rotation. * WP_Error if error while rotating. */ public function maybe_exif_rotate() { if ( is_callable( array( $this->image, 'setImageOrientation' ) ) && defined( 'Imagick::ORIENTATION_TOPLEFT' ) ) { return parent::maybe_exif_rotate(); } else { return new WP_Error( 'write_exif_error', __( 'The image cannot be rotated because the embedded meta data cannot be updated.' ) ); } } /** * Saves current image to file. * * @since 3.5.0 * * @param string $destfilename * @param string $mime_type * @return array|WP_Error {'path'=>string, 'file'=>string, 'width'=>int, 'height'=>int, 'mime-type'=>string} */ public function save( $destfilename = null, $mime_type = null ) { $saved = $this->_save( $this->image, $destfilename, $mime_type ); if ( ! is_wp_error( $saved ) ) { $this->file = $saved['path']; $this->mime_type = $saved['mime-type']; try { $this->image->setImageFormat( strtoupper( $this->get_extension( $this->mime_type ) ) ); } catch ( Exception $e ) { return new WP_Error( 'image_save_error', $e->getMessage(), $this->file ); } } return $saved; } /** * @param Imagick $image * @param string $filename * @param string $mime_type * @return array|WP_Error */ protected function _save( $image, $filename = null, $mime_type = null ) { list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type ); if ( ! $filename ) { $filename = $this->generate_filename( null, null, $extension ); } try { // Store initial format. $orig_format = $this->image->getImageFormat(); $this->image->setImageFormat( strtoupper( $this->get_extension( $mime_type ) ) ); $this->make_image( $filename, array( $image, 'writeImage' ), array( $filename ) ); // Reset original format. $this->image->setImageFormat( $orig_format ); } catch ( Exception $e ) { return new WP_Error( 'image_save_error', $e->getMessage(), $filename ); } // Set correct file permissions. $stat = stat( dirname( $filename ) ); $perms = $stat['mode'] & 0000666; // Same permissions as parent folder, strip off the executable bits. chmod( $filename, $perms ); return array( 'path' => $filename, /** This filter is documented in wp-includes/class-wp-image-editor-gd.php */ 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ), 'width' => $this->size['width'], 'height' => $this->size['height'], 'mime-type' => $mime_type, ); } /** * Streams current image to browser. * * @since 3.5.0 * * @param string $mime_type The mime type of the image. * @return bool|WP_Error True on success, WP_Error object on failure. */ public function stream( $mime_type = null ) { list( $filename, $extension, $mime_type ) = $this->get_output_format( null, $mime_type ); try { // Temporarily change format for stream. $this->image->setImageFormat( strtoupper( $extension ) ); // Output stream of image content. header( "Content-Type: $mime_type" ); print $this->image->getImageBlob(); // Reset image to original format. $this->image->setImageFormat( $this->get_extension( $this->mime_type ) ); } catch ( Exception $e ) { return new WP_Error( 'image_stream_error', $e->getMessage() ); } return true; } /** * Strips all image meta except color profiles from an image. * * @since 4.5.0 * * @return true|WP_Error True if stripping metadata was successful. WP_Error object on error. */ protected function strip_meta() { if ( ! is_callable( array( $this->image, 'getImageProfiles' ) ) ) { /* translators: %s: ImageMagick method name. */ return new WP_Error( 'image_strip_meta_error', sprintf( __( '%s is required to strip image meta.' ), 'Imagick::getImageProfiles()' ) ); } if ( ! is_callable( array( $this->image, 'removeImageProfile' ) ) ) { /* translators: %s: ImageMagick method name. */ return new WP_Error( 'image_strip_meta_error', sprintf( __( '%s is required to strip image meta.' ), 'Imagick::removeImageProfile()' ) ); } /* * Protect a few profiles from being stripped for the following reasons: * * - icc: Color profile information * - icm: Color profile information * - iptc: Copyright data * - exif: Orientation data * - xmp: Rights usage data */ $protected_profiles = array( 'icc', 'icm', 'iptc', 'exif', 'xmp', ); try { // Strip profiles. foreach ( $this->image->getImageProfiles( '*', true ) as $key => $value ) { if ( ! in_array( $key, $protected_profiles, true ) ) { $this->image->removeImageProfile( $key ); } } } catch ( Exception $e ) { return new WP_Error( 'image_strip_meta_error', $e->getMessage() ); } return true; } /** * Sets up Imagick for PDF processing. * Increases rendering DPI and only loads first page. * * @since 4.7.0 * * @return string|WP_Error File to load or WP_Error on failure. */ protected function pdf_setup() { try { // By default, PDFs are rendered in a very low resolution. // We want the thumbnail to be readable, so increase the rendering DPI. $this->image->setResolution( 128, 128 ); // When generating thumbnails from cropped PDF pages, Imagemagick uses the uncropped // area (resulting in unnecessary whitespace) unless the following option is set. $this->image->setOption( 'pdf:use-cropbox', true ); // Only load the first page. return $this->file . '[0]'; } catch ( Exception $e ) { return new WP_Error( 'pdf_setup_failed', $e->getMessage(), $this->file ); } } }