PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/PHPMapper/Map/Image.php

https://github.com/andrew-kandels/PHPMapper
PHP | 262 lines | 145 code | 30 blank | 87 comment | 23 complexity | 294feec2d1cf25b511b0bd077e6fd7b3 MD5 | raw file
  1. <?php
  2. /**
  3. * PHPMapper_Map_Image
  4. *
  5. * Model for loading the map image, shading in areas, and outputting
  6. * the result.
  7. *
  8. * @package PHPMapper
  9. * @author Andrew Kandels <me@andrewkandels.com>
  10. * @access public
  11. */
  12. class PHPMapper_Map_Image
  13. {
  14. protected $_maxWidth = null;
  15. protected $_maxHeight = null;
  16. protected $_image = null;
  17. /**
  18. * Creates a PHPMapper_Map class object.
  19. *
  20. * @param string Image file
  21. * @return void
  22. * @throws PHPMapper_Exception
  23. */
  24. public function __construct($file)
  25. {
  26. // GD is required for image processing
  27. if (!extension_loaded('gd') || !function_exists('imagecreatefrompng'))
  28. {
  29. throw new PHPMapper_Exception(
  30. 'The PHP GD extension is required.'
  31. );;
  32. }
  33. if (!$this->_image = imagecreatefrompng($file))
  34. {
  35. throw new PHPMapper_Exception_Image("Failed to load {$file}.");
  36. }
  37. list($this->_maxWidth, $this->_maxHeight) = getimagesize($file);
  38. }
  39. /**
  40. * Sets the number of areas on the map that can be shaded. Colors not
  41. * in these areas will be whited out to clean the image from shadows
  42. * and such.
  43. *
  44. * @param integer Number of shaders
  45. * @return PHPMapper_Map_Image
  46. */
  47. public function setNumAreas($num)
  48. {
  49. // White-out pixels that aren't valid areas
  50. for ($i = 0; $i < imagecolorstotal($this->_image); $i++)
  51. {
  52. $raw = imagecolorsforindex($this->_image, $i);
  53. $hex = $this->convertRgbToHex($raw['red'], $raw['green'], $raw['blue']);
  54. if (($raw['red'] != $raw['green'] || $raw['green'] != $raw['blue'] ||
  55. $raw['red'] > $num) && $hex != 'ffffff')
  56. {
  57. imagecolorset($this->_image, $i, 255, 255, 255);
  58. }
  59. }
  60. return $this;
  61. }
  62. /**
  63. * Converts a hexidecimal representation of a color (think: XHTML/CSS) into
  64. * an RGB 3-item array.
  65. *
  66. * @param string Hexidecimal color representation
  67. * @return array (R,G,B)
  68. */
  69. public function convertHexToRgb($hex)
  70. {
  71. list($r, $g, $b) = array(
  72. $hex[0] . $hex[1],
  73. $hex[2] . $hex[3],
  74. $hex[4] . $hex[5]
  75. );
  76. return array(hexdec($r), hexdec($g), hexdec($b));
  77. }
  78. /**
  79. * Converts a RGB representation of a color to a hexidecimal one.
  80. *
  81. * @param integer Red
  82. * @param integer Green
  83. * @param integer Blue
  84. * @return string Hex
  85. */
  86. public function convertRgbToHex($r, $g, $b)
  87. {
  88. $r = dechex($r<0?0:($r>255?255:$r));
  89. $g = dechex($g<0?0:($g>255?255:$g));
  90. $b = dechex($b<0?0:($b>255?255:$b));
  91. $color = (strlen($r) < 2?'0':'').$r;
  92. $color .= (strlen($g) < 2?'0':'').$g;
  93. $color .= (strlen($b) < 2?'0':'').$b;
  94. return $color;
  95. }
  96. /**
  97. * Returns the color setting with its intensity set to the item's
  98. * value.
  99. *
  100. * @param array RGB color
  101. * @param float Percentage of intensity
  102. * @return array (R,G,B)
  103. */
  104. public function getColorAlpha($color, $pct)
  105. {
  106. if ($pct > 1) $pct = 1;
  107. if ($color === null) $color = $this->_color;
  108. return array(
  109. ((1 - $pct) * 255) + ($pct * $color[0]),
  110. ((1 - $pct) * 255) + ($pct * $color[1]),
  111. ((1 - $pct) * 255) + ($pct * $color[2])
  112. );
  113. }
  114. /**
  115. * Resizes the image a new width while maintaining aspect ratio.
  116. *
  117. * @param integer Width in pixels
  118. * @return PHPMapper_Image
  119. */
  120. public function resize($width)
  121. {
  122. // Validation
  123. if ($width > $this->_maxWidth)
  124. {
  125. $width = $this->_maxWidth;
  126. }
  127. else if ($width < PHPMapper::MIN_WIDTH)
  128. {
  129. throw new PHPMapper_Exception(
  130. 'Image width should be at least ' . PHPMapper::MIN_WIDTH . ' pixels wide.'
  131. );
  132. }
  133. // Resize the image while maintaining ratio
  134. $ratio = $this->_maxHeight / $this->_maxWidth;
  135. $height = floor($width * $ratio);
  136. $out = imagecreate($width, $height);
  137. imagealphablending($out, false);
  138. imagesavealpha($out, false);
  139. imagecopyresampled($out, $this->_image, 0, 0, 0, 0, $width, $height,
  140. $this->_maxWidth, $this->_maxHeight
  141. );
  142. imagedestroy($this->_image);
  143. $this->_image = $out;
  144. return $this;
  145. }
  146. /**
  147. * Outputs a GD image object either to the browser or to a file.
  148. *
  149. * @param string File name or null for standard out
  150. * @return PHPMapper_Image
  151. * @throws PHPMapper_Exception_Image
  152. */
  153. public function draw($file = null, $compression = 4)
  154. {
  155. if (!$file)
  156. {
  157. header('Content-type: image/png');
  158. }
  159. if (!imagepng($this->_image, $file, $compression))
  160. {
  161. throw new PHPMapper_Exception_Image("Failed to create $file");
  162. }
  163. imagedestroy($this->_image);
  164. if (!$file)
  165. {
  166. die();
  167. }
  168. return $this;
  169. }
  170. /**
  171. * Takes the input value of a color in either RGB or as a hex string
  172. * and converts it to an RGB array.
  173. *
  174. * @param mixed RGB color or hex string
  175. * @return array RGB
  176. * @throws PHPMapper_Exception_BadColorValue
  177. */
  178. public function getRgbColorFromInput($color)
  179. {
  180. if (is_array($color))
  181. {
  182. if (count($color) != 3)
  183. {
  184. throw new PHPMapper_Exception_BadColorValue();
  185. }
  186. else
  187. {
  188. $color = $color;
  189. }
  190. }
  191. else
  192. {
  193. $color = $this->convertHexToRgb($color);
  194. }
  195. return $color;
  196. }
  197. /**
  198. * Shades in a areas of the map to the percentage (alpha) of
  199. * a provided color.
  200. *
  201. * @param integer ID on the map (1-255) to shade
  202. * @param mixed Color (RGB array or hex color)
  203. * @param float Alpha percentage (1 = fully visible, 0 = fully opaque)
  204. * @return PHPMapper_Image
  205. */
  206. public function setShading($id, $color, $pct = 1.0)
  207. {
  208. // Get the color assigned to the item
  209. $r = $g = $b = $id;
  210. $index = imagecolorexact($this->_image, $r, $g, $b);
  211. // Pull up to the minimum to avoid white-out
  212. if ($pct < PHPMapper::MIN_THRESHOLD)
  213. {
  214. $pct = PHPMapper::MIN_THRESHOLD;
  215. }
  216. // Detect craziness
  217. if ($pct > 1)
  218. {
  219. throw new PHPMapper_Exception_BadColorValue(
  220. "Alpha percentage should be 0 - 1, not $pct."
  221. );
  222. }
  223. // Get the color after applying the alpha
  224. list($r, $g, $b) = $this->getColorAlpha(
  225. $this->getRgbColorFromInput($color),
  226. $pct
  227. );
  228. // Replace the base color with the new alpha version
  229. imagecolorset($this->_image, $index, $r, $g, $b);
  230. return $this;
  231. }
  232. }