source: spip-zone/_plugins_/filtres_images_vectorise/trunk/lib/geometrize/src/shape/Rectangle.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;
6
7class Rectangle implements Shape {
8
9        /**
10         * @var int
11         */
12        protected $x1;
13
14        /**
15         * @var int
16         */
17        protected $y1;
18
19        /**
20         * @var int
21         */
22        protected $x2;
23
24        /**
25         * @var int
26         */
27        protected $y2;
28
29        /**
30         * @var int
31         */
32        protected $xBound;
33
34        /**
35         * @var int
36         */
37        protected $yBound;
38
39        /**
40         * @var int
41         */
42        public $color;
43
44        /**
45         * Rasterized lines
46         * @var null|array
47         */
48        protected $lines = null;
49
50        public function __construct($xBound, $yBound, $sizeFactor=1.0, $isBackground = false){
51                if ($isBackground) {
52                        // be sure to cover all the surface, even in case of resizing
53                        $this->x1 = -1;
54                        $this->y1 = -1;
55                        $this->x2 = $xBound;
56                        $this->y2 = $yBound;
57                }
58                else {
59                        $this->x1 = mt_rand(0, $xBound-1);
60                        $this->y1 = mt_rand(0, $yBound-1);
61
62                        $this->x2 = $this->x1 + intval(mt_rand(0, +$xBound>>2) * $sizeFactor);
63                        $this->x2 = min($this->x2, $xBound-1);
64
65                        $this->y2 = $this->y1 + intval(mt_rand(0, +$yBound>>2) * $sizeFactor);
66                        $this->y2 = min($this->y2, $yBound-1);
67                }
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                        list($xm1, $ym1, $xm2, $ym2) = $this->getRawShapeData();
81
82                        $this->lines = [];
83                        if ($xm2>$xm1){
84                                for ($y = $ym1; $y<=$ym2; $y++){
85                                        $this->lines[] = ['y' => $y, 'x1' => $xm1, 'x2' => $xm2];
86                                }
87                        }
88                }
89
90                return $this->lines;
91        }
92
93        /**
94         * Mutate the shape
95         * @throws \Exception
96         */
97        public function mutate(){
98                $r = mt_rand(0, 1);
99                switch ($r) {
100                        case 0:
101                                $this->x1 += mt_rand(-16, +16);
102                                $this->x1 = max(min($this->x1, $this->xBound-1),0);
103                                $this->y1 += mt_rand(-16, +16);
104                                $this->y1 = max(min($this->y1, $this->yBound-1),0);
105                                break;
106                        case 1:
107                                $this->x2 += mt_rand(-16, +16);
108                                $this->x2 = max(min($this->x2, $this->xBound-1),0);
109                                $this->y2 += mt_rand(-16, +16);
110                                $this->y2 = max(min($this->y2, $this->yBound-1),0);
111                                break;
112                }
113
114                // force to rasterize the new shape
115                $this->lines = null;
116        }
117
118        public function getSizeFactor(){
119
120                $dx = abs($this->x1-$this->x2);
121                $dy = abs($this->y1-$this->y2);
122
123                return $dx / $this->xBound + $dy / $this->yBound;
124        }
125
126        public function rescale($xBound, $yBound){
127                $xScale = ($xBound-1) / ($this->xBound-1);
128                $yScale = ($yBound-1) / ($this->yBound-1);
129                $this->xBound = $xBound;
130                $this->yBound = $yBound;
131                $this->x1 = intval(round($this->x1*$xScale));
132                $this->y1 = intval(round($this->y1*$yScale));
133                $this->x2 = intval(round($this->x2*$xScale));
134                $this->y2 = intval(round($this->y2*$yScale));
135
136                // need to rasterize again
137                $this->lines = null;
138        }
139
140        public function getType(){
141                return ShapeTypes::T_RECTANGLE;
142        }
143
144        /**
145         * @return array
146         */
147        public function getRawShapeData(){
148                if ($this->x1<$this->x2){
149                        $xfirst = $this->x1;
150                        $xsecond = $this->x2;
151                } else {
152                        $xfirst = $this->x2;
153                        $xsecond = $this->x1;
154                }
155                if ($this->y1<$this->y2){
156                        $yfirst = $this->y1;
157                        $ysecond = $this->y2;
158                } else {
159                        $yfirst = $this->y2;
160                        $ysecond = $this->y1;
161                }
162
163                return [
164                        $xfirst,
165                        $yfirst,
166                        $xsecond,
167                        $ysecond,
168                ];
169        }
170
171        /**
172         * @return string
173         */
174        public function getSvgShapeData(){
175                // exportPolygon is able to generape a <path...> more compact than the basic <rect>
176                list($xm1, $ym1, $xm2, $ym2) = $this->getRawShapeData();
177                $points = [
178                        ["x" => $xm1, "y" => $ym1],
179                        ["x" => $xm1, "y" => $ym2],
180                        ["x" => $xm2, "y" => $ym2],
181                        ["x" => $xm2, "y" => $ym1]
182                ];
183                return SvgExporter::exportPolygon($points);
184        }
185
186}
Note: See TracBrowser for help on using the repository browser.