run:R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
23.8 KB
2026-03-11 16:18:51
R W Run
7.8 KB
2026-03-11 16:18:52
R W Run
36.1 KB
2026-03-11 16:18:51
R W Run
11.9 KB
2026-03-11 16:18:52
R W Run
18.94 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:52
R W Run
28.6 KB
2026-03-11 16:18:51
R W Run
316 By
2026-03-11 16:18:51
R W Run
12.9 KB
2026-03-11 16:18:51
R W Run
61.02 KB
2026-03-11 16:18:52
R W Run
15 KB
2026-03-11 16:18:51
R W Run
112.05 KB
2026-03-11 16:18:51
R W Run
12.47 KB
2026-03-11 16:18:51
R W Run
15.07 KB
2026-03-11 16:18:52
R W Run
9.84 KB
2026-03-11 16:18:52
R W Run
13.17 KB
2026-03-11 16:18:52
R W Run
33.83 KB
2026-03-11 16:18:51
R W Run
42.63 KB
2026-03-11 16:18:51
R W Run
55.71 KB
2026-03-11 16:18:52
R W Run
12.53 KB
2026-03-11 16:18:51
R W Run
2.55 KB
2026-03-11 16:18:52
R W Run
28.92 KB
2026-03-11 16:18:52
R W Run
539 By
2026-03-11 16:18:51
R W Run
367 By
2026-03-11 16:18:52
R W Run
42.65 KB
2026-03-11 16:18:51
R W Run
401 By
2026-03-11 16:18:51
R W Run
6.61 KB
2026-03-11 16:18:51
R W Run
664 By
2026-03-11 16:18:52
R W Run
20.63 KB
2026-03-11 16:18:51
R W Run
2.18 KB
2026-03-11 16:18:52
R W Run
453 By
2026-03-11 16:18:52
R W Run
457 By
2026-03-11 16:18:51
R W Run
36.83 KB
2026-03-11 16:18:52
R W Run
2.41 KB
2026-03-11 16:18:52
R W Run
8.28 KB
2026-03-11 16:18:51
R W Run
13.89 KB
2026-03-11 16:18:51
R W Run
11.76 KB
2026-03-11 16:18:51
R W Run
2.65 KB
2026-03-11 16:18:51
R W Run
7.43 KB
2026-03-11 16:18:51
R W Run
17.46 KB
2026-03-11 16:18:51
R W Run
5.14 KB
2026-03-11 16:18:52
R W Run
16.7 KB
2026-03-11 16:18:51
R W Run
8.28 KB
2026-03-11 16:18:52
R W Run
2.92 KB
2026-03-11 16:18:52
R W Run
1.32 KB
2026-03-11 16:18:51
R W Run
4.6 KB
2026-03-11 16:18:52
R W Run
11.62 KB
2026-03-11 16:18:52
R W Run
2.5 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
11.25 KB
2026-03-11 16:18:52
R W Run
5.32 KB
2026-03-11 16:18:51
R W Run
10.99 KB
2026-03-11 16:18:52
R W Run
68.32 KB
2026-03-11 16:18:51
R W Run
6.34 KB
2026-03-11 16:18:51
R W Run
5.49 KB
2026-03-11 16:18:51
R W Run
1.99 KB
2026-03-11 16:18:52
R W Run
7.02 KB
2026-03-11 16:18:51
R W Run
4.91 KB
2026-03-11 16:18:52
R W Run
16.86 KB
2026-03-11 16:18:51
R W Run
24.23 KB
2026-03-11 16:18:51
R W Run
3.97 KB
2026-03-11 16:18:51
R W Run
47.66 KB
2026-03-11 16:18:51
R W Run
9.22 KB
2026-03-11 16:18:51
R W Run
25.51 KB
2026-03-11 16:18:51
R W Run
198.38 KB
2026-03-11 16:18:52
R W Run
56.65 KB
2026-03-11 16:18:51
R W Run
10.46 KB
2026-03-11 16:18:51
R W Run
10.95 KB
2026-03-11 16:18:52
R W Run
29.26 KB
2026-03-11 16:18:51
R W Run
70.91 KB
2026-03-11 16:18:52
R W Run
35.3 KB
2026-03-11 16:18:52
R W Run
16.61 KB
2026-03-11 16:18:52
R W Run
2.57 KB
2026-03-11 16:18:52
R W Run
39.83 KB
2026-03-11 16:18:51
R W Run
70.64 KB
2026-03-11 16:18:51
R W Run
15.56 KB
2026-03-11 16:18:52
R W Run
7.33 KB
2026-03-11 16:18:52
R W Run
253 By
2026-03-11 16:18:51
R W Run
7.96 KB
2026-03-11 16:18:52
R W Run
3.23 KB
2026-03-11 16:18:52
R W Run
969 By
2026-03-11 16:18:52
R W Run
16.28 KB
2026-03-11 16:18:51
R W Run
7.22 KB
2026-03-11 16:18:51
R W Run
12.95 KB
2026-03-11 16:18:51
R W Run
6.53 KB
2026-03-11 16:18:51
R W Run
3.42 KB
2026-03-11 16:18:52
R W Run
5.84 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
4.3 KB
2026-03-11 16:18:52
R W Run
2.91 KB
2026-03-11 16:18:51
R W Run
16.46 KB
2026-03-11 16:18:52
R W Run
40.6 KB
2026-03-11 16:18:51
R W Run
20.22 KB
2026-03-11 16:18:51
R W Run
36.11 KB
2026-03-11 16:18:52
R W Run
17.01 KB
2026-03-11 16:18:51
R W Run
7.27 KB
2026-03-11 16:18:52
R W Run
6.62 KB
2026-03-11 16:18:52
R W Run
16.49 KB
2026-03-11 16:18:52
R W Run
1.79 KB
2026-03-11 16:18:52
R W Run
29.82 KB
2026-03-11 16:18:51
R W Run
6.67 KB
2026-03-11 16:18:52
R W Run
8.98 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:51
R W Run
12.01 KB
2026-03-11 16:18:51
R W Run
17.11 KB
2026-03-11 16:18:51
R W Run
6.74 KB
2026-03-11 16:18:52
R W Run
30.93 KB
2026-03-11 16:18:51
R W Run
4.99 KB
2026-03-11 16:18:51
R W Run
4.25 KB
2026-03-11 16:18:51
R W Run
24.72 KB
2026-03-11 16:18:51
R W Run
29.96 KB
2026-03-11 16:18:52
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
160 KB
2026-03-11 16:18:51
R W Run
6.72 KB
2026-03-11 16:18:52
R W Run
10.92 KB
2026-03-11 16:18:51
R W Run
4.77 KB
2026-03-11 16:18:51
R W Run
3.38 KB
2026-03-11 16:18:51
R W Run
11.18 KB
2026-03-11 16:18:51
R W Run
62.19 KB
2026-03-11 16:18:51
R W Run
2.46 KB
2026-03-11 16:18:51
R W Run
9.17 KB
2026-03-11 16:18:51
R W Run
32.15 KB
2026-03-11 16:18:51
R W Run
34.05 KB
2026-03-11 16:18:52
R W Run
7.15 KB
2026-03-11 16:18:51
R W Run
3.47 KB
2026-03-11 16:18:52
R W Run
1.87 KB
2026-03-11 16:18:52
R W Run
30.91 KB
2026-03-11 16:18:51
R W Run
7.29 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:51
R W Run
12.54 KB
2026-03-11 16:18:51
R W Run
19.12 KB
2026-03-11 16:18:51
R W Run
18.12 KB
2026-03-11 16:18:52
R W Run
39.99 KB
2026-03-11 16:18:52
R W Run
5.17 KB
2026-03-11 16:18:52
R W Run
979 By
2026-03-11 16:18:51
R W Run
18.44 KB
2026-03-11 16:18:52
R W Run
10.24 KB
2026-03-11 16:18:51
R W Run
1.77 KB
2026-03-11 16:18:52
R W Run
34.9 KB
2026-03-11 16:18:51
R W Run
7.19 KB
2026-03-11 16:18:52
R W Run
160.5 KB
2026-03-11 16:18:51
R W Run
64.27 KB
2026-03-11 16:18:51
R W Run
27.95 KB
2026-03-11 16:18:51
R W Run
4.69 KB
2026-03-11 16:18:51
R W Run
2.94 KB
2026-03-11 16:18:51
R W Run
43.13 KB
2026-03-11 16:18:52
R W Run
2.25 KB
2026-03-11 16:18:52
R W Run
22.5 KB
2026-03-11 16:18:51
R W Run
13.01 KB
2026-03-11 16:18:52
R W Run
3.27 KB
2026-03-11 16:18:51
R W Run
18 KB
2026-03-11 16:18:51
R W Run
210.4 KB
2026-03-11 16:18:52
R W Run
25.86 KB
2026-03-11 16:18:52
R W Run
115.85 KB
2026-03-11 16:18:51
R W Run
373 By
2026-03-11 16:18:52
R W Run
343 By
2026-03-11 16:18:52
R W Run
338 By
2026-03-11 16:18:51
R W Run
100.73 KB
2026-03-11 16:18:52
R W Run
130.93 KB
2026-03-11 16:18:51
R W Run
19.1 KB
2026-03-11 16:18:51
R W Run
17.41 KB
2026-03-11 16:18:52
R W Run
41.98 KB
2026-03-11 16:18:52
R W Run
400 By
2026-03-11 16:18:52
R W Run
11.1 KB
2026-03-11 16:18:52
R W Run
37.02 KB
2026-03-11 16:18:51
R W Run
2.24 KB
2026-03-11 16:18:51
R W Run
188.13 KB
2026-03-11 16:18:51
R W Run
338 By
2026-03-11 16:18:51
R W Run
38 KB
2026-03-11 16:18:51
R W Run
4.02 KB
2026-03-11 16:18:52
R W Run
5.38 KB
2026-03-11 16:18:51
R W Run
3.05 KB
2026-03-11 16:18:52
R W Run
2.61 KB
2026-03-11 16:18:51
R W Run
1.16 KB
2026-03-11 16:18:52
R W Run
4.04 KB
2026-03-11 16:18:51
R W Run
3.71 KB
2026-03-11 16:18:51
R W Run
24.6 KB
2026-03-11 16:18:51
R W Run
9.56 KB
2026-03-11 16:18:51
R W Run
346.43 KB
2026-03-11 16:18:52
R W Run
281.84 KB
2026-03-11 16:18:52
R W Run
14.95 KB
2026-03-11 16:18:51
R W Run
8.44 KB
2026-03-11 16:18:52
R W Run
168.95 KB
2026-03-11 16:18:52
R W Run
20.71 KB
2026-03-11 16:18:52
R W Run
25.27 KB
2026-03-11 16:18:51
R W Run
5.72 KB
2026-03-11 16:18:51
R W Run
4.63 KB
2026-03-11 16:18:52
R W Run
81.73 KB
2026-03-11 16:18:51
R W Run
67.18 KB
2026-03-11 16:18:51
R W Run
156.36 KB
2026-03-11 16:18:52
R W Run
55.19 KB
2026-03-11 16:18:51
R W Run
162 By
2026-03-11 16:18:51
R W Run
61.72 KB
2026-03-11 16:18:51
R W Run
216.06 KB
2026-03-11 16:18:52
R W Run
65.09 KB
2026-03-11 16:18:51
R W Run
25.24 KB
2026-03-11 16:18:52
R W Run
4.81 KB
2026-03-11 16:18:51
R W Run
6.48 KB
2026-03-11 16:18:52
R W Run
21.25 KB
2026-03-11 16:18:51
R W Run
2.79 KB
2026-03-11 16:18:52
R W Run
89.69 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:52
R W Run
3.69 KB
2026-03-11 16:18:52
R W Run
4.11 KB
2026-03-11 16:18:51
R W Run
40.74 KB
2026-03-11 16:18:51
R W Run
25.38 KB
2026-03-11 16:18:51
R W Run
43.31 KB
2026-03-11 16:18:52
R W Run
102.57 KB
2026-03-11 16:18:52
R W Run
6.18 KB
2026-03-11 16:18:51
R W Run
124.47 KB
2026-03-11 16:18:52
R W Run
35.65 KB
2026-03-11 16:18:52
R W Run
6.94 KB
2026-03-11 16:18:52
R W Run
67.04 KB
2026-03-11 16:18:52
R W Run
10.62 KB
2026-03-11 16:18:51
R W Run
289.35 KB
2026-03-11 16:18:52
R W Run
36.23 KB
2026-03-11 16:18:51
R W Run
200 By
2026-03-11 16:18:52
R W Run
200 By
2026-03-11 16:18:52
R W Run
98.29 KB
2026-03-11 16:18:52
R W Run
30.02 KB
2026-03-11 16:18:52
R W Run
19.03 KB
2026-03-11 16:18:52
R W Run
5.06 KB
2026-03-11 16:18:52
R W Run
255 By
2026-03-11 16:18:51
R W Run
22.66 KB
2026-03-11 16:18:52
R W Run
154.63 KB
2026-03-11 16:18:51
R W Run
9.68 KB
2026-03-11 16:18:51
R W Run
258 By
2026-03-11 16:18:51
R W Run
23.49 KB
2026-03-11 16:18:51
R W Run
3.16 KB
2026-03-11 16:18:51
R W Run
8.4 KB
2026-03-11 16:18:52
R W Run
441 By
2026-03-11 16:18:51
R W Run
7.39 KB
2026-03-11 16:18:51
R W Run
173 KB
2026-03-11 16:18:52
R W Run
544 By
2026-03-11 16:18:52
R W Run
4.17 KB
2026-03-11 16:18:51
R W Run
35.97 KB
2026-03-11 16:18:52
R W Run
1.69 KB
2026-03-11 16:18:51
R W Run
2.84 KB
2026-03-11 16:18:52
R W Run
6.09 KB
2026-03-11 16:18:51
R W Run
8.71 KB
2026-03-11 16:18:51
R W Run
131.84 KB
2026-03-11 16:18:51
R W Run
37.45 KB
2026-03-11 16:18:51
R W Run
173.89 KB
2026-03-11 16:18:51
R W Run
7.09 KB
2026-03-11 16:18:51
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
1.08 KB
2026-03-11 16:18:51
R W Run
69.46 KB
2026-03-11 16:18:52
R W Run
445 By
2026-03-11 16:18:51
R W Run
799 By
2026-03-11 16:18:52
R W Run
error_log
📄class-wp-image-editor-imagick.php
1<?php
2/**
3 * WordPress Imagick Image Editor
4 *
5 * @package WordPress
6 * @subpackage Image_Editor
7 */
8
9/**
10 * WordPress Image Editor Class for Image Manipulation through Imagick PHP Module
11 *
12 * @since 3.5.0
13 *
14 * @see WP_Image_Editor
15 */
16class WP_Image_Editor_Imagick extends WP_Image_Editor {
17 /**
18 * Imagick object.
19 *
20 * @var Imagick
21 */
22 protected $image;
23
24 public function __destruct() {
25 if ( $this->image instanceof Imagick ) {
26 // We don't need the original in memory anymore.
27 $this->image->clear();
28 $this->image->destroy();
29 }
30 }
31
32 /**
33 * Checks to see if current environment supports Imagick.
34 *
35 * We require Imagick 2.2.0 or greater, based on whether the queryFormats()
36 * method can be called statically.
37 *
38 * @since 3.5.0
39 *
40 * @param array $args
41 * @return bool
42 */
43 public static function test( $args = array() ) {
44
45 // First, test Imagick's extension and classes.
46 if ( ! extension_loaded( 'imagick' ) || ! class_exists( 'Imagick', false ) || ! class_exists( 'ImagickPixel', false ) ) {
47 return false;
48 }
49
50 if ( version_compare( phpversion( 'imagick' ), '2.2.0', '<' ) ) {
51 return false;
52 }
53
54 $required_methods = array(
55 'clear',
56 'destroy',
57 'valid',
58 'getimage',
59 'writeimage',
60 'getimageblob',
61 'getimagegeometry',
62 'getimageformat',
63 'setimageformat',
64 'setimagecompression',
65 'setimagecompressionquality',
66 'setimagepage',
67 'setoption',
68 'scaleimage',
69 'cropimage',
70 'rotateimage',
71 'flipimage',
72 'flopimage',
73 'readimage',
74 'readimageblob',
75 );
76
77 // Now, test for deep requirements within Imagick.
78 if ( ! defined( 'imagick::COMPRESSION_JPEG' ) ) {
79 return false;
80 }
81
82 $class_methods = array_map( 'strtolower', get_class_methods( 'Imagick' ) );
83 if ( array_diff( $required_methods, $class_methods ) ) {
84 return false;
85 }
86
87 return true;
88 }
89
90 /**
91 * Checks to see if editor supports the mime-type specified.
92 *
93 * @since 3.5.0
94 *
95 * @param string $mime_type
96 * @return bool
97 */
98 public static function supports_mime_type( $mime_type ) {
99 $imagick_extension = strtoupper( self::get_extension( $mime_type ) );
100
101 if ( ! $imagick_extension ) {
102 return false;
103 }
104
105 /*
106 * setIteratorIndex is optional unless mime is an animated format.
107 * Here, we just say no if you are missing it and aren't loading a jpeg.
108 */
109 if ( ! method_exists( 'Imagick', 'setIteratorIndex' ) && 'image/jpeg' !== $mime_type ) {
110 return false;
111 }
112
113 try {
114 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
115 return ( (bool) @Imagick::queryFormats( $imagick_extension ) );
116 } catch ( Exception $e ) {
117 return false;
118 }
119 }
120
121 /**
122 * Loads image from $this->file into new Imagick Object.
123 *
124 * @since 3.5.0
125 *
126 * @return true|WP_Error True if loaded; WP_Error on failure.
127 */
128 public function load() {
129 if ( $this->image instanceof Imagick ) {
130 return true;
131 }
132
133 if ( ! is_file( $this->file ) && ! wp_is_stream( $this->file ) ) {
134 return new WP_Error( 'error_loading_image', __( 'File does not exist?' ), $this->file );
135 }
136
137 /*
138 * Even though Imagick uses less PHP memory than GD, set higher limit
139 * for users that have low PHP.ini limits.
140 */
141 wp_raise_memory_limit( 'image' );
142
143 try {
144 $this->image = new Imagick();
145 $file_extension = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) );
146
147 if ( 'pdf' === $file_extension ) {
148 $pdf_loaded = $this->pdf_load_source();
149
150 if ( is_wp_error( $pdf_loaded ) ) {
151 return $pdf_loaded;
152 }
153 } else {
154 if ( wp_is_stream( $this->file ) ) {
155 // Due to reports of issues with streams with `Imagick::readImageFile()`, uses `Imagick::readImageBlob()` instead.
156 $this->image->readImageBlob( file_get_contents( $this->file ), $this->file );
157 } else {
158 $this->image->readImage( $this->file );
159 }
160 }
161
162 if ( ! $this->image->valid() ) {
163 return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file );
164 }
165
166 // Select the first frame to handle animated images properly.
167 if ( is_callable( array( $this->image, 'setIteratorIndex' ) ) ) {
168 $this->image->setIteratorIndex( 0 );
169 }
170
171 if ( 'pdf' === $file_extension ) {
172 $this->remove_pdf_alpha_channel();
173 }
174
175 $this->mime_type = $this->get_mime_type( $this->image->getImageFormat() );
176 } catch ( Exception $e ) {
177 return new WP_Error( 'invalid_image', $e->getMessage(), $this->file );
178 }
179
180 $updated_size = $this->update_size();
181
182 if ( is_wp_error( $updated_size ) ) {
183 return $updated_size;
184 }
185
186 return $this->set_quality();
187 }
188
189 /**
190 * Sets Image Compression quality on a 1-100% scale.
191 *
192 * @since 3.5.0
193 * @since 6.8.0 The `$dims` parameter was added.
194 *
195 * @param int $quality Compression Quality. Range: [1,100]
196 * @param array $dims Optional. Image dimensions array with 'width' and 'height' keys.
197 * @return true|WP_Error True if set successfully; WP_Error on failure.
198 */
199 public function set_quality( $quality = null, $dims = array() ) {
200 $quality_result = parent::set_quality( $quality, $dims );
201 if ( is_wp_error( $quality_result ) ) {
202 return $quality_result;
203 } else {
204 $quality = $this->get_quality();
205 }
206
207 try {
208 switch ( $this->mime_type ) {
209 case 'image/jpeg':
210 $this->image->setImageCompressionQuality( $quality );
211 $this->image->setCompressionQuality( $quality );
212 $this->image->setImageCompression( imagick::COMPRESSION_JPEG );
213 break;
214 case 'image/webp':
215 $webp_info = wp_get_webp_info( $this->file );
216
217 if ( 'lossless' === $webp_info['type'] ) {
218 // Use WebP lossless settings.
219 $this->image->setImageCompressionQuality( 100 );
220 $this->image->setCompressionQuality( 100 );
221 $this->image->setOption( 'webp:lossless', 'true' );
222 parent::set_quality( 100 );
223 } else {
224 $this->image->setImageCompressionQuality( $quality );
225 $this->image->setCompressionQuality( $quality );
226 }
227 break;
228 case 'image/avif':
229 // Set the AVIF encoder to work faster, with minimal impact on image size.
230 $this->image->setOption( 'heic:speed', 7 );
231 $this->image->setImageCompressionQuality( $quality );
232 $this->image->setCompressionQuality( $quality );
233 break;
234 default:
235 $this->image->setImageCompressionQuality( $quality );
236 $this->image->setCompressionQuality( $quality );
237 }
238 } catch ( Exception $e ) {
239 return new WP_Error( 'image_quality_error', $e->getMessage() );
240 }
241 return true;
242 }
243
244
245 /**
246 * Sets or updates current image size.
247 *
248 * @since 3.5.0
249 *
250 * @param int $width
251 * @param int $height
252 * @return true|WP_Error
253 */
254 protected function update_size( $width = null, $height = null ) {
255 $size = null;
256 if ( ! $width || ! $height ) {
257 try {
258 $size = $this->image->getImageGeometry();
259 } catch ( Exception $e ) {
260 return new WP_Error( 'invalid_image', __( 'Could not read image size.' ), $this->file );
261 }
262 }
263
264 if ( ! $width ) {
265 $width = $size['width'];
266 }
267
268 if ( ! $height ) {
269 $height = $size['height'];
270 }
271
272 /*
273 * If we still don't have the image size, fall back to `wp_getimagesize`. This ensures AVIF and HEIC images
274 * are properly sized without affecting previous `getImageGeometry` behavior.
275 */
276 if ( ( ! $width || ! $height ) && ( 'image/avif' === $this->mime_type || wp_is_heic_image_mime_type( $this->mime_type ) ) ) {
277 $size = wp_getimagesize( $this->file );
278 $width = $size[0];
279 $height = $size[1];
280 }
281
282 return parent::update_size( $width, $height );
283 }
284
285 /**
286 * Sets Imagick time limit.
287 *
288 * Depending on configuration, Imagick processing may take time.
289 *
290 * Multiple problems exist if PHP times out before ImageMagick completed:
291 * 1. Temporary files aren't cleaned by ImageMagick garbage collection.
292 * 2. No clear error is provided.
293 * 3. The cause of such timeout can be hard to pinpoint.
294 *
295 * This function, which is expected to be run before heavy image routines, resolves
296 * point 1 above by aligning Imagick's timeout with PHP's timeout, assuming it is set.
297 *
298 * However seems it introduces more problems than it fixes,
299 * see https://core.trac.wordpress.org/ticket/58202.
300 *
301 * Note:
302 * - Imagick resource exhaustion does not issue catchable exceptions (yet).
303 * See https://github.com/Imagick/imagick/issues/333.
304 * - The resource limit is not saved/restored. It applies to subsequent
305 * image operations within the time of the HTTP request.
306 *
307 * @since 6.2.0
308 * @deprecated 6.3.0 No longer used in core.
309 *
310 * @return int|null The new limit on success, null on failure.
311 */
312 public static function set_imagick_time_limit() {
313 _deprecated_function( __METHOD__, '6.3.0' );
314
315 if ( ! defined( 'Imagick::RESOURCETYPE_TIME' ) ) {
316 return null;
317 }
318
319 // Returns PHP_FLOAT_MAX if unset.
320 $imagick_timeout = Imagick::getResourceLimit( Imagick::RESOURCETYPE_TIME );
321
322 // Convert to an integer, keeping in mind that: 0 === (int) PHP_FLOAT_MAX.
323 $imagick_timeout = $imagick_timeout > PHP_INT_MAX ? PHP_INT_MAX : (int) $imagick_timeout;
324
325 $php_timeout = (int) ini_get( 'max_execution_time' );
326
327 if ( $php_timeout > 1 && $php_timeout < $imagick_timeout ) {
328 $limit = (float) 0.8 * $php_timeout;
329 Imagick::setResourceLimit( Imagick::RESOURCETYPE_TIME, $limit );
330
331 return $limit;
332 }
333 }
334
335 /**
336 * Resizes current image.
337 *
338 * At minimum, either a height or width must be provided.
339 * If one of the two is set to null, the resize will
340 * maintain aspect ratio according to the provided dimension.
341 *
342 * @since 3.5.0
343 *
344 * @param int|null $max_w Image width.
345 * @param int|null $max_h Image height.
346 * @param bool|array $crop {
347 * Optional. Image cropping behavior. If false, the image will be scaled (default).
348 * If true, image will be cropped to the specified dimensions using center positions.
349 * If an array, the image will be cropped using the array to specify the crop location:
350 *
351 * @type string $0 The x crop position. Accepts 'left', 'center', or 'right'.
352 * @type string $1 The y crop position. Accepts 'top', 'center', or 'bottom'.
353 * }
354 * @return true|WP_Error
355 */
356 public function resize( $max_w, $max_h, $crop = false ) {
357 if ( ( $this->size['width'] === $max_w ) && ( $this->size['height'] === $max_h ) ) {
358 return true;
359 }
360
361 $dims = image_resize_dimensions( $this->size['width'], $this->size['height'], $max_w, $max_h, $crop );
362 if ( ! $dims ) {
363 return new WP_Error( 'error_getting_dimensions', __( 'Could not calculate resized image dimensions' ) );
364 }
365
366 list( $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h ) = $dims;
367
368 if ( $crop ) {
369 return $this->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h );
370 }
371
372 $this->set_quality(
373 null,
374 array(
375 'width' => $dst_w,
376 'height' => $dst_h,
377 )
378 );
379
380 // Execute the resize.
381 $thumb_result = $this->thumbnail_image( $dst_w, $dst_h );
382 if ( is_wp_error( $thumb_result ) ) {
383 return $thumb_result;
384 }
385
386 return $this->update_size( $dst_w, $dst_h );
387 }
388
389 /**
390 * Efficiently resize the current image
391 *
392 * This is a WordPress specific implementation of Imagick::thumbnailImage(),
393 * which resizes an image to given dimensions and removes any associated profiles.
394 *
395 * @since 4.5.0
396 *
397 * @param int $dst_w The destination width.
398 * @param int $dst_h The destination height.
399 * @param string $filter_name Optional. The Imagick filter to use when resizing. Default 'FILTER_TRIANGLE'.
400 * @param bool $strip_meta Optional. Strip all profiles, excluding color profiles, from the image. Default true.
401 * @return void|WP_Error
402 */
403 protected function thumbnail_image( $dst_w, $dst_h, $filter_name = 'FILTER_TRIANGLE', $strip_meta = true ) {
404 $allowed_filters = array(
405 'FILTER_POINT',
406 'FILTER_BOX',
407 'FILTER_TRIANGLE',
408 'FILTER_HERMITE',
409 'FILTER_HANNING',
410 'FILTER_HAMMING',
411 'FILTER_BLACKMAN',
412 'FILTER_GAUSSIAN',
413 'FILTER_QUADRATIC',
414 'FILTER_CUBIC',
415 'FILTER_CATROM',
416 'FILTER_MITCHELL',
417 'FILTER_LANCZOS',
418 'FILTER_BESSEL',
419 'FILTER_SINC',
420 );
421
422 /**
423 * Set the filter value if '$filter_name' name is in the allowed list and the related
424 * Imagick constant is defined or fall back to the default filter.
425 */
426 if ( in_array( $filter_name, $allowed_filters, true ) && defined( 'Imagick::' . $filter_name ) ) {
427 $filter = constant( 'Imagick::' . $filter_name );
428 } else {
429 $filter = defined( 'Imagick::FILTER_TRIANGLE' ) ? Imagick::FILTER_TRIANGLE : false;
430 }
431
432 /**
433 * Filters whether to strip metadata from images when they're resized.
434 *
435 * This filter only applies when resizing using the Imagick editor since GD
436 * always strips profiles by default.
437 *
438 * @since 4.5.0
439 *
440 * @param bool $strip_meta Whether to strip image metadata during resizing. Default true.
441 */
442 if ( apply_filters( 'image_strip_meta', $strip_meta ) ) {
443 $this->strip_meta(); // Fail silently if not supported.
444 }
445
446 try {
447 /**
448 * Special handling for certain types of PNG images:
449 * 1. For PNG images, we need to specify compression settings and remove unneeded chunks.
450 * 2. For indexed PNG images, the number of colors must not exceed 256.
451 * 3. For indexed PNG images with an alpha channel, the tRNS chunk must be preserved.
452 * 4. For indexed PNG images with true alpha transparency (an alpha channel > 1 bit), we need to avoid saving
453 * the image using ImageMagick's 'png8' format, because that supports only binary (1 bit) transparency.
454 *
455 * For #4 we want to check whether the image has a 1-bit alpha channel before resizing, because resizing
456 * may cause the number of alpha values to multiply due to antialiasing. If the original image had only a
457 * 1-bit alpha channel, then a 1-bit alpha channel should be good enough for the resized images.
458 *
459 * Perform all the necessary checks before resizing the image and store the results in variables for later use.
460 */
461 $is_png = false;
462 $is_indexed_png = false;
463 $is_indexed_png_with_alpha_channel = false;
464 $is_indexed_png_with_true_alpha_transparency = false;
465
466 if ( 'image/png' === $this->mime_type ) {
467 $is_png = true;
468
469 if (
470 is_callable( array( $this->image, 'getImageProperty' ) )
471 && '3' === $this->image->getImageProperty( 'png:IHDR.color-type-orig' )
472 ) {
473 $is_indexed_png = true;
474
475 if (
476 is_callable( array( $this->image, 'getImageAlphaChannel' ) )
477 && $this->image->getImageAlphaChannel()
478 ) {
479 $is_indexed_png_with_alpha_channel = true;
480
481 if (
482 is_callable( array( $this->image, 'getImageChannelDepth' ) )
483 && defined( 'Imagick::CHANNEL_ALPHA' )
484 && 1 < $this->image->getImageChannelDepth( Imagick::CHANNEL_ALPHA )
485 ) {
486 $is_indexed_png_with_true_alpha_transparency = true;
487 }
488 }
489 }
490 }
491
492 /*
493 * To be more efficient, resample large images to 5x the destination size before resizing
494 * whenever the output size is less that 1/3 of the original image size (1/3^2 ~= .111),
495 * unless we would be resampling to a scale smaller than 128x128.
496 */
497 if ( is_callable( array( $this->image, 'sampleImage' ) ) ) {
498 $resize_ratio = ( $dst_w / $this->size['width'] ) * ( $dst_h / $this->size['height'] );
499 $sample_factor = 5;
500
501 if ( $resize_ratio < .111 && ( $dst_w * $sample_factor > 128 && $dst_h * $sample_factor > 128 ) ) {
502 $this->image->sampleImage( $dst_w * $sample_factor, $dst_h * $sample_factor );
503 }
504 }
505
506 /*
507 * Use resizeImage() when it's available and a valid filter value is set.
508 * Otherwise, fall back to the scaleImage() method for resizing, which
509 * results in better image quality over resizeImage() with default filter
510 * settings and retains backward compatibility with pre 4.5 functionality.
511 */
512 if ( is_callable( array( $this->image, 'resizeImage' ) ) && $filter ) {
513 $this->image->setOption( 'filter:support', '2.0' );
514 $this->image->resizeImage( $dst_w, $dst_h, $filter, 1 );
515 } else {
516 $this->image->scaleImage( $dst_w, $dst_h );
517 }
518
519 // Set appropriate quality settings after resizing.
520 if ( 'image/jpeg' === $this->mime_type ) {
521 if ( is_callable( array( $this->image, 'unsharpMaskImage' ) ) ) {
522 $this->image->unsharpMaskImage( 0.25, 0.25, 8, 0.065 );
523 }
524
525 $this->image->setOption( 'jpeg:fancy-upsampling', 'off' );
526 }
527
528 if ( $is_png ) {
529 $this->image->setOption( 'png:compression-filter', '5' );
530 $this->image->setOption( 'png:compression-level', '9' );
531 $this->image->setOption( 'png:compression-strategy', '1' );
532
533 // Indexed PNG files get some additional handling.
534 // See #63448 for details.
535 if ( $is_indexed_png ) {
536
537 // Check for an alpha channel.
538 if ( $is_indexed_png_with_alpha_channel ) {
539 $this->image->setOption( 'png:include-chunk', 'tRNS' );
540 } else {
541 $this->image->setOption( 'png:exclude-chunk', 'all' );
542 }
543
544 $this->image->quantizeImage( 256, $this->image->getColorspace(), 0, false, false );
545
546 /*
547 * If the colorspace is 'gray', use the png8 format to ensure it stays indexed.
548 * ImageMagick tends to save grayscale images as grayscale PNGs rather than indexed PNGs,
549 * even though grayscale PNGs usually have considerably larger file sizes.
550 * But we can force ImageMagick to save the image as an indexed PNG instead,
551 * by telling it to use png8 format.
552 *
553 * Note that we need to first call quantizeImage() before checking getImageColorspace(),
554 * because only after calling quantizeImage() will the colorspace be COLORSPACE_GRAY for grayscale images
555 * (and we have not found any other way to identify grayscale images).
556 *
557 * We need to avoid forcing indexed format for images with true alpha transparency,
558 * because ImageMagick does not support saving an image with true alpha transparency as an indexed PNG.
559 */
560 if ( Imagick::COLORSPACE_GRAY === $this->image->getImageColorspace() && ! $is_indexed_png_with_true_alpha_transparency ) {
561 // Set the image format to Indexed PNG.
562 $this->image->setOption( 'png:format', 'png8' );
563 }
564 } else {
565 $this->image->setOption( 'png:exclude-chunk', 'all' );
566 }
567 }
568
569 /*
570 * If alpha channel is not defined, set it opaque.
571 *
572 * Note that Imagick::getImageAlphaChannel() is only available if Imagick
573 * has been compiled against ImageMagick version 6.4.0 or newer.
574 */
575 if ( is_callable( array( $this->image, 'getImageAlphaChannel' ) )
576 && is_callable( array( $this->image, 'setImageAlphaChannel' ) )
577 && defined( 'Imagick::ALPHACHANNEL_UNDEFINED' )
578 && defined( 'Imagick::ALPHACHANNEL_OPAQUE' )
579 ) {
580 if ( $this->image->getImageAlphaChannel() === Imagick::ALPHACHANNEL_UNDEFINED ) {
581 $this->image->setImageAlphaChannel( Imagick::ALPHACHANNEL_OPAQUE );
582 }
583 }
584
585 // Limit the bit depth of resized images.
586 if ( is_callable( array( $this->image, 'getImageDepth' ) ) && is_callable( array( $this->image, 'setImageDepth' ) ) ) {
587 /**
588 * Filters the maximum bit depth of resized images.
589 *
590 * This filter only applies when resizing using the Imagick editor since GD
591 * does not support getting or setting bit depth.
592 *
593 * Use this to adjust the maximum bit depth of resized images.
594 *
595 * @since 6.8.0
596 *
597 * @param int $max_depth The maximum bit depth. Default is the input depth.
598 * @param int $image_depth The bit depth of the original image.
599 */
600 $max_depth = apply_filters( 'image_max_bit_depth', $this->image->getImageDepth(), $this->image->getImageDepth() );
601 $this->image->setImageDepth( $max_depth );
602 }
603 } catch ( Exception $e ) {
604 return new WP_Error( 'image_resize_error', $e->getMessage() );
605 }
606 }
607
608 /**
609 * Create multiple smaller images from a single source.
610 *
611 * Attempts to create all sub-sizes and returns the meta data at the end. This
612 * may result in the server running out of resources. When it fails there may be few
613 * "orphaned" images left over as the meta data is never returned and saved.
614 *
615 * As of 5.3.0 the preferred way to do this is with `make_subsize()`. It creates
616 * the new images one at a time and allows for the meta data to be saved after
617 * each new image is created.
618 *
619 * @since 3.5.0
620 *
621 * @param array $sizes {
622 * An array of image size data arrays.
623 *
624 * Either a height or width must be provided.
625 * If one of the two is set to null, the resize will
626 * maintain aspect ratio according to the provided dimension.
627 *
628 * @type array ...$0 {
629 * Array of height, width values, and whether to crop.
630 *
631 * @type int $width Image width. Optional if `$height` is specified.
632 * @type int $height Image height. Optional if `$width` is specified.
633 * @type bool|array $crop Optional. Whether to crop the image. Default false.
634 * }
635 * }
636 * @return array An array of resized images' metadata by size.
637 */
638 public function multi_resize( $sizes ) {
639 $metadata = array();
640
641 foreach ( $sizes as $size => $size_data ) {
642 $meta = $this->make_subsize( $size_data );
643
644 if ( ! is_wp_error( $meta ) ) {
645 $metadata[ $size ] = $meta;
646 }
647 }
648
649 return $metadata;
650 }
651
652 /**
653 * Create an image sub-size and return the image meta data value for it.
654 *
655 * @since 5.3.0
656 *
657 * @param array $size_data {
658 * Array of size data.
659 *
660 * @type int $width The maximum width in pixels.
661 * @type int $height The maximum height in pixels.
662 * @type bool|array $crop Whether to crop the image to exact dimensions.
663 * }
664 * @return array|WP_Error The image data array for inclusion in the `sizes` array in the image meta,
665 * WP_Error object on error.
666 */
667 public function make_subsize( $size_data ) {
668 if ( ! isset( $size_data['width'] ) && ! isset( $size_data['height'] ) ) {
669 return new WP_Error( 'image_subsize_create_error', __( 'Cannot resize the image. Both width and height are not set.' ) );
670 }
671
672 $orig_size = $this->size;
673 $orig_image = $this->image->getImage();
674
675 if ( ! isset( $size_data['width'] ) ) {
676 $size_data['width'] = null;
677 }
678
679 if ( ! isset( $size_data['height'] ) ) {
680 $size_data['height'] = null;
681 }
682
683 if ( ! isset( $size_data['crop'] ) ) {
684 $size_data['crop'] = false;
685 }
686
687 if ( ( $this->size['width'] === $size_data['width'] ) && ( $this->size['height'] === $size_data['height'] ) ) {
688 return new WP_Error( 'image_subsize_create_error', __( 'The image already has the requested size.' ) );
689 }
690
691 $resized = $this->resize( $size_data['width'], $size_data['height'], $size_data['crop'] );
692
693 if ( is_wp_error( $resized ) ) {
694 $saved = $resized;
695 } else {
696 $saved = $this->_save( $this->image );
697
698 $this->image->clear();
699 $this->image->destroy();
700 $this->image = null;
701 }
702
703 $this->size = $orig_size;
704 $this->image = $orig_image;
705
706 if ( ! is_wp_error( $saved ) ) {
707 unset( $saved['path'] );
708 }
709
710 return $saved;
711 }
712
713 /**
714 * Crops Image.
715 *
716 * @since 3.5.0
717 *
718 * @param int $src_x The start x position to crop from.
719 * @param int $src_y The start y position to crop from.
720 * @param int $src_w The width to crop.
721 * @param int $src_h The height to crop.
722 * @param int $dst_w Optional. The destination width.
723 * @param int $dst_h Optional. The destination height.
724 * @param bool $src_abs Optional. If the source crop points are absolute.
725 * @return true|WP_Error
726 */
727 public function crop( $src_x, $src_y, $src_w, $src_h, $dst_w = null, $dst_h = null, $src_abs = false ) {
728 if ( $src_abs ) {
729 $src_w -= $src_x;
730 $src_h -= $src_y;
731 }
732
733 try {
734 $this->image->cropImage( $src_w, $src_h, $src_x, $src_y );
735 $this->image->setImagePage( $src_w, $src_h, 0, 0 );
736
737 if ( $dst_w || $dst_h ) {
738 /*
739 * If destination width/height isn't specified,
740 * use same as width/height from source.
741 */
742 if ( ! $dst_w ) {
743 $dst_w = $src_w;
744 }
745 if ( ! $dst_h ) {
746 $dst_h = $src_h;
747 }
748
749 $thumb_result = $this->thumbnail_image( $dst_w, $dst_h );
750 if ( is_wp_error( $thumb_result ) ) {
751 return $thumb_result;
752 }
753
754 return $this->update_size();
755 }
756 } catch ( Exception $e ) {
757 return new WP_Error( 'image_crop_error', $e->getMessage() );
758 }
759
760 return $this->update_size();
761 }
762
763 /**
764 * Rotates current image counter-clockwise by $angle.
765 *
766 * @since 3.5.0
767 *
768 * @param float $angle
769 * @return true|WP_Error
770 */
771 public function rotate( $angle ) {
772 /**
773 * $angle is 360-$angle because Imagick rotates clockwise
774 * (GD rotates counter-clockwise)
775 */
776 try {
777 $this->image->rotateImage( new ImagickPixel( 'none' ), 360 - $angle );
778
779 // Normalize EXIF orientation data so that display is consistent across devices.
780 if ( is_callable( array( $this->image, 'setImageOrientation' ) ) && defined( 'Imagick::ORIENTATION_TOPLEFT' ) ) {
781 $this->image->setImageOrientation( Imagick::ORIENTATION_TOPLEFT );
782 }
783
784 // Since this changes the dimensions of the image, update the size.
785 $result = $this->update_size();
786 if ( is_wp_error( $result ) ) {
787 return $result;
788 }
789
790 $this->image->setImagePage( $this->size['width'], $this->size['height'], 0, 0 );
791 } catch ( Exception $e ) {
792 return new WP_Error( 'image_rotate_error', $e->getMessage() );
793 }
794
795 return true;
796 }
797
798 /**
799 * Flips current image.
800 *
801 * @since 3.5.0
802 *
803 * @param bool $horz Flip along Horizontal Axis
804 * @param bool $vert Flip along Vertical Axis
805 * @return true|WP_Error
806 */
807 public function flip( $horz, $vert ) {
808 try {
809 if ( $horz ) {
810 $this->image->flipImage();
811 }
812
813 if ( $vert ) {
814 $this->image->flopImage();
815 }
816
817 // Normalize EXIF orientation data so that display is consistent across devices.
818 if ( is_callable( array( $this->image, 'setImageOrientation' ) ) && defined( 'Imagick::ORIENTATION_TOPLEFT' ) ) {
819 $this->image->setImageOrientation( Imagick::ORIENTATION_TOPLEFT );
820 }
821 } catch ( Exception $e ) {
822 return new WP_Error( 'image_flip_error', $e->getMessage() );
823 }
824
825 return true;
826 }
827
828 /**
829 * Check if a JPEG image has EXIF Orientation tag and rotate it if needed.
830 *
831 * As ImageMagick copies the EXIF data to the flipped/rotated image, proceed only
832 * if EXIF Orientation can be reset afterwards.
833 *
834 * @since 5.3.0
835 *
836 * @return bool|WP_Error True if the image was rotated. False if no EXIF data or if the image doesn't need rotation.
837 * WP_Error if error while rotating.
838 */
839 public function maybe_exif_rotate() {
840 if ( is_callable( array( $this->image, 'setImageOrientation' ) ) && defined( 'Imagick::ORIENTATION_TOPLEFT' ) ) {
841 return parent::maybe_exif_rotate();
842 } else {
843 return new WP_Error( 'write_exif_error', __( 'The image cannot be rotated because the embedded meta data cannot be updated.' ) );
844 }
845 }
846
847 /**
848 * Saves current image to file.
849 *
850 * @since 3.5.0
851 * @since 6.0.0 The `$filesize` value was added to the returned array.
852 *
853 * @param string $destfilename Optional. Destination filename. Default null.
854 * @param string $mime_type Optional. The mime-type. Default null.
855 * @return array|WP_Error {
856 * Array on success or WP_Error if the file failed to save.
857 *
858 * @type string $path Path to the image file.
859 * @type string $file Name of the image file.
860 * @type int $width Image width.
861 * @type int $height Image height.
862 * @type string $mime-type The mime type of the image.
863 * @type int $filesize File size of the image.
864 * }
865 */
866 public function save( $destfilename = null, $mime_type = null ) {
867 $saved = $this->_save( $this->image, $destfilename, $mime_type );
868
869 if ( ! is_wp_error( $saved ) ) {
870 $this->file = $saved['path'];
871 $this->mime_type = $saved['mime-type'];
872
873 try {
874 $this->image->setImageFormat( strtoupper( $this->get_extension( $this->mime_type ) ) );
875 } catch ( Exception $e ) {
876 return new WP_Error( 'image_save_error', $e->getMessage(), $this->file );
877 }
878 }
879
880 return $saved;
881 }
882
883 /**
884 * Removes PDF alpha after it's been read.
885 *
886 * @since 6.4.0
887 */
888 protected function remove_pdf_alpha_channel() {
889 $version = Imagick::getVersion();
890 // Remove alpha channel if possible to avoid black backgrounds for Ghostscript >= 9.14. RemoveAlphaChannel added in ImageMagick 6.7.5.
891 if ( $version['versionNumber'] >= 0x675 ) {
892 try {
893 // Imagick::ALPHACHANNEL_REMOVE mapped to RemoveAlphaChannel in PHP imagick 3.2.0b2.
894 $this->image->setImageAlphaChannel( defined( 'Imagick::ALPHACHANNEL_REMOVE' ) ? Imagick::ALPHACHANNEL_REMOVE : 12 );
895 } catch ( Exception $e ) {
896 return new WP_Error( 'pdf_alpha_process_failed', $e->getMessage() );
897 }
898 }
899 }
900
901 /**
902 * @since 3.5.0
903 * @since 6.0.0 The `$filesize` value was added to the returned array.
904 *
905 * @param Imagick $image
906 * @param string $filename
907 * @param string $mime_type
908 * @return array|WP_Error {
909 * Array on success or WP_Error if the file failed to save.
910 *
911 * @type string $path Path to the image file.
912 * @type string $file Name of the image file.
913 * @type int $width Image width.
914 * @type int $height Image height.
915 * @type string $mime-type The mime type of the image.
916 * @type int $filesize File size of the image.
917 * }
918 */
919 protected function _save( $image, $filename = null, $mime_type = null ) {
920 list( $filename, $extension, $mime_type ) = $this->get_output_format( $filename, $mime_type );
921
922 if ( ! $filename ) {
923 $filename = $this->generate_filename( null, null, $extension );
924 }
925
926 try {
927 // Store initial format.
928 $orig_format = $this->image->getImageFormat();
929
930 $this->image->setImageFormat( strtoupper( $this->get_extension( $mime_type ) ) );
931 } catch ( Exception $e ) {
932 return new WP_Error( 'image_save_error', $e->getMessage(), $filename );
933 }
934
935 if ( method_exists( $this->image, 'setInterlaceScheme' )
936 && method_exists( $this->image, 'getInterlaceScheme' )
937 && defined( 'Imagick::INTERLACE_PLANE' )
938 ) {
939 $orig_interlace = $this->image->getInterlaceScheme();
940
941 /** This filter is documented in wp-includes/class-wp-image-editor-gd.php */
942 if ( apply_filters( 'image_save_progressive', false, $mime_type ) ) {
943 $this->image->setInterlaceScheme( Imagick::INTERLACE_PLANE ); // True - line interlace output.
944 } else {
945 $this->image->setInterlaceScheme( Imagick::INTERLACE_NO ); // False - no interlace output.
946 }
947 }
948
949 $write_image_result = $this->write_image( $this->image, $filename );
950 if ( is_wp_error( $write_image_result ) ) {
951 return $write_image_result;
952 }
953
954 try {
955 // Reset original format.
956 $this->image->setImageFormat( $orig_format );
957
958 if ( isset( $orig_interlace ) ) {
959 $this->image->setInterlaceScheme( $orig_interlace );
960 }
961 } catch ( Exception $e ) {
962 return new WP_Error( 'image_save_error', $e->getMessage(), $filename );
963 }
964
965 // Set correct file permissions.
966 $stat = stat( dirname( $filename ) );
967 $perms = $stat['mode'] & 0000666; // Same permissions as parent folder, strip off the executable bits.
968 chmod( $filename, $perms );
969
970 return array(
971 'path' => $filename,
972 /** This filter is documented in wp-includes/class-wp-image-editor-gd.php */
973 'file' => wp_basename( apply_filters( 'image_make_intermediate_size', $filename ) ),
974 'width' => $this->size['width'],
975 'height' => $this->size['height'],
976 'mime-type' => $mime_type,
977 'filesize' => wp_filesize( $filename ),
978 );
979 }
980
981 /**
982 * Writes an image to a file or stream.
983 *
984 * @since 5.6.0
985 *
986 * @param Imagick $image
987 * @param string $filename The destination filename or stream URL.
988 * @return true|WP_Error
989 */
990 private function write_image( $image, $filename ) {
991 if ( wp_is_stream( $filename ) ) {
992 /*
993 * Due to reports of issues with streams with `Imagick::writeImageFile()` and `Imagick::writeImage()`, copies the blob instead.
994 * Checks for exact type due to: https://www.php.net/manual/en/function.file-put-contents.php
995 */
996 if ( file_put_contents( $filename, $image->getImageBlob() ) === false ) {
997 return new WP_Error(
998 'image_save_error',
999 sprintf(
1000 /* translators: %s: PHP function name. */
1001 __( '%s failed while writing image to stream.' ),
1002 '<code>file_put_contents()</code>'
1003 ),
1004 $filename
1005 );
1006 } else {
1007 return true;
1008 }
1009 } else {
1010 $dirname = dirname( $filename );
1011
1012 if ( ! wp_mkdir_p( $dirname ) ) {
1013 return new WP_Error(
1014 'image_save_error',
1015 sprintf(
1016 /* translators: %s: Directory path. */
1017 __( 'Unable to create directory %s. Is its parent directory writable by the server?' ),
1018 esc_html( $dirname )
1019 )
1020 );
1021 }
1022
1023 try {
1024 return $image->writeImage( $filename );
1025 } catch ( Exception $e ) {
1026 return new WP_Error( 'image_save_error', $e->getMessage(), $filename );
1027 }
1028 }
1029 }
1030
1031 /**
1032 * Streams current image to browser.
1033 *
1034 * @since 3.5.0
1035 *
1036 * @param string $mime_type The mime type of the image.
1037 * @return true|WP_Error True on success, WP_Error object on failure.
1038 */
1039 public function stream( $mime_type = null ) {
1040 list( $filename, $extension, $mime_type ) = $this->get_output_format( null, $mime_type );
1041
1042 try {
1043 // Temporarily change format for stream.
1044 $this->image->setImageFormat( strtoupper( $extension ) );
1045
1046 // Output stream of image content.
1047 header( "Content-Type: $mime_type" );
1048 print $this->image->getImageBlob();
1049
1050 // Reset image to original format.
1051 $this->image->setImageFormat( $this->get_extension( $this->mime_type ) );
1052 } catch ( Exception $e ) {
1053 return new WP_Error( 'image_stream_error', $e->getMessage() );
1054 }
1055
1056 return true;
1057 }
1058
1059 /**
1060 * Strips all image meta except color profiles from an image.
1061 *
1062 * @since 4.5.0
1063 *
1064 * @return true|WP_Error True if stripping metadata was successful. WP_Error object on error.
1065 */
1066 protected function strip_meta() {
1067
1068 if ( ! is_callable( array( $this->image, 'getImageProfiles' ) ) ) {
1069 return new WP_Error(
1070 'image_strip_meta_error',
1071 sprintf(
1072 /* translators: %s: ImageMagick method name. */
1073 __( '%s is required to strip image meta.' ),
1074 '<code>Imagick::getImageProfiles()</code>'
1075 )
1076 );
1077 }
1078
1079 if ( ! is_callable( array( $this->image, 'removeImageProfile' ) ) ) {
1080 return new WP_Error(
1081 'image_strip_meta_error',
1082 sprintf(
1083 /* translators: %s: ImageMagick method name. */
1084 __( '%s is required to strip image meta.' ),
1085 '<code>Imagick::removeImageProfile()</code>'
1086 )
1087 );
1088 }
1089
1090 /*
1091 * Protect a few profiles from being stripped for the following reasons:
1092 *
1093 * - icc: Color profile information
1094 * - icm: Color profile information
1095 * - iptc: Copyright data
1096 * - exif: Orientation data
1097 * - xmp: Rights usage data
1098 */
1099 $protected_profiles = array(
1100 'icc',
1101 'icm',
1102 'iptc',
1103 'exif',
1104 'xmp',
1105 );
1106
1107 try {
1108 // Strip profiles.
1109 foreach ( $this->image->getImageProfiles( '*', true ) as $key => $value ) {
1110 if ( ! in_array( $key, $protected_profiles, true ) ) {
1111 $this->image->removeImageProfile( $key );
1112 }
1113 }
1114 } catch ( Exception $e ) {
1115 return new WP_Error( 'image_strip_meta_error', $e->getMessage() );
1116 }
1117
1118 return true;
1119 }
1120
1121 /**
1122 * Sets up Imagick for PDF processing.
1123 * Increases rendering DPI and only loads first page.
1124 *
1125 * @since 4.7.0
1126 *
1127 * @return string|WP_Error File to load or WP_Error on failure.
1128 */
1129 protected function pdf_setup() {
1130 try {
1131 /*
1132 * By default, PDFs are rendered in a very low resolution.
1133 * We want the thumbnail to be readable, so increase the rendering DPI.
1134 */
1135 $this->image->setResolution( 128, 128 );
1136
1137 // Only load the first page.
1138 return $this->file . '[0]';
1139 } catch ( Exception $e ) {
1140 return new WP_Error( 'pdf_setup_failed', $e->getMessage(), $this->file );
1141 }
1142 }
1143
1144 /**
1145 * Load the image produced by Ghostscript.
1146 *
1147 * Includes a workaround for a bug in Ghostscript 8.70 that prevents processing of some PDF files
1148 * when `use-cropbox` is set.
1149 *
1150 * @since 5.6.0
1151 *
1152 * @return true|WP_Error
1153 */
1154 protected function pdf_load_source() {
1155 $filename = $this->pdf_setup();
1156
1157 if ( is_wp_error( $filename ) ) {
1158 return $filename;
1159 }
1160
1161 try {
1162 /*
1163 * When generating thumbnails from cropped PDF pages, Imagemagick uses the uncropped
1164 * area (resulting in unnecessary whitespace) unless the following option is set.
1165 */
1166 $this->image->setOption( 'pdf:use-cropbox', true );
1167
1168 /*
1169 * Reading image after Imagick instantiation because `setResolution`
1170 * only applies correctly before the image is read.
1171 */
1172 $this->image->readImage( $filename );
1173 } catch ( Exception $e ) {
1174 // Attempt to run `gs` without the `use-cropbox` option. See #48853.
1175 $this->image->setOption( 'pdf:use-cropbox', false );
1176
1177 $this->image->readImage( $filename );
1178 }
1179
1180 return true;
1181 }
1182}
1183
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1