SVG to picture converter in PHP http://labs.shikiryu.com/svgtoimage/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

svgtoimage.php 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. <?
  2. include 'log.php';
  3. class SVGTOIMAGE{
  4. protected $_svg;
  5. protected $_svgXML;
  6. protected $_image;
  7. protected $_format;
  8. protected $_log;
  9. protected $_x;
  10. protected $_y;
  11. protected $_width;
  12. protected $_height;
  13. protected $_showDesc = false;
  14. private $transparentColor = array(0,0,255);
  15. public $_debug = true;
  16. public function __construct($svg, $format = 'png'){
  17. if($this->_debug) $this->_log = new Log('log.dat');
  18. $this->_svg = $svg;
  19. if($this->_debug) $this->_log->message('Ouverture du fichier contentant : '.$svg);
  20. $this->_svgXML = simplexml_load_string($this->_svg);
  21. $this->_format = $format;
  22. }
  23. public static function load($file){
  24. $svg = file_get_contents($file);
  25. return new SVGTOIMAGE($svg);
  26. }
  27. public static function parse($xml){
  28. return new SVGTOIMAGE($xml);
  29. }
  30. public function __destruct(){
  31. imagedestroy($this->_image);
  32. }
  33. public function setShowDesc($showDesc = true){
  34. if(is_bool($showDesc)){
  35. if($this->_debug) $this->_log->message('Passage de showDesc en '.$showDesc);
  36. $this->_showDesc = $showDesc;
  37. }else{
  38. if($this->_debug) $this->_log->error('Erreur dans la fonction showDesc, doit recevoir booléen, a reçu : '.$showDesc);
  39. }
  40. }
  41. public function setX($x){
  42. if(is_int($x)){
  43. if($this->_debug) $this->_log->message('Passage de x en '.$x);
  44. $this->_x = $x;
  45. }else{
  46. if($this->_debug) $this->_log->error('Erreur dans la fonction setX, doit recevoir int, a reçu : '.$x);
  47. }
  48. }
  49. public function setY($y){
  50. if(is_int($y)){
  51. if($this->_debug) $this->_log->message('Passage de y en '.$y);
  52. $this->_y = $y;
  53. }else{
  54. if($this->_debug) $this->_log->error('Erreur dans la fonction setY, doit recevoir int, a reçu : '.$y);
  55. }
  56. }
  57. public function setWidth($width){
  58. if(is_int($width)){
  59. if($this->_debug) $this->_log->message('Passage de width en '.$width);
  60. $this->_width = $width;
  61. }else{
  62. if($this->_debug) $this->_log->error('Erreur dans la fonction setWidth, doit recevoir int, a reçu : '.$width);
  63. }
  64. }
  65. public function setHeight($height){
  66. if(is_int($height)){
  67. if($this->_debug) $this->_log->message('Passage de height en '.$height);
  68. $this->_height = $height;
  69. }else{
  70. if($this->_debug) $this->_log->error('Erreur dans la fonction setHeight, doit recevoir int, a reçu : '.$height);
  71. }
  72. }
  73. /* return width and height from the SVG */
  74. private function _getImageSize(){
  75. $imageSize = array();
  76. $imageSize['width'] = $this->_svgXML->attributes()->width;
  77. $imageSize['height'] = $this->_svgXML->attributes()->height;
  78. if($this->_debug) $this->_log->message('taille de l\'image : largeur : '.$imageSize['width'].' - longueur : '.$imageSize['height']);
  79. return $imageSize;
  80. }
  81. private function _getImageWidth(){
  82. return isset($this->_width) ? $this->_width : $this->_svgXML->attributes()->width;
  83. }
  84. private function _getImageHeight(){
  85. return isset($this->_height) ? $this->_height : $this->_svgXML->attributes()->height;
  86. }
  87. private function _parseColor($colorCode){
  88. if(strlen($colorCode) == 7){
  89. if($this->_debug) $this->_log->message('Parse Color '.$colorCode);
  90. return array(
  91. base_convert(substr($colorCode, 1, 2), 16, 10),
  92. base_convert(substr($colorCode, 3, 2), 16, 10),
  93. base_convert(substr($colorCode, 5, 2), 16, 10),
  94. );
  95. }
  96. if(strlen($colorCode) == 4){
  97. if($this->_debug) $this->_log->message('Parse Color '.$colorCode);
  98. return array(
  99. base_convert(substr($colorCode, 1, 1).substr($colorCode, 1, 1), 16, 10),
  100. base_convert(substr($colorCode, 2, 1).substr($colorCode, 2, 1), 16, 10),
  101. base_convert(substr($colorCode, 3, 1).substr($colorCode, 3, 1), 16, 10),
  102. );
  103. }
  104. if($this->_debug) $this->_log->error('Couleur mal indiquée '.$colorCode);
  105. return array(0,0,0);
  106. }
  107. private function _parseImage($imageNode){
  108. $x = 0;
  109. $y = 0;
  110. $width = 0;
  111. $height = 0;
  112. $href = '';
  113. $r = 0;
  114. foreach($imageNode->attributes() as $name => $value){
  115. switch($name){
  116. case 'x': $x = $value; break;
  117. case 'y': $y = $value; break;
  118. case 'width': $width = $value; break;
  119. case 'height': $height = $value; break;
  120. case 'href':
  121. case 'xlink:href':$href = $value; break;
  122. case 'r' : $r = $value; break;
  123. case 'style' : if(strripos($value, 'display: none') || strripos($value, 'display:none')) return; break;
  124. }
  125. }
  126. if($width == 0 || $height == 0 || $href == '')
  127. return;
  128. if($this->_debug) $this->_log->message('Image - x : '.$x.' - y : '.$y.' - largeur : '.$width.' - longueur : '.$height.' - url : '.$href.' - angle : '.$r);
  129. $imageTypeArray = explode('.', $href);
  130. $lastElementFromImageType = count($imageTypeArray);
  131. $imageType = $imageTypeArray[$lastElementFromImageType-1];
  132. if($imageType == 'jpg' || $imageType == 'jpeg')
  133. $newImage = imagecreatefromjpeg($href);
  134. else if($imageType == 'png')
  135. $newImage = imagecreatefrompng($href);
  136. else if($imageType == 'gif')
  137. $newImage = imagecreatefromgif($href);
  138. else return;
  139. imagealphablending($newImage, true);
  140. //rotating the image if needed
  141. if($r != 0){
  142. if($this->_debug){
  143. if($newImage = imagerotate($newImage, - floatval($r), -1))
  144. $this->_log->message('Rotating image');
  145. else
  146. $this->_log->error('Rotating image');
  147. }else{
  148. $newImage = imagerotate($newImage, - floatval($r), -1);
  149. }
  150. $blue = imagecolorallocate($newImage, $this->transparentColor[0], $this->transparentColor[1],$this->transparentColor[2]);
  151. imagecolortransparent($newImage, $blue);
  152. }
  153. imagecopy($this->_image,$newImage,$x,$y,0,0,imagesx($newImage) , imagesy($newImage));
  154. }
  155. private function _parseCircle($circleNode){
  156. $x = 0;
  157. $y = 0;
  158. $r = 0;
  159. $fill = '';
  160. $stroke = '';
  161. foreach($circleNode->attributes() as $name => $value){
  162. switch($name){
  163. //TODO style display:none
  164. case 'cx': $x = $value; break;
  165. case 'cy': $y = $value; break;
  166. case 'r': $r = $value; break;
  167. case 'fill': $fill = ($value == 'none') ? '' : $value; break;
  168. case 'stroke': $stroke = $value; break;
  169. case 'style' : if(strripos($value, 'display: none') || strripos($value, 'display:none')) return; break;
  170. }
  171. }
  172. if($r == 0)
  173. return;
  174. $colorStroke = $this->_parseColor($stroke);
  175. $colorFill = $this->_parseColor($fill);
  176. if($this->_debug) $this->_log->message('Cercle - x : '.$x.' - y : '.$y.' - rayon : '.$r.' - fill : '.$colorFill[0].'-'.$colorFill[1].'-'.$colorFill[2].' - stroke : '.$colorStroke[0].'-'.$colorStroke[1].'-'.$colorStroke[2]);
  177. if($fill == ''){
  178. imageellipse ($this->_image , $x , $y , $r*2 , $r*2, imagecolorallocate($this->_image, $colorStroke[0], $colorStroke[1], $colorStroke[2]) );
  179. }else{
  180. imagefilledellipse($this->_image , $x , $y , $r*2 , $r*2 , imagecolorallocate($this->_image, $colorFill[0], $colorFill[1], $colorFill[2]) );
  181. }
  182. }
  183. private function _parseRectangle($rectNode){
  184. //<rect x="168" y="275" width="52" height="70" r="0" rx="0" ry="0" fill="none" stroke="#000" stroke-dasharray="8,3" transform="rotate(21.91207728 194 310)" style="opacity: 1; display: none; " opacity="1"></rect>
  185. $x = 0;
  186. $y = 0;
  187. $width = 0;
  188. $height = 0;
  189. $r = 0;
  190. $fill = '';
  191. $stroke = '';
  192. foreach($rectNode->attributes() as $name => $value){
  193. switch($name){
  194. //TODO style display:none
  195. case 'x': $x = $value; break;
  196. case 'y': $y = $value; break;
  197. case 'r': $r = $value; break;
  198. case 'width': $width = $value; break;
  199. case 'height': $height = $value; break;
  200. case 'fill': $fill = ($value == 'none') ? '' : $value; break;
  201. case 'stroke': $stroke = $value; break;
  202. case 'style' : if(strripos($value, 'display: none') || strripos($value, 'display:none')) return; break;
  203. }
  204. }
  205. if($width == 0 || $height == 0)
  206. return;
  207. $colorStroke = $this->_parseColor($stroke);
  208. $colorFill = $this->_parseColor($fill);
  209. if($this->_debug) $this->_log->message('Rectangle - x : '.$x.' - y : '.$y.' - width : '.$width.' - height : '.$height.' - fill : '.$colorFill[0].'-'.$colorFill[1].'-'.$colorFill[2].' - stroke : '.$colorStroke[0].'-'.$colorStroke[1].'-'.$colorStroke[2]);
  210. if($fill == ''){
  211. imagerectangle($this->_image , $x , $y , $x+$width , $y+$height, imagecolorallocate($this->_image, $colorStroke[0], $colorStroke[1], $colorStroke[2]) ); //resource $image , int $x1 , int $y1 , int $x2 , int $y2 , int $color
  212. }else{
  213. imagefilledrectangle ($this->_image , $x , $y , $x+$width , $y+$height, imagecolorallocate($this->_image, $colorFill[0], $colorFill[1], $colorFill[2]) );
  214. }
  215. }
  216. private function _parseDescription($desc){
  217. if($this->_debug) $this->_log->message('Ajout de la description : '.$desc);
  218. return imagestring ( $this->_image , 2, 10, $this->_getImageHeight()-20, $desc , imagecolorallocate($this->_image, 255, 255, 255));
  219. }
  220. public function toImage(){
  221. $writeDesc = null;
  222. $this->_image = imagecreatetruecolor($this->_getImageWidth(), $this->_getImageHeight());
  223. foreach($this->_svgXML->children() as $element){
  224. if($element->getName() == 'image')
  225. $this->_parseImage($element);
  226. if($element->getName() == 'circle')
  227. $this->_parseCircle($element);
  228. if($element->getName() == 'rect')
  229. $this->_parseRectangle($element);
  230. if($element->getName() == 'desc' && $this->_showDesc)
  231. $writeDesc = $element;
  232. }
  233. if($writeDesc) $this->_parseDescription($writeDesc);
  234. return imagepng($this->_image);
  235. }
  236. }