oont-contents/plugins/jetpack/_inc/lib/tonesque.php
2025-02-08 15:10:23 +01:00

284 lines
6.9 KiB
PHP

<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
/**
* Tonesque
* Grab an average color representation from an image.
*
* @author Automattic
* @author Matias Ventura
* @package automattic/jetpack
*/
if ( ! class_exists( 'Tonesque' ) ) {
/**
* Color representation class.
*/
class Tonesque {
/**
* Image URL.
*
* @var string
*/
private $image_url = '';
/**
* Image identifier representing the image.
*
* @var null|object
*/
private $image_obj = null;
/**
* Color code.
*
* @var string
*/
private $color = '';
/**
* Constructor.
*
* @param string $image_url Image URL.
*/
public function __construct( $image_url ) {
_deprecated_function( 'Tonesque::__construct', 'jetpack-13.8' );
if ( ! class_exists( 'Jetpack_Color' ) ) {
require_once JETPACK__PLUGIN_DIR . '/_inc/lib/class.color.php';
}
$this->image_url = esc_url_raw( $image_url );
$this->image_url = trim( $this->image_url );
/**
* Allows any image URL to be passed in for $this->image_url.
*
* @module theme-tools
*
* @since 2.5.0
*
* @param string $image_url The URL to any image
*/
$this->image_url = apply_filters( 'tonesque_image_url', $this->image_url );
$this->image_obj = self::imagecreatefromurl( $this->image_url );
}
/**
* Get an image object from a URL.
*
* @param string $image_url Image URL.
*
* @return object|bool Image object or false if the image could not be loaded.
*/
public static function imagecreatefromurl( $image_url ) {
_deprecated_function( 'Tonesque::imagecreatefromurl', 'jetpack-13.8' );
$data = null;
// If it's a URL.
if ( preg_match( '#^https?://#i', $image_url ) ) {
// If it's a url pointing to a local media library url.
$content_url = content_url();
$_image_url = set_url_scheme( $image_url );
if ( str_starts_with( $_image_url, $content_url ) ) {
$_image_path = str_replace( $content_url, WP_CONTENT_DIR, $_image_url );
if ( file_exists( $_image_path ) ) {
$filetype = wp_check_filetype( $_image_path );
$type = $filetype['type'];
if ( str_starts_with( $type, 'image/' ) ) {
$data = file_get_contents( $_image_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
}
}
}
if ( empty( $data ) ) {
$response = wp_safe_remote_get( $image_url );
$response_code = wp_remote_retrieve_response_code( $response );
if (
is_wp_error( $response )
|| ! $response_code
|| $response_code < 200
|| $response_code >= 300
) {
return false;
}
$data = wp_remote_retrieve_body( $response );
}
}
// If it's a local path in our WordPress install.
if ( file_exists( $image_url ) ) {
$filetype = wp_check_filetype( $image_url );
$type = $filetype['type'];
if ( str_starts_with( $type, 'image/' ) ) {
$data = file_get_contents( $image_url ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
}
}
if ( null === $data ) {
return false;
}
// Now turn it into an image and return it.
return imagecreatefromstring( $data );
}
/**
* Construct object from image.
*
* @param string $type Type (hex, rgb, hsv) (optional).
*
* @return string|bool color as a string formatted as $type or false if the image could not be loaded.
*/
public function color( $type = 'hex' ) {
// Bail if there is no image to work with.
if ( ! $this->image_obj ) {
return false;
}
// Finds dominant color.
$color = self::grab_color();
// Passes value to Color class.
return self::get_color( $color, $type );
}
/**
* Grabs the color index for each of five sample points of the image
*
* @param string $type can be 'index' or 'hex'.
*
* @return array|false color indices or false if the image could not be loaded.
*/
public function grab_points( $type = 'index' ) {
$img = $this->image_obj;
if ( ! $img ) {
return false;
}
$height = imagesy( $img );
$width = imagesx( $img );
/*
* Sample five points in the image
* based on rule of thirds and center.
*/
$topy = round( $height / 3 );
$bottomy = round( ( $height / 3 ) * 2 );
$leftx = round( $width / 3 );
$rightx = round( ( $width / 3 ) * 2 );
$centery = round( $height / 2 );
$centerx = round( $width / 2 );
// Cast those colors into an array.
$points = array(
imagecolorat( $img, $leftx, $topy ),
imagecolorat( $img, $rightx, $topy ),
imagecolorat( $img, $leftx, $bottomy ),
imagecolorat( $img, $rightx, $bottomy ),
imagecolorat( $img, $centerx, $centery ),
);
if ( 'hex' === $type ) {
foreach ( $points as $i => $p ) {
$c = imagecolorsforindex( $img, $p );
$points[ $i ] = self::get_color(
array(
'r' => $c['red'],
'g' => $c['green'],
'b' => $c['blue'],
),
'hex'
);
}
}
return $points;
}
/**
* Finds the average color of the image based on five sample points
*
* @return array|bool array with rgb color or false if the image could not be loaded.
*/
public function grab_color() {
$img = $this->image_obj;
if ( ! $img ) {
return false;
}
$rgb = self::grab_points();
$r = array();
$g = array();
$b = array();
/*
* Process the color points
* Find the average representation
*/
foreach ( $rgb as $color ) {
$index = imagecolorsforindex( $img, $color );
$r[] = $index['red'];
$g[] = $index['green'];
$b[] = $index['blue'];
}
$red = round( array_sum( $r ) / 5 );
$green = round( array_sum( $g ) / 5 );
$blue = round( array_sum( $b ) / 5 );
// The average color of the image as rgb array.
$color = array(
'r' => $red,
'g' => $green,
'b' => $blue,
);
return $color;
}
/**
* Get a Color object using /lib class.color
* Convert to appropriate type
*
* @param string $color Color code.
* @param string $type Color type (rgb, hex, hsv).
*
* @return string
*/
public function get_color( $color, $type ) {
$c = new Jetpack_Color( $color, 'rgb' );
$this->color = $c;
switch ( $type ) {
case 'rgb':
$color = implode( ',', $c->toRgbInt() );
break;
case 'hex':
$color = $c->toHex();
break;
case 'hsv':
$color = implode( ',', $c->toHsvInt() );
break;
default:
return $c->toHex();
}
return $color;
}
/**
*
* Checks contrast against main color
* Gives either black or white for using with opacity
*
* @return string|bool Returns black or white or false if the image could not be loaded.
*/
public function contrast() {
if ( ! $this->color ) {
return false;
}
$c = $this->color->getMaxContrastColor();
return implode( ',', $c->toRgbInt() );
}
}
}