source: spip-zone/_plugins_/filtres_images_vectorise/trunk/lib/geometrize/src/shape/QuadraticBezier.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: 3.5 KB
Line 
1<?php
2
3namespace Cerdic\Geometrize\Shape;
4
5use \Cerdic\Geometrize\Exporter\SvgExporter;
6use \Cerdic\Geometrize\Rasterizer\Rasterizer;
7
8class QuadraticBezier implements Shape {
9
10        /**
11         * @var int
12         */
13        protected $cx;
14
15        /**
16         * @var int
17         */
18        protected $cy;
19
20        /**
21         * @var int
22         */
23        protected $x1;
24
25        /**
26         * @var int
27         */
28        protected $y1;
29
30        /**
31         * @var int
32         */
33        protected $x2;
34
35        /**
36         * @var int
37         */
38        protected $y2;
39
40        /**
41         * @var int
42         */
43        protected $xBound;
44
45        /**
46         * @var int
47         */
48        protected $yBound;
49
50        /**
51         * @var int
52         */
53        public $color;
54
55        /**
56         * Rasterized lines
57         * @var null|array
58         */
59        protected $lines = null;
60
61        public function __construct($xBound, $yBound, $sizeFactor=1.0){
62                $this->x1 = mt_rand(0, $xBound-1);
63                $this->y1 = mt_rand(0, $yBound-1);
64
65                $this->x2 = mt_rand(0, $xBound-1);
66                $this->y2 = mt_rand(0, $yBound-1);
67
68                $this->cx = mt_rand(0, $xBound-1);
69                $this->cy = mt_rand(0, $yBound-1);
70
71                $this->xBound = $xBound;
72                $this->yBound = $yBound;
73        }
74
75        public function rasterize(){
76                if (!$this->lines){
77                        $points = [];
78                        $pointCount = 20;
79
80                        for ($i=0;$i<=$pointCount;$i++) {
81                                $t = $i/$pointCount;
82                                $tp = 1-$t;
83                                $x = intval(round($tp*($tp*$this->x1+$t*$this->cx)+$t*($tp*$this->cx+$t*$this->x2)));
84                                $y = intval(round($tp*($tp*$this->y1+$t*$this->cy)+$t*($tp*$this->cy+$t*$this->y2)));
85                                $points[] = ["x" => $x, "y" => $y];
86                        }
87
88                        $prevPoint = array_shift($points);
89                        $this->lines = [];
90                        foreach ($points as $point){
91                                $this->lines = array_merge($this->lines, Rasterizer::scanlinesForPath([$prevPoint, $point], $this->xBound, $this->yBound));
92                                $prevPoint = $point;
93                        }
94                }
95
96                return $this->lines;
97        }
98
99        /**
100         * Mutate the shape
101         */
102        public function mutate(){
103                $r = mt_rand(0, 2);
104                switch ($r) {
105                        case 0:
106                                $this->cx += mt_rand(-8, +8);
107                                $this->cx = max(min($this->cx, $this->xBound-1),0);
108                                $this->cy += mt_rand(-8, +8);
109                                $this->cy = max(min($this->cy, $this->yBound-1),0);
110                                break;
111
112                        case 1:
113                                $this->x1 += mt_rand(-8, +8);
114                                $this->x1 = max(min($this->x1, $this->xBound-1),0);
115                                $this->y1 += mt_rand(-8, +8);
116                                $this->y1 = max(min($this->y1, $this->yBound-1),0);
117                                break;
118
119                        case 2:
120                                $this->x2 += mt_rand(-8, +8);
121                                $this->x2 = max(min($this->x2, $this->xBound-1),0);
122                                $this->y2 += mt_rand(-8, +8);
123                                $this->y2 = max(min($this->y2, $this->yBound-1),0);
124                                break;
125                }
126
127                // force to rasterize the new shape
128                $this->lines = null;
129        }
130
131        public function getSizeFactor(){
132
133                $dx = abs($this->x1-$this->x2);
134                $dy = abs($this->y1-$this->y2);
135
136                return $dx / $this->xBound + $dy / $this->yBound;
137        }
138
139        public function rescale($xBound, $yBound){
140                $xScale = ($xBound-1) / ($this->xBound-1);
141                $yScale = ($yBound-1) / ($this->yBound-1);
142                $this->xBound = $xBound;
143                $this->yBound = $yBound;
144                $this->cx = intval(round($this->cx*$xScale));
145                $this->cy = intval(round($this->cy*$yScale));
146                $this->x1 = intval(round($this->x1*$xScale));
147                $this->y1 = intval(round($this->y1*$yScale));
148                $this->x2 = intval(round($this->x2*$xScale));
149                $this->y2 = intval(round($this->y2*$yScale));
150
151                // need to rasterize again
152                $this->lines = null;
153        }
154
155
156        public function getType(){
157                return ShapeTypes::T_QUADRATIC_BEZIER;
158        }
159
160        /**
161         * @return array
162         */
163        public function getRawShapeData(){
164                return [
165                        $this->x1,
166                        $this->y1,
167                        $this->cx,
168                        $this->cy,
169                        $this->x2,
170                        $this->y2
171                ];
172        }
173
174        /**
175         * @return string
176         */
177        public function getSvgShapeData(){
178                return "<path d=\"M" . $this->x1 . "," . $this->y1 . "Q" . $this->cx . "," . $this->cy . " " . $this->x2 . "," . $this->y2 . "\" " . SvgExporter::$SVG_STYLE_HOOK . " />";
179        }
180
181}
Note: See TracBrowser for help on using the repository browser.