Issues (26)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

tests/ImageTest.php (12 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace TraderInteractive\Util;
4
5
use PHPUnit\Framework\Constraint\GreaterThan;
6
use PHPUnit\Framework\TestCase;
7
8
/**
9
 * @coversDefaultClass \TraderInteractive\Util\Image
10
 * @covers ::<private>
11
 */
12
final class ImageTest extends TestCase
13
{
14
    private $sourceFilesDir;
15
    private $tempDir;
16
17
    public function setUp()
18
    {
19
        $this->sourceFilesDir = __DIR__ . '/_files';
20
        $this->tempDir = sys_get_temp_dir() . '/imageUtilTest';
21
        if (is_dir($this->tempDir)) {
22
            foreach (glob("{$this->tempDir}/*") as $file) {
23
                unlink($file);
24
            }
25
26
            rmdir($this->tempDir);
27
        }
28
    }
29
30
    /**
31
     * Downsize ratio 2.0 to 0.25
32
     *
33
     * @test
34
     * @covers ::resize
35
     */
36
    public function resizeDownsizeToMoreVerticalAspect()
37
    {
38
        $source = new \Imagick('pattern:gray0');
39
        $source->scaleImage(100, 50);
40
41
        $imagick = Image::resize($source, 10, 40, ['color' => 'white', 'maxWidth' => 10000, 'maxHeight' => 10000]);
42
43
        //making sure source didnt resize
44
        $this->assertSame(100, $source->getImageWidth());
45
        $this->assertSame(50, $source->getImageHeight());
46
47
        $this->assertSame(10, $imagick->getImageWidth());
48
        $this->assertSame(40, $imagick->getImageHeight());
49
50
        $whiteBarTop = $imagick->getImagePixelColor(4, 16)->getHsl();
51
        $whiteBarBottom = $imagick->getImagePixelColor(4, 22)->getHsl();
52
53
        $imageLeft = $imagick->getImagePixelColor(0, 19)->getHsl();
54
        $imageRight = $imagick->getImagePixelColor(9, 19)->getHsl();
55
        $imageTop = $imagick->getImagePixelColor(4, 17)->getHsl();
56
        $imageBottom = $imagick->getImagePixelColor(4, 21)->getHsl();
57
58
        $this->assertGreaterThan(0.9, $whiteBarTop['luminosity']);
59
        $this->assertGreaterThan(0.9, $whiteBarBottom['luminosity']);
60
61
        $this->assertLessThan(0.1, $imageLeft['luminosity']);
62
        $this->assertLessThan(0.1, $imageRight['luminosity']);
63
        $this->assertLessThan(0.1, $imageTop['luminosity']);
64
        $this->assertLessThan(0.1, $imageBottom['luminosity']);
65
    }
66
67
    /**
68
     * Downsize ratio 2.0 to 4.0
69
     *
70
     * @test
71
     * @covers ::resize
72
     */
73 View Code Duplication
    public function resizeDownsizeToMoreHorizontalAspect()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
74
    {
75
        $source = new \Imagick('pattern:gray0');
76
        $source->scaleImage(100, 50);
77
78
        $imagick = Image::resize($source, 40, 10);
79
80
        //making sure source didnt resize
81
        $this->assertSame(100, $source->getImageWidth());
82
        $this->assertSame(50, $source->getImageHeight());
83
84
        $this->assertSame(40, $imagick->getImageWidth());
85
        $this->assertSame(10, $imagick->getImageHeight());
86
87
        $whiteBarLeft = $imagick->getImagePixelColor(9, 4)->getHsl();
88
        $whiteBarRight = $imagick->getImagePixelColor(30, 4)->getHsl();
89
90
        $imageLeft = $imagick->getImagePixelColor(10, 4)->getHsl();
91
        $imageRight = $imagick->getImagePixelColor(29, 4)->getHsl();
92
        $imageTop = $imagick->getImagePixelColor(19, 0)->getHsl();
93
        $imageBottom = $imagick->getImagePixelColor(19, 9)->getHsl();
94
95
        $this->assertGreaterThan(0.9, $whiteBarLeft['luminosity']);
96
        $this->assertGreaterThan(0.9, $whiteBarRight['luminosity']);
97
98
        $this->assertLessThan(0.1, $imageLeft['luminosity']);
99
        $this->assertLessThan(0.1, $imageRight['luminosity']);
100
        $this->assertLessThan(0.1, $imageTop['luminosity']);
101
        $this->assertLessThan(0.1, $imageBottom['luminosity']);
102
    }
103
104
    /**
105
     * Upsize ratio 2.0 to 4.0
106
     *
107
     * @test
108
     * @covers ::resize
109
     */
110 View Code Duplication
    public function resizeUpsizeToMoreHorizontalAspectWithoutGrow()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
111
    {
112
        $source = new \Imagick('pattern:gray0');
113
        $source->scaleImage(100, 50);
114
115
        $imagick = Image::resize($source, 400, 100);
116
117
        //making sure source didnt resize
118
        $this->assertSame(100, $source->getImageWidth());
119
        $this->assertSame(50, $source->getImageHeight());
120
121
        $this->assertSame(400, $imagick->getImageWidth());
122
        $this->assertSame(100, $imagick->getImageHeight());
123
124
        $whiteBarLeft = $imagick->getImagePixelColor(99, 49)->getHsl();
125
        $whiteBarRight = $imagick->getImagePixelColor(300, 49)->getHsl();
126
127
        $imageTop = $imagick->getImagePixelColor(200, 26)->getHsl();
128
        $imageBottom = $imagick->getImagePixelColor(200, 74)->getHsl();
129
        $imageLeft = $imagick->getImagePixelColor(151, 50)->getHsl();
130
        $imageRight = $imagick->getImagePixelColor(249, 50)->getHsl();
131
132
        $this->assertGreaterThan(0.9, $whiteBarLeft['luminosity']);
133
        $this->assertGreaterThan(0.9, $whiteBarRight['luminosity']);
134
135
        $this->assertLessThan(0.1, $imageLeft['luminosity']);
136
        $this->assertLessThan(0.1, $imageRight['luminosity']);
137
        $this->assertLessThan(0.1, $imageTop['luminosity']);
138
        $this->assertLessThan(0.1, $imageBottom['luminosity']);
139
    }
140
141
    /**
142
     * Upsize ratio 2.0 to 4.0
143
     *
144
     * @test
145
     * @covers ::resize
146
     */
147 View Code Duplication
    public function resizeUpsizeToMoreHorizontalAspectWithGrow()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
148
    {
149
        $source = new \Imagick('pattern:gray0');
150
        $source->scaleImage(100, 50);
151
152
        $imagick = Image::resize($source, 400, 100, ['upsize' => true]);
153
154
        //making sure source didnt resize
155
        $this->assertSame(100, $source->getImageWidth());
156
        $this->assertSame(50, $source->getImageHeight());
157
158
        $this->assertSame(400, $imagick->getImageWidth());
159
        $this->assertSame(100, $imagick->getImageHeight());
160
161
        $whiteBarLeft = $imagick->getImagePixelColor(99, 49)->getHsl();
162
        $whiteBarRight = $imagick->getImagePixelColor(300, 49)->getHsl();
163
164
        $imageTop = $imagick->getImagePixelColor(249, 0)->getHsl();
165
        $imageBottom = $imagick->getImagePixelColor(249, 99)->getHsl();
166
        $imageLeft = $imagick->getImagePixelColor(100, 49)->getHsl();
167
        $imageRight = $imagick->getImagePixelColor(299, 49)->getHsl();
168
169
        $this->assertGreaterThan(0.9, $whiteBarLeft['luminosity']);
170
        $this->assertGreaterThan(0.9, $whiteBarRight['luminosity']);
171
172
        $this->assertLessThan(0.1, $imageLeft['luminosity']);
173
        $this->assertLessThan(0.1, $imageRight['luminosity']);
174
        $this->assertLessThan(0.1, $imageTop['luminosity']);
175
        $this->assertLessThan(0.1, $imageBottom['luminosity']);
176
    }
177
178
    /**
179
     * Upsize ratio 2.0 to 4.0
180
     *
181
     * @test
182
     * @covers ::resize
183
     */
184 View Code Duplication
    public function resizeUpsizeToMoreVerticalAspect()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
185
    {
186
        $source = new \Imagick('pattern:gray0');
187
        $source->scaleImage(100, 50);
188
189
        $imagick = Image::resize($source, 200, 400);
190
191
        //making sure source didnt resize
192
        $this->assertSame(100, $source->getImageWidth());
193
        $this->assertSame(50, $source->getImageHeight());
194
195
        $this->assertSame(200, $imagick->getImageWidth());
196
        $this->assertSame(400, $imagick->getImageHeight());
197
198
        $whiteBarLeft = $imagick->getImagePixelColor(49, 200)->getHsl();
199
        $whiteBarRight = $imagick->getImagePixelColor(151, 200)->getHsl();
200
201
        $imageTop = $imagick->getImagePixelColor(100, 176)->getHsl();
202
        $imageBottom = $imagick->getImagePixelColor(100, 224)->getHsl();
203
        $imageLeft = $imagick->getImagePixelColor(51, 200)->getHsl();
204
        $imageRight = $imagick->getImagePixelColor(149, 200)->getHsl();
205
206
        $this->assertGreaterThan(0.9, $whiteBarLeft['luminosity']);
207
        $this->assertGreaterThan(0.9, $whiteBarRight['luminosity']);
208
209
        $this->assertLessThan(0.1, $imageLeft['luminosity']);
210
        $this->assertLessThan(0.1, $imageRight['luminosity']);
211
        $this->assertLessThan(0.1, $imageTop['luminosity']);
212
        $this->assertLessThan(0.1, $imageBottom['luminosity']);
213
    }
214
215
    /**
216
     * @test
217
     * @covers ::resize
218
     */
219
    public function resizeWithUpsizeAndBestFit()
220
    {
221
        $source = new \Imagick('pattern:gray0');
222
        $source->scaleImage(85, 45);
223
        $notBestFit = Image::resize($source, 300, 300, ['upsize' => true, 'bestfit' => false]);
224
        $this->assertSame('srgb(0,0,0)', $notBestFit->getImagePixelColor(299, 100)->getColorAsString());
225
        $bestFit = Image::resize($source, 300, 300, ['upsize' => true, 'bestfit' => true]);
226
        $this->assertSame('srgb(255,255,255)', $bestFit->getImagePixelColor(299, 100)->getColorAsString());
227
    }
228
229
    /**
230
     * @test
231
     * @covers ::resize
232
     */
233 View Code Duplication
    public function resizeWithColorOfBlur()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
234
    {
235
        $source = $this->getTestImage('portrait.jpg');
236
        $actual = Image::resize($source, 1024, 768, ['upsize' => true, 'bestfit' => false, 'color' => 'blur']);
237
        $expected = $this->getTestImage('blur.jpg');
238
        $this->assertSameImage($expected, $actual);
239
    }
240
241
    /**
242
     * @test
243
     * @covers ::resize
244
     */
245 View Code Duplication
    public function resizeWithBlurBackground()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
246
    {
247
        $source = $this->getTestImage('portrait.jpg');
248
        $actual = Image::resize($source, 1024, 768, ['upsize' => true, 'bestfit' => false, 'blurBackground' => true]);
249
        $expected = $this->getTestImage('blur.jpg');
250
        $this->assertSameImage($expected, $actual);
251
    }
252
253
    /**
254
     * @test
255
     * @covers ::resize
256
     */
257 View Code Duplication
    public function resizeWithBurredBackgroundWithCustomBlurValue()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
258
    {
259
        $source = $this->getTestImage('portrait.jpg');
260
        $options = ['upsize' => true, 'bestfit' => false, 'blurBackground' => true, 'blurValue' => 30.0];
261
        $actual = Image::resize($source, 1024, 768, $options);
262
        $expected = $this->getTestImage('blur-30.jpg');
263
        $this->assertSameImage($expected, $actual);
264
    }
265
266
    /**
267
     * @test
268
     * @covers ::resize
269
     * @covers ::resizeMulti
270
     * @expectedException \InvalidArgumentException
271
     * @expectedExceptionMessage a $boxSizes width was not between 0 and $options["maxWidth"]
272
     */
273
    public function resizeZeroBoxWidth()
274
    {
275
        Image::resize(new \Imagick(), 0, 10);
276
    }
277
278
    /**
279
     * @test
280
     * @covers ::resize
281
     * @covers ::resizeMulti
282
     * @expectedException \InvalidArgumentException
283
     * @expectedExceptionMessage a $boxSizes width was not between 0 and $options["maxWidth"]
284
     */
285
    public function resizeLargeBoxWidth()
286
    {
287
        Image::resize(new \Imagick(), 10001, 10, ['maxWidth' => 10000]);
288
    }
289
290
    /**
291
     * @test
292
     * @covers ::resize
293
     * @covers ::resizeMulti
294
     * @expectedException \InvalidArgumentException
295
     * @expectedExceptionMessage a $boxSizes height was not between 0 and $options["maxHeight"]
296
     */
297
    public function resizeZeroBoxHeight()
298
    {
299
        Image::resize(new \Imagick(), 10, 0);
300
    }
301
302
    /**
303
     * @test
304
     * @covers ::resize
305
     * @covers ::resizeMulti
306
     * @expectedException \InvalidArgumentException
307
     * @expectedExceptionMessage a $boxSizes height was not between 0 and $options["maxHeight"]
308
     */
309
    public function resizeLargeBoxHeight()
310
    {
311
        Image::resize(new \Imagick(), 10, 10001, ['maxHeight' => 10000]);
312
    }
313
314
    /**
315
     * @test
316
     * @covers ::resize
317
     * @covers ::resizeMulti
318
     * @expectedException \InvalidArgumentException
319
     * @expectedExceptionMessage $options["color"] was not a string
320
     */
321
    public function resizeNonStringColor()
322
    {
323
        Image::resize(new \Imagick(), 10, 10, ['color' => 0]);
324
    }
325
326
    /**
327
     * @test
328
     * @covers ::resize
329
     * @covers ::resizeMulti
330
     * @expectedException \InvalidArgumentException
331
     * @expectedExceptionMessage $options["maxWidth"] was not an int
332
     */
333
    public function resizeonIntMaxWidth()
334
    {
335
        Image::resize(new \Imagick(), 10, 10, ['maxWidth' => 'not int']);
336
    }
337
338
    /**
339
     * @test
340
     * @covers ::resize
341
     * @covers ::resizeMulti
342
     * @expectedException \InvalidArgumentException
343
     * @expectedExceptionMessage $options["maxHeight"] was not an int
344
     */
345
    public function resizeNonIntMaxHeight()
346
    {
347
        Image::resize(new \Imagick(), 10, 10, ['maxHeight' => 'not int']);
348
    }
349
350
    /**
351
     * @test
352
     * @covers ::resize
353
     * @covers ::resizeMulti
354
     * @expectedException \InvalidArgumentException
355
     * @expectedExceptionMessage $options["upsize"] was not a bool
356
     */
357
    public function resizeNonBoolUpsize()
358
    {
359
        Image::resize(new \Imagick(), 10, 10, ['upsize' => 'not bool']);
360
    }
361
362
    /**
363
     * @test
364
     * @covers ::resize
365
     * @covers ::resizeMulti
366
     * @expectedException \InvalidArgumentException
367
     * @expectedExceptionMessage $options["bestfit"] was not a bool
368
     */
369
    public function resizeNonBoolBestFit()
370
    {
371
        Image::resize(new \Imagick(), 10, 10, ['bestfit' => 'not bool']);
372
    }
373
374
    /**
375
     * Verify images are rotated according to EXIF header
376
     * @test
377
     * @covers ::resize
378
     */
379
    public function resizeOrientation()
380
    {
381
        $files = [
382
            "{$this->sourceFilesDir}/bottom-right.jpg",
383
            "{$this->sourceFilesDir}/left-bottom.jpg",
384
            "{$this->sourceFilesDir}/right-top.jpg",
385
            "{$this->sourceFilesDir}/top-left.jpg",
386
        ];
387
388
        $imageResults = [];
389
390
        foreach ($files as $file) {
391
            $source = new \Imagick($file);
392
            $imageWidth = $source->getimagewidth();
393
            $imageHeight = $source->getimageheight();
394
            $imageResults[] = Image::resize($source, $imageWidth, $imageHeight, []);
395
        }
396
397
        $this->assertSame(
398
            ['r' => 254, 'g' => 0, 'b' => 0, 'a' => 1],
399
            $imageResults[0]->getImagePixelColor(0, 0)->getColor()
400
        );
401
        $this->assertSame(
402
            ['r' => 0, 'g' => 0, 'b' => 0, 'a' => 1],
403
            $imageResults[1]->getImagePixelColor(0, 0)->getColor()
404
        );
405
        $this->assertSame(
406
            ['r' => 0, 'g' => 255, 'b' => 1, 'a' => 1],
407
            $imageResults[2]->getImagePixelColor(0, 0)->getColor()
408
        );
409
        $this->assertSame(
410
            ['r' => 0, 'g' => 0, 'b' => 254, 'a' => 1],
411
            $imageResults[3]->getImagePixelColor(0, 0)->getColor()
412
        );
413
    }
414
415
    /**
416
     * Downsize ratio 2.0 to 0.25 and 2.0 to 4.0
417
     *
418
     * @test
419
     * @covers ::resizeMulti
420
     */
421
    public function resizeMultiDownsizeToMoreVerticalAndMoreHorizontalAspect()
422
    {
423
        $source = new \Imagick('pattern:gray0');
424
        $source->scaleImage(100, 50);
425
426
        $results = Image::resizeMulti($source, [['width' => 10, 'height' => 40], ['width' => 40, 'height' => 10]]);
427
        $imagickOne = $results[0];
428
        $imagickTwo = $results[1];
429
430
        //making sure source didnt resize
431
        $this->assertSame(100, $source->getImageWidth());
432
        $this->assertSame(50, $source->getImageHeight());
433
434
        //check $imagick1
435
436
        $this->assertSame(10, $imagickOne->getImageWidth());
437
        $this->assertSame(40, $imagickOne->getImageHeight());
438
439
        $oneWhiteBarTop = $imagickOne->getImagePixelColor(4, 16)->getHsl();
440
        $oneWhiteBarBottom = $imagickOne->getImagePixelColor(4, 22)->getHsl();
441
442
        $oneImageLeft = $imagickOne->getImagePixelColor(0, 19)->getHsl();
443
        $oneImageRight = $imagickOne->getImagePixelColor(9, 19)->getHsl();
444
        $oneImageTop = $imagickOne->getImagePixelColor(4, 17)->getHsl();
445
        $oneImageBottom = $imagickOne->getImagePixelColor(4, 21)->getHsl();
446
447
        $this->assertGreaterThan(0.9, $oneWhiteBarTop['luminosity']);
448
        $this->assertGreaterThan(0.9, $oneWhiteBarBottom['luminosity']);
449
450
        $this->assertLessThan(0.1, $oneImageLeft['luminosity']);
451
        $this->assertLessThan(0.1, $oneImageRight['luminosity']);
452
        $this->assertLessThan(0.1, $oneImageTop['luminosity']);
453
        $this->assertLessThan(0.1, $oneImageBottom['luminosity']);
454
455
        //check $imagick2
456
457
        $this->assertSame(40, $imagickTwo->getImageWidth());
458
        $this->assertSame(10, $imagickTwo->getImageHeight());
459
460
        $twoWhiteBarLeft = $imagickTwo->getImagePixelColor(9, 4)->getHsl();
461
        $twoWhiteBarRight = $imagickTwo->getImagePixelColor(30, 4)->getHsl();
462
463
        $twoImageLeft = $imagickTwo->getImagePixelColor(10, 4)->getHsl();
464
        $twoImageRight = $imagickTwo->getImagePixelColor(29, 4)->getHsl();
465
        $twoImageTop = $imagickTwo->getImagePixelColor(19, 0)->getHsl();
466
        $twoImageBottom = $imagickTwo->getImagePixelColor(19, 9)->getHsl();
467
468
        $this->assertGreaterThan(0.9, $twoWhiteBarLeft['luminosity']);
469
        $this->assertGreaterThan(0.9, $twoWhiteBarRight['luminosity']);
470
471
        $this->assertLessThan(0.1, $twoImageLeft['luminosity']);
472
        $this->assertLessThan(0.1, $twoImageRight['luminosity']);
473
        $this->assertLessThan(0.1, $twoImageTop['luminosity']);
474
        $this->assertLessThan(0.1, $twoImageBottom['luminosity']);
475
    }
476
477
    /**
478
     * @test
479
     * @covers ::resizeMulti
480
     */
481
    public function resizeMultiPerformance()
482
    {
483
        $source = new \Imagick('pattern:gray0');
484
        $source->scaleImage(2000, 500);
485
486
        $count = 10;
487
488
        $beforeSingle = microtime(true);
489
        for ($i = 0; $i < $count; ++$i) {
490
            Image::resizeMulti($source, [['width' => 1100, 'height' => 400]]);
491
            Image::resizeMulti($source, [['width' => 100, 'height' => 400]]);
492
            Image::resizeMulti($source, [['width' => 10, 'height' => 40]]);
493
        }
494
495
        $singleTime = microtime(true) - $beforeSingle;
496
497
        $beforeMulti = microtime(true);
498
        for ($i = 0; $i < $count; ++$i) {
499
            Image::resizeMulti(
500
                $source,
501
                [['width' => 1100, 'height' => 400], ['width' => 100, 'height' => 400], ['width' => 10, 'height' => 40]]
502
            );
503
        }
504
505
        $multiTime = microtime(true) - $beforeMulti;
506
507
        $this->assertLessThan($singleTime, $multiTime * 0.75);
508
    }
509
510
    /**
511
     * @test
512
     * @covers ::resizeMulti
513
     * @expectedException \InvalidArgumentException
514
     * @expectedExceptionMessage a width in a $boxSizes value was not an int
515
     */
516
    public function resizeMultiNonIntWidth()
517
    {
518
        Image::resizeMulti(new \Imagick(), [['width' => true, 'height' => 10]]);
519
    }
520
521
    /**
522
     * @test
523
     * @covers ::resizeMulti
524
     * @expectedException \InvalidArgumentException
525
     * @expectedExceptionMessage a height in a $boxSizes value was not an int
526
     */
527
    public function resizeMultiNonIntHeight()
528
    {
529
        Image::resizeMulti(new \Imagick(), [['width' => 10, 'height' => true]]);
530
    }
531
532
    /**
533
     * @test
534
     * @covers ::resize
535
     */
536 View Code Duplication
    public function resizeTransparentImageWithTransparentBackground()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
537
    {
538
        $source = $this->getTestImage('transparent.png');
539
        $actual = Image::resize($source, 128, 128, ['color' => 'transparent']);
540
        $expected = $this->getTestImage('transparent-resize.png');
541
        $this->assertSameImage($expected, $actual);
542
    }
543
544
    /**
545
     * @test
546
     * @covers ::resize
547
     */
548 View Code Duplication
    public function resizeTransparentImageWithColorBackground()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
549
    {
550
        $source = $this->getTestImage('transparent.png');
551
        $actual = Image::resize($source, 128, 128, ['color' => 'green']);
552
        $expected = $this->getTestImage('transparent-resize-color.png');
553
        $this->assertSameImage($expected, $actual);
554
    }
555
556
    /**
557
     * @test
558
     * @covers ::resize
559
     */
560 View Code Duplication
    public function resizeTransparentImageWithUpsize()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
561
    {
562
        $source = $this->getTestImage('transparent.png');
563
        $actual = Image::resize($source, 128, 128, ['upsize' => true]);
564
        $expected = $this->getTestImage('transparent-upsize.png');
565
        $this->assertSameImage($expected, $actual);
566
    }
567
568
    /**
569
     * @test
570
     * @covers ::resize
571
     */
572 View Code Duplication
    public function resizeTransparentImageWithColorOfBlur()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
573
    {
574
        $source = $this->getTestImage('transparent.png');
575
        $actual = Image::resize($source, 128, 128, ['color' => 'blur']);
576
        $expected = $this->getTestImage('transparent-blur.png');
577
        $this->assertSameImage($expected, $actual);
578
    }
579
580
    /**
581
     * @test
582
     * @covers ::resize
583
     */
584 View Code Duplication
    public function resizeTransparentImageWithBlurBackground()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
585
    {
586
        $source = $this->getTestImage('transparent.png');
587
        $actual = Image::resize($source, 128, 128, ['blurBackground' => true]);
588
        $expected = $this->getTestImage('transparent-blur.png');
589
        $this->assertSameImage($expected, $actual);
590
    }
591
592
    /**
593
     * @test
594
     * @covers ::write
595
     */
596
    public function write()
597
    {
598
        $destPath = "{$this->tempDir}/dest.jpeg";
599
600
        $source = new \Imagick("{$this->sourceFilesDir}/exif.jpg");
601
        $source->setImageFormat('png');
602
603
        Image::write(
604
            $source,
605
            $destPath,
606
            ['format' => 'jpeg', 'directoryMode' => 0775, 'fileMode' => 0776, 'stripHeaders' => true]
607
        );
608
609
        $destImage = new \Imagick($destPath);
610
611
        $this->assertSame(0, count($destImage->getImageProperties('exif:*')));
612
        $this->assertSame('JPEG', $destImage->getImageFormat());
613
614
        $directoryPermissions = substr(sprintf('%o', fileperms($this->tempDir)), -4);
615
        $filePermissions = substr(sprintf('%o', fileperms($destPath)), -4);
616
617
        $this->assertSame('0775', $directoryPermissions);
618
        $this->assertSame('0776', $filePermissions);
619
    }
620
621
    /**
622
     * @test
623
     * @covers ::write
624
     * @expectedException \InvalidArgumentException
625
     * @expectedExceptionMessage $options["directoryMode"] was not an int
626
     */
627
    public function writeNonIntDirectoryMode()
628
    {
629
        Image::write(new \Imagick(), 'not under test', ['directoryMode' => 'not int']);
630
    }
631
632
    /**
633
     * @test
634
     * @covers ::write
635
     * @expectedException \InvalidArgumentException
636
     * @expectedExceptionMessage $options["fileMode"] was not an int
637
     */
638
    public function writeNonIntFileMode()
639
    {
640
        Image::write(new \Imagick(), 'not under test', ['fileMode' => 'not int']);
641
    }
642
643
    /**
644
     * @test
645
     * @covers ::write
646
     * @expectedException \InvalidArgumentException
647
     * @expectedExceptionMessage $options["format"] was not a string
648
     */
649
    public function writeNonStringFormat()
650
    {
651
        Image::write(new \Imagick(), 'not under test', ['format' => true]);
652
    }
653
654
    /**
655
     * @test
656
     * @covers ::write
657
     * @expectedException \InvalidArgumentException
658
     * @expectedExceptionMessage $options["stripHeaders"] was not a bool
659
     */
660
    public function writeNonBoolStripHeaders()
661
    {
662
        Image::write(new \Imagick(), 'not under test', ['stripHeaders' => 'not bool']);
663
    }
664
665
    /**
666
     * Verify that stripHeaders strips exif headers.
667
     *
668
     * @test
669
     * @covers ::stripHeaders
670
     */
671
    public function stripHeaders()
672
    {
673
        $path = "{$this->tempDir}/stripHeaders.jpg";
674
675
        mkdir($this->tempDir);
676
        copy("{$this->sourceFilesDir}/exif.jpg", $path);
677
678
        Image::stripHeaders($path);
679
680
        $imagick = new \Imagick($path);
681
        $this->assertSame(0, count($imagick->getImageProperties('exif:*')));
682
    }
683
684
    /**
685
     * Verify that stripHeaders fails with a missing image.
686
     *
687
     * @test
688
     * @covers ::stripHeaders
689
     * @expectedException \ImagickException
690
     */
691
    public function stripHeadersMissingImage()
692
    {
693
        Image::stripHeaders("{$this->tempDir}/doesnotexist.jpg");
694
    }
695
696
    private function assertSameImage(\Imagick $expected, \Imagick $actual)
697
    {
698
        $comparison = $expected->compareImages($actual, \Imagick::METRIC_UNDEFINED);
699
        $this->assertThat($comparison[1], new GreaterThan(.99));
700
    }
701
702
    private function getTestImage(string $filename) : \Imagick
703
    {
704
        $image = new \Imagick();
705
        $image->readImage("{$this->sourceFilesDir}/{$filename}");
706
        return $image;
707
    }
708
}
709