PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
jetpack / jetpack_vendor / automattic / jetpack-classic-theme-helper / _inc / lib / tonesque.php

tonesque.php in Jetpack – WP Security, Backup, Speed, & Growth 16.3, at jetpack_vendor/automattic/jetpack-classic-theme-helper/_inc/lib/tonesque.php

281 lines 6.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 /**
3 * Tonesque
4 * Grab an average color representation from an image.
5 *
6 * @author Automattic
7 * @author Matias Ventura
8 * @package automattic/jetpack
9 */
10
11 if ( ! class_exists( 'Tonesque' ) ) {
12 /**
13 * Color representation class.
14 */
15 class Tonesque {
16 /**
17 * Image URL.
18 *
19 * @var string
20 */
21 private $image_url = '';
22 /**
23 * Image identifier representing the image.
24 *
25 * @var null|object
26 */
27 private $image_obj = null;
28 /**
29 * Color code.
30 *
31 * @var string
32 */
33 private $color = '';
34
35 /**
36 * Constructor.
37 *
38 * @param string $image_url Image URL.
39 */
40 public function __construct( $image_url ) {
41 if ( ! class_exists( 'Jetpack_Color' ) ) {
42 require_once __DIR__ . '/class.color.php';
43 }
44
45 $this->image_url = esc_url_raw( $image_url );
46 $this->image_url = trim( $this->image_url );
47 /**
48 * Allows any image URL to be passed in for $this->image_url.
49 *
50 * @module theme-tools
51 *
52 * @since 2.5.0
53 *
54 * @param string $image_url The URL to any image
55 */
56 $this->image_url = apply_filters( 'tonesque_image_url', $this->image_url );
57
58 $this->image_obj = self::imagecreatefromurl( $this->image_url );
59 }
60
61 /**
62 * Get an image object from a URL.
63 *
64 * @param string $image_url Image URL.
65 *
66 * @return object|bool Image object or false if the image could not be loaded.
67 */
68 public static function imagecreatefromurl( $image_url ) {
69 $data = null;
70
71 // If it's a URL.
72 if ( preg_match( '#^https?://#i', $image_url ) ) {
73 // If it's a url pointing to a local media library url.
74 $content_url = content_url();
75 $_image_url = set_url_scheme( $image_url );
76 if ( str_starts_with( $_image_url, $content_url ) ) {
77 $_image_path = str_replace( $content_url, WP_CONTENT_DIR, $_image_url );
78 if ( file_exists( $_image_path ) ) {
79 $filetype = wp_check_filetype( $_image_path );
80 $type = $filetype['type'];
81
82 if ( str_starts_with( $type, 'image/' ) ) {
83 $data = file_get_contents( $_image_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
84 }
85 }
86 }
87
88 if ( empty( $data ) ) {
89 $response = wp_safe_remote_get( $image_url );
90 $response_code = wp_remote_retrieve_response_code( $response );
91 if (
92 is_wp_error( $response )
93 || ! $response_code
94 || $response_code < 200
95 || $response_code >= 300
96 ) {
97 return false;
98 }
99 $data = wp_remote_retrieve_body( $response );
100 }
101 }
102
103 // If it's a local path in our WordPress install.
104 if ( file_exists( $image_url ) ) {
105 $filetype = wp_check_filetype( $image_url );
106 $type = $filetype['type'];
107
108 if ( str_starts_with( $type, 'image/' ) ) {
109 $data = file_get_contents( $image_url ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
110 }
111 }
112
113 if ( null === $data ) {
114 return false;
115 }
116
117 // Now turn it into an image and return it.
118 return imagecreatefromstring( $data );
119 }
120
121 /**
122 * Construct object from image.
123 *
124 * @param string $type Type (hex, rgb, hsv) (optional).
125 *
126 * @return string|bool color as a string formatted as $type or false if the image could not be loaded.
127 */
128 public function color( $type = 'hex' ) {
129 // Bail if there is no image to work with.
130 if ( ! $this->image_obj ) {
131 return false;
132 }
133
134 // Finds dominant color.
135 $color = self::grab_color();
136 // Passes value to Color class.
137 return self::get_color( $color, $type );
138 }
139
140 /**
141 * Grabs the color index for each of five sample points of the image
142 *
143 * @param string $type can be 'index' or 'hex'.
144 *
145 * @return array|false color indices or false if the image could not be loaded.
146 */
147 public function grab_points( $type = 'index' ) {
148 $img = $this->image_obj;
149 if ( ! $img ) {
150 return false;
151 }
152
153 $height = imagesy( $img );
154 $width = imagesx( $img );
155
156 /*
157 * Sample five points in the image
158 * based on rule of thirds and center.
159 */
160 $topy = (int) round( $height / 3 );
161 $bottomy = (int) round( ( $height / 3 ) * 2 );
162 $leftx = (int) round( $width / 3 );
163 $rightx = (int) round( ( $width / 3 ) * 2 );
164 $centery = (int) round( $height / 2 );
165 $centerx = (int) round( $width / 2 );
166
167 // Cast those colors into an array.
168 $points = array(
169 imagecolorat( $img, $leftx, $topy ),
170 imagecolorat( $img, $rightx, $topy ),
171 imagecolorat( $img, $leftx, $bottomy ),
172 imagecolorat( $img, $rightx, $bottomy ),
173 imagecolorat( $img, $centerx, $centery ),
174 );
175
176 if ( 'hex' === $type ) {
177 foreach ( $points as $i => $p ) {
178 $c = imagecolorsforindex( $img, $p );
179 $points[ $i ] = self::get_color(
180 array(
181 'r' => $c['red'],
182 'g' => $c['green'],
183 'b' => $c['blue'],
184 ),
185 'hex'
186 );
187 }
188 }
189
190 return $points;
191 }
192
193 /**
194 * Finds the average color of the image based on five sample points
195 *
196 * @return array|bool array with rgb color or false if the image could not be loaded.
197 */
198 public function grab_color() {
199 $img = $this->image_obj;
200 if ( ! $img ) {
201 return false;
202 }
203
204 $rgb = self::grab_points();
205
206 $r = array();
207 $g = array();
208 $b = array();
209
210 /*
211 * Process the color points
212 * Find the average representation
213 */
214 foreach ( $rgb as $color ) {
215 $index = imagecolorsforindex( $img, $color );
216 $r[] = $index['red'];
217 $g[] = $index['green'];
218 $b[] = $index['blue'];
219 }
220 $red = round( array_sum( $r ) / 5 );
221 $green = round( array_sum( $g ) / 5 );
222 $blue = round( array_sum( $b ) / 5 );
223
224 // The average color of the image as rgb array.
225 $color = array(
226 'r' => $red,
227 'g' => $green,
228 'b' => $blue,
229 );
230
231 return $color;
232 }
233
234 /**
235 * Get a Color object using /lib class.color
236 * Convert to appropriate type
237 *
238 * @param string $color Color code.
239 * @param string $type Color type (rgb, hex, hsv).
240 *
241 * @return string
242 */
243 public function get_color( $color, $type ) {
244 $c = new Jetpack_Color( $color, 'rgb' );
245 $this->color = $c;
246
247 switch ( $type ) {
248 case 'rgb':
249 $color = implode( ',', $c->toRgbInt() );
250 break;
251 case 'hex':
252 $color = $c->toHex();
253 break;
254 case 'hsv':
255 $color = implode( ',', $c->toHsvInt() );
256 break;
257 default:
258 return $c->toHex();
259 }
260
261 return $color;
262 }
263
264 /**
265 *
266 * Checks contrast against main color
267 * Gives either black or white for using with opacity
268 *
269 * @return string|bool Returns black or white or false if the image could not be loaded.
270 */
271 public function contrast() {
272 if ( ! $this->color ) {
273 return false;
274 }
275
276 $c = $this->color->getMaxContrastColor();
277 return implode( ',', $c->toRgbInt() );
278 }
279 }
280 }
281