Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
namespace PhpOffice\PhpSpreadsheet\Worksheet;
4
 
5
use GdImage;
6
use PhpOffice\PhpSpreadsheet\Exception;
7
use PhpOffice\PhpSpreadsheet\Shared\File;
8
 
9
class MemoryDrawing extends BaseDrawing
10
{
11
    // Rendering functions
12
    const RENDERING_DEFAULT = 'imagepng';
13
    const RENDERING_PNG = 'imagepng';
14
    const RENDERING_GIF = 'imagegif';
15
    const RENDERING_JPEG = 'imagejpeg';
16
 
17
    // MIME types
18
    const MIMETYPE_DEFAULT = 'image/png';
19
    const MIMETYPE_PNG = 'image/png';
20
    const MIMETYPE_GIF = 'image/gif';
21
    const MIMETYPE_JPEG = 'image/jpeg';
22
 
23
    const SUPPORTED_MIME_TYPES = [
24
        self::MIMETYPE_GIF,
25
        self::MIMETYPE_JPEG,
26
        self::MIMETYPE_PNG,
27
    ];
28
 
29
    /**
30
     * Image resource.
31
     *
32
     * @var null|GdImage|resource
33
     */
34
    private $imageResource;
35
 
36
    /**
37
     * Rendering function.
38
     *
39
     * @var string
40
     */
41
    private $renderingFunction;
42
 
43
    /**
44
     * Mime type.
45
     *
46
     * @var string
47
     */
48
    private $mimeType;
49
 
50
    /**
51
     * Unique name.
52
     *
53
     * @var string
54
     */
55
    private $uniqueName;
56
 
57
    /** @var null|resource */
58
    private $alwaysNull;
59
 
60
    /**
61
     * Create a new MemoryDrawing.
62
     */
63
    public function __construct()
64
    {
65
        // Initialise values
66
        $this->renderingFunction = self::RENDERING_DEFAULT;
67
        $this->mimeType = self::MIMETYPE_DEFAULT;
68
        $this->uniqueName = md5(mt_rand(0, 9999) . time() . mt_rand(0, 9999));
69
        $this->alwaysNull = null;
70
 
71
        // Initialize parent
72
        parent::__construct();
73
    }
74
 
75
    public function __destruct()
76
    {
77
        if ($this->imageResource) {
78
            $rslt = @imagedestroy($this->imageResource);
79
            // "Fix" for Scrutinizer
80
            $this->imageResource = $rslt ? null : $this->alwaysNull;
81
        }
82
    }
83
 
84
    public function __clone()
85
    {
86
        parent::__clone();
87
        $this->cloneResource();
88
    }
89
 
90
    private function cloneResource(): void
91
    {
92
        if (!$this->imageResource) {
93
            return;
94
        }
95
 
96
        $width = (int) imagesx($this->imageResource);
97
        $height = (int) imagesy($this->imageResource);
98
 
99
        if (imageistruecolor($this->imageResource)) {
100
            $clone = imagecreatetruecolor($width, $height);
101
            if (!$clone) {
102
                throw new Exception('Could not clone image resource');
103
            }
104
 
105
            imagealphablending($clone, false);
106
            imagesavealpha($clone, true);
107
        } else {
108
            $clone = imagecreate($width, $height);
109
            if (!$clone) {
110
                throw new Exception('Could not clone image resource');
111
            }
112
 
113
            // If the image has transparency...
114
            $transparent = imagecolortransparent($this->imageResource);
115
            if ($transparent >= 0) {
116
                $rgb = imagecolorsforindex($this->imageResource, $transparent);
117
                if (empty($rgb)) {
118
                    throw new Exception('Could not get image colors');
119
                }
120
 
121
                imagesavealpha($clone, true);
122
                $color = imagecolorallocatealpha($clone, $rgb['red'], $rgb['green'], $rgb['blue'], $rgb['alpha']);
123
                if ($color === false) {
124
                    throw new Exception('Could not get image alpha color');
125
                }
126
 
127
                imagefill($clone, 0, 0, $color);
128
            }
129
        }
130
 
131
        //Create the Clone!!
132
        imagecopy($clone, $this->imageResource, 0, 0, 0, 0, $width, $height);
133
 
134
        $this->imageResource = $clone;
135
    }
136
 
137
    /**
138
     * @param resource $imageStream Stream data to be converted to a Memory Drawing
139
     *
140
     * @throws Exception
141
     */
142
    public static function fromStream($imageStream): self
143
    {
144
        $streamValue = stream_get_contents($imageStream);
145
        if ($streamValue === false) {
146
            throw new Exception('Unable to read data from stream');
147
        }
148
 
149
        return self::fromString($streamValue);
150
    }
151
 
152
    /**
153
     * @param string $imageString String data to be converted to a Memory Drawing
154
     *
155
     * @throws Exception
156
     */
157
    public static function fromString(string $imageString): self
158
    {
159
        $gdImage = @imagecreatefromstring($imageString);
160
        if ($gdImage === false) {
161
            throw new Exception('Value cannot be converted to an image');
162
        }
163
 
164
        $mimeType = self::identifyMimeType($imageString);
165
        $renderingFunction = self::identifyRenderingFunction($mimeType);
166
 
167
        $drawing = new self();
168
        $drawing->setImageResource($gdImage);
169
        $drawing->setRenderingFunction($renderingFunction);
170
        $drawing->setMimeType($mimeType);
171
 
172
        return $drawing;
173
    }
174
 
175
    private static function identifyRenderingFunction(string $mimeType): string
176
    {
177
        switch ($mimeType) {
178
            case self::MIMETYPE_PNG:
179
                return self::RENDERING_PNG;
180
            case self::MIMETYPE_JPEG:
181
                return self::RENDERING_JPEG;
182
            case self::MIMETYPE_GIF:
183
                return self::RENDERING_GIF;
184
        }
185
 
186
        return self::RENDERING_DEFAULT;
187
    }
188
 
189
    /**
190
     * @throws Exception
191
     */
192
    private static function identifyMimeType(string $imageString): string
193
    {
194
        $temporaryFileName = File::temporaryFilename();
195
        file_put_contents($temporaryFileName, $imageString);
196
 
197
        $mimeType = self::identifyMimeTypeUsingExif($temporaryFileName);
198
        if ($mimeType !== null) {
199
            unlink($temporaryFileName);
200
 
201
            return $mimeType;
202
        }
203
 
204
        $mimeType = self::identifyMimeTypeUsingGd($temporaryFileName);
205
        if ($mimeType !== null) {
206
            unlink($temporaryFileName);
207
 
208
            return $mimeType;
209
        }
210
 
211
        unlink($temporaryFileName);
212
 
213
        return self::MIMETYPE_DEFAULT;
214
    }
215
 
216
    private static function identifyMimeTypeUsingExif(string $temporaryFileName): ?string
217
    {
218
        if (function_exists('exif_imagetype')) {
219
            $imageType = @exif_imagetype($temporaryFileName);
220
            $mimeType = ($imageType) ? image_type_to_mime_type($imageType) : null;
221
 
222
            return self::supportedMimeTypes($mimeType);
223
        }
224
 
225
        return null;
226
    }
227
 
228
    private static function identifyMimeTypeUsingGd(string $temporaryFileName): ?string
229
    {
230
        if (function_exists('getimagesize')) {
231
            $imageSize = @getimagesize($temporaryFileName);
232
            if (is_array($imageSize)) {
233
                $mimeType = $imageSize['mime'] ?? null;
234
 
235
                return self::supportedMimeTypes($mimeType);
236
            }
237
        }
238
 
239
        return null;
240
    }
241
 
242
    private static function supportedMimeTypes(?string $mimeType = null): ?string
243
    {
244
        if (in_array($mimeType, self::SUPPORTED_MIME_TYPES, true)) {
245
            return $mimeType;
246
        }
247
 
248
        return null;
249
    }
250
 
251
    /**
252
     * Get image resource.
253
     *
254
     * @return null|GdImage|resource
255
     */
256
    public function getImageResource()
257
    {
258
        return $this->imageResource;
259
    }
260
 
261
    /**
262
     * Set image resource.
263
     *
264
     * @param GdImage|resource $value
265
     *
266
     * @return $this
267
     */
268
    public function setImageResource($value)
269
    {
270
        $this->imageResource = $value;
271
 
272
        if ($this->imageResource !== null) {
273
            // Get width/height
274
            $this->width = (int) imagesx($this->imageResource);
275
            $this->height = (int) imagesy($this->imageResource);
276
        }
277
 
278
        return $this;
279
    }
280
 
281
    /**
282
     * Get rendering function.
283
     *
284
     * @return string
285
     */
286
    public function getRenderingFunction()
287
    {
288
        return $this->renderingFunction;
289
    }
290
 
291
    /**
292
     * Set rendering function.
293
     *
294
     * @param string $value see self::RENDERING_*
295
     *
296
     * @return $this
297
     */
298
    public function setRenderingFunction($value)
299
    {
300
        $this->renderingFunction = $value;
301
 
302
        return $this;
303
    }
304
 
305
    /**
306
     * Get mime type.
307
     *
308
     * @return string
309
     */
310
    public function getMimeType()
311
    {
312
        return $this->mimeType;
313
    }
314
 
315
    /**
316
     * Set mime type.
317
     *
318
     * @param string $value see self::MIMETYPE_*
319
     *
320
     * @return $this
321
     */
322
    public function setMimeType($value)
323
    {
324
        $this->mimeType = $value;
325
 
326
        return $this;
327
    }
328
 
329
    /**
330
     * Get indexed filename (using image index).
331
     */
332
    public function getIndexedFilename(): string
333
    {
334
        $extension = strtolower($this->getMimeType());
335
        $extension = explode('/', $extension);
336
        $extension = $extension[1];
337
 
338
        return $this->uniqueName . $this->getImageIndex() . '.' . $extension;
339
    }
340
 
341
    /**
342
     * Get hash code.
343
     *
344
     * @return string Hash code
345
     */
346
    public function getHashCode()
347
    {
348
        return md5(
349
            $this->renderingFunction .
350
            $this->mimeType .
351
            $this->uniqueName .
352
            parent::getHashCode() .
353
            __CLASS__
354
        );
355
    }
356
}