source: spip-zone/_plugins_/filtres_images_vectorise/trunk/lib/geometrize/src/exporter/SvgExporter.php @ 116199

Last change on this file since 116199 was 116199, checked in by cedric@…, 21 months ago

Un plugin pour vectoriser en SVG des images bitmap, qui propose 4 nouveaux filtres

  • extraire_palette_couleurs permet d'extraire une palette de couleur d'une image (par defaut les 3 couleurs les plus representees) en utilisant un calcul des couleurs dominantes par partitionnement en k-moyennes

`
<BOUCLE_palette(POUR){tableau #FICHIER|extraire_palette_couleurs{3}}>
<div style="display: inline-block;width: 30px;height: 15px;background-color: #VALEUR;"></div>
</BOUCLE_palette>
`

  • image_geometrize permet de creer une image SVG approchante de l'image d'origine en utilisant le lib GeometrizePHP https://github.com/Cerdic/geometrize-php/ (attention methode gourmande en temps de calcul)
  • image_potrace permet de generer un trace SVG depuis l'image d'origine, a l'aide de Potracio PHP qui est un portage PHP de PotRace? https://seenthis.net/messages/645575
  • image_geopotrize combine les 2 techniques : un background geometrize qui n'a pas besoin d'un grand nombre de shapes et un trace potrace superpose/mixe

Les 3 filtres ont tout un tas d'option pour qui veut jouer avec, mais les reglages par defaut permettent d'avoir immediatement un joli resultat exploitable
A noter que pour image_geometrize, le temps de calcul peut depasser les 30s pour generer le nombre de shapes demandees, selon les reglages utilises.
Dans ce cas le calcul est arrete au bout de 20s, on stocke et on renvoie l'image provisoire incomplete, et on stocke l'etat du calcul qui reprendra au prochain calcul de la page.

