mirror of
https://github.com/Chouchen/svgToImage.git
synced 2020-02-03 22:08:42 +01:00
1st version, working for my project, will add more specification later
This commit is contained in:
commit
31a3a2e277
12
basic.svg
Normal file
12
basic.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="512">
|
||||
<desc>Created with Raphael</desc>
|
||||
<defs></defs>
|
||||
<image x="0" y="0" width="300" height="512" preserveAspectRatio="none" href="http://labs.shikiryu.com/experimental-cut/images/pieces/fond.jpg"></image>
|
||||
<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>
|
||||
<circle cx="50" cy="50" r="50" fill="none" stroke="#00AAFF"></circle>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
29
log.php
Normal file
29
log.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?
|
||||
class Log {
|
||||
|
||||
protected $logfile;
|
||||
|
||||
function __construct($filename) {
|
||||
$file = $filename;
|
||||
$this->logfile = fopen($file, 'a+');
|
||||
$this->message('Starting log');
|
||||
}
|
||||
|
||||
function message($message) {
|
||||
$message = '['. date("Y-m-d / H:i:s") . '] @MESSAGE'.' - '.$message;
|
||||
$message .= "\n";
|
||||
return fwrite( $this->logfile, $message );
|
||||
}
|
||||
|
||||
function error($message) {
|
||||
$message = '['. date("Y-m-d / H:i:s") . '] @ERROR'.' - '.$message;
|
||||
$message .= "\n";
|
||||
return fwrite( $this->logfile, $message );
|
||||
}
|
||||
|
||||
function __destruct(){
|
||||
$this->message("Finishing log\n-----------------------");
|
||||
return fclose( $this->logfile );
|
||||
}
|
||||
}
|
||||
|
262
svgtoimage.php
Normal file
262
svgtoimage.php
Normal file
@ -0,0 +1,262 @@
|
||||
<?
|
||||
include 'log.php';
|
||||
class SVGTOIMAGE{
|
||||
|
||||
protected $_svg;
|
||||
protected $_svgXML;
|
||||
protected $_image;
|
||||
protected $_format;
|
||||
protected $_log;
|
||||
protected $_x;
|
||||
protected $_y;
|
||||
protected $_width;
|
||||
protected $_height;
|
||||
protected $_showDesc = false;
|
||||
private $transparentColor = array(0,0,255);
|
||||
public $_debug = true;
|
||||
|
||||
public function __construct($svg, $format = 'png'){
|
||||
if($this->_debug) $this->_log = new Log('log.dat');
|
||||
$this->_svg = $svg;
|
||||
if($this->_debug) $this->_log->message('Ouverture du fichier contentant : '.$svg);
|
||||
$this->_svgXML = simplexml_load_string($this->_svg);
|
||||
$this->_format = $format;
|
||||
}
|
||||
|
||||
public static function load($file){
|
||||
$svg = file_get_contents($file);
|
||||
return new SVGTOIMAGE($svg);
|
||||
}
|
||||
|
||||
public static function parse($xml){
|
||||
return new SVGTOIMAGE($xml);
|
||||
}
|
||||
|
||||
public function __destruct(){
|
||||
imagedestroy($this->_image);
|
||||
}
|
||||
|
||||
public function setShowDesc($showDesc = true){
|
||||
if(is_bool($showDesc)){
|
||||
if($this->_debug) $this->_log->message('Passage de showDesc en '.$showDesc);
|
||||
$this->_showDesc = $showDesc;
|
||||
}else{
|
||||
if($this->_debug) $this->_log->error('Erreur dans la fonction showDesc, doit recevoir booléen, a reçu : '.$showDesc);
|
||||
}
|
||||
}
|
||||
|
||||
public function setX($x){
|
||||
if(is_int($x)){
|
||||
if($this->_debug) $this->_log->message('Passage de x en '.$x);
|
||||
$this->_x = $x;
|
||||
}else{
|
||||
if($this->_debug) $this->_log->error('Erreur dans la fonction setX, doit recevoir int, a reçu : '.$x);
|
||||
}
|
||||
}
|
||||
|
||||
public function setY($y){
|
||||
if(is_int($y)){
|
||||
if($this->_debug) $this->_log->message('Passage de y en '.$y);
|
||||
$this->_y = $y;
|
||||
}else{
|
||||
if($this->_debug) $this->_log->error('Erreur dans la fonction setY, doit recevoir int, a reçu : '.$y);
|
||||
}
|
||||
}
|
||||
|
||||
public function setWidth($width){
|
||||
if(is_int($width)){
|
||||
if($this->_debug) $this->_log->message('Passage de width en '.$width);
|
||||
$this->_width = $width;
|
||||
}else{
|
||||
if($this->_debug) $this->_log->error('Erreur dans la fonction setWidth, doit recevoir int, a reçu : '.$width);
|
||||
}
|
||||
}
|
||||
|
||||
public function setHeight($height){
|
||||
if(is_int($height)){
|
||||
if($this->_debug) $this->_log->message('Passage de height en '.$height);
|
||||
$this->_height = $height;
|
||||
}else{
|
||||
if($this->_debug) $this->_log->error('Erreur dans la fonction setHeight, doit recevoir int, a reçu : '.$height);
|
||||
}
|
||||
}
|
||||
|
||||
/* return width and height from the SVG */
|
||||
private function _getImageSize(){
|
||||
$imageSize = array();
|
||||
$imageSize['width'] = $this->_svgXML->attributes()->width;
|
||||
$imageSize['height'] = $this->_svgXML->attributes()->height;
|
||||
if($this->_debug) $this->_log->message('taille de l\'image : largeur : '.$imageSize['width'].' - longueur : '.$imageSize['height']);
|
||||
return $imageSize;
|
||||
}
|
||||
|
||||
private function _getImageWidth(){
|
||||
return isset($this->_width) ? $this->_width : $this->_svgXML->attributes()->width;
|
||||
}
|
||||
|
||||
private function _getImageHeight(){
|
||||
return isset($this->_height) ? $this->_height : $this->_svgXML->attributes()->height;
|
||||
}
|
||||
|
||||
|
||||
private function _parseColor($colorCode){
|
||||
if(strlen($colorCode) == 7){
|
||||
if($this->_debug) $this->_log->message('Parse Color '.$colorCode);
|
||||
return array(
|
||||
base_convert(substr($colorCode, 1, 2), 16, 10),
|
||||
base_convert(substr($colorCode, 3, 2), 16, 10),
|
||||
base_convert(substr($colorCode, 5, 2), 16, 10),
|
||||
);
|
||||
}
|
||||
if(strlen($colorCode) == 4){
|
||||
if($this->_debug) $this->_log->message('Parse Color '.$colorCode);
|
||||
return array(
|
||||
base_convert(substr($colorCode, 1, 1).substr($colorCode, 1, 1), 16, 10),
|
||||
base_convert(substr($colorCode, 2, 1).substr($colorCode, 2, 1), 16, 10),
|
||||
base_convert(substr($colorCode, 3, 1).substr($colorCode, 3, 1), 16, 10),
|
||||
);
|
||||
}
|
||||
if($this->_debug) $this->_log->error('Couleur mal indiquée '.$colorCode);
|
||||
return array(0,0,0);
|
||||
}
|
||||
|
||||
private function _parseImage($imageNode){
|
||||
$x = 0;
|
||||
$y = 0;
|
||||
$width = 0;
|
||||
$height = 0;
|
||||
$href = '';
|
||||
$r = 0;
|
||||
foreach($imageNode->attributes() as $name => $value){
|
||||
switch($name){
|
||||
case 'x': $x = $value; break;
|
||||
case 'y': $y = $value; break;
|
||||
case 'width': $width = $value; break;
|
||||
case 'height': $height = $value; break;
|
||||
case 'href':
|
||||
case 'xlink:href':$href = $value; break;
|
||||
case 'r' : $r = $value; break;
|
||||
case 'style' : if(strripos($value, 'display: none') || strripos($value, 'display:none')) return; break;
|
||||
}
|
||||
}
|
||||
if($width == 0 || $height == 0 || $href == '')
|
||||
return;
|
||||
if($this->_debug) $this->_log->message('Image - x : '.$x.' - y : '.$y.' - largeur : '.$width.' - longueur : '.$height.' - url : '.$href.' - angle : '.$r);
|
||||
$imageTypeArray = explode('.', $href);
|
||||
$lastElementFromImageType = count($imageTypeArray);
|
||||
$imageType = $imageTypeArray[$lastElementFromImageType-1];
|
||||
if($imageType == 'jpg' || $imageType == 'jpeg')
|
||||
$newImage = imagecreatefromjpeg($href);
|
||||
else if($imageType == 'png')
|
||||
$newImage = imagecreatefrompng($href);
|
||||
else if($imageType == 'gif')
|
||||
$newImage = imagecreatefromgif($href);
|
||||
else return;
|
||||
|
||||
imagealphablending($newImage, true);
|
||||
|
||||
//rotating the image if needed
|
||||
if($r != 0){
|
||||
if($this->_debug){
|
||||
if($newImage = imagerotate($newImage, - floatval($r), -1))
|
||||
$this->_log->message('Rotating image');
|
||||
else
|
||||
$this->_log->error('Rotating image');
|
||||
}else{
|
||||
$newImage = imagerotate($newImage, - floatval($r), -1);
|
||||
}
|
||||
$blue = imagecolorallocate($newImage, $this->transparentColor[0], $this->transparentColor[1],$this->transparentColor[2]);
|
||||
imagecolortransparent($newImage, $blue);
|
||||
}
|
||||
|
||||
imagecopy($this->_image,$newImage,$x,$y,0,0,imagesx($newImage) , imagesy($newImage));
|
||||
}
|
||||
|
||||
private function _parseCircle($circleNode){
|
||||
$x = 0;
|
||||
$y = 0;
|
||||
$r = 0;
|
||||
$fill = '';
|
||||
$stroke = '';
|
||||
foreach($circleNode->attributes() as $name => $value){
|
||||
switch($name){
|
||||
//TODO style display:none
|
||||
case 'cx': $x = $value; break;
|
||||
case 'cy': $y = $value; break;
|
||||
case 'r': $r = $value; break;
|
||||
case 'fill': $fill = ($value == 'none') ? '' : $value; break;
|
||||
case 'stroke': $stroke = $value; break;
|
||||
case 'style' : if(strripos($value, 'display: none') || strripos($value, 'display:none')) return; break;
|
||||
}
|
||||
}
|
||||
if($r == 0)
|
||||
return;
|
||||
$colorStroke = $this->_parseColor($stroke);
|
||||
$colorFill = $this->_parseColor($fill);
|
||||
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]);
|
||||
if($fill == ''){
|
||||
|
||||
imageellipse ($this->_image , $x , $y , $r*2 , $r*2, imagecolorallocate($this->_image, $colorStroke[0], $colorStroke[1], $colorStroke[2]) );
|
||||
}else{
|
||||
|
||||
imagefilledellipse($this->_image , $x , $y , $r*2 , $r*2 , imagecolorallocate($this->_image, $colorFill[0], $colorFill[1], $colorFill[2]) );
|
||||
}
|
||||
}
|
||||
|
||||
private function _parseRectangle($rectNode){
|
||||
//<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>
|
||||
$x = 0;
|
||||
$y = 0;
|
||||
$width = 0;
|
||||
$height = 0;
|
||||
$r = 0;
|
||||
$fill = '';
|
||||
$stroke = '';
|
||||
foreach($rectNode->attributes() as $name => $value){
|
||||
switch($name){
|
||||
//TODO style display:none
|
||||
case 'x': $x = $value; break;
|
||||
case 'y': $y = $value; break;
|
||||
case 'r': $r = $value; break;
|
||||
case 'width': $width = $value; break;
|
||||
case 'height': $height = $value; break;
|
||||
case 'fill': $fill = ($value == 'none') ? '' : $value; break;
|
||||
case 'stroke': $stroke = $value; break;
|
||||
case 'style' : if(strripos($value, 'display: none') || strripos($value, 'display:none')) return; break;
|
||||
}
|
||||
}
|
||||
if($width == 0 || $height == 0)
|
||||
return;
|
||||
$colorStroke = $this->_parseColor($stroke);
|
||||
$colorFill = $this->_parseColor($fill);
|
||||
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]);
|
||||
if($fill == ''){
|
||||
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
|
||||
}else{
|
||||
imagefilledrectangle ($this->_image , $x , $y , $x+$width , $y+$height, imagecolorallocate($this->_image, $colorFill[0], $colorFill[1], $colorFill[2]) );
|
||||
}
|
||||
}
|
||||
|
||||
private function _parseDescription($desc){
|
||||
if($this->_debug) $this->_log->message('Ajout de la description : '.$desc);
|
||||
return imagestring ( $this->_image , 2, 10, $this->_getImageHeight()-20, $desc , imagecolorallocate($this->_image, 255, 255, 255));
|
||||
}
|
||||
|
||||
public function toImage(){
|
||||
$writeDesc = null;
|
||||
$this->_image = imagecreatetruecolor($this->_getImageWidth(), $this->_getImageHeight());
|
||||
foreach($this->_svgXML->children() as $element){
|
||||
if($element->getName() == 'image')
|
||||
$this->_parseImage($element);
|
||||
if($element->getName() == 'circle')
|
||||
$this->_parseCircle($element);
|
||||
if($element->getName() == 'rect')
|
||||
$this->_parseRectangle($element);
|
||||
if($element->getName() == 'desc' && $this->_showDesc)
|
||||
$writeDesc = $element;
|
||||
}
|
||||
if($writeDesc) $this->_parseDescription($writeDesc);
|
||||
return imagepng($this->_image);
|
||||
}
|
||||
|
||||
}
|
22
test.php
Normal file
22
test.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?
|
||||
include 'svgtoimage.php';
|
||||
/*
|
||||
<image x="184" y="286" width="10" height="10" preserveAspectRatio="none" href="imageurl4.png" style="cursor: pointer; opacity: 1; display: none; " opacity="1"></image>
|
||||
<image x="204" y="286" width="10" height="10" preserveAspectRatio="none" href="imageurl5.png" style="cursor: pointer; opacity: 1; display: none; " opacity="1"></image>
|
||||
*/
|
||||
$svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="512">
|
||||
<desc>Created with Raphael</desc>
|
||||
<defs></defs>
|
||||
<image x="0" y="0" width="300" height="512" preserveAspectRatio="none" href="http://labs.shikiryu.com/experimental-cut/images/pieces/fond.jpg"></image>
|
||||
<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>
|
||||
<circle cx="50" cy="50" r="50" fill="#FFFFFF" stroke="#000"></circle>
|
||||
<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>
|
||||
</svg>';
|
||||
|
||||
//$svgtoimage = new SVGTOIMAGE($svg);
|
||||
$svgtoimage = SVGTOIMAGE::load('basic.svg');
|
||||
$svgtoimage->setShowDesc();
|
||||
$svgtoimage->setWidth(300);
|
||||
$svgtoimage->setHeight(512);
|
||||
header('Content-type: image/png');
|
||||
echo $svgtoimage->toImage();
|
Loading…
Reference in New Issue
Block a user