PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/site/application/helpers/colors_helper.php

https://bitbucket.org/tmvg/order.tv-digital-service.de
PHP | 333 lines | 264 code | 29 blank | 40 comment | 54 complexity | 8fb21badbcb5e0151233e564abd769bf MD5 | raw file
Possible License(s): MIT, BSD-3-Clause, LGPL-2.1, MPL-2.0-no-copyleft-exception, Apache-2.0
  1. <?php
  2. /**
  3. * This class can be used to get the most common colors in an image.
  4. * It needs one parameter:
  5. * $image - the filename of the image you want to process.
  6. * Optional parameters:
  7. *
  8. * $count - how many colors should be returned. 0 mmeans all. default=20
  9. * $reduce_brightness - reduce (not eliminate) brightness variants? default=true
  10. * $reduce_gradients - reduce (not eliminate) gradient variants? default=true
  11. * $delta - the amount of gap when quantizing color values.
  12. * Lower values mean more accurate colors. default=16
  13. *
  14. * Author: Csongor Zalatnai
  15. *
  16. * Modified By: Kepler Gelotte - Added the gradient and brightness variation
  17. * reduction routines. Kudos to Csongor for an excellent class. The original
  18. * version can be found at:
  19. *
  20. * http://www.phpclasses.org/browse/package/3370.html
  21. *
  22. */
  23. class colors_helper{
  24. var $PREVIEW_WIDTH = 150;
  25. var $PREVIEW_HEIGHT = 150;
  26. var $error;
  27. /**
  28. * Returns the colors of the image in an array, ordered in descending order, where the keys are the colors, and the values are the count of the color.
  29. *
  30. * @return array
  31. */
  32. function Get_Color( $img, $count=20, $reduce_brightness=true, $reduce_gradients=true, $delta=16 )
  33. {
  34. if (is_readable( $img ))
  35. {
  36. if ( $delta > 2 )
  37. {
  38. $half_delta = $delta / 2 - 1;
  39. }
  40. else
  41. {
  42. $half_delta = 0;
  43. }
  44. // WE HAVE TO RESIZE THE IMAGE, BECAUSE WE ONLY NEED THE MOST SIGNIFICANT COLORS.
  45. $size = GetImageSize($img);
  46. $scale = 1;
  47. if ($size[0]>0)
  48. $scale = min($this->PREVIEW_WIDTH/$size[0], $this->PREVIEW_HEIGHT/$size[1]);
  49. if ($scale < 1)
  50. {
  51. $width = floor($scale*$size[0]);
  52. $height = floor($scale*$size[1]);
  53. }
  54. else
  55. {
  56. $width = $size[0];
  57. $height = $size[1];
  58. }
  59. $image_resized = imagecreatetruecolor($width, $height);
  60. if ($size[2] == 1)
  61. $image_orig = imagecreatefromgif($img);
  62. if ($size[2] == 2)
  63. $image_orig = imagecreatefromjpeg($img);
  64. if ($size[2] == 3)
  65. $image_orig = imagecreatefrompng($img);
  66. // WE NEED NEAREST NEIGHBOR RESIZING, BECAUSE IT DOESN'T ALTER THE COLORS
  67. imagecopyresampled($image_resized, $image_orig, 0, 0, 0, 0, $width, $height, $size[0], $size[1]);
  68. $im = $image_resized;
  69. $imgWidth = imagesx($im);
  70. $imgHeight = imagesy($im);
  71. $total_pixel_count = 0;
  72. for ($y=0; $y < $imgHeight; $y++)
  73. {
  74. for ($x=0; $x < $imgWidth; $x++)
  75. {
  76. $total_pixel_count++;
  77. $index = imagecolorat($im,$x,$y);
  78. $colors = imagecolorsforindex($im,$index);
  79. // ROUND THE COLORS, TO REDUCE THE NUMBER OF DUPLICATE COLORS
  80. if ( $delta > 1 )
  81. {
  82. $colors['red'] = intval((($colors['red'])+$half_delta)/$delta)*$delta;
  83. $colors['green'] = intval((($colors['green'])+$half_delta)/$delta)*$delta;
  84. $colors['blue'] = intval((($colors['blue'])+$half_delta)/$delta)*$delta;
  85. if ($colors['red'] >= 256)
  86. {
  87. $colors['red'] = 255;
  88. }
  89. if ($colors['green'] >= 256)
  90. {
  91. $colors['green'] = 255;
  92. }
  93. if ($colors['blue'] >= 256)
  94. {
  95. $colors['blue'] = 255;
  96. }
  97. }
  98. $hex = substr("0".dechex($colors['red']),-2).substr("0".dechex($colors['green']),-2).substr("0".dechex($colors['blue']),-2);
  99. if ( ! isset( $hexarray[$hex] ) )
  100. {
  101. $hexarray[$hex] = 1;
  102. }
  103. else
  104. {
  105. $hexarray[$hex]++;
  106. }
  107. }
  108. }
  109. // Reduce gradient colors
  110. if ( $reduce_gradients )
  111. {
  112. // if you want to *eliminate* gradient variations use:
  113. // ksort( $hexarray );
  114. arsort( $hexarray, SORT_NUMERIC );
  115. $gradients = array();
  116. foreach ($hexarray as $hex => $num)
  117. {
  118. if ( ! isset($gradients[$hex]) )
  119. {
  120. $new_hex = $this->_find_adjacent( $hex, $gradients, $delta );
  121. $gradients[$hex] = $new_hex;
  122. }
  123. else
  124. {
  125. $new_hex = $gradients[$hex];
  126. }
  127. if ($hex != $new_hex)
  128. {
  129. $hexarray[$hex] = 0;
  130. $hexarray[$new_hex] += $num;
  131. }
  132. }
  133. }
  134. // Reduce brightness variations
  135. if ( $reduce_brightness )
  136. {
  137. // if you want to *eliminate* brightness variations use:
  138. // ksort( $hexarray );
  139. arsort( $hexarray, SORT_NUMERIC );
  140. $brightness = array();
  141. foreach ($hexarray as $hex => $num)
  142. {
  143. if ( ! isset($brightness[$hex]) )
  144. {
  145. $new_hex = $this->_normalize( $hex, $brightness, $delta );
  146. $brightness[$hex] = $new_hex;
  147. }
  148. else
  149. {
  150. $new_hex = $brightness[$hex];
  151. }
  152. if ($hex != $new_hex)
  153. {
  154. $hexarray[$hex] = 0;
  155. $hexarray[$new_hex] += $num;
  156. }
  157. }
  158. }
  159. arsort( $hexarray, SORT_NUMERIC );
  160. // convert counts to percentages
  161. foreach ($hexarray as $key => $value)
  162. {
  163. $hexarray[$key] = (float)$value / $total_pixel_count;
  164. }
  165. if ( $count > 0 )
  166. {
  167. // only works in PHP5
  168. // return array_slice( $hexarray, 0, $count, true );
  169. $arr = array();
  170. foreach ($hexarray as $key => $value)
  171. {
  172. if ($count == 0)
  173. {
  174. break;
  175. }
  176. $count--;
  177. $arr[$key] = $value;
  178. }
  179. return $arr;
  180. }
  181. else
  182. {
  183. return $hexarray;
  184. }
  185. }
  186. else
  187. {
  188. $this->error = "Image ".$img." does not exist or is unreadable";
  189. return false;
  190. }
  191. }
  192. function _normalize( $hex, $hexarray, $delta )
  193. {
  194. $lowest = 255;
  195. $highest = 0;
  196. $colors['red'] = hexdec( substr( $hex, 0, 2 ) );
  197. $colors['green'] = hexdec( substr( $hex, 2, 2 ) );
  198. $colors['blue'] = hexdec( substr( $hex, 4, 2 ) );
  199. if ($colors['red'] < $lowest)
  200. {
  201. $lowest = $colors['red'];
  202. }
  203. if ($colors['green'] < $lowest )
  204. {
  205. $lowest = $colors['green'];
  206. }
  207. if ($colors['blue'] < $lowest )
  208. {
  209. $lowest = $colors['blue'];
  210. }
  211. if ($colors['red'] > $highest)
  212. {
  213. $highest = $colors['red'];
  214. }
  215. if ($colors['green'] > $highest )
  216. {
  217. $highest = $colors['green'];
  218. }
  219. if ($colors['blue'] > $highest )
  220. {
  221. $highest = $colors['blue'];
  222. }
  223. // Do not normalize white, black, or shades of grey unless low delta
  224. if ( $lowest == $highest )
  225. {
  226. if ($delta <= 32)
  227. {
  228. if ( $lowest == 0 || $highest >= (255 - $delta) )
  229. {
  230. return $hex;
  231. }
  232. }
  233. else
  234. {
  235. return $hex;
  236. }
  237. }
  238. for (; $highest < 256; $lowest += $delta, $highest += $delta)
  239. {
  240. $new_hex = substr("0".dechex($colors['red'] - $lowest),-2).substr("0".dechex($colors['green'] - $lowest),-2).substr("0".dechex($colors['blue'] - $lowest),-2);
  241. if ( isset( $hexarray[$new_hex] ) )
  242. {
  243. // same color, different brightness - use it instead
  244. return $new_hex;
  245. }
  246. }
  247. return $hex;
  248. }
  249. function _find_adjacent( $hex, $gradients, $delta )
  250. {
  251. $red = hexdec( substr( $hex, 0, 2 ) );
  252. $green = hexdec( substr( $hex, 2, 2 ) );
  253. $blue = hexdec( substr( $hex, 4, 2 ) );
  254. if ($red > $delta)
  255. {
  256. $new_hex = substr("0".dechex($red - $delta),-2).substr("0".dechex($green),-2).substr("0".dechex($blue),-2);
  257. if ( isset($gradients[$new_hex]) )
  258. {
  259. return $gradients[$new_hex];
  260. }
  261. }
  262. if ($green > $delta)
  263. {
  264. $new_hex = substr("0".dechex($red),-2).substr("0".dechex($green - $delta),-2).substr("0".dechex($blue),-2);
  265. if ( isset($gradients[$new_hex]) )
  266. {
  267. return $gradients[$new_hex];
  268. }
  269. }
  270. if ($blue > $delta)
  271. {
  272. $new_hex = substr("0".dechex($red),-2).substr("0".dechex($green),-2).substr("0".dechex($blue - $delta),-2);
  273. if ( isset($gradients[$new_hex]) )
  274. {
  275. return $gradients[$new_hex];
  276. }
  277. }
  278. if ($red < (255 - $delta))
  279. {
  280. $new_hex = substr("0".dechex($red + $delta),-2).substr("0".dechex($green),-2).substr("0".dechex($blue),-2);
  281. if ( isset($gradients[$new_hex]) )
  282. {
  283. return $gradients[$new_hex];
  284. }
  285. }
  286. if ($green < (255 - $delta))
  287. {
  288. $new_hex = substr("0".dechex($red),-2).substr("0".dechex($green + $delta),-2).substr("0".dechex($blue),-2);
  289. if ( isset($gradients[$new_hex]) )
  290. {
  291. return $gradients[$new_hex];
  292. }
  293. }
  294. if ($blue < (255 - $delta))
  295. {
  296. $new_hex = substr("0".dechex($red),-2).substr("0".dechex($green),-2).substr("0".dechex($blue + $delta),-2);
  297. if ( isset($gradients[$new_hex]) )
  298. {
  299. return $gradients[$new_hex];
  300. }
  301. }
  302. return $hex;
  303. }
  304. }