source: spip-zone/_plugins_/filtres_images_vectorise/trunk/lib/geometrize/src/shape/RotatedRectangle.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.1 KB
Line 
1<?php
2
3namespace Cerdic\Geometrize\Shape;
4
5use \Cerdic\Geometrize\Exporter\SvgExporter;
6use \Cerdic\Geometrize\Rasterizer\Rasterizer;
7
8
9class RotatedRectangle implements Shape {
10
11        /**
12         * @var int
13         */
14        protected $x1;
15
16        /**
17         * @var int
18         */
19        protected $y1;
20
21        /**
22         * @var int
23         */
24        protected $x2;
25
26        /**
27         * @var int
28         */
29        protected $y2;
30
31        /**
32         * @var int
33         */
34        protected $angle;
35
36        /**
37         * @var int
38         */
39        protected $xBound;
40
41        /**
42         * @var int
43         */
44        protected $yBound;
45
46        /**
47         * @var int
48         */
49        public $color;
50
51        /**
52         * Rasterized lines
53         * @var null|array
54         */
55        protected $lines = null;
56
57        public function __construct($xBound, $yBound, $sizeFactor=1.0){
58                $this->x1 = mt_rand(0, $xBound-1);
59                $this->y1 = mt_rand(0, $yBound-1);
60
61                $this->x2 = $this->x1 + intval(mt_rand(0, +$xBound>>2) * $sizeFactor);
62                $this->x2 = min($this->x2, $xBound-1);
63
64                $this->y2 = $this->y1 + intval(mt_rand(0, +$yBound>>2) * $sizeFactor);
65                $this->y2 = min($this->y2, $yBound-1);
66
67                $this->angle = mt_rand(0, 359);
68
69                $this->xBound = $xBound;
70                $this->yBound = $yBound;
71        }
72
73        /**
74         * Rasterize the shape
75         * @return array
76         * @throws \Exception
77         */
78        public function rasterize(){
79                if (!$this->lines){
80                        $points = $this->getCornerPoints();
81                        $this->lines = Rasterizer::scanlinesForPolygon($points, $this->xBound, $this->yBound);
82                }
83                return $this->lines;
84        }
85
86        /**
87         * Mutate the shape
88         * @throws \Exception
89         */
90        public function mutate(){
91                $r = mt_rand(0, 2);
92                switch ($r) {
93                        case 0:
94                                $this->x1 += mt_rand(-16, +16);
95                                $this->x1 = max(min($this->x1, $this->xBound-1),0);
96                                $this->y1 += mt_rand(-16, +16);
97                                $this->y1 = max(min($this->y1, $this->yBound-1),0);
98                                break;
99                        case 1:
100                                $this->x2 += mt_rand(-16, +16);
101                                $this->x2 = max(min($this->x2, $this->xBound-1),0);
102                                $this->y2 += mt_rand(-16, +16);
103                                $this->y2 = max(min($this->y2, $this->yBound-1),0);
104                                break;
105                        case 2:
106                                $this->angle += mt_rand(-4, +4);
107                                $this->angle = (360 + $this->angle) % 360;
108                                break;
109                }
110
111                // force to rasterize the new shape
112                $this->lines = null;
113        }
114
115        public function getSizeFactor(){
116
117                $dx = abs($this->x1-$this->x2);
118                $dy = abs($this->y1-$this->y2);
119
120                return $dx / $this->xBound + $dy / $this->yBound;
121        }
122
123
124        public function rescale($xBound, $yBound){
125                $xScale = ($xBound-1) / ($this->xBound-1);
126                $yScale = ($yBound-1) / ($this->yBound-1);
127                $this->xBound = $xBound;
128                $this->yBound = $yBound;
129                $this->x1 = intval(round($this->x1*$xScale));
130                $this->y1 = intval(round($this->y1*$yScale));
131                $this->x2 = intval(round($this->x2*$xScale));
132                $this->y2 = intval(round($this->y2*$yScale));
133
134                // need to rasterize again
135                $this->lines = null;
136        }
137
138        public function getType(){
139                return ShapeTypes::T_ROTATED_RECTANGLE;
140        }
141
142        /**
143         * @return array
144         */
145        public function getRawShapeData(){
146                if ($this->x1<$this->x2){
147                        $xfirst = $this->x1;
148                        $xsecond = $this->x2;
149                } else {
150                        $xfirst = $this->x2;
151                        $xsecond = $this->x1;
152                }
153                if ($this->y1<$this->y2){
154                        $yfirst = $this->y1;
155                        $ysecond = $this->y2;
156                } else {
157                        $yfirst = $this->y2;
158                        $ysecond = $this->y1;
159                }
160
161                return [
162                        $xfirst,
163                        $yfirst,
164                        $xsecond,
165                        $ysecond,
166                        $this->angle
167                ];
168        }
169
170        /**
171         * @return string
172         */
173        public function getSvgShapeData(){
174                $points = $this->getCornerPoints();
175                return SvgExporter::exportPolygon($points);
176        }
177
178        /**
179         * @return array
180         */
181        public function getCornerPoints(){
182                list($xm1, $ym1, $xm2, $ym2, $angle) = $this->getRawShapeData();
183
184                $cx = intval(($xm1+$xm2)/2);
185                $cy = intval(($ym1+$ym2)/2);
186                $ox1 = $xm1-$cx;
187                $ox2 = $xm2-$cx;
188                $oy1 = $ym1-$cy;
189                $oy2 = $ym2-$cy;
190                $rads = $this->angle * M_PI/180.0;
191                $c = cos($rads);
192                $s = sin($rads);
193
194                $ulx = intval(round($ox1*$c-$oy1*$s+$cx));
195                $uly = intval(round($ox1*$s+$oy1*$c+$cy));
196                $blx = intval(round($ox1*$c-$oy2*$s+$cx));
197                $bly = intval(round($ox1*$s+$oy2*$c+$cy));
198                $urx = intval(round($ox2*$c-$oy1*$s+$cx));
199                $ury = intval(round($ox2*$s+$oy1*$c+$cy));
200                $brx = intval(round($ox2*$c-$oy2*$s+$cx));
201                $bry = intval(round($ox2*$s+$oy2*$c+$cy));
202
203                $corners = [
204                        ["x" => $ulx, "y" => $uly],
205                        ["x" => $urx, "y" => $ury],
206                        ["x" => $brx, "y" => $bry],
207                        ["x" => $blx, "y" => $bly]
208                ];
209                return $corners;
210        }
211
212}
Note: See TracBrowser for help on using the repository browser.