Ver código fonte

1st version, working for my project, will add more specification later

master
Shikiryu 8 anos atrás
commit
31a3a2e277
4 arquivos alterados com 325 adições e 0 exclusões
  1. 12
    0
      basic.svg
  2. 29
    0
      log.php
  3. 262
    0
      svgtoimage.php
  4. 22
    0
      test.php

+ 12
- 0
basic.svg Ver arquivo

@@ -0,0 +1,12 @@
1
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="512">
2
+<desc>Created with Raphael</desc>
3
+<defs></defs>
4
+<image x="0" y="0" width="300" height="512" preserveAspectRatio="none" href="http://labs.shikiryu.com/experimental-cut/images/pieces/fond.jpg"></image>
5
+<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>
6
+<circle cx="50" cy="50" r="50" fill="none" stroke="#00AAFF"></circle>
7
+<image x="358" y="10" width="39" height="138" preserveAspectRatio="none" href="http://labs.shikiryu.com/experimental-cut/images/pieces/2.png" style="cursor: move; "></image>
8
+<image x="397" y="10" width="99" height="153" preserveAspectRatio="none" href="http://labs.shikiryu.com/experimental-cut/images/pieces/3.png" style="cursor: move; "></image>
9
+<image x="184" y="286" width="10" height="10" preserveAspectRatio="none" href="http://labs.shikiryu.com/experimental-cut/images/pieces/flecheGauche.png" style="cursor: pointer; opacity: 1; display: none; " opacity="1"></image>
10
+<image x="204" y="286" width="10" height="10" preserveAspectRatio="none" href="http://labs.shikiryu.com/experimental-cut/images/pieces/flecheDroite.png" style="cursor: pointer; opacity: 1; display: none; " opacity="1"></image>
11
+<image x="170" y="277" width="48" height="66" preserveAspectRatio="none" href="http://labs.shikiryu.com/experimental-cut/images/pieces/1.png" style="cursor: move; opacity: 1; " r="50" opacity="1" transform="rotate(21.91207728 194 310)"></image>
12
+</svg>

+ 29
- 0
log.php Ver arquivo

@@ -0,0 +1,29 @@
1
+<?
2
+class Log {
3
+
4
+	protected $logfile;
5
+	
6
+    function __construct($filename) {
7
+		$file 			= $filename;
8
+		$this->logfile 	= fopen($file, 'a+');
9
+		$this->message('Starting log');
10
+    }
11
+
12
+    function message($message) {
13
+		$message 		= '['. date("Y-m-d / H:i:s") . '] @MESSAGE'.' - '.$message;
14
+        $message 		.= "\n";
15
+        return fwrite( $this->logfile, $message );
16
+    }
17
+	
18
+	function error($message) {
19
+		$message 		= '['. date("Y-m-d / H:i:s") . '] @ERROR'.' - '.$message;
20
+        $message 		.= "\n";
21
+        return fwrite( $this->logfile, $message );
22
+    }
23
+	
24
+	function __destruct(){
25
+		$this->message("Finishing log\n-----------------------");
26
+		return fclose( $this->logfile );
27
+	}
28
+}
29
+

+ 262
- 0
svgtoimage.php Ver arquivo

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

+ 22
- 0
test.php Ver arquivo

@@ -0,0 +1,22 @@
1
+<? 
2
+include 'svgtoimage.php';
3
+/*
4
+<image x="184" y="286" width="10" height="10" preserveAspectRatio="none" href="imageurl4.png" style="cursor: pointer; opacity: 1; display: none; " opacity="1"></image>
5
+<image x="204" y="286" width="10" height="10" preserveAspectRatio="none" href="imageurl5.png" style="cursor: pointer; opacity: 1; display: none; " opacity="1"></image>
6
+*/
7
+$svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="512">
8
+<desc>Created with Raphael</desc>
9
+<defs></defs>
10
+<image x="0" y="0" width="300" height="512" preserveAspectRatio="none" href="http://labs.shikiryu.com/experimental-cut/images/pieces/fond.jpg"></image>
11
+<rect x="168" y="275" width="52" height="70" r="0" rx="0" ry="0" fill="none" stroke="#FFF" stroke-dasharray="8,3" transform="rotate(21.91207728 194 310)" style="opacity: 1; display: none; " opacity="1"></rect>
12
+<circle cx="50" cy="50" r="50" fill="#FFFFFF" stroke="#000"></circle>
13
+<image x="170" y="277" width="48" height="66" preserveAspectRatio="none" href="http://labs.shikiryu.com/experimental-cut/images/pieces/1.png" style="cursor: move; opacity: 1; " r="90" opacity="1" transform="rotate(21.91207728 194 310)"></image>
14
+</svg>';
15
+
16
+//$svgtoimage = new SVGTOIMAGE($svg);
17
+$svgtoimage = SVGTOIMAGE::load('basic.svg');
18
+$svgtoimage->setShowDesc();
19
+$svgtoimage->setWidth(300);
20
+$svgtoimage->setHeight(512);
21
+header('Content-type: image/png');
22
+echo $svgtoimage->toImage();

Carregando…
Cancelar
Salvar