3
* Gallery - a web based photo album viewer and editor
4
* Copyright (C) 2000-2007 Bharat Mediratta
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or (at
9
* your option) any later version.
11
* This program is distributed in the hope that it will be useful, but
12
* WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
21
GalleryCoreApi::requireOnce('modules/imagemagick/classes/ImageMagickToolkit.class');
24
* Test ImageMagickToolkit functionality
25
* @package ImageMagick
27
* @author Bharat Mediratta <bharat@menalto.com>
28
* @version $Revision: 15513 $
30
class ImageMagickToolkitTest extends GalleryTestCase {
33
* The array with environment information, from ImEnvironments.inc
35
var $_environments = array();
38
* The current environment array item we are processing
40
var $_currentEnvironment = array();
43
* Information about files in our pseudo-platform.
44
* Better would be to store the files information in the Platform, but
45
* since Gallery::getPlatform() will return a copy of the platform, we
46
* cannot keep them there.
48
var $_files = array();
50
function ImageMagickToolkitTest($methodName) {
51
$this->GalleryTestCase($methodName);
53
/* Load our environments */
54
include(dirname(__FILE__) . '/ImEnvironments.inc');
55
$this->_environments = $imEnvironment;
63
$ret = $this->_markPluginParametersForCleanup('module', 'imagemagick');
65
print $ret->getAsHtml();
69
/* Reset to the defaults -- tearDown will undo this */
70
foreach (array('jpegQuality' => 75) as $key => $value) {
71
$ret = GalleryCoreApi::setPluginParameter('module', 'imagemagick', $key, $value);
73
print $ret->getAsHtml();
74
return $this->failWithStatus($ret);
78
$this->_platform = new ImageMagickToolkitTestPlatform($gallery->getPlatform(),
79
$this->_files, $this);
80
$gallery->setPlatform($this->_platform);
82
/* Get a toolkit to work with */
83
$this->_toolkit =& new ImageMagickToolkit();
87
* Prepare to emulate a different version of IM/GM
89
* @param array $environment the array item of the environment
92
function _setEnvironment($environment) {
93
$environment['path'] = '/' . $environment['name'] . $environment['version'] . '/';
95
$ret = GalleryCoreApi::setPluginParameter('module', 'imagemagick',
96
'path', $environment['path']);
98
print $ret->getAsHtml();
99
return $this->failWithStatus($ret);
102
$this->_currentEnvironment = $environment;
103
$this->_platform->setEnvironment($environment);
105
$ret = ImageMagickToolkitHelper::savePlatformParameters();
107
print $ret->getAsHtml();
108
return $this->failWithStatus($ret);
114
function _envName() {
115
return $this->_currentEnvironment['name'] . ' ' . $this->_currentEnvironment['version'];
119
* Helper to test a certain operation
121
* @param string $mimeType
122
* @param string $operation
123
* @param string $src filename
124
* @param string $dst filename
125
* @param array $params indexed array
126
* @param array $namedParams assoc-array with paramName=>paramValue
127
* @param string $quality (optional)
128
* @return object GalleryStatus
131
function _testOperation($mimeType, $operation, $src, $dst, $params, $namedParams,
133
$this->_chmodWasCalled = false;
134
list ($ret, $outputMimeType) =
135
$this->_toolkit->performOperation($mimeType, $operation,
136
$src, $dst, $params);
140
$expected = $this->_currentEnvironment['operations'][$operation];
142
if (in_array($mimeType, array('image/tiff', 'application/pdf', 'application/postscript'))) {
143
if ($operation == 'select-page') {
144
$src .= '[' . ($params[0] - 1) . ']';
148
} else if ($mimeType == 'image/gif') {
149
foreach (array_keys($expected) as $key) {
150
if (is_int($i = array_search('%src%', $expected[$key]))) {
151
$expected[$key][$i] = '-deconstruct';
153
array_unshift($expected[$key], '-coalesce', '%src%');
157
$search = array('|%src%|', '|%dst%|');
158
$replace = array($src, $dst);
159
foreach ($namedParams as $key => $value) {
160
$search[] = sprintf('|%%%s%%|', $key);
163
foreach (array_keys($expected) as $key) {
164
$expected[$key] = preg_replace($search, $replace, $expected[$key]);
167
if ($outputMimeType == 'image/jpeg' || $outputMimeType == 'image/png') {
168
if (!isset($quality)) {
171
foreach (array_keys($expected) as $key) {
172
$expected[$key] = array_merge(array('-quality', $quality), $expected[$key]);
176
$this->assertEquals($expected, $this->_files[$dst]['operation'],
177
$this->_currentEnvironment['path'] . " $operation " . implode(' ', $params));
178
$this->assert($this->_chmodWasCalled, 'chmod not called');
183
function testPerformOperations() {
185
foreach ($this->_environments as $environment) {
186
$this->_setEnvironment($environment);
188
$ret = $this->_testOperation('image/gif', 'thumbnail',
189
'test[1000x1000].gif', 'output.gif',
191
array('width' => 100, 'height' => 100));
193
return $this->failWithStatus($ret);
196
$ret = $this->_testOperation('image/jpeg', 'thumbnail',
197
'test[1000x1000].jpg', 'output.jpg',
199
array('width' => 100, 'height' => 100));
201
return $this->failWithStatus($ret);
204
$ret = $this->_testOperation('image/tiff', 'rotate',
205
'test.tiff', 'output.tiff',
206
array(90), array('angle' => 90));
208
return $this->failWithStatus($ret);
211
$ret = $this->_testOperation('image/bmp', 'rotate',
212
'test.bmp', 'output.bmp',
213
array(180), array('angle' => 180));
215
return $this->failWithStatus($ret);
218
$ret = $this->_testOperation('image/png', 'crop',
219
'test[640x480].png', 'output.png',
220
array('24.667', '23.5', '51.375', '52'),
221
array('width' => '329', 'height' => '250',
222
'x' => '158', 'y' => '113'));
224
return $this->failWithStatus($ret);
227
$ret = $this->_testOperation('image/gif', 'convert-to-image/png',
228
'test.gif', 'output.png',
231
return $this->failWithStatus($ret);
234
$ret = $this->_testOperation('application/pdf', 'select-page',
235
'test.pdf', 'output.pdf',
236
array('2'), array());
238
return $this->failWithStatus($ret);
241
/* Test a basic composite operation (top right corner) */
242
$dataDir = $gallery->getConfig('data.gallery.base');
243
$ret = $this->_testOperation('image/png', 'composite',
244
'test.png', /* composite */
245
'output.png', /* composited */
246
array('image.gif', /* image */
247
'image/gif', /* mimeType */
248
5, 5, /* image width, height */
249
'top-right', /* alignment type */
250
0, 0), /* image alignment (unused w/ 'top-right') */
251
array('image' => $dataDir . 'image.gif',
257
return $this->failWithStatus($ret);
260
/* Test another composite with out of range params that should get corrected */
261
$ret = $this->_testOperation('image/png', 'composite',
262
'test.png', /* composite */
263
'output.png', /* composited */
264
array('image.gif', /* image */
265
'image/gif', /* mimeType */
266
50, 50, /* image width, height */
267
'manual', /* alignment type */
268
151, 151), /* image alignment x, y */
269
array('image' => $dataDir . 'image.gif',
275
return $this->failWithStatus($ret);
279
$this->_files['compressMe.jpg']['size'] = 250 << 10;
280
$this->_platform->_counter = 2;
281
$ret = $this->_testOperation('image/jpeg', 'compress',
282
'compressMe.jpg', 'compressed.jpg',
286
return $this->failWithStatus($ret);
289
if (in_array('image/jpeg-cmyk', $environment['mimeTypes'])) {
290
$ret = $this->_testOperation('image/jpeg-cmyk', 'convert-to-image/jpeg',
291
'cmyk.jpg', 'rgb.jpg',
294
return $this->failWithStatus($ret);
298
list ($ret, $mimeType) =
299
$this->_toolkit->performOperation('image/png', 'BOGUS',
304
$this->assert($ret->getErrorCode() & ERROR_UNSUPPORTED_OPERATION, 'bad op');
309
function testPercentParameters() {
310
foreach ($this->_environments as $environment) {
311
$this->_setEnvironment($environment);
313
$ret = $this->_testOperation('image/gif', 'thumbnail',
314
'test[1000x1000].gif', 'output.gif',
316
array('width' => 150, 'height' => 150));
318
return $this->failWithStatus($ret);
321
$ret = $this->_testOperation('image/jpeg', 'scale',
322
'test[1000x1000].jpg', 'output.jpg',
324
array('width' => 500, 'height' => 400));
326
return $this->failWithStatus($ret);
329
$ret = $this->_testOperation('image/png', 'resize',
330
'test[1000x1000].png', 'output.png',
332
array('width' => 600, 'height' => 800));
334
return $this->failWithStatus($ret);
339
function testPngQuality() {
340
$ret = GalleryCoreApi::setPluginParameter('module', 'imagemagick', 'jpegQuality', 94);
342
return $this->failWithStatus($ret);
345
foreach ($this->_environments as $environment) {
346
$this->_setEnvironment($environment);
349
* Make sure that PNG quality uses only the compression, not the filter
350
* so our quality level (94) becomes compression (9) and filter (4). We
351
* change that in the toolkit to compression (9) and filter (5) for a result
352
* of 95. When we implement PNG quality correctly, we should change this back.
354
$ret = $this->_testOperation('image/png', 'rotate',
355
'qualityTestIn.png', 'qualityTestOut.png',
356
array(90), array('angle' => 90), 95);
358
return $this->failWithStatus($ret);
364
* Ensure multiple "convert" operations in sequence only makes one exec call. Perform a
365
* thumbnail followed by a crop. This is not a commonly performed sequence; normally we do the
366
* crop first, however that causes problems with some versions of ImageMagick, and this still
367
* serves as a good test for our sequences.
369
function testOperationSequence() {
370
$this->_platform->_copyOk = true;
372
foreach ($this->_environments as $environment) {
373
$this->_setEnvironment($environment);
374
$context = array('next.toolkit' => $this->_toolkit, 'next.operation' => 'crop');
376
list ($ret, $outputMimeType, $context) =
377
$this->_toolkit->performOperation('image/png', 'thumbnail',
378
'test[640x480].png', 'outputTmp.png',
379
array('150'), $context);
381
return $this->failWithStatus($ret);
384
$this->assertEquals(array(), $this->_files, 'no exec yet ' . $this->_envName());
385
$context['next.toolkit'] = null;
386
$context['next.operation'] = null;
387
$this->assertEquals(array('next.toolkit' => null, 'next.operation' => null,
388
'width' => 150, 'height' => 113,
389
'imagemagick.transform' => array_merge(
390
array('-size', '150x150',
391
'-geometry', '150x150'),
392
$environment['removeMetaDataSwitch']),
393
'imagemagick.mime' => 'image/png'),
394
$context, 'context after thumbnail ' . $this->_envName());
396
list ($ret, $outputMimeType, $context) =
397
$this->_toolkit->performOperation('image/png', 'crop',
398
'outputTmp.png', 'output.png',
399
array('24.667', '23.5', '51.375', '52'),
402
return $this->failWithStatus($ret);
407
array('-quality', 75,
408
'-geometry', '150x150'),
409
$environment['removeMetaDataSwitch'],
410
array('-crop', '77x59+37+27'),
411
array('outputTmp.png', 'output.png')),
412
$this->_files['output.png']['operation']['convert'], 'output ' . $this->_envName());
413
$this->assertEquals(array('next.toolkit' => null, 'next.operation' => null,
414
'width' => 77, 'height' => 59),
415
$context, 'context at end ' . $this->_envName());
417
unset($this->_files['output.png']);
422
* Some versions of ImageMagick bomb if you do a -crop followed by a -geometry. See the
423
* comment in the mock platform for more details. So make sure that these are NOT done in a
426
function testOperationSequenceCropAndGeometrySeparate() {
427
$this->_platform->_copyOk = true;
429
foreach ($this->_environments as $environment) {
430
$this->_setEnvironment($environment);
431
$context = array('next.toolkit' => $this->_toolkit, 'next.operation' => 'thumbnail');
433
list ($ret, $outputMimeType, $context) =
434
$this->_toolkit->performOperation('image/png', 'crop',
435
'test[640x480].png', 'output1.png',
436
array('24.667', '23.5', '51.375', '52'),
439
return $this->failWithStatus($ret);
444
array('-quality', 75, '-crop', '329x250+158+113'),
445
array('test[640x480].png', 'output1.png')),
446
$this->_files['output1.png']['operation']['convert'], 'output ' .
448
$this->assertEquals(array('next.toolkit' => $this->_toolkit,
449
'next.operation' => 'thumbnail',
450
'width' => 329, 'height' => 250),
451
$context, 'context after crop ' . $this->_envName());
453
$context['next.toolkit'] = null;
454
$context['next.operation'] = null;
456
list ($ret, $outputMimeType, $context) =
457
$this->_toolkit->performOperation('image/png', 'thumbnail',
458
'output1.png', 'output.png',
459
array('150'), $context);
461
return $this->failWithStatus($ret);
466
array('-quality', 75, '-size', '150x150', '-geometry', '150x150'),
467
$environment['removeMetaDataSwitch'],
468
array('output1.png', 'output.png')),
469
$this->_files['output.png']['operation']['convert'], 'output ' . $this->_envName());
470
$this->assertEquals(array('next.toolkit' => null, 'next.operation' => null,
471
'width' => 150, 'height' => 114),
472
$context, 'context at end ' . $this->_envName());
474
unset($this->_files['output1.png']);
475
unset($this->_files['output.png']);
480
* Ensure queued operations that affect image size are taken into account
481
* for subsequent operations..
483
function testOperationSequenceSizeChange() {
484
$this->_platform->_copyOk = true;
486
foreach ($this->_environments as $environment) {
487
$this->_setEnvironment($environment);
488
$context = array('next.toolkit' => $this->_toolkit, 'next.operation' => 'rotate',
489
'width' => 640, 'height' => 480);
491
list ($ret, $outputMimeType, $context) =
492
$this->_toolkit->performOperation('image/png', 'resize',
493
'test.png', 'output.png',
497
return $this->failWithStatus($ret);
500
$this->assertEquals(array(), $this->_files, 'no exec yet ' . $this->_envName());
501
$this->assertEquals(array('next.toolkit' => $this->_toolkit,
502
'next.operation' => 'rotate',
503
'width' => 320, 'height' => 240,
504
'imagemagick.transform' => array(
506
'-geometry', '320x240'
508
'imagemagick.mime' => 'image/png'),
509
$context, 'context after scale ' . $this->_envName());
510
$context['next.operation'] = 'thumbnail';
512
list ($ret, $outputMimeType, $context) =
513
$this->_toolkit->performOperation('image/png', 'rotate',
514
'output.png', 'output.png',
515
array('90'), $context);
517
return $this->failWithStatus($ret);
520
$context['next.toolkit'] = null;
521
$context['next.operation'] = null;
522
$this->assertEquals(array(), $this->_files, 'still no exec ' . $this->_envName());
523
$this->assertEquals(array('next.toolkit' => null, 'next.operation' => null,
524
'width' => 240, 'height' => 320,
525
'imagemagick.transform' =>
526
array('-geometry', '320x240', '-rotate', '90'),
527
'imagemagick.mime' => 'image/png'),
528
$context, 'context after rotate ' . $this->_envName());
530
list ($ret, $outputMimeType, $context) =
531
$this->_toolkit->performOperation('image/png', 'thumbnail',
532
'output.png', 'output.png',
533
array('150'), $context);
535
return $this->failWithStatus($ret);
538
$this->assertEquals(array_merge(
539
array('-quality', '75',
540
'-geometry', '320x240',
542
'-geometry', '150x150'),
543
$environment['removeMetaDataSwitch'],
544
array('output.png', 'output.png')),
545
$this->_files['output.png']['operation']['convert'], 'output ' . $this->_envName());
546
$this->assertEquals(array('next.toolkit' => null, 'next.operation' => null,
547
'width' => 113, 'height' => 150),
548
$context, 'context at end ' . $this->_envName());
550
unset($this->_files['output.png']);
554
/* Ensure queued operations handle change of mime type correctly */
555
function testOperationSequenceMimeChange() {
556
$this->_platform->_copyOk = true;
558
foreach ($this->_environments as $environment) {
559
$this->_setEnvironment($environment);
560
$context = array('next.toolkit' => $this->_toolkit, 'next.operation' => 'thumbnail');
562
list ($ret, $outputMimeType, $context) =
563
$this->_toolkit->performOperation('application/pdf', 'convert-to-image/jpeg',
564
'test.pdf', 'TEMPFILE', array(), $context);
566
return $this->failWithStatus($ret);
569
$context['next.toolkit'] = null;
570
$context['next.operation'] = null;
571
$this->assertEquals(array(), $this->_files, 'no exec yet ' . $this->_envName());
572
$this->assertEquals(array('next.toolkit' => null, 'next.operation' => null,
573
'width' => '612', 'height' => '792',
574
'imagemagick.transform' => array(),
575
'imagemagick.mime' => 'application/pdf'),
576
$context, 'context after convert ' . $this->_envName());
577
$this->assertEquals('image/jpeg', $outputMimeType, 'jpeg ' . $this->_envName());
579
list ($ret, $outputMimeType, $context) =
580
$this->_toolkit->performOperation('image/jpeg', 'thumbnail',
581
'TEMPFILE', 'output.jpg',
582
array('150'), $context);
584
return $this->failWithStatus($ret);
587
$this->assertEquals(array_merge(
588
array('-quality', '75', '-size', '150x150', '-geometry', '150x150'),
589
$environment['removeMetaDataSwitch'],
590
array('TEMPFILE[0]', 'jpeg:output.jpg')),
591
$this->_files['output.jpg']['operation']['convert'], 'output ' . $this->_envName());
592
$this->assertEquals(array('next.toolkit' => null, 'next.operation' => null,
593
'width' => 116, 'height' => 150),
594
$context, 'context at end ' . $this->_envName());
596
unset($this->_files['output.jpg']);
601
function testGetProperties() {
602
foreach ($this->_environments as $environment) {
603
$this->_setEnvironment($environment);
605
list ($ret, $results) =
606
$this->_toolkit->getProperty('image/gif', 'dimensions', 'test[10x20].gif');
608
return $this->failWithStatus($ret);
610
$this->assertEquals(array(10, 20), $results, 'dimensions ' . $this->_envName());
612
list ($ret, $results) =
613
$this->_toolkit->getProperty('application/pdf', 'page-count', 'test.pdf');
615
return $this->failWithStatus($ret);
617
$this->assertEquals(array(2), $results, 'page-count ' . $this->_envName());
619
if (in_array('image/jpeg-cmyk', $environment['mimeTypes'])) {
620
list ($ret, $results) =
621
$this->_toolkit->getProperty('image/jpeg', 'colorspace', 'cmyk.jpg');
623
return $this->failWithStatus($ret);
625
$this->assertEquals(array('CMYK'), $results, 'colorspace ' . $this->_envName());
628
list ($ret, $results) =
629
$this->_toolkit->getProperty('image/gif', 'BOGUS', 'BOGUS');
630
$this->assert($ret->getErrorCode() & ERROR_UNIMPLEMENTED,
631
'bad op ' . $this->_envName());
635
function testMergeOperations() {
636
list ($success, $operation, $args) =
637
$this->_toolkit->mergeOperations('crop', array(1, 2, 3, 4), 'crop', array(3, 4, 5, 6));
638
$this->assert($success);
639
$this->assertEquals('crop', $operation);
640
$this->assertEquals(array(3, 4, 5, 6), $args);
642
list ($success, $operation, $args) =
643
$this->_toolkit->mergeOperations('resize', array(1, 2), 'resize', array(3, 4));
644
$this->assert($success);
645
$this->assertEquals('resize', $operation);
646
$this->assertEquals(array(3, 4), $args);
648
list ($success, $operation, $args) =
649
$this->_toolkit->mergeOperations('thumbnail', array(1, 2), 'resize', array(3, 4));
650
$this->assert($success);
651
$this->assertEquals('resize', $operation);
652
$this->assertEquals(array(3, 4), $args);
654
list ($success, $operation, $args) =
655
$this->_toolkit->mergeOperations('thumbnail', array(1, 2), 'thumbnail', array(3, 4));
656
$this->assert($success);
657
$this->assertEquals('thumbnail', $operation);
658
$this->assertEquals(array(3, 4), $args);
660
list ($success, $operation, $args) =
661
$this->_toolkit->mergeOperations('scale', array(1, 2), 'thumbnail', array(3, 4));
662
$this->assert($success);
663
$this->assertEquals('thumbnail', $operation);
664
$this->assertEquals(array(3, 4), $args);
666
list ($success, $operation, $args) =
667
$this->_toolkit->mergeOperations('rotate', array(90), 'rotate', array(90));
668
$this->assert($success);
669
$this->assertEquals('rotate', $operation);
670
$this->assertEquals(array(180), $args);
672
list ($success, $operation, $args) =
673
$this->_toolkit->mergeOperations('rotate', array(90), 'rotate', array(-90));
674
$this->assert($success);
675
$this->assertEquals(null, $operation);
676
$this->assertEquals(null, $args);
678
list ($success, $operation, $args) =
679
$this->_toolkit->mergeOperations('rotate', array(270), 'rotate', array(180));
680
$this->assert($success);
681
$this->assertEquals('rotate', $operation);
682
$this->assertEquals(array(90), $args);
684
list ($success, $operation, $args) =
685
$this->_toolkit->mergeOperations('rotate', array(90), 'rotate', array(-180));
686
$this->assert($success);
687
$this->assertEquals('rotate', $operation);
688
$this->assertEquals(array(-90), $args);
690
list ($success, $operation, $args) =
691
$this->_toolkit->mergeOperations('rotate', array(90), 'rotate', array(180));
692
$this->assert($success);
693
$this->assertEquals('rotate', $operation);
694
$this->assertEquals(array(-90), $args);
696
list ($success, $operation, $args) =
697
$this->_toolkit->mergeOperations('rotate', array(270), 'rotate', array(90));
698
$this->assert($success);
699
$this->assertEquals(null, $operation);
700
$this->assertEquals(null, $args);
702
list ($success, $operation, $args) =
703
$this->_toolkit->mergeOperations('crop', array(1, 2, 3, 4), 'thumbnail', array(3, 4));
704
$this->assert(!$success);
707
function testDiscoverMimeTypes() {
708
foreach ($this->_environments as $environment) {
709
$this->_setEnvironment($environment);
711
list ($ret, $results) =
712
ImageMagickToolkitHelper::discoverMimeTypes($this->_currentEnvironment['path']);
714
return $this->failWithStatus($ret);
716
$this->assertEquals($environment['mimeTypes'], $results);
720
function testGetOperationsAndProperties() {
721
foreach ($this->_environments as $environment) {
722
$this->_setEnvironment($environment);
724
list ($ret, $results) = ImageMagickToolkitHelper::getOperationsAndProperties();
726
return $this->failWithStatus($ret);
729
$canConvert = array();
730
foreach (array('image/jpeg', 'image/png', 'image/gif', 'image/tiff', 'image/jp2')
732
if (is_int($i = array_search($mimeType, $environment['mimeTypes']))) {
733
$convertTo = array_merge(
734
$environment['mimeTypes'], array('image/x-portable-pixmap'));
735
array_splice($convertTo, $i, 1);
736
$canConvert['convert-to-' . $mimeType] = array(
738
'description' => 'Convert to ' . $mimeType,
739
'mimeTypes' => $convertTo,
740
'outputMimeType' => $mimeType);
743
$wantToPage = array('image/tiff', 'application/pdf',
744
'application/postscript', 'application/photoshop');
745
$canPage = array_intersect($wantToPage, $environment['mimeTypes']);
746
$qualityMimeTypes = array_intersect(array('image/jpeg', 'image/png'),
747
$environment['mimeTypes']);
749
$this->assertEquals(array_merge($canConvert, array(
754
'description' => 'target width (# pixels or #% of full size)'),
757
'description' => '(optional) target height, defaults to same as width')
759
'description' => 'Scale the image to the target size, maintain aspect ratio',
760
'mimeTypes' => $environment['mimeTypes'],
762
'thumbnail' => array(
766
'description' => 'target width (# pixels or #% of full size)'),
769
'description' => '(optional) target height, defaults to same as width')
771
'description' => 'Scale the image to the target size, maintain aspect ratio',
772
'mimeTypes' => $environment['mimeTypes'],
778
'description' => 'target width (# pixels or #% of full size)'),
781
'description' => 'target height (# pixels or #% of full size)')
783
'description' => 'Resize the image to the target dimensions',
784
'mimeTypes' => $environment['mimeTypes'],
790
'description' => 'rotation degrees')
792
'description' => 'Rotate the image',
793
'mimeTypes' => $environment['mimeTypes'],
799
'description' => 'left edge %'),
802
'description' => 'top edge %'),
805
'description' => 'width %'),
808
'description' => 'height %')
810
'description' => 'Crop the image',
811
'mimeTypes' => $environment['mimeTypes'],
813
'composite' => array(
817
'description' => 'overlay path'),
820
'description' => 'overlay mime type'),
823
'description' => 'overlay width'),
826
'description' => 'overlay height'),
829
'description' => 'alignment type'),
832
'description' => 'alignment x %'),
835
'description' => 'alignment y %'),
837
'description' => 'Overlay source image with a second one',
838
'mimeTypes' => $environment['mimeTypes'],
840
'select-page' => array(
844
'description' => 'page number'),
846
'description' => 'Select a single page from a multi-page file',
847
'mimeTypes' => $canPage,
853
'description' => 'target size in kb')
855
'description' => 'Reduce image quality to reach target file size',
856
'mimeTypes' => $qualityMimeTypes
858
)), $results['operations'], $this->_envName());
861
'dimensions' => array(
863
'description' => 'Get the width and height of the image',
864
'mimeTypes' => array_merge(
865
$environment['mimeTypes'],
866
array('image/x-portable-pixmap', 'application/x-shockwave-flash'))
868
'page-count' => array(
870
'description' => 'Get the number of pages',
871
'mimeTypes' => $canPage
874
if (in_array('image/jpeg-cmyk', $environment['mimeTypes'])) {
875
$properties['colorspace'] = array(
877
'description' => 'Get the colorspace of the image',
878
'mimeTypes' => array('image/jpeg', 'image/tiff', 'application/photoshop')
881
$this->assertEquals($properties, $results['properties'], $this->_envName());
885
function testBinaries() {
886
foreach ($this->_environments as $environment) {
887
$this->_setEnvironment($environment);
889
list ($ret, $results) =
890
ImageMagickToolkitHelper::testBinaries($this->_currentEnvironment['path']);
892
return $this->failWithStatus($ret);
895
$wanted = array('identify', 'convert', 'combine', 'composite');
897
foreach ($wanted as $binary) {
898
if (in_array($binary, $this->_currentEnvironment['binaries'])) {
899
$expected[] = array('name' => $binary, 'success' => true);
903
$this->assertEquals($expected, $results);
906
list ($ret, $results) = ImageMagickToolkitHelper::testBinaries('/bogusPath');
907
$this->assert($ret->getErrorCode() & ERROR_BAD_PATH);
914
* @package ImageMagick
915
* @subpackage PHPUnit
917
class ImageMagickToolkitTestPlatform {
919
var $_environment = array();
922
function ImageMagickToolkitTestPlatform($originalPlatform, &$files, &$test) {
923
$this->_platform = $originalPlatform;
924
$this->_files =& $files;
925
$this->_test =& $test;
928
function setEnvironment($environment) {
929
$this->_environment = $environment;
932
function exec($cmd) {
933
list ($ret, $imageMagickPath) =
934
GalleryCoreApi::getPluginParameter('module', 'imagemagick', 'path');
936
return array($ret, null);
940
if ($this->_environment['binary'] != '') {
941
if (basename($firstCmd[0]) != $this->_environment['binary']) {
942
return array(0, array('unprepared for exec()'));
944
array_shift($firstCmd);
950
$binary = array_shift($firstCmd);
951
$binary = basename($binary);
952
if ($binary == 'identify') {
953
$file = basename(array_shift($firstCmd));
954
$data = $this->_environment['identify'];
955
if ($file == '-format' && count($firstCmd) >= 2) {
956
/* Cmd to identify colorspace */
957
$data = $data['-format'];
958
$file = basename($firstCmd[1]);
959
if (isset($this->_files[$file]['operation']['convert'][0]) &&
960
$this->_files[$file]['operation']['convert'][0] == '-colorspace') {
964
if (isset($data[$file])) {
965
$output = split("\n", $data[$file]);
967
$output = split("\n", $this->_environment['identify']['UNKNOWN']);
970
} else if (($binary == 'convert' && in_array('convert', $this->_environment['binaries']))
971
|| ($binary == 'composite' && in_array('composite',
972
$this->_environment['binaries']))
973
|| ($binary == 'combine' && in_array('combine',
974
$this->_environment['binaries'])) ) {
975
$params = array_slice($firstCmd, 0);
976
$src = basename($firstCmd[count($firstCmd) - 2]);
977
$dst = basename($firstCmd[count($firstCmd) - 1]);
978
if (preg_match('#(.*):(.*)$#', $dst, $matches)) {
979
/* Format 'jpeg:filename.jpg' */
982
if ($src == 'testProfile.jpg') {
983
/* ImageMagickToolkitHelper is testing our removeMetaDataSwitch */
984
$params = array_slice($firstCmd, 0, count($firstCmd) - 2);
985
if ($this->_environment['removeMetaDataSwitch'] == $params) {
986
$this->_files[$dst] = array('size' => 50000);
988
$this->_files[$dst] = array('size' => 0);
994
* ImageMagick 6.1.6 has a bug where if you do -crop followed by -geometry it
995
* gets confused about the size of the image and the -geometry check applies
996
* to the original dimensions, instead of the new, cropped dimensions. This
997
* can result it in it returning "convert: geometry does not contain image"
998
* and a 0x0 pixel image.
1000
* I haven't verified that 6.1.3 does this also, but since we don't have a
1001
* 6.1.6 ImEnvironment yet, I'll credit this bug to 6.1.3 for now.
1003
if ($this->_environment['version'] == '6.1.3' &&
1004
preg_match('/crop.*geometry/', join(' ', $params))) {
1006
* Note: This doesn't exactly simulate what IM does. It will continue like
1007
* everything is normal. We just force the test to fail for now.
1009
$output = array('convert: geometry does not contain image');
1011
print 'Error: invalid -crop followed by -geometry in same convert command!';
1014
* Remember how we converted from $src to $dst, so we can compare it later
1015
* with what we really wanted
1017
$this->_files[$dst] = array('operation' => array($binary => $params));
1025
return array(1, $output);
1027
echo $this->_environment['path'] . ": ERROR exec()ing:<pre>";
1030
return array(0, array('unprepared for exec()'));
1033
function rename($oldName, $newName) {
1034
$oldBase = basename($oldName);
1035
$newBase = basename($newName);
1036
if (isset($this->_files[$oldBase])) {
1037
$this->_files[$newBase] = $this->_files[$oldBase];
1038
if (isset($this->_files[$newBase]['operation'])) {
1039
foreach (array_keys($this->_files[$newBase]['operation']) as $operation) {
1040
$count = count($this->_files[$newBase]['operation'][$operation]);
1041
$val = $this->_files[$newBase]['operation'][$operation][$count - 1];
1042
if (preg_match('/^(jpeg|png):/', $val, $regs)) {
1043
$val = $regs[1] . ':' . $newName;
1047
$this->_files[$newBase]['operation'][$operation][$count - 1] = $val;
1050
unset($this->_files[$oldBase]);
1053
echo $this->_environment['path'] . ": rename($oldName, $newName)<br>\n";
1057
function isRestrictedByOpenBaseDir($path) {
1058
/* echo $this->_environment['path'] . ": isRestrictedByOpenBaseDir($path)<br>\n"; */
1062
function file_exists($path) {
1063
if ($path == $this->_environment['path']) {
1066
$dirName = dirname($path) . '/';
1067
$baseName = basename($path);
1068
if ($dirName == $this->_environment['path']) {
1069
if ($this->_environment['binary'] != '' && $baseName == $this->_environment['binary']) {
1072
if ($this->_environment['binary'] == ''
1073
&& in_array($baseName, $this->_environment['binaries']) ) {
1077
/*echo $this->_environment['path'] . ": file_exists($path)<br>\n"; */
1081
function is_dir($path) {
1082
if ($path == $this->_environment['path']) {
1085
/* echo $this->_environment['path'] . ": is_dir($path)<br>\n"; */
1089
function is_executable($file) {
1090
$dirName = dirname($file) . '/';
1091
$baseName = basename($file);
1092
if ($dirName == $this->_environment['path']) {
1093
if ($this->_environment['binary'] != '' && $baseName == $this->_environment['binary']) {
1096
if ($this->_environment['binary'] == ''
1097
&& in_array($baseName, $this->_environment['binaries']) ) {
1102
echo $this->_environment['path'] . ": is_executable($file)<br>\n";
1106
function copy($file1, $file2) {
1107
if (isset($this->_copyOk)) {
1110
echo $this->_environment['path'] . ": copy($file1, $file2)<br>\n";
1113
function filesize($file) {
1114
$basename = basename($file);
1115
if ($basename == 'testProfile.jpg') {
1118
if ($basename == 'compressed.jpg') {
1119
switch ($this->_counter--) {
1128
if (isset($this->_files[$basename]['size'])) {
1129
return $this->_files[$basename]['size'];
1131
echo $this->_environment['path'] . ": filesize($file)<br>\n";
1135
function tempnam($dir, $prefix) {
1136
$fileName = $dir . $prefix . md5(rand());
1137
$this->_files[basename($fileName)] = 'temp';
1138
/*echo $this->_environment['path'] . ": tempnam($dir, $prefix) = $fileName<br>\n"; */
1142
function unlink($path) {
1143
$baseName = basename($path);
1144
if (isset($this->_files[$baseName])) {
1145
unset($this->_files[$baseName]);
1148
echo $this->_environment['path'] . ": unlink($path)<br>\n";
1152
function getimagesize($path) {
1153
$basename = basename($path);
1154
if (preg_match('#\[(\d+)x(\d+)\]#', $basename, $matches)) {
1155
$result = array($matches[1], $matches[2], 1,
1156
sprintf('height="%d" width="%d"', $matches[1], $matches[2]));
1158
/*echo $this->_environment['path'] . ": getimagesize($path)<br>\n"; */
1165
function getDirectorySeparator() {
1166
return $this->_platform->getDirectorySeparator();
1169
function realpath($path) {
1170
return $this->_platform->realpath($path);
1173
function chdir($path) {
1181
function chmod($path, $mode=null) {
1182
$this->_test->_chmodWasCalled = true;