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