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
← All changes | _inc/lib/tonesque.php +284 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,284 @@
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 = (int) round( $height / 3 );
165 + $bottomy = (int) round( ( $height / 3 ) * 2 );
166 + $leftx = (int) round( $width / 3 );
167 + $rightx = (int) round( ( $width / 3 ) * 2 );
168 + $centery = (int) round( $height / 2 );
169 + $centerx = (int) 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 +}