Completed
Push — master ( 8b07a4...42b368 )
by Emmanuel
04:15
created

GlLazyLoadImg::getLossyDataURI()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 10
nc 1
nop 2
1
<?php
2
3
/**
4
 * Lazy loading images
5
 *
6
 * PHP version 5.4
7
 *
8
 * @category  GLICER
9
 * @package   Contact
10
 * @author    Emmanuel ROECKER <[email protected]>
11
 * @author    Rym BOUCHAGOUR <[email protected]>
12
 * @copyright 2012-2013 GLICER
13
 * @license   Proprietary property of GLICER
14
 * @link      http://www.glicer.com
15
 *
16
 * Created : 8/26/16
17
 * File : GlLazyLoadImg.php
18
 *
19
 */
20
21
namespace GlLazyLoadImg;
22
23
use GlHtml\GlHtml;
24
25
class GlLazyLoadImg
26
{
27
    const BLANK = 0;
28
    const LOSSY = 1;
29
30
    /**
31
     * @var string rootpath
32
     */
33
    private $rootpath;
34
35
    /**
36
     * @var int
37
     */
38
    private $type;
39
40
41
    /**
42
     * @var string
43
     */
44
    private $moveToAttribute;
45
46
    /**
47
     * @var array
48
     */
49
    private $excludeAttributesList;
50
51
    /**
52
     * constructor - set root directory to relative url
53
     *
54
     * @param string $rootpath
55
     * @param int    $type
56
     * @param string $moveToAttribute
57
     * @param array  $excludeAttributesList
58
     */
59
    public function __construct(
60
        $rootpath,
61
        $type = self::BLANK,
62
        $moveToAttribute = 'data-original',
63
        array $excludeAttributesList = []
64
    ) {
65
        $this->rootpath              = $rootpath;
66
        $this->type                  = $type;
67
        $this->moveToAttribute       = $moveToAttribute;
68
        $this->excludeAttributesList = $excludeAttributesList;
69
    }
70
71
    
72
    private function gcd($a,$b) {
73
         return ($a % $b) ? $this->gcd($b,$a % $b) : $b;
74
    }
75
    
76
    /**
77
     * create lossy image and encode to data uri format
78
     * minimal size is jpeg
79
     *
80
     * @param     $src          resource GD library
81
     * @param int $minwidth     min width in pixels (height autocalculte)
82
     *                          
83
     * @return string           data uri format
84
     */
85
    public function getLossyDataURI($src, $minwidth = 75)
86
    {            
87
        $src = imagescale($src,$minwidth,-1,IMG_NEAREST_NEIGHBOUR);
88
        
89
        ob_start();
90
        imagegif($src);
91
        $data = ob_get_contents();
92
        ob_end_clean();
93
94
        imagedestroy($src);
95
        
96
        $base64 = base64_encode($data);
97
98
        $mime = 'image/gif';
99
      
100
        return ('data:' . $mime . ';base64,' . $base64);
101
    }
102
103
    /**
104
     * create blank image with same size in data uri format
105
     * minimal size is gif
106
     *
107
     * @param      $src          resource GD library
108
     * @param int  $red          red component background color (default 255)
109
     * @param int  $green        green component background color (default 255)
110
     * @param int  $blue         blue component background color (default 255)
111
     * @param bool $minsize      rescale to min size (default true)
112
     *
113
     * @return string            data uri format
114
     */
115
    public function getBlankDataURI($src, $red = 255, $green = 255, $blue = 255, $minsize = true)
116
    {
117
        $width  = imagesx($src);
118
        $height = imagesy($src);
119
120
        if ($minsize) {
121
            $gcd    = $this->gcd($width, $height);
122
            $width  = $width / $gcd;
123
            $height = $height / $gcd;
124
        }
125
        
126
        $img   = imagecreatetruecolor($width, $height);
127
        $bgcol = imagecolorallocate($img, $red, $green, $blue);
128
        imageFill($img, 0, 0, $bgcol);
129
130
        ob_start();
131
        imagegif($img);
132
        $data = ob_get_contents();
133
        ob_end_clean();
134
135
        $base64 = base64_encode($data);
136
137
        imagedestroy($img);
138
139
        $mime = 'image/gif';
140
141
        return ('data:' . $mime . ';base64,' . $base64);
142
    }
143
144
145
    /**
146
     * find type of image and open it
147
     *
148
     * @param string $file
149
     *
150
     * @return bool|resource
151
     */
152
    private function openImage($file)
153
    {
154
        if (!file_exists($file)) {
155
            return false;
156
        }
157
158
        $size = getimagesize($file);
159
        switch ($size["mime"]) {
160
            case "image/jpeg":
161
                $im = imagecreatefromjpeg($file);
162
                break;
163
            case "image/gif":
164
                $im = imagecreatefromgif($file);
165
                break;
166
            case "image/png":
167
                $im = imagecreatefrompng($file);
168
                break;
169
            default:
170
                $im = false;
171
                break;
172
        }
173
174
        return $im;
175
    }
176
177
    /**
178
     * replace all src attributes from img tags with datauri and set another attribute with old src value
179
     * support jpeg, png or gif file format
180
     *
181
     * @param string $html
182
     * @param bool   $minsize  rescale to minsize (default true)
183
     * 
184
     * @throws \Exception
185
     * @return string
186
     */
187
    public function autoDataURI($html, $minsize=true)
188
    {
189
        $html = new GlHtml($html);
190
        $imgs = $html->get('img');
191
        foreach ($imgs as $img) {
192
            $src          = $img->getAttribute('src');
193
            $pathimagesrc = $this->rootpath . '/' . $src;
194
195
            $imgbin = $this->openImage($pathimagesrc);
196
            if ($imgbin) {
197
                switch ($this->type) {
198
                    case self::BLANK:
199
                        $datauri = $this->getBlankDataURI($imgbin);
200
                        break;
201
                    case self::LOSSY:
202
                        $datauri = $this->getLossyDataURI($imgbin);
203
                        break;
204
                    default:
205
                        throw new \Exception("Type unknown (only self::BLANK=0 or self::LOSSY=1 accepted) : " . $this->type);
206
                }
207
208
                if ($minsize) {
209
                    // keep original size
210
                    $width  = imagesx($imgbin);
211
                    $height = imagesy($imgbin);
212
                    $img->setAttributes(['width' => $width, 'height' => $height]);
213
                }
214
215
                if (!$img->hasAttributes($this->excludeAttributesList)) {
216
                    $img->setAttributes([$this->moveToAttribute => $src, 'src' => $datauri]);
217
                }
218
                imagedestroy($imgbin);
219
            }
220
        }
221
222
        return $html->html();
223
    }
224
225
    /**
226
     * @param string $html
227
     *
228
     * @throws \Exception
229
     * @return string
230
     */
231
    public function autoWidthHeight($html)
232
    {
233
        $html = new GlHtml($html);
234
        $imgs = $html->get('img');
235
        foreach ($imgs as $img) {
236
            $src          = $img->getAttribute('src');
237
            $pathimagesrc = $this->rootpath . '/' . $src;
238
239
            $imgbin = $this->openImage($pathimagesrc);
240
            if ($imgbin) {
241
                $width  = imagesx($imgbin);
242
                $height = imagesy($imgbin);
243
                $img->setAttributes(['width' => $width, 'height' => $height]);
244
245
                if (!$img->hasAttributes($this->excludeAttributesList)) {
246
                    $img->setAttributes(['data-original' => $src, 'src' => '#']);
247
                }
248
                imagedestroy($imgbin);
249
            }
250
        }
251
252
        return $html->html();
253
    }
254
}
255