tonesque.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. <?php
  2. /*
  3. Plugin Name: Tonesque
  4. Plugin URI: http://automattic.com/
  5. Description: Grab an average color representation from an image.
  6. Version: 1.0
  7. Author: Automattic, Matias Ventura
  8. Author URI: http://automattic.com/
  9. License: GNU General Public License v2 or later
  10. License URI: http://www.gnu.org/licenses/gpl-2.0.html
  11. */
  12. class Tonesque {
  13. private $image_url = '';
  14. private $image_obj = NULL;
  15. private $color = '';
  16. function __construct( $image_url ) {
  17. if ( ! class_exists( 'Jetpack_Color' ) ) {
  18. jetpack_require_lib( 'class.color' );
  19. }
  20. $this->image_url = esc_url_raw( $image_url );
  21. $this->image_url = trim( $this->image_url );
  22. /**
  23. * Allows any image URL to be passed in for $this->image_url.
  24. *
  25. * @module theme-tools
  26. *
  27. * @since 2.5.0
  28. *
  29. * @param string $image_url The URL to any image
  30. */
  31. $this->image_url = apply_filters( 'tonesque_image_url', $this->image_url );
  32. $this->image_obj = self::imagecreatefromurl( $this->image_url );
  33. }
  34. public static function imagecreatefromurl( $image_url ) {
  35. $data = null;
  36. // If it's a URL:
  37. if ( preg_match( '#^https?://#i', $image_url ) ) {
  38. // If it's a url pointing to a local media library url:
  39. $content_url = content_url();
  40. $_image_url = set_url_scheme( $image_url );
  41. if ( wp_startswith( $_image_url, $content_url ) ) {
  42. $_image_path = str_replace( $content_url, WP_CONTENT_DIR, $_image_url );
  43. if ( file_exists( $_image_path ) ) {
  44. $filetype = wp_check_filetype( $_image_path );
  45. $ext = $filetype['ext'];
  46. $type = $filetype['type'];
  47. if ( wp_startswith( $type, 'image/' ) ) {
  48. $data = file_get_contents( $_image_path );
  49. }
  50. }
  51. }
  52. if ( empty( $data ) ) {
  53. $response = wp_remote_get( $image_url );
  54. if ( is_wp_error( $response ) ) {
  55. return false;
  56. }
  57. $data = wp_remote_retrieve_body( $response );
  58. }
  59. }
  60. // If it's a local path in our WordPress install:
  61. if ( file_exists( $image_url ) ) {
  62. $filetype = wp_check_filetype( $image_url );
  63. $ext = $filetype['ext'];
  64. $type = $filetype['type'];
  65. if ( wp_startswith( $type, 'image/' ) ) {
  66. $data = file_get_contents( $image_url );
  67. }
  68. }
  69. // Now turn it into an image and return it.
  70. return imagecreatefromstring( $data );
  71. }
  72. /**
  73. *
  74. * Construct object from image.
  75. *
  76. * @param optional $type (hex, rgb, hsl)
  77. * @return color as a string formatted as $type
  78. *
  79. */
  80. function color( $type = 'hex' ) {
  81. // Bail if there is no image to work with
  82. if ( ! $this->image_obj )
  83. return false;
  84. // Finds dominant color
  85. $color = self::grab_color();
  86. // Passes value to Color class
  87. $color = self::get_color( $color, $type );
  88. return $color;
  89. }
  90. /**
  91. *
  92. * Grabs the color index for each of five sample points of the image
  93. *
  94. * @param $image
  95. * @param $type can be 'index' or 'hex'
  96. * @return array() with color indices
  97. *
  98. */
  99. function grab_points( $type = 'index' ) {
  100. $img = $this->image_obj;
  101. if ( ! $img )
  102. return false;
  103. $height = imagesy( $img );
  104. $width = imagesx( $img );
  105. // Sample five points in the image
  106. // Based on rule of thirds and center
  107. $topy = round( $height / 3 );
  108. $bottomy = round( ( $height / 3 ) * 2 );
  109. $leftx = round( $width / 3 );
  110. $rightx = round( ( $width / 3 ) * 2 );
  111. $centery = round( $height / 2 );
  112. $centerx = round( $width / 2 );
  113. // Cast those colors into an array
  114. $points = array(
  115. imagecolorat( $img, $leftx, $topy ),
  116. imagecolorat( $img, $rightx, $topy ),
  117. imagecolorat( $img, $leftx, $bottomy ),
  118. imagecolorat( $img, $rightx, $bottomy ),
  119. imagecolorat( $img, $centerx, $centery ),
  120. );
  121. if ( 'hex' == $type ) {
  122. foreach ( $points as $i => $p ) {
  123. $c = imagecolorsforindex( $img, $p );
  124. $points[ $i ] = self::get_color( array(
  125. 'r' => $c['red'],
  126. 'g' => $c['green'],
  127. 'b' => $c['blue'],
  128. ), 'hex' );
  129. }
  130. }
  131. return $points;
  132. }
  133. /**
  134. *
  135. * Finds the average color of the image based on five sample points
  136. *
  137. * @param $image
  138. * @return array() with rgb color
  139. *
  140. */
  141. function grab_color() {
  142. $img = $this->image_obj;
  143. if ( ! $img )
  144. return false;
  145. $rgb = self::grab_points();
  146. // Process the color points
  147. // Find the average representation
  148. foreach ( $rgb as $color ) {
  149. $index = imagecolorsforindex( $img, $color );
  150. $r[] = $index['red'];
  151. $g[] = $index['green'];
  152. $b[] = $index['blue'];
  153. $red = round( array_sum( $r ) / 5 );
  154. $green = round( array_sum( $g ) / 5 );
  155. $blue = round( array_sum( $b ) / 5 );
  156. }
  157. // The average color of the image as rgb array
  158. $color = array(
  159. 'r' => $red,
  160. 'g' => $green,
  161. 'b' => $blue,
  162. );
  163. return $color;
  164. }
  165. /**
  166. *
  167. * Get a Color object using /lib class.color
  168. * Convert to appropriate type
  169. *
  170. * @return string
  171. *
  172. */
  173. function get_color( $color, $type ) {
  174. $c = new Jetpack_Color( $color, 'rgb' );
  175. $this->color = $c;
  176. switch ( $type ) {
  177. case 'rgb' :
  178. $color = implode( $c->toRgbInt(), ',' );
  179. break;
  180. case 'hex' :
  181. $color = $c->toHex();
  182. break;
  183. case 'hsv' :
  184. $color = implode( $c->toHsvInt(), ',' );
  185. break;
  186. default:
  187. return $color = $c->toHex();
  188. }
  189. return $color;
  190. }
  191. /**
  192. *
  193. * Checks contrast against main color
  194. * Gives either black or white for using with opacity
  195. *
  196. * @return string
  197. *
  198. */
  199. function contrast() {
  200. if ( ! $this->color )
  201. return false;
  202. $c = $this->color->getMaxContrastColor();
  203. return implode( $c->toRgbInt(), ',' );
  204. }
  205. };