(J'evite les screenshots dans le message de commit mais le coeur y est)

File size: 4.9 KB
Line 
1<?php
2
3namespace Cerdic\Geometrize\Exporter;
4
5use \Cerdic\Geometrize\Shape\ShapeTypes;
6
7class SvgExporter {
8        public function __construct(){
9        }
10
11        static $SVG_STYLE_HOOK = "::svg_style_hook::";
12
13        /**
14         * @param array $shapes
15         * @param int $boxWidth
16         * @param int $boxHeight
17         * @param int $imageWidth
18         * @param int $imageHeight
19         * @return string
20         */
21        static function export($shapes, $boxWidth, $boxHeight, $imageWidth=0, $imageHeight=0){
22                $out = SvgExporter::getSvgPrelude();
23                $out .= SvgExporter::getSvgNodeOpen($boxWidth, $boxHeight, $imageWidth, $imageHeight);
24                $out .= SvgExporter::exportShapes($shapes);
25                $out .= SvgExporter::getSvgNodeClose();
26                return $out;
27        }
28
29        /**
30         * @param array $shapes
31         * @return string
32         */
33        static function exportShapes($shapes){
34                $out = [];
35                foreach ($shapes as $shape) {
36                        $out[] = SvgExporter::exportShape($shape);
37                }
38                $out = implode("\x0A", $out);
39                return $out;
40        }
41
42        /**
43         * @param \Cerdic\Geometrize\Shape\Shape $shape
44         * @return string
45         */
46        static function exportShape($shape){
47                $s = $shape->getSvgShapeData();
48                $sub = SvgExporter::$SVG_STYLE_HOOK;
49                $by = SvgExporter::stylesForShape($shape);
50                if ($sub===""){
51                        return implode(str_split($s), $by);
52                } else {
53                        return str_replace($sub, $by, $s);
54                }
55        }
56
57        static public function exportPolygon($points) {
58                return SvgExporter::exportLines($points, true);
59        }
60
61        /**
62         * @param array $points
63         *   each element is a ['x'=>int, 'y'=>int] array
64         * @param bool $closed
65         * @return string
66         */
67        static public function exportLines($points, $closed = false) {
68                $s1 = "<path d=\"M";
69
70                $point = array_shift($points);
71                $s1 .= $point['x'] . "," . $point['y'];
72
73                $prevPoint = $point;
74                foreach ($points as $point) {
75                        // find the shortest command to draw a line to this new point
76                        $dx = $point['x']-$prevPoint['x'];
77                        $dy = $point['y']-$prevPoint['y'];
78                        if ($dx === 0) {
79                                $pa = "V".$point['y'];
80                                $pr = "v".$dy;
81                        } elseif ($dy === 0) {
82                                $pa = "H".$point['x'];
83                                $pr = "h".$dx;
84                        }
85                        else {
86                                $pa = "L" . $point['x'] . "," . $point['y'];
87                                $pr = "l" . $dx . ',' . $dy;
88                        }
89                        if (strlen($pr)<strlen($pa)) {
90                                $s1 .= $pr;
91                        }
92                        else {
93                                $s1 .= $pa;
94                        }
95                        $prevPoint = $point;
96                }
97                if ($closed) {
98                        $s1 .= "z";
99                }
100                $s1 .= "\" " . SvgExporter::$SVG_STYLE_HOOK . "/>";
101                return $s1;
102        }
103
104        /**
105         * @return string
106         */
107        static function getSvgPrelude(){
108                return "<?xml version=\"1.0\"?>\x0A";
109        }
110
111        /**
112         * @param int $boxWidth
113         * @param int $boxHeight
114         * @param int $imageWidth
115         * @param int $imageHeight
116         * @return string
117         */
118        static function getSvgNodeOpen($boxWidth, $boxHeight, $imageWidth=0, $imageHeight=0){
119                $viewBox = "0 0 " . intval($boxWidth -1) . " " . intval($boxHeight -1);
120                $attrWH = "";
121                if ($imageWidth = intval($imageWidth)) {
122                        $attrWH .= " width=\"$imageWidth\"";
123                }
124                if ($imageHeight = intval($imageHeight)) {
125                        $attrWH .= " height=\"$imageHeight\"";
126                }
127                return "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.2\" viewBox=\"$viewBox\"$attrWH>\x0A";
128        }
129
130        /**
131         * @return string
132         */
133        static function getSvgNodeClose(){
134                return "</svg>";
135        }
136
137        /**
138         * @param \Cerdic\Geometrize\Shape\Shape $shape
139         * @return string
140         */
141        static function stylesForShape($shape){
142                $style = "";
143                switch ($shape->getType()) {
144                        case ShapeTypes::T_LINE:
145                                $style = SvgExporter::strokeForColor($shape->color);
146                                $style .= SvgExporter::strokeOpacityForAlpha($shape->color & 255);
147                                break;
148                        case ShapeTypes::T_QUADRATIC_BEZIER:
149                                $style = SvgExporter::strokeForColor($shape->color) . " fill=\"none\" ";
150                                $style .= SvgExporter::strokeOpacityForAlpha($shape->color & 255);
151                                break;
152                        default:
153                                $style = SvgExporter::fillForColor($shape->color) . " ";
154                                $style .= SvgExporter::fillOpacityForAlpha($shape->color & 255);
155                                break;
156                }
157                return $style ;
158        }
159
160        /**
161         * @param int $color
162         * @return string
163         */
164        static function rgbForColor($color){
165                return "rgb(" . ($color >> 24 & 255) . "," . ($color >> 16 & 255) . "," . ($color >> 8 & 255) . ")";
166        }
167
168        /**
169         * @param $color
170         * @return string
171         */
172        static function hexaForColor($color) {
173                $red = str_pad(dechex($color >> 24 & 255), 2, "0", STR_PAD_LEFT);
174                $green = str_pad(dechex($color >> 16 & 255), 2, "0", STR_PAD_LEFT);
175                $blue = str_pad(dechex($color >> 8 & 255), 2, "0", STR_PAD_LEFT);
176                return "#".$red.$green.$blue;
177        }
178
179        /**
180         * @param int $color
181         * @return string
182         */
183        static function strokeForColor($color){
184                return "stroke=\"" . SvgExporter::hexaForColor($color) . "\"";
185        }
186
187        /**
188         * @param int $color
189         * @return string
190         */
191        static function fillForColor($color){
192                return "fill=\"" . SvgExporter::hexaForColor($color) . "\"";
193        }
194
195        /**
196         * @param int $alpha
197         * @return string
198         */
199        static function fillOpacityForAlpha($alpha){
200                if ($alpha === 255) {
201                        return "";
202                }
203                return "fill-opacity=\"" . ($alpha/255.0) . "\"";
204        }
205
206        /**
207         * @param int $alpha
208         * @return string
209         */
210        static function strokeOpacityForAlpha($alpha){
211                if ($alpha === 255) {
212                        return "";
213                }
214                return "stroke-opacity=\"" . ($alpha/255.0)  . "\"";
215        }
216
217}
Note: See TracBrowser for help on using the repository browser.