├── .gitignore ├── .php_cs.dist ├── CHANGELOG.md ├── LICENSE ├── README ├── build.xml ├── composer.json ├── demo ├── bg.gif ├── demo_screen.php ├── demos │ ├── addNoise.php │ ├── applyConvolution.php │ ├── applyFilter.php │ ├── applyMask.php │ ├── asGrayscale.php │ ├── asNegative.php │ ├── autoCrop.php │ ├── correctGamma.php │ ├── crop.php │ ├── flip.php │ ├── getCanvas.php │ ├── getChannels.php │ ├── getMask.php │ ├── merge.php │ ├── mirror.php │ ├── resize.php │ ├── resizeCanvas.php │ ├── rotate.php │ ├── roundCorners.php │ └── unsharp.php ├── font.php ├── fonts │ ├── COPYRIGHT.TXT │ ├── README.TXT │ ├── RELEASENOTES.TXT │ ├── Vera.ttf │ ├── VeraBI.ttf │ ├── VeraBd.ttf │ ├── VeraIt.ttf │ ├── VeraMoBI.ttf │ ├── VeraMoBd.ttf │ ├── VeraMoIt.ttf │ ├── VeraMono.ttf │ ├── VeraSe.ttf │ ├── VeraSeBd.ttf │ └── local.conf ├── helpers │ ├── AngleField.php │ ├── CheckboxField.php │ ├── CheckboxSetField.php │ ├── ColorField.php │ ├── CoordinateField.php │ ├── Demo.php │ ├── Field.php │ ├── FileSelectField.php │ ├── FloatField.php │ ├── FormatSelectField.php │ ├── IntField.php │ ├── Request.php │ ├── SelectField.php │ └── common.php ├── image.php ├── images │ ├── 1-rainbow.png │ ├── 2-blue-alpha.png │ ├── 3-smiley.gif │ ├── 4-color-hole.gif │ ├── 5-circle.png │ ├── 6-logo.gif │ ├── 7-overlay.png │ ├── bg03.bmp │ └── fgnl.jpg ├── index.php └── masks │ ├── mask-circle.gif │ ├── mask-circle.png │ ├── mask-diagonal.gif │ └── mask-smiley.gif ├── gpl.txt ├── lgpl.txt ├── lib ├── Canvas.php ├── Coordinate.php ├── Exception │ ├── Exception.php │ ├── GDFunctionResultException.php │ ├── InvalidCanvasMethodException.php │ ├── InvalidCoordinateException.php │ ├── InvalidFontFileException.php │ ├── InvalidImageDimensionException.php │ ├── InvalidImageHandleException.php │ ├── InvalidImageSourceException.php │ ├── NoFontException.php │ ├── UnknownErrorWhileMappingException.php │ ├── UnknownImageOperationException.php │ └── UnsupportedFormatException.php ├── Font │ ├── GDF.php │ ├── PS.php │ └── TTF.php ├── Image.php ├── Mapper │ ├── BMP.php │ ├── GD.php │ ├── GD2.php │ ├── GIF.php │ ├── JPEG.php │ ├── PNG.php │ ├── TGA.php │ └── WEBP.php ├── MapperFactory.php ├── Operation │ ├── AddNoise.php │ ├── ApplyConvolution.php │ ├── ApplyFilter.php │ ├── ApplyMask.php │ ├── AsGrayscale.php │ ├── AsNegative.php │ ├── AutoCrop.php │ ├── CopyChannelsPalette.php │ ├── CopyChannelsTrueColor.php │ ├── CorrectGamma.php │ ├── Crop.php │ ├── Exception │ │ ├── InvalidFitMethodException.php │ │ └── InvalidResizeDimensionException.php │ ├── Flip.php │ ├── GetMask.php │ ├── Merge.php │ ├── Mirror.php │ ├── Resize.php │ ├── ResizeCanvas.php │ ├── Rotate.php │ ├── RoundCorners.php │ └── Unsharp.php ├── OperationFactory.php ├── PaletteImage.php ├── TrueColorImage.php ├── WideImage.php └── vendor │ └── de77 │ ├── BMP.php │ └── TGA.php ├── phpunit.xml └── test ├── WideImage ├── CanvasTest.php ├── CoordinateTest.php ├── ImageTest.php ├── Mapper │ ├── BMPTest.php │ ├── FOO.php │ ├── FOO2.php │ ├── GD2Test.php │ ├── GDTest.php │ ├── GIFTest.php │ ├── JPEGTest.php │ ├── PNGTest.php │ └── TGATest.php ├── MapperFactoryTest.php ├── Operation │ ├── ApplyConvolutionTest.php │ ├── ApplyFilterTest.php │ ├── ApplyMaskTest.php │ ├── AsGrayscaleTest.php │ ├── AsNegativeTest.php │ ├── AutoCrop.test.php │ ├── CorrectGammaTest.php │ ├── CropTest.php │ ├── CustomOp.php │ ├── FlipTest.php │ ├── GetChannelsTest.php │ ├── GetMaskTest.php │ ├── MergeTest.php │ ├── MirrorTest.php │ ├── MyOperation.php │ ├── ResizeCanvasTest.php │ ├── ResizeTest.php │ ├── RotateTest.php │ ├── RoundCornersTest.php │ └── UnsharpTest.php ├── OperationFactoryTest.php ├── PaletteImageTest.php ├── TrueColorImageTest.php └── WideImageTest.php ├── images ├── 100x100-blue-alpha.png ├── 100x100-color-hole.gif ├── 100x100-color-hole.png ├── 100x100-rainbow.png ├── 100x100-red-spot-half-cut.png ├── 100x100-red-spot.png ├── 100x100-red-transparent.gif ├── 100x100-rgbyg.png ├── 100x100-square-overlay.png ├── 100x50-rgbt.gif ├── 75x25-gray.png ├── actually-a-png.jpg ├── bmp │ ├── favicon.ico │ ├── rainbow-16b-x.bmp │ ├── rainbow-16b.bmp │ ├── rainbow-24b.bmp │ ├── rainbow-32b.bmp │ └── rainbow-palette-rle.bmp ├── fakeimage.png ├── fgnl-bmp.jpg ├── fgnl.bmp ├── fgnl.jpg ├── image-actually-foo.foo2 ├── image.foo ├── logo.gif ├── splat.tga └── temp │ └── .gitkeep ├── run.bat ├── run.sh └── test-init.php /.gitignore: -------------------------------------------------------------------------------- 1 | /.buildpath 2 | /.idea 3 | /.php_cs.cache 4 | /.project 5 | /.settings 6 | /bin/* 7 | /build 8 | /composer.lock 9 | /nbproject 10 | /test/images/temp/* 11 | /test/images/temp/!.gitkeep 12 | /vendor 13 | -------------------------------------------------------------------------------- /.php_cs.dist: -------------------------------------------------------------------------------- 1 | in([ 5 | __DIR__ . '/demo', 6 | __DIR__ . '/lib', 7 | __DIR__ . '/test', 8 | ]) 9 | ; 10 | 11 | $config = new PhpCsFixer\Config(); 12 | 13 | return $config->setFinder($finder) 14 | ->setRules([ 15 | '@PSR2' => true, 16 | 'array_syntax' => ['syntax' => 'short'], 17 | ]) 18 | ; 19 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | 9 | ### Fixed 10 | - Added partial support for PHP 8.0 11 | - Fixed issues in PHP 7.0+ 12 | 13 | ### Changed 14 | - `ext-gd` is now required when installing the library through composer 15 | 16 | ### Removed 17 | - Removed support for PHP 5.3 - 5.5, the minimum supported version is now PHP 5.6 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | WideImage, a PHP image manipulation library 2 | Copyright 2007-2021 Gasper Kozak 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU Lesser General Public License 6 | as published by the Free Software Foundation; either version 2.1 7 | of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU Lesser General Public License for more details. 13 | 14 | You should have received a copy of the GNU Lesser General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | WideImage, a PHP image manipulation library 2 | Copyright 2007-2021 Gasper Kozak 3 | 4 | For documentation, please visit http://wideimage.sourceforge.net/ 5 | 6 | 7 | This file is part of WideImage. 8 | 9 | WideImage is free software; you can redistribute it and/or modify 10 | it under the terms of the GNU Lesser General Public License as published by 11 | the Free Software Foundation; either version 2.1 of the License, or 12 | (at your option) any later version. 13 | 14 | WideImage is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public License 20 | along with WideImage; if not, write to the Free Software 21 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "smottt/wideimage", 3 | "description": "An open-source PHP library for image manipulation", 4 | "homepage": "http://wideimage.sourceforge.net", 5 | "type": "library", 6 | "license": [ 7 | "GPL-2.0", 8 | "LGPL-2.1" 9 | ], 10 | "version": "2.0.0-dev", 11 | "autoload": { 12 | "psr-4": { 13 | "WideImage\\": "lib/" 14 | } 15 | }, 16 | "require": { 17 | "php": ">=5.6", 18 | "ext-gd": "*" 19 | }, 20 | "require-dev": { 21 | "symfony/phpunit-bridge": "^5.2", 22 | "friendsofphp/php-cs-fixer": "~2.17" 23 | }, 24 | "config": { 25 | "bin-dir": "bin" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /demo/bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/bg.gif -------------------------------------------------------------------------------- /demo/demo_screen.php: -------------------------------------------------------------------------------- 1 | 6 |
7 | 8 |
9 | 10 | fields as $field) { 12 | $field->render(); 13 | } 14 | ?> 15 |
16 | 17 | Read the API documentation for this operation. 18 | 19 | 20 |
21 | render(); 23 | echo "
\n"; 24 | echo ' Palette options (only for png8 and gif output):
'; 25 | $top_form['ncolors']->render(); 26 | echo "
\n"; 27 | $top_form['dither']->render(); 28 | $top_form['match_palette']->render(); 29 | ?> 30 |
31 |
32 |
33 | 34 | text(); 36 | ?> 37 | 38 | 39 | isDot() && strpos($file->getFilename(), '.') !== 0) { 46 | $images[] = $file->getFilename(); 47 | } 48 | } 49 | 50 | asort($images); 51 | foreach ($images as $image_file) { 52 | echo '
'; 53 | echo ''; 54 | $img_url = 'image.php?image=' . $image_file . '&output=' . $top_form['output']->value . 55 | '&colors=' . $top_form['ncolors']->value . '&dither=' . $top_form['dither']->value . 56 | '&match_palette=' . $top_form['match_palette']->value . '&demo=' . $activeDemo->name; 57 | foreach ($activeDemo->fields as $field) { 58 | $img_url .= '&' . $field->getURLValue(); 59 | } 60 | 61 | echo ' '; 62 | echo ''; 63 | echo ''; 64 | echo ''; 65 | echo "
\n"; 66 | } 67 | ?> 68 |
69 | 70 | -------------------------------------------------------------------------------- /demo/demos/addNoise.php: -------------------------------------------------------------------------------- 1 | addField(new IntField('amount', 300)); 12 | $this->addField(new SelectField('type', ['salt&pepper','mono','color'], 'mono')); 13 | } 14 | 15 | public function execute($image, $request) 16 | { 17 | return $image->addNoise($this->fields['amount']->value, $this->fields['type']->value); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /demo/demos/applyConvolution.php: -------------------------------------------------------------------------------- 1 | addField(new Field('matrix', '2 0 0, 0 -1 0, 0 0 -1', '3x3 float matrix; separate rows with a comma, and columns with a space')); 14 | $this->addField(new FloatField('div', 1)); 15 | $this->addField(new FloatField('offset', 220)); 16 | } 17 | 18 | public function execute($image, $request) 19 | { 20 | $mstr = $this->fval('matrix'); 21 | $rows = explode(',', $mstr); 22 | 23 | $matrix = []; 24 | foreach ($this->base_matrix as $idx => $base_row) { 25 | $build_row = []; 26 | if (isset($rows[$idx])) { 27 | $row = trim($rows[$idx]); 28 | $cols = explode(' ', $row); 29 | for ($c = 0; $c < 3; $c++) { 30 | if (isset($cols[$c])) { 31 | $build_row[] = floatval(trim($cols[$c])); 32 | } else { 33 | $build_row[] = $base_row[$c]; 34 | } 35 | } 36 | } else { 37 | $build_row = $base_row; 38 | } 39 | 40 | $matrix[] = $build_row; 41 | } 42 | 43 | return $image->applyConvolution($matrix, $this->fval('div'), $this->fval('offset')); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /demo/demos/applyFilter.php: -------------------------------------------------------------------------------- 1 | addField( 12 | new SelectField('filter', [ 13 | 'IMG_FILTER_NEGATE', 14 | 'IMG_FILTER_GRAYSCALE', 15 | 'IMG_FILTER_BRIGHTNESS', 16 | 'IMG_FILTER_CONTRAST', 17 | 'IMG_FILTER_COLORIZE', 18 | 'IMG_FILTER_EDGEDETECT', 19 | 'IMG_FILTER_EMBOSS', 20 | 'IMG_FILTER_GAUSSIAN_BLUR', 21 | 'IMG_FILTER_SELECTIVE_BLUR', 22 | 'IMG_FILTER_MEAN_REMOVAL', 23 | 'IMG_FILTER_SMOOTH' 24 | ]) 25 | ); 26 | $this->addField(new IntField('arg1', null)); 27 | $this->addField(new IntField('arg2', null)); 28 | $this->addField(new IntField('arg3', null)); 29 | } 30 | 31 | public function execute($image) 32 | { 33 | $filter = constant($this->fields['filter']->value); 34 | $arg1 = $this->fields['arg1']->value; 35 | $arg2 = $this->fields['arg2']->value; 36 | $arg3 = $this->fields['arg3']->value; 37 | 38 | return $image->applyFilter($filter, $arg1, $arg2, $arg3); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /demo/demos/applyMask.php: -------------------------------------------------------------------------------- 1 | addField(new FileSelectField('mask', 'masks')); 12 | $this->addField(new CoordinateField('left', 10)); 13 | $this->addField(new CoordinateField('top', '30%')); 14 | 15 | if (!$this->request->get('mask')) { 16 | $this->request->set('mask', 'mask-circle.gif'); 17 | } 18 | } 19 | 20 | public function execute($image) 21 | { 22 | $mask = \WideImage\WideImage::load(DEMO_PATH . 'masks/' . $this->fields['mask']->value); 23 | $left = $this->fields['left']->value; 24 | $top = $this->fields['top']->value; 25 | 26 | return $image->applyMask($mask, $left, $top); 27 | } 28 | 29 | public function getFormat() 30 | { 31 | return 'png'; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /demo/demos/asGrayscale.php: -------------------------------------------------------------------------------- 1 | asGrayscale(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /demo/demos/asNegative.php: -------------------------------------------------------------------------------- 1 | asNegative(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /demo/demos/autoCrop.php: -------------------------------------------------------------------------------- 1 | addField(new IntField('margin', 0)); 12 | $this->addField(new IntField('rgb_threshold', 0)); 13 | $this->addField(new IntField('pixel_cutoff', 1)); 14 | $this->addField(new IntField('base_color', null, 'Index of the color')); 15 | } 16 | 17 | public function execute($image, $request) 18 | { 19 | $margin = $this->fields['margin']->value; 20 | $rgb_threshold = $this->fields['rgb_threshold']->value; 21 | $pixel_cutoff = $this->fields['pixel_cutoff']->value; 22 | $base_color = $this->fields['base_color']->value; 23 | 24 | return $image->autoCrop($margin, $rgb_threshold, $pixel_cutoff, $base_color); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /demo/demos/correctGamma.php: -------------------------------------------------------------------------------- 1 | addField(new FloatField('in_gamma', 1.1)); 12 | $this->addField(new FloatField('out_gamma', 3.7)); 13 | } 14 | 15 | public function execute($image, $request) 16 | { 17 | return $image->correctGamma($this->fval('in_gamma'), $this->fval('out_gamma')); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /demo/demos/crop.php: -------------------------------------------------------------------------------- 1 | addField(new CoordinateField('left', 10)); 12 | $this->addField(new CoordinateField('top', 20)); 13 | $this->addField(new CoordinateField('width', 120)); 14 | $this->addField(new CoordinateField('height', 60)); 15 | } 16 | 17 | public function execute($image, $request) 18 | { 19 | $left = $this->fields['left']->value; 20 | $top = $this->fields['top']->value; 21 | $width = $this->fields['width']->value; 22 | $height = $this->fields['height']->value; 23 | 24 | return $image->crop($left, $top, $width, $height); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /demo/demos/flip.php: -------------------------------------------------------------------------------- 1 | flip(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /demo/demos/getCanvas.php: -------------------------------------------------------------------------------- 1 | addField(new Field('text', 'Hello world!')); 12 | $this->addField(new CoordinateField('x', 'middle')); 13 | $this->addField(new CoordinateField('y', 'bottom-5')); 14 | $this->addField(new IntField('angle', 5)); 15 | $this->addField(new FileSelectField('font', 'fonts', ['show' => false, 'pattern' => '/(.*)\.ttf$/', 'default' => 'VeraSe.ttf'])); 16 | $this->addField(new IntField('size', 18)); 17 | } 18 | 19 | public function execute($image, $request) 20 | { 21 | $text = $this->fields['text']->value; 22 | $x = $this->fields['x']->value; 23 | $y = $this->fields['y']->value; 24 | $angle = $this->fields['angle']->value; 25 | $font = $this->fields['font']->value; 26 | $font_size = $this->fields['size']->value; 27 | 28 | $canvas = $image->getCanvas(); 29 | 30 | $canvas->filledRectangle(10, 10, 80, 40, $image->allocateColor(255, 127, 255)); 31 | $canvas->line(60, 80, 30, 100, $image->allocateColor(255, 0, 0)); 32 | 33 | $font_file = DEMO_PATH . 'fonts/' . $font; 34 | 35 | $canvas->useFont($font_file, $font_size, $image->allocateColor(0, 0, 0)); 36 | $canvas->writeText("$x+1", "$y+1", $text, $angle); 37 | 38 | $canvas->useFont($font_file, $font_size, $image->allocateColor(200, 220, 255)); 39 | $canvas->writeText($x, $y, $text, $angle); 40 | 41 | return $image; 42 | } 43 | 44 | public function et($name) 45 | { 46 | return htmlentities($this->fval($name)); 47 | } 48 | 49 | public function text() 50 | { 51 | echo "This demo executes: 52 |
53 | 	\$canvas->filledRectangle(10, 10, 80, 40, \$img->allocateColor(255, 127, 255));
54 | 	\$canvas->line(60, 80, 30, 100, \$img->allocateColor(255, 0, 0));
55 | 	
56 | 	\$canvas->useFont('{$this->et('font')}', '{$this->et('size')}', \$image->allocateColor(0, 0, 0));
57 | 	\$canvas->writeText('{$this->et('x')}+1', '{$this->et('y')}+1', '{$this->et('text')}', {$this->et('angle')});
58 | 	
59 | 	\$canvas->useFont('{$this->et('font')}', '{$this->et('size')}', \$image->allocateColor(200, 220, 255));
60 | 	\$canvas->writeText('{$this->et('x')}', '{$this->et('y')}', '{$this->et('text')}', {$this->et('angle')});
61 | 	
"; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /demo/demos/getChannels.php: -------------------------------------------------------------------------------- 1 | addField(new CheckboxField('red', true)); 14 | $this->addField(new CheckboxField('green', false)); 15 | $this->addField(new CheckboxField('blue', true)); 16 | $this->addField(new CheckboxField('alpha', false)); 17 | } 18 | 19 | public function execute($img, $request) 20 | { 21 | $on = []; 22 | foreach ($this->channels as $name) { 23 | if ($this->fields[$name]->value) { 24 | $on[] = $name; 25 | } 26 | } 27 | 28 | return $img->getChannels($on); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /demo/demos/getMask.php: -------------------------------------------------------------------------------- 1 | getMask(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /demo/demos/merge.php: -------------------------------------------------------------------------------- 1 | addField(new FileSelectField('overlay', 'images', ['default' => '6-logo.gif'])); 12 | $this->addField(new CoordinateField('left', 'right-10')); 13 | $this->addField(new CoordinateField('top', 'bottom-15%')); 14 | $this->addField(new IntField('opacity', 50)); 15 | } 16 | 17 | public function execute($image, $request) 18 | { 19 | $overlay = \WideImage\WideImage::load(DEMO_PATH . 'images/' . $this->fields['overlay']->value); 20 | $left = $this->fields['left']->value; 21 | $top = $this->fields['top']->value; 22 | $opacity = $this->fields['opacity']->value; 23 | 24 | return $image->merge($overlay, $left, $top, $opacity); 25 | } 26 | 27 | public function text() 28 | { 29 | echo "For alpha images, set opacity=100, otherwise alpha channel won't work."; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /demo/demos/mirror.php: -------------------------------------------------------------------------------- 1 | mirror(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /demo/demos/resize.php: -------------------------------------------------------------------------------- 1 | addField(new CoordinateField('width', 120)); 12 | $this->addField(new CoordinateField('height', null)); 13 | $this->addField(new SelectField('fit', ['inside', 'fill', 'outside'])); 14 | $this->addField(new SelectField('scale', ['any', 'down', 'up'])); 15 | } 16 | 17 | public function execute($image, $request) 18 | { 19 | $width = $this->fields['width']->value; 20 | $height = $this->fields['height']->value; 21 | $fit = $this->fields['fit']->value; 22 | $scale = $this->fields['scale']->value; 23 | 24 | return $image->resize($width, $height, $fit, $scale); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /demo/demos/resizeCanvas.php: -------------------------------------------------------------------------------- 1 | addField(new CoordinateField('width', '100%+30')); 12 | $this->addField(new CoordinateField('height', 200)); 13 | $this->addField(new CoordinateField('left', '2')); 14 | $this->addField(new CoordinateField('top', 'bottom-10')); 15 | $this->addField(new ColorField('color', 'ffffff')); 16 | $this->addField(new SelectField('scale', ['any', 'down', 'up'], 'any')); 17 | $this->addField(new CheckboxField('merge', false, "Merge or copy over")); 18 | } 19 | 20 | public function execute($image, $request) 21 | { 22 | $width = $this->fields['width']->value; 23 | $height = $this->fields['height']->value; 24 | $left = $this->fields['left']->value; 25 | $top = $this->fields['top']->value; 26 | $color = $this->fields['color']->value; 27 | $scale = $this->fields['scale']->value; 28 | $merge = $this->fields['merge']->value; 29 | 30 | return $image->resizeCanvas($width, $height, $left, $top, $color ? hexdec($color) : null, $scale, $merge); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /demo/demos/rotate.php: -------------------------------------------------------------------------------- 1 | addField(new AngleField('angle', 25)); 12 | $this->addField(new ColorField('color', '')); 13 | } 14 | 15 | public function execute($image, $request) 16 | { 17 | $angle = $this->fields['angle']->value; 18 | $color = $this->fields['color']->value; 19 | 20 | return $image->rotate($angle, $color ? hexdec($color) : null); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /demo/demos/roundCorners.php: -------------------------------------------------------------------------------- 1 | addField(new IntField('radius', 30)); 12 | $this->addField(new ColorField('color', 'ffffff')); 13 | $this->addField(new IntField('smoothness', 2)); 14 | 15 | $this->addField(new CheckboxField('top-left', true)); 16 | $this->addField(new CheckboxField('top-right', true)); 17 | $this->addField(new CheckboxField('bottom-right', true)); 18 | $this->addField(new CheckboxField('bottom-left', true)); 19 | } 20 | 21 | public function execute($image, $request) 22 | { 23 | $color = $this->fields['color']->value; 24 | $radius = $this->fields['radius']->value; 25 | $smoothness = $this->fields['smoothness']->value; 26 | 27 | $corners = 0; 28 | if ($this->fval('top-left')) { 29 | $corners += \WideImage\WideImage::SIDE_TOP_LEFT; 30 | } 31 | 32 | if ($this->fval('top-right')) { 33 | $corners += \WideImage\WideImage::SIDE_TOP_RIGHT; 34 | } 35 | 36 | if ($this->fval('bottom-right')) { 37 | $corners += \WideImage\WideImage::SIDE_BOTTOM_RIGHT; 38 | } 39 | 40 | if ($this->fval('bottom-left')) { 41 | $corners += \WideImage\WideImage::SIDE_BOTTOM_LEFT; 42 | } 43 | 44 | return $image->roundCorners($radius, $color ? hexdec($color) : null, $smoothness, $corners); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /demo/demos/unsharp.php: -------------------------------------------------------------------------------- 1 | addField(new IntField('amount', 300)); 12 | $this->addField(new IntField('radius', 3)); 13 | $this->addField(new IntField('threshold', 2)); 14 | } 15 | 16 | public function execute($image, $request) 17 | { 18 | return $image->unsharp($this->fields['amount']->value, $this->fields['radius']->value, $this->fields['threshold']->value); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /demo/font.php: -------------------------------------------------------------------------------- 1 | getCanvas(); 6 | $canvas->useFont('fonts/Vera.ttf', 36, $img->allocateColor(255, 0, 0)); 7 | $canvas->writeText('left', 'top', 'abc', 0); 8 | $canvas->writeText('right', 'top', 'def', 15); 9 | $canvas->writeText('right', 'bottom', 'ghi', 30); 10 | $canvas->writeText('left', 'bottom', 'jkl', 45); 11 | $canvas->writeText('center', 'center', 'mno', 60); 12 | $img->output('png'); 13 | exit; 14 | 15 | // Create a 300x150 image 16 | $im = imagecreatetruecolor(600, 350); 17 | $black = imagecolorallocate($im, 0, 0, 0); 18 | $bgcolor = imagecolorallocate($im, 255, 255, 0); 19 | 20 | // Set the background to be white 21 | imagefilledrectangle($im, 0, 0, imagesx($im), imagesy($im), $bgcolor); 22 | 23 | // Path to our font file 24 | $font = './fonts/Vera.ttf'; 25 | 26 | $angle = 340; 27 | $font_size = 20; 28 | $text = 'jW| asdkasdlk alk,.,wedwer|w[r=?'; 29 | $text = '#j'; 30 | 31 | // First we create our bounding box 32 | $bbox = imageftbbox($font_size, $angle, $font, $text); 33 | 34 | 35 | function normalize_bbox($bbox) 36 | { 37 | return [ 38 | 'up-left' => ['x' => $bbox[6], 'y' => $bbox[7]], 39 | 'up-right' => ['x' => $bbox[4], 'y' => $bbox[5]], 40 | 'down-left' => ['x' => $bbox[0], 'y' => $bbox[1]], 41 | 'down-right' => ['x' => $bbox[2], 'y' => $bbox[3]], 42 | ]; 43 | } 44 | 45 | function outer_box($box) 46 | { 47 | return [ 48 | 'left' => min($box['up-left']['x'], $box['up-right']['x'], $box['down-left']['x'], $box['down-right']['x']), 49 | 'top' => min($box['up-left']['y'], $box['up-right']['y'], $box['down-left']['y'], $box['down-right']['y']), 50 | 'right' => max($box['up-left']['x'], $box['up-right']['x'], $box['down-left']['x'], $box['down-right']['x']), 51 | 'bottom' => max($box['up-left']['y'], $box['up-right']['y'], $box['down-left']['y'], $box['down-right']['y']) 52 | ]; 53 | } 54 | 55 | $box = normalize_bbox($bbox); 56 | 57 | // This is our cordinates for X and Y 58 | #$x = $bbox[0] + (imagesx($im) / 2) - ($bbox[4] / 2) - 5; 59 | #$y = $bbox[1] + (imagesy($im) / 2) - ($bbox[5] / 2) - 5; 60 | #$x = 300; 61 | #$y = 175; 62 | 63 | $obox = outer_box(normalize_bbox(imageftbbox($font_size, $angle, $font, ''))); 64 | $obox = outer_box(normalize_bbox(imageftbbox($font_size, $angle, $font, $text))); 65 | 66 | #$x = imagesx($im) - $obox['right'] - 1; 67 | #$y = imagesy($im) - $obox['bottom'] - 1; 68 | $x = 0; 69 | $y = 0; 70 | 71 | $gc = imagecolorallocate($im, 255, 200, 200); 72 | imageline($im, imagesx($im) / 2, 0, imagesx($im) / 2, imagesy($im), $gc); 73 | imageline($im, 0, imagesy($im) / 2, imagesx($im), imagesy($im) / 2, $gc); 74 | 75 | 76 | imagefttext($im, $font_size, $angle, $x, $y, $black, $font, $text); 77 | #imagefttext($im, $font_size, $angle, $x, $y, $black, $font, 'aj'); 78 | 79 | $c = imagecolorallocate($im, 0, 255, 0); 80 | imageline($im, $box['up-left']['x'] + $x, $box['up-left']['y'] + $y, $box['up-right']['x'] + $x, $box['up-right']['y'] + $y, $c); 81 | imageline($im, $box['up-right']['x'] + $x, $box['up-right']['y'] + $y, $box['down-right']['x'] + $x, $box['down-right']['y'] + $y, $c); 82 | imageline($im, $box['down-right']['x'] + $x, $box['down-right']['y'] + $y, $box['down-left']['x'] + $x, $box['down-left']['y'] + $y, $c); 83 | imageline($im, $box['down-left']['x'] + $x, $box['down-left']['y'] + $y, $box['up-left']['x'] + $x, $box['up-left']['y'] + $y, $c); 84 | 85 | $c = imagecolorallocate($im, 0, 127, 255); 86 | $obox = outer_box($box); 87 | imageline($im, $obox['left'] + $x, $obox['top'] + $y, $obox['right'] + $x, $obox['top'] + $y, $c); 88 | imageline($im, $obox['right'] + $x, $obox['top'] + $y, $obox['right'] + $x, $obox['bottom'] + $y, $c); 89 | imageline($im, $obox['right'] + $x, $obox['bottom'] + $y, $obox['left'] + $x, $obox['bottom'] + $y, $c); 90 | imageline($im, $obox['left'] + $x, $obox['bottom'] + $y, $obox['left'] + $x, $obox['top'] + $y, $c); 91 | 92 | imagefilledellipse($im, $x, $y, 3, 3, imagecolorallocate($im, 255, 0, 0)); 93 | 94 | 95 | // Output to browser 96 | header('Content-type: image/png'); 97 | 98 | imagepng($im); 99 | imagedestroy($im); 100 | -------------------------------------------------------------------------------- /demo/fonts/README.TXT: -------------------------------------------------------------------------------- 1 | Contained herin is the Bitstream Vera font family. 2 | 3 | The Copyright information is found in the COPYRIGHT.TXT file (along 4 | with being incoporated into the fonts themselves). 5 | 6 | The releases notes are found in the file "RELEASENOTES.TXT". 7 | 8 | We hope you enjoy Vera! 9 | 10 | Bitstream, Inc. 11 | The Gnome Project 12 | -------------------------------------------------------------------------------- /demo/fonts/Vera.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/fonts/Vera.ttf -------------------------------------------------------------------------------- /demo/fonts/VeraBI.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/fonts/VeraBI.ttf -------------------------------------------------------------------------------- /demo/fonts/VeraBd.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/fonts/VeraBd.ttf -------------------------------------------------------------------------------- /demo/fonts/VeraIt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/fonts/VeraIt.ttf -------------------------------------------------------------------------------- /demo/fonts/VeraMoBI.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/fonts/VeraMoBI.ttf -------------------------------------------------------------------------------- /demo/fonts/VeraMoBd.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/fonts/VeraMoBd.ttf -------------------------------------------------------------------------------- /demo/fonts/VeraMoIt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/fonts/VeraMoIt.ttf -------------------------------------------------------------------------------- /demo/fonts/VeraMono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/fonts/VeraMono.ttf -------------------------------------------------------------------------------- /demo/fonts/VeraSe.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/fonts/VeraSe.ttf -------------------------------------------------------------------------------- /demo/fonts/VeraSeBd.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/fonts/VeraSeBd.ttf -------------------------------------------------------------------------------- /demo/fonts/local.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 14 | 15 | serif 16 | 17 | Bitstream Vera Serif 18 | 19 | 20 | 21 | sans-serif 22 | 23 | Bitstream Vera Sans 24 | 25 | 26 | 27 | monospace 28 | 29 | Bitstream Vera Sans Mono 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /demo/helpers/AngleField.php: -------------------------------------------------------------------------------- 1 | value = $request->get($this->name, $this->default ? '1' : null) === '1'; 10 | } 11 | 12 | public function renderBody($name, $id) 13 | { 14 | if ($this->value) { 15 | $chk = 'checked="checked"'; 16 | } else { 17 | $chk = ''; 18 | } 19 | 20 | echo ''; 21 | echo ''; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /demo/helpers/CheckboxSetField.php: -------------------------------------------------------------------------------- 1 | name = $name; 13 | $this->options = $options; 14 | } 15 | 16 | public function init($request) 17 | { 18 | $this->value = []; 19 | if (is_array($request->get($this->name))) { 20 | foreach ($request->get($this->name) as $val) { 21 | if (in_array($val, $this->options)) { 22 | $this->value[] = $val; 23 | } 24 | } 25 | } 26 | } 27 | 28 | public function render() 29 | { 30 | $request = $this->request; 31 | foreach ($this->options as $option) { 32 | if (is_array($request->get($this->name)) && in_array($option, $request->get($this->name))) { 33 | $chk = 'checked="checked"'; 34 | } else { 35 | $chk = ''; 36 | } 37 | 38 | $name = $this->name . '[]'; 39 | $id = $this->name . '_' . $option; 40 | echo ''; 41 | echo ' '; 42 | } 43 | } 44 | 45 | public function getURLValue() 46 | { 47 | $v = ''; 48 | foreach ($this->value as $value) { 49 | $v .= $this->name . '[]=' . $value . '&'; 50 | } 51 | return $v; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /demo/helpers/ColorField.php: -------------------------------------------------------------------------------- 1 | getColor($this->name, $this->default); 15 | if ($c === '') { 16 | $this->value = null; 17 | } else { 18 | $this->value = str_pad(dechex(hexdec($c)), 6, '0', STR_PAD_LEFT); 19 | } 20 | } 21 | 22 | public function getRenderValue() 23 | { 24 | return $this->value; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /demo/helpers/CoordinateField.php: -------------------------------------------------------------------------------- 1 | value = $request->getCoordinate($this->name, $this->default); 15 | if ($this->value > 1000) { 16 | $this->value = 1000; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /demo/helpers/Demo.php: -------------------------------------------------------------------------------- 1 | name = $name; 15 | } 16 | 17 | public function init() 18 | { 19 | } 20 | 21 | public static function create($name) 22 | { 23 | $file = DEMO_PATH . '/demos/' . $name . '.php'; 24 | if (!file_exists($file)) { 25 | throw new Exception("Invalid demo: {$name}"); 26 | } 27 | include $file; 28 | $className = 'Demo_' . $name; 29 | $demo = new $className($name); 30 | $demo->request = Request::getInstance(); 31 | $demo->init(); 32 | foreach ($demo->fields as $field) { 33 | $field->request = Request::getInstance(); 34 | $field->init(Request::getInstance()); 35 | } 36 | return $demo; 37 | } 38 | 39 | public function getFormat() 40 | { 41 | return 'as input'; 42 | } 43 | 44 | public function addField($field) 45 | { 46 | $this->fields[$field->name] = $field; 47 | } 48 | 49 | public function __toString() 50 | { 51 | return $this->name; 52 | } 53 | 54 | public function text() 55 | { 56 | } 57 | 58 | public function fval($name) 59 | { 60 | return $this->fields[$name]->value; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /demo/helpers/Field.php: -------------------------------------------------------------------------------- 1 | name = $name; 16 | $this->default = $default; 17 | 18 | if ($hint == '') { 19 | $hint = $name; 20 | } 21 | 22 | $this->hint = $hint; 23 | } 24 | 25 | public function init($request) 26 | { 27 | $this->value = $request->get($this->name, $this->default); 28 | } 29 | 30 | public function render() 31 | { 32 | $id = htmlentities($this->name); 33 | echo ' '; 37 | } 38 | 39 | public function renderBody($name, $id) 40 | { 41 | echo ''; 42 | } 43 | 44 | public function getRenderValue() 45 | { 46 | return $this->value; 47 | } 48 | 49 | public function getUrlValue() 50 | { 51 | return urlencode($this->name) . '=' . urlencode($this->value); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /demo/helpers/FileSelectField.php: -------------------------------------------------------------------------------- 1 | name = $name; 14 | $this->path = $path; 15 | $this->options = $options; 16 | 17 | if (!isset($options['show'])) { 18 | $this->options['show'] = true; 19 | } 20 | 21 | if (!isset($options['pattern'])) { 22 | $this->options['pattern'] = '/(.*)/'; 23 | } 24 | } 25 | 26 | public function init($request) 27 | { 28 | $this->value = null; 29 | $di = new DirectoryIterator(DEMO_PATH . $this->path); 30 | foreach ($di as $file) { 31 | if (!$file->isDot() && strpos($file->getFilename(), '.') !== 0 && preg_match($this->options['pattern'], $file->getFilename())) { 32 | $this->files[] = $file->getFilename(); 33 | if ($this->value === null && isset($this->options['default']) && $this->options['default'] == $file->getFilename()) { 34 | $this->value = $this->options['default']; 35 | } 36 | 37 | if ($this->request->get($this->name) == $file->getFilename()) { 38 | $this->value = $file->getFilename(); 39 | } 40 | } 41 | } 42 | 43 | sort($this->files); 44 | 45 | if (!$this->value && count($this->files) > 0) { 46 | $this->value = $this->files[0]; 47 | } 48 | } 49 | 50 | public function renderBody($name, $id) 51 | { 52 | if ($this->options['show']) { 53 | $onch = "document.getElementById('sel_{$id}').src = '{$this->path}/' + this.options[this.selectedIndex].value;"; 54 | } else { 55 | $onch = ''; 56 | } 57 | 58 | echo ''; 71 | 72 | if ($this->options['show'] && $selected_file) { 73 | echo '
'; 74 | echo ' '; 75 | echo "               "; 76 | echo '
'; 77 | } 78 | } 79 | 80 | public function getURLValue() 81 | { 82 | return $this->name . '=' . $this->value; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /demo/helpers/FloatField.php: -------------------------------------------------------------------------------- 1 | value = $request->getFloat($this->name, $this->default); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /demo/helpers/FormatSelectField.php: -------------------------------------------------------------------------------- 1 | value = $request->getInt($this->name, $this->default); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /demo/helpers/SelectField.php: -------------------------------------------------------------------------------- 1 | name = $name; 13 | $this->options = $options; 14 | if ($default === null) { 15 | $this->default = $options[0]; 16 | } else { 17 | $this->default = $default; 18 | } 19 | } 20 | 21 | public function init($request) 22 | { 23 | $this->value = $this->default; 24 | $v = str_replace('+', ' ', $request->get($this->name)); 25 | if (in_array($v, $this->options)) { 26 | $this->value = $v; 27 | } 28 | } 29 | 30 | public function renderBody($name, $id) 31 | { 32 | echo ''; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /demo/helpers/common.php: -------------------------------------------------------------------------------- 1 | get('demo')); 10 | $image = \WideImage\WideImage::load('images/' . $request->get('image')); 11 | 12 | $result = $demo->execute($image, $request); 13 | 14 | $output = new FormatSelectField('output'); 15 | $output->init(Request::getInstance()); 16 | 17 | if ($output->value == 'preset for demo') { 18 | $format = $demo->getFormat(); 19 | } else { 20 | $format = $output->value; 21 | } 22 | 23 | if ($format === 'as input') { 24 | $format = substr($request->get('image'), -3); 25 | } 26 | 27 | $output = 24; 28 | if ($format == 'png8') { 29 | $output = 8; 30 | $format = 'png'; 31 | } elseif ($format == 'png24') { 32 | $format = 'png'; 33 | } elseif ($format == 'gif') { 34 | $output = 8; 35 | } 36 | 37 | if ($output == 8) { 38 | $ncolors = new IntField('colors', 255); 39 | $ncolors->init(Request::getInstance()); 40 | 41 | $dither = new CheckboxField('dither', true); 42 | $dither->init(Request::getInstance()); 43 | 44 | $match_palette = new CheckboxField('match_palette', true); 45 | $match_palette->init(Request::getInstance()); 46 | 47 | $result = $result->asPalette($ncolors->value, $dither->value, $match_palette->value); 48 | } 49 | 50 | $result->output($format); 51 | -------------------------------------------------------------------------------- /demo/images/1-rainbow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/images/1-rainbow.png -------------------------------------------------------------------------------- /demo/images/2-blue-alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/images/2-blue-alpha.png -------------------------------------------------------------------------------- /demo/images/3-smiley.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/images/3-smiley.gif -------------------------------------------------------------------------------- /demo/images/4-color-hole.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/images/4-color-hole.gif -------------------------------------------------------------------------------- /demo/images/5-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/images/5-circle.png -------------------------------------------------------------------------------- /demo/images/6-logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/images/6-logo.gif -------------------------------------------------------------------------------- /demo/images/7-overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/images/7-overlay.png -------------------------------------------------------------------------------- /demo/images/bg03.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/images/bg03.bmp -------------------------------------------------------------------------------- /demo/images/fgnl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/images/fgnl.jpg -------------------------------------------------------------------------------- /demo/masks/mask-circle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/masks/mask-circle.gif -------------------------------------------------------------------------------- /demo/masks/mask-circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/masks/mask-circle.png -------------------------------------------------------------------------------- /demo/masks/mask-diagonal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/masks/mask-diagonal.gif -------------------------------------------------------------------------------- /demo/masks/mask-smiley.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/demo/masks/mask-smiley.gif -------------------------------------------------------------------------------- /lib/Exception/Exception.php: -------------------------------------------------------------------------------- 1 | = 1 && $face <= 5) { 39 | $this->font = $face; 40 | } else { 41 | $this->font = imageloadfont($face); 42 | } 43 | 44 | $this->color = $color; 45 | } 46 | 47 | public function writeText($image, $x, $y, $text) 48 | { 49 | imagestring($image->getHandle(), $this->font, $x, $y, $text, $this->color); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/Font/PS.php: -------------------------------------------------------------------------------- 1 | handle = imagepsloadfont($file); 40 | $this->size = $size; 41 | $this->color = $color; 42 | 43 | if ($bgcolor === null) { 44 | $this->bgcolor = $color; 45 | } else { 46 | $this->color = $color; 47 | } 48 | } 49 | 50 | public function writeText($image, $x, $y, $text, $angle = 0) 51 | { 52 | if ($image->isTrueColor()) { 53 | $image->alphaBlending(true); 54 | } 55 | 56 | imagepstext($image->getHandle(), $text, $this->handle, $this->size, $this->color, $this->bgcolor, $x, $y, 0, 0, $angle, 4); 57 | } 58 | 59 | public function __destruct() 60 | { 61 | imagepsfreefont($this->handle); 62 | $this->handle = null; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/Font/TTF.php: -------------------------------------------------------------------------------- 1 | face = $face; 42 | $this->size = $size; 43 | $this->color = $color; 44 | } 45 | 46 | /** 47 | * Writes text onto an image 48 | * 49 | * @param \WideImage\Image $image 50 | * @param mixed $x smart coordinate 51 | * @param mixed $y smart coordinate 52 | * @param string $text 53 | * @param int $angle Angle in degrees clockwise 54 | */ 55 | public function writeText($image, $x, $y, $text, $angle = 0) 56 | { 57 | if ($image->isTrueColor()) { 58 | $image->alphaBlending(true); 59 | } 60 | 61 | $box = imageftbbox($this->size, $angle, $this->face, $text); 62 | $obox = [ 63 | 'left' => min($box[0], $box[2], $box[4], $box[6]), 64 | 'top' => min($box[1], $box[3], $box[5], $box[7]), 65 | 'right' => max($box[0], $box[2], $box[4], $box[6]) - 1, 66 | 'bottom' => max($box[1], $box[3], $box[5], $box[7]) - 1 67 | ]; 68 | $obox['width'] = abs($obox['left']) + abs($obox['right']); 69 | $obox['height'] = abs($obox['top']) + abs($obox['bottom']); 70 | 71 | $x = Coordinate::fix($x, $image->getWidth(), $obox['width']); 72 | $y = Coordinate::fix($y, $image->getHeight(), $obox['height']); 73 | 74 | $fixed_x = $x - $obox['left']; 75 | $fixed_y = $y - $obox['top']; 76 | 77 | imagettftext($image->getHandle(), $this->size, $angle, $fixed_x, $fixed_y, $this->color, $this->face, $text); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /lib/Mapper/BMP.php: -------------------------------------------------------------------------------- 1 | asTrueColor(); 47 | 48 | if (!imageconvolution($new->getHandle(), $matrix, $div, $offset)) { 49 | throw new GDFunctionResultException("imageconvolution() returned false"); 50 | } 51 | 52 | return $new; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/Operation/ApplyFilter.php: -------------------------------------------------------------------------------- 1 | asTrueColor(); 55 | 56 | if (in_array($filter, static::$one_arg_filters)) { 57 | $res = imagefilter($new->getHandle(), $filter, $arg1); 58 | } elseif (defined('IMG_FILTER_PIXELATE') && $filter == IMG_FILTER_PIXELATE) { 59 | $res = imagefilter($new->getHandle(), $filter, $arg1, $arg2); 60 | } elseif ($filter == IMG_FILTER_COLORIZE) { 61 | $res = imagefilter($new->getHandle(), $filter, $arg1, $arg2, $arg3, $arg4); 62 | } else { 63 | $res = imagefilter($new->getHandle(), $filter); 64 | } 65 | 66 | if (!$res) { 67 | throw new GDFunctionResultException("imagefilter() returned false"); 68 | } 69 | 70 | return $new; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /lib/Operation/ApplyMask.php: -------------------------------------------------------------------------------- 1 | getWidth(), $mask->getWidth()); 47 | $top = Coordinate::fix($top, $image->getHeight(), $mask->getHeight()); 48 | 49 | $width = $image->getWidth(); 50 | $mask_width = $mask->getWidth(); 51 | 52 | $height = $image->getHeight(); 53 | $mask_height = $mask->getHeight(); 54 | 55 | $result = $image->asTrueColor(); 56 | 57 | $result->alphaBlending(false); 58 | $result->saveAlpha(true); 59 | 60 | $srcTransparentColor = $result->getTransparentColor(); 61 | 62 | if ($srcTransparentColor >= 0) { 63 | $destTransparentColor = $srcTransparentColor; 64 | } else { 65 | $destTransparentColor = $result->allocateColorAlpha(255, 255, 255, 127); 66 | } 67 | 68 | for ($x = 0; $x < $width; $x++) { 69 | for ($y = 0; $y < $height; $y++) { 70 | $mx = $x - $left; 71 | $my = $y - $top; 72 | 73 | if ($mx >= 0 && $mx < $mask_width && $my >= 0 && $my < $mask_height) { 74 | $srcColor = $image->getColorAt($x, $y); 75 | 76 | if ($srcColor == $srcTransparentColor) { 77 | $destColor = $destTransparentColor; 78 | } else { 79 | $maskRGB = $mask->getRGBAt($mx, $my); 80 | 81 | if ($maskRGB['red'] == 0) { 82 | $destColor = $destTransparentColor; 83 | } elseif ($srcColor >= 0) { 84 | $imageRGB = $image->getRGBAt($x, $y); 85 | $level = ($maskRGB['red'] / 255) * (1 - $imageRGB['alpha'] / 127); 86 | $imageRGB['alpha'] = 127 - round($level * 127); 87 | 88 | if ($imageRGB['alpha'] == 127) { 89 | $destColor = $destTransparentColor; 90 | } else { 91 | $destColor = $result->allocateColorAlpha($imageRGB); 92 | } 93 | } else { 94 | $destColor = $destTransparentColor; 95 | } 96 | } 97 | 98 | $result->setColorAt($x, $y, $destColor); 99 | } 100 | } 101 | } 102 | 103 | return $result; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /lib/Operation/AsGrayscale.php: -------------------------------------------------------------------------------- 1 | asTrueColor(); 44 | 45 | if (!imagefilter($new->getHandle(), IMG_FILTER_GRAYSCALE)) { 46 | throw new GDFunctionResultException("imagefilter() returned false"); 47 | } 48 | 49 | if (!$image->isTrueColor()) { 50 | $new = $new->asPalette(); 51 | } 52 | 53 | return $new; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /lib/Operation/AsNegative.php: -------------------------------------------------------------------------------- 1 | isTrueColor(); 44 | $transparent = $image->isTransparent(); 45 | 46 | if ($palette && $transparent) { 47 | $tcrgb = $image->getTransparentColorRGB(); 48 | } 49 | 50 | $new = $image->asTrueColor(); 51 | 52 | if (!imagefilter($new->getHandle(), IMG_FILTER_NEGATE)) { 53 | throw new GDFunctionResultException("imagefilter() returned false"); 54 | } 55 | 56 | if ($palette) { 57 | $new = $new->asPalette(); 58 | 59 | if ($transparent) { 60 | $irgb = [ 61 | 'red' => 255 - $tcrgb['red'], 62 | 'green' => 255 - $tcrgb['green'], 63 | 'blue' => 255 - $tcrgb['blue'], 64 | 'alpha' => 127 65 | ]; 66 | 67 | // needs imagecolorexactalpha instead of imagecolorexact, otherwise doesn't work on some transparent GIF images 68 | $new_tci = imagecolorexactalpha($new->getHandle(), $irgb['red'], $irgb['green'], $irgb['blue'], 127); 69 | $new->setTransparentColor($new_tci); 70 | } 71 | } 72 | 73 | return $new; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /lib/Operation/CopyChannelsPalette.php: -------------------------------------------------------------------------------- 1 | 0, 48 | 'green' => 0, 49 | 'blue' => 0 50 | ]; 51 | 52 | if (isset($channels['alpha'])) { 53 | unset($channels['alpha']); 54 | } 55 | 56 | $width = $img->getWidth(); 57 | $height = $img->getHeight(); 58 | $copy = PaletteImage::create($width, $height); 59 | 60 | if ($img->isTransparent()) { 61 | $otci = $img->getTransparentColor(); 62 | $TRGB = $img->getColorRGB($otci); 63 | $tci = $copy->allocateColor($TRGB); 64 | } else { 65 | $otci = null; 66 | $tci = null; 67 | } 68 | 69 | for ($x = 0; $x < $width; $x++) { 70 | for ($y = 0; $y < $height; $y++) { 71 | $ci = $img->getColorAt($x, $y); 72 | 73 | if ($ci === $otci) { 74 | $copy->setColorAt($x, $y, $tci); 75 | continue; 76 | } 77 | 78 | $RGB = $img->getColorRGB($ci); 79 | 80 | $newRGB = $blank; 81 | 82 | foreach ($channels as $channel) { 83 | $newRGB[$channel] = $RGB[$channel]; 84 | } 85 | 86 | $color = $copy->getExactColor($newRGB); 87 | 88 | if ($color == -1) { 89 | $color = $copy->allocateColor($newRGB); 90 | } 91 | 92 | $copy->setColorAt($x, $y, $color); 93 | } 94 | } 95 | 96 | if ($img->isTransparent()) { 97 | $copy->setTransparentColor($tci); 98 | } 99 | 100 | return $copy; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /lib/Operation/CopyChannelsTrueColor.php: -------------------------------------------------------------------------------- 1 | 0, 48 | 'green' => 0, 49 | 'blue' => 0, 50 | 'alpha' => 0 51 | ]; 52 | 53 | $width = $img->getWidth(); 54 | $height = $img->getHeight(); 55 | $copy = TrueColorImage::create($width, $height); 56 | 57 | if (count($channels) > 0) { 58 | for ($x = 0; $x < $width; $x++) { 59 | for ($y = 0; $y < $height; $y++) { 60 | $RGBA = $img->getRGBAt($x, $y); 61 | $newRGBA = $blank; 62 | 63 | foreach ($channels as $channel) { 64 | $newRGBA[$channel] = $RGBA[$channel]; 65 | } 66 | 67 | $color = $copy->getExactColorAlpha($newRGBA); 68 | 69 | if ($color == -1) { 70 | $color = $copy->allocateColorAlpha($newRGBA); 71 | } 72 | 73 | $copy->setColorAt($x, $y, $color); 74 | } 75 | } 76 | } 77 | 78 | return $copy; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /lib/Operation/CorrectGamma.php: -------------------------------------------------------------------------------- 1 | copy(); 46 | 47 | if (!imagegammacorrect($new->getHandle(), $input_gamma, $output_gamma)) { 48 | throw new GDFunctionResultException("imagegammacorrect() returned false"); 49 | } 50 | 51 | return $new; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/Operation/Crop.php: -------------------------------------------------------------------------------- 1 | getWidth(), $width); 51 | $height = Coordinate::fix($height, $img->getHeight(), $height); 52 | $left = Coordinate::fix($left, $img->getWidth(), $width); 53 | $top = Coordinate::fix($top, $img->getHeight(), $height); 54 | 55 | if ($left < 0) { 56 | $width = $left + $width; 57 | $left = 0; 58 | } 59 | 60 | if ($width > $img->getWidth() - $left) { 61 | $width = $img->getWidth() - $left; 62 | } 63 | 64 | if ($top < 0) { 65 | $height = $top + $height; 66 | $top = 0; 67 | } 68 | 69 | if ($height > $img->getHeight() - $top) { 70 | $height = $img->getHeight() - $top; 71 | } 72 | 73 | if ($width <= 0 || $height <= 0) { 74 | throw new Exception("Can't crop outside of an image."); 75 | } 76 | 77 | $new = $img->doCreate($width, $height); 78 | 79 | if ($img->isTransparent() || $img instanceof PaletteImage) { 80 | $new->copyTransparencyFrom($img); 81 | 82 | if (!imagecopyresized($new->getHandle(), $img->getHandle(), 0, 0, $left, $top, $width, $height, $width, $height)) { 83 | throw new GDFunctionResultException("imagecopyresized() returned false"); 84 | } 85 | } else { 86 | $new->alphaBlending(false); 87 | $new->saveAlpha(true); 88 | 89 | if (!imagecopyresampled($new->getHandle(), $img->getHandle(), 0, 0, $left, $top, $width, $height, $width, $height)) { 90 | throw new GDFunctionResultException("imagecopyresampled() returned false"); 91 | } 92 | } 93 | 94 | return $new; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /lib/Operation/Exception/InvalidFitMethodException.php: -------------------------------------------------------------------------------- 1 | copy(); 44 | 45 | $width = $image->getWidth(); 46 | $height = $image->getHeight(); 47 | 48 | if ($new->isTransparent()) { 49 | imagefilledrectangle($new->getHandle(), 0, 0, $width, $height, $new->getTransparentColor()); 50 | } 51 | 52 | for ($y = 0; $y < $height; $y++) { 53 | if (!imagecopy($new->getHandle(), $image->getHandle(), 0, $y, 0, $height - $y - 1, $width, 1)) { 54 | throw new GDFunctionResultException("imagecopy() returned false"); 55 | } 56 | } 57 | 58 | return $new; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /lib/Operation/GetMask.php: -------------------------------------------------------------------------------- 1 | getWidth(); 44 | $height = $image->getHeight(); 45 | 46 | $mask = TrueColorImage::create($width, $height); 47 | $mask->setTransparentColor(-1); 48 | $mask->alphaBlending(false); 49 | $mask->saveAlpha(false); 50 | 51 | $greyscale = []; 52 | 53 | for ($i = 0; $i <= 255; $i++) { 54 | $greyscale[$i] = ImageColorAllocate($mask->getHandle(), $i, $i, $i); 55 | } 56 | 57 | imagefilledrectangle($mask->getHandle(), 0, 0, $width, $height, $greyscale[255]); 58 | 59 | $transparentColor = $image->getTransparentColor(); 60 | $alphaToGreyRatio = 255 / 127; 61 | 62 | for ($x = 0; $x < $width; $x++) { 63 | for ($y = 0; $y < $height; $y++) { 64 | $color = $image->getColorAt($x, $y); 65 | 66 | if ($color == $transparentColor) { 67 | $rgba = ['alpha' => 127]; 68 | } else { 69 | $rgba = $image->getColorRGB($color); 70 | } 71 | 72 | imagesetpixel($mask->getHandle(), $x, $y, $greyscale[255 - round($rgba['alpha'] * $alphaToGreyRatio)]); 73 | } 74 | } 75 | 76 | return $mask; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /lib/Operation/Merge.php: -------------------------------------------------------------------------------- 1 | getWidth(), $overlay->getWidth()); 49 | $y = Coordinate::fix($top, $base->getHeight(), $overlay->getHeight()); 50 | 51 | $result = $base->asTrueColor(); 52 | $result->alphaBlending(true); 53 | $result->saveAlpha(true); 54 | 55 | if ($pct <= 0) { 56 | return $result; 57 | } 58 | 59 | if ($pct < 100) { 60 | if (!imagecopymerge( 61 | $result->getHandle(), 62 | $overlay->getHandle(), 63 | $x, 64 | $y, 65 | 0, 66 | 0, 67 | $overlay->getWidth(), 68 | $overlay->getHeight(), 69 | $pct 70 | )) { 71 | throw new GDFunctionResultException("imagecopymerge() returned false"); 72 | } 73 | } else { 74 | if (!imagecopy( 75 | $result->getHandle(), 76 | $overlay->getHandle(), 77 | $x, 78 | $y, 79 | 0, 80 | 0, 81 | $overlay->getWidth(), 82 | $overlay->getHeight() 83 | )) { 84 | throw new GDFunctionResultException("imagecopy() returned false"); 85 | } 86 | } 87 | 88 | return $result; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /lib/Operation/Mirror.php: -------------------------------------------------------------------------------- 1 | copy(); 44 | 45 | $width = $image->getWidth(); 46 | $height = $image->getHeight(); 47 | 48 | if ($new->isTransparent()) { 49 | imagefilledrectangle($new->getHandle(), 0, 0, $width, $height, $new->getTransparentColor()); 50 | } 51 | 52 | for ($x = 0; $x < $width; $x++) { 53 | if (!imagecopy($new->getHandle(), $image->getHandle(), $x, 0, $width - $x - 1, 0, 1, $height)) { 54 | throw new GDFunctionResultException("imagecopy() returned false"); 55 | } 56 | } 57 | 58 | return $new; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /lib/Operation/ResizeCanvas.php: -------------------------------------------------------------------------------- 1 | getWidth()); 54 | $new_height = Coordinate::fix($height, $img->getHeight()); 55 | 56 | if ($scale == 'down') { 57 | $new_width = min($new_width, $img->getWidth()); 58 | $new_height = min($new_height, $img->getHeight()); 59 | } elseif ($scale == 'up') { 60 | $new_width = max($new_width, $img->getWidth()); 61 | $new_height = max($new_height, $img->getHeight()); 62 | } 63 | 64 | $new = WideImage::createTrueColorImage($new_width, $new_height); 65 | 66 | if ($img->isTrueColor()) { 67 | if ($color === null) { 68 | $color = $new->allocateColorAlpha(0, 0, 0, 127); 69 | } 70 | } else { 71 | imagepalettecopy($new->getHandle(), $img->getHandle()); 72 | 73 | if ($img->isTransparent()) { 74 | $new->copyTransparencyFrom($img); 75 | $tc_rgb = $img->getTransparentColorRGB(); 76 | $t_color = $new->allocateColorAlpha($tc_rgb); 77 | } 78 | 79 | if ($color === null) { 80 | if ($img->isTransparent()) { 81 | $color = $t_color; 82 | } else { 83 | $color = $new->allocateColorAlpha(255, 0, 127, 127); 84 | } 85 | 86 | imagecolortransparent($new->getHandle(), $color); 87 | } 88 | } 89 | 90 | $new->fill(0, 0, $color); 91 | 92 | $x = Coordinate::fix($left, $new->getWidth(), $img->getWidth()); 93 | $y = Coordinate::fix($top, $new->getHeight(), $img->getHeight()); 94 | 95 | // blending for truecolor images 96 | if ($img->isTrueColor()) { 97 | $new->alphaBlending($merge); 98 | } 99 | 100 | // not-blending for palette images 101 | if (!$merge && !$img->isTrueColor() && isset($t_color)) { 102 | $new->getCanvas()->filledRectangle($x, $y, $x + $img->getWidth(), $y + $img->getHeight(), $t_color); 103 | } 104 | 105 | $img->copyTo($new, $x, $y); 106 | 107 | return $new; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /lib/Operation/Rotate.php: -------------------------------------------------------------------------------- 1 | copy(); 56 | } 57 | 58 | $image = $image->asTrueColor(); 59 | 60 | if ($bgColor === null) { 61 | $bgColor = $image->getTransparentColor(); 62 | 63 | if ($bgColor == -1) { 64 | $bgColor = $image->allocateColorAlpha(255, 255, 255, 127); 65 | imagecolortransparent($image->getHandle(), $bgColor); 66 | } 67 | } 68 | 69 | return new TrueColorImage(imagerotate($image->getHandle(), $angle, $bgColor, $ignoreTransparent)); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/OperationFactory.php: -------------------------------------------------------------------------------- 1 | copy(); 71 | } 72 | 73 | /** 74 | * Returns a copy of the image 75 | * 76 | * @param $trueColor True if the new image should be truecolor 77 | * @return \WideImage\Image 78 | */ 79 | protected function copyAsNew($trueColor = false) 80 | { 81 | $width = $this->getWidth(); 82 | $height = $this->getHeight(); 83 | 84 | if ($trueColor) { 85 | $new = TrueColorImage::create($width, $height); 86 | } else { 87 | $new = PaletteImage::create($width, $height); 88 | } 89 | 90 | // copy transparency of source to target 91 | if ($this->isTransparent()) { 92 | $rgb = $this->getTransparentColorRGB(); 93 | 94 | if (is_array($rgb)) { 95 | $tci = $new->allocateColor($rgb['red'], $rgb['green'], $rgb['blue']); 96 | $new->fill(0, 0, $tci); 97 | $new->setTransparentColor($tci); 98 | } 99 | } 100 | 101 | imageCopy($new->getHandle(), $this->handle, 0, 0, 0, 0, $width, $height); 102 | 103 | return $new; 104 | } 105 | 106 | /** 107 | * (non-PHPdoc) 108 | * @see \WideImage\Image#asTrueColor() 109 | */ 110 | public function asTrueColor() 111 | { 112 | $width = $this->getWidth(); 113 | $height = $this->getHeight(); 114 | $new = WideImage::createTrueColorImage($width, $height); 115 | 116 | if ($this->isTransparent()) { 117 | $new->copyTransparencyFrom($this); 118 | } 119 | 120 | if (!imageCopy($new->getHandle(), $this->handle, 0, 0, 0, 0, $width, $height)) { 121 | throw new GDFunctionResultException("imagecopy() returned false"); 122 | } 123 | 124 | return $new; 125 | } 126 | 127 | /** 128 | * (non-PHPdoc) 129 | * @see \WideImage\Image#getChannels() 130 | */ 131 | public function getChannels() 132 | { 133 | $args = func_get_args(); 134 | 135 | if (count($args) == 1 && is_array($args[0])) { 136 | $args = $args[0]; 137 | } 138 | 139 | return OperationFactory::get('CopyChannelsPalette')->execute($this, $args); 140 | } 141 | 142 | /** 143 | * (non-PHPdoc) 144 | * @see \WideImage\Image#copyNoAlpha() 145 | */ 146 | public function copyNoAlpha() 147 | { 148 | return WideImage::loadFromString($this->asString('png')); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | test/tests 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | lib 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /test/WideImage/CanvasTest.php: -------------------------------------------------------------------------------- 1 | getCanvas(); 37 | $this->assertInstanceOf('WideImage\\Canvas', $canvas1); 38 | 39 | $canvas2 = $img->getCanvas(); 40 | $this->assertSame($canvas1, $canvas2); 41 | } 42 | 43 | public function testMagicCallDrawRectangle() 44 | { 45 | $img = WideImage::createTrueColorImage(10, 10); 46 | $canvas = $img->getCanvas(); 47 | $canvas->filledRectangle(1, 1, 5, 5, $img->allocateColorAlpha(255, 0, 0, 64)); 48 | $this->assertRGBAt($img, 3, 3, ['red' => 255, 'green' => 0, 'blue' => 0, 'alpha' => 64]); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /test/WideImage/Mapper/BMPTest.php: -------------------------------------------------------------------------------- 1 | mapper = MapperFactory::selectMapper(null, 'bmp'); 46 | } 47 | 48 | /** 49 | * @after 50 | */ 51 | public function doTearDown() 52 | { 53 | $this->mapper = null; 54 | } 55 | 56 | public function imageProvider() 57 | { 58 | return [ 59 | [IMG_PATH . 'fgnl.bmp', 174, 287], 60 | [IMG_PATH . 'bmp' . DIRECTORY_SEPARATOR . 'favicon.ico', 30, 30] 61 | ]; 62 | } 63 | 64 | /** 65 | * @dataProvider imageProvider 66 | */ 67 | public function testLoad($image, $width, $height) 68 | { 69 | $handle = $this->mapper->load($image); 70 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 71 | $this->assertEquals($width, imagesx($handle)); 72 | $this->assertEquals($height, imagesy($handle)); 73 | imagedestroy($handle); 74 | } 75 | 76 | public function testSaveToString() 77 | { 78 | $handle = de77\BMP::imagecreatefrombmp(IMG_PATH . 'fgnl.bmp'); 79 | ob_start(); 80 | $this->mapper->save($handle); 81 | $string = ob_get_clean(); 82 | $this->assertTrue(strlen($string) > 0); 83 | imagedestroy($handle); 84 | 85 | // string contains valid image data 86 | $handle = $this->mapper->loadFromString($string); 87 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 88 | imagedestroy($handle); 89 | } 90 | 91 | public function testSaveToFile() 92 | { 93 | $handle = imagecreatefromgif(IMG_PATH . '100x100-color-hole.gif'); 94 | $this->mapper->save($handle, IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.bmp'); 95 | $this->assertTrue(filesize(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.bmp') > 0); 96 | imagedestroy($handle); 97 | 98 | // file is a valid image 99 | $handle = $this->mapper->load(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.bmp'); 100 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 101 | imagedestroy($handle); 102 | 103 | unlink(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.bmp'); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /test/WideImage/Mapper/FOO.php: -------------------------------------------------------------------------------- 1 | mapper = MapperFactory::selectMapper(null, 'gd2'); 41 | } 42 | 43 | /** 44 | * @after 45 | */ 46 | public function doTearDown() 47 | { 48 | $this->mapper = null; 49 | 50 | if (file_exists(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gd2')) { 51 | unlink(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gd2'); 52 | } 53 | } 54 | 55 | public function testSaveToString() 56 | { 57 | $handle = imagecreatefromgif(IMG_PATH . '100x100-color-hole.gif'); 58 | ob_start(); 59 | $this->mapper->save($handle); 60 | $string = ob_get_clean(); 61 | $this->assertTrue(strlen($string) > 0); 62 | imagedestroy($handle); 63 | 64 | // string contains valid image data 65 | $handle = imagecreatefromstring($string); 66 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 67 | imagedestroy($handle); 68 | } 69 | 70 | public function testSaveToFile() 71 | { 72 | $handle = imagecreatefromgif(IMG_PATH . '100x100-color-hole.gif'); 73 | $this->mapper->save($handle, IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gd2'); 74 | $this->assertTrue(filesize(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gd2') > 0); 75 | imagedestroy($handle); 76 | 77 | // file is a valid image 78 | $handle = imagecreatefromgd2(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gd2'); 79 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 80 | imagedestroy($handle); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /test/WideImage/Mapper/GDTest.php: -------------------------------------------------------------------------------- 1 | mapper = MapperFactory::selectMapper(null, 'gd'); 44 | } 45 | 46 | /** 47 | * @after 48 | */ 49 | public function doTearDown() 50 | { 51 | $this->mapper = null; 52 | 53 | if (file_exists(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gd')) { 54 | unlink(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gd'); 55 | } 56 | } 57 | 58 | public function testSaveAndLoad() 59 | { 60 | $handle = imagecreatefromgif(IMG_PATH . '100x100-color-hole.gif'); 61 | $this->mapper->save($handle, IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gd'); 62 | $this->assertTrue(filesize(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gd') > 0); 63 | imagedestroy($handle); 64 | 65 | // file is a valid image 66 | $handle = $this->mapper->load(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gd'); 67 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 68 | imagedestroy($handle); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /test/WideImage/Mapper/GIFTest.php: -------------------------------------------------------------------------------- 1 | mapper = MapperFactory::selectMapper(null, 'gif'); 44 | } 45 | 46 | /** 47 | * @after 48 | */ 49 | public function doTearDown() 50 | { 51 | $this->mapper = null; 52 | 53 | if (file_exists(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gif')) { 54 | unlink(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gif'); 55 | } 56 | } 57 | 58 | public function testLoad() 59 | { 60 | $handle = $this->mapper->load(IMG_PATH . '100x100-color-hole.gif'); 61 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 62 | $this->assertEquals(100, imagesx($handle)); 63 | $this->assertEquals(100, imagesy($handle)); 64 | imagedestroy($handle); 65 | } 66 | 67 | public function testSaveToString() 68 | { 69 | $handle = imagecreatefromgif(IMG_PATH . '100x100-color-hole.gif'); 70 | ob_start(); 71 | $this->mapper->save($handle); 72 | $string = ob_get_clean(); 73 | $this->assertTrue(strlen($string) > 0); 74 | imagedestroy($handle); 75 | 76 | // string contains valid image data 77 | $handle = imagecreatefromstring($string); 78 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 79 | imagedestroy($handle); 80 | } 81 | 82 | public function testSaveToFile() 83 | { 84 | $handle = imagecreatefromgif(IMG_PATH . '100x100-color-hole.gif'); 85 | $this->mapper->save($handle, IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gif'); 86 | $this->assertTrue(filesize(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gif') > 0); 87 | imagedestroy($handle); 88 | 89 | // file is a valid image 90 | $handle = imagecreatefromgif(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.gif'); 91 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 92 | imagedestroy($handle); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /test/WideImage/Mapper/JPEGTest.php: -------------------------------------------------------------------------------- 1 | mapper = MapperFactory::selectMapper(null, 'jpg'); 41 | } 42 | 43 | /** 44 | * @after 45 | */ 46 | public function doTearDown() 47 | { 48 | $this->mapper = null; 49 | 50 | if (file_exists(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.jpg')) { 51 | unlink(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.jpg'); 52 | } 53 | } 54 | 55 | public function testLoad() 56 | { 57 | $handle = $this->mapper->load(IMG_PATH . 'fgnl.jpg'); 58 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 59 | $this->assertEquals(174, imagesx($handle)); 60 | $this->assertEquals(287, imagesy($handle)); 61 | imagedestroy($handle); 62 | } 63 | 64 | public function testSaveToString() 65 | { 66 | $handle = imagecreatefromjpeg(IMG_PATH . 'fgnl.jpg'); 67 | ob_start(); 68 | $this->mapper->save($handle); 69 | $string = ob_get_clean(); 70 | $this->assertTrue(strlen($string) > 0); 71 | imagedestroy($handle); 72 | 73 | // string contains valid image data 74 | $handle = imagecreatefromstring($string); 75 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 76 | imagedestroy($handle); 77 | } 78 | 79 | public function testSaveToFile() 80 | { 81 | $handle = imagecreatefromjpeg(IMG_PATH . 'fgnl.jpg'); 82 | $this->mapper->save($handle, IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.jpg'); 83 | $this->assertTrue(filesize(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.jpg') > 0); 84 | imagedestroy($handle); 85 | 86 | // file is a valid image 87 | $handle = imagecreatefromjpeg(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.jpg'); 88 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 89 | imagedestroy($handle); 90 | } 91 | 92 | public function testQuality() 93 | { 94 | $handle = imagecreatefromjpeg(IMG_PATH . 'fgnl.jpg'); 95 | 96 | ob_start(); 97 | $this->mapper->save($handle, null, 100); 98 | $hq = ob_get_clean(); 99 | 100 | ob_start(); 101 | $this->mapper->save($handle, null, 10); 102 | $lq = ob_get_clean(); 103 | 104 | $this->assertTrue(strlen($hq) > 0); 105 | $this->assertTrue(strlen($lq) > 0); 106 | $this->assertTrue(strlen($hq) > strlen($lq)); 107 | imagedestroy($handle); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /test/WideImage/Mapper/PNGTest.php: -------------------------------------------------------------------------------- 1 | mapper = MapperFactory::selectMapper(null, 'png'); 41 | } 42 | 43 | /** 44 | * @after 45 | */ 46 | public function doTearDown() 47 | { 48 | $this->mapper = null; 49 | 50 | if (file_exists(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.png')) { 51 | unlink(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.png'); 52 | } 53 | } 54 | 55 | public function testLoad() 56 | { 57 | $handle = $this->mapper->load(IMG_PATH . '100x100-color-hole.png'); 58 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 59 | $this->assertEquals(100, imagesx($handle)); 60 | $this->assertEquals(100, imagesy($handle)); 61 | imagedestroy($handle); 62 | } 63 | 64 | public function testSaveToString() 65 | { 66 | $handle = imagecreatefrompng(IMG_PATH . '100x100-color-hole.png'); 67 | ob_start(); 68 | $this->mapper->save($handle); 69 | $string = ob_get_clean(); 70 | $this->assertTrue(strlen($string) > 0); 71 | imagedestroy($handle); 72 | 73 | // string contains valid image data 74 | $handle = imagecreatefromstring($string); 75 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 76 | imagedestroy($handle); 77 | } 78 | 79 | public function testSaveToFile() 80 | { 81 | $handle = imagecreatefrompng(IMG_PATH . '100x100-color-hole.png'); 82 | $this->mapper->save($handle, IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.png'); 83 | $this->assertTrue(filesize(IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.png') > 0); 84 | imagedestroy($handle); 85 | 86 | // file is a valid image 87 | $handle = imagecreatefrompng(IMG_PATH . 'temp/test.png'); 88 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 89 | imagedestroy($handle); 90 | } 91 | 92 | public function testSaveCompression() 93 | { 94 | $handle = $this->mapper->load(IMG_PATH . '100x100-rainbow.png'); 95 | $file1 = IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test-comp-0.png'; 96 | $file2 = IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test-comp-9.png'; 97 | $this->mapper->save($handle, $file1, 0); 98 | $this->mapper->save($handle, $file2, 9); 99 | $this->assertTrue(filesize($file1) > filesize($file2)); 100 | 101 | unlink($file1); 102 | unlink($file2); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /test/WideImage/Mapper/TGATest.php: -------------------------------------------------------------------------------- 1 | mapper = MapperFactory::selectMapper(null, 'tga'); 46 | } 47 | 48 | /** 49 | * @after 50 | */ 51 | public function doTearDown() 52 | { 53 | $this->mapper = null; 54 | } 55 | 56 | public function testLoad() 57 | { 58 | $handle = $this->mapper->load(IMG_PATH . 'splat.tga'); 59 | $this->assertTrue(WideImage::isValidImageHandle($handle)); 60 | $this->assertEquals(100, imagesx($handle)); 61 | $this->assertEquals(100, imagesy($handle)); 62 | imagedestroy($handle); 63 | } 64 | 65 | public function testSaveToStringNotSupported() 66 | { 67 | $this->expectException(\WideImage\Exception\Exception::class); 68 | $handle = de77\BMP::imagecreatefrombmp(IMG_PATH . 'splat.tga'); 69 | $this->mapper->save($handle); 70 | } 71 | 72 | public function testSaveToFileNotSupported() 73 | { 74 | $this->expectException(\WideImage\Exception\Exception::class); 75 | $handle = imagecreatefromgif(IMG_PATH . '100x100-color-hole.gif'); 76 | $this->mapper->save($handle, IMG_PATH . 'temp' . DIRECTORY_SEPARATOR . 'test.bmp'); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /test/WideImage/MapperFactoryTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf("WideImage\\Mapper\\PNG", $mapper); 36 | } 37 | 38 | public function testMapperGIFByURI() 39 | { 40 | $mapper = MapperFactory::selectMapper('uri.gif'); 41 | $this->assertInstanceOf("WideImage\\Mapper\\GIF", $mapper); 42 | } 43 | 44 | public function testMapperJPGByURI() 45 | { 46 | $mapper = MapperFactory::selectMapper('uri.jpg'); 47 | $this->assertInstanceOf("WideImage\\Mapper\\JPEG", $mapper); 48 | } 49 | 50 | public function testMapperBMPByURI() 51 | { 52 | $mapper = MapperFactory::selectMapper('uri.bmp'); 53 | $this->assertInstanceOf("WideImage\\Mapper\\BMP", $mapper); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /test/WideImage/Operation/ApplyConvolutionTest.php: -------------------------------------------------------------------------------- 1 | applyConvolution([[2, 0, 0], [0, -1, 0], [0, 0, -1]], 1, 220); 38 | 39 | $this->assertTrue($result instanceof TrueColorImage); 40 | $this->assertTrue($result->isTransparent()); 41 | 42 | $this->assertEquals(100, $result->getWidth()); 43 | $this->assertEquals(100, $result->getHeight()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /test/WideImage/Operation/ApplyFilterTest.php: -------------------------------------------------------------------------------- 1 | applyFilter(IMG_FILTER_EDGEDETECT); 38 | 39 | $this->assertTrue($result instanceof TrueColorImage); 40 | $this->assertTrue($result->isTransparent()); 41 | 42 | $this->assertEquals(100, $result->getWidth()); 43 | $this->assertEquals(100, $result->getHeight()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /test/WideImage/Operation/ApplyMaskTest.php: -------------------------------------------------------------------------------- 1 | applyMask($mask); 39 | $this->assertTrue($result instanceof TrueColorImage); 40 | $this->assertTrue($result->isTransparent()); 41 | 42 | $this->assertEquals(100, $result->getWidth()); 43 | $this->assertEquals(100, $result->getHeight()); 44 | 45 | $this->assertRGBNear($result->getRGBAt(10, 10), 255, 255, 255); 46 | $this->assertRGBNear($result->getRGBAt(30, 10), 255, 255, 0, 64); 47 | $this->assertRGBNear($result->getRGBAt(60, 10), 0, 0, 255, 0); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /test/WideImage/Operation/AsGrayscaleTest.php: -------------------------------------------------------------------------------- 1 | skipUnless(function_exists('imagefilter')); 37 | } 38 | 39 | public function testTransparentGIF() 40 | { 41 | $img = WideImage::load(IMG_PATH . '100x100-color-hole.gif'); 42 | 43 | $gray = $img->asGrayscale(); 44 | $this->assertTrue($gray instanceof PaletteImage); 45 | 46 | $this->assertEquals(100, $gray->getWidth()); 47 | $this->assertEquals(100, $gray->getHeight()); 48 | 49 | $this->assertRGBNear($gray->getRGBAt(10, 10), 227, 227, 227); 50 | $this->assertRGBNear($gray->getRGBAt(90, 10), 28, 28, 28); 51 | $this->assertRGBNear($gray->getRGBAt(90, 90), 150, 150, 150); 52 | $this->assertRGBNear($gray->getRGBAt(10, 90), 76, 76, 76); 53 | 54 | // preserves transparency 55 | $this->assertTrue($gray->isTransparent()); 56 | $this->assertEquals($gray->getColorAt(50, 50), $gray->getTransparentColor()); 57 | } 58 | 59 | public function testTransparentLogoGIF() 60 | { 61 | $img = $this->load('logo.gif'); 62 | $this->assertTransparentColorAt($img, 1, 1); 63 | 64 | $res = $img->asGrayscale(); 65 | $this->assertDimensions($res, 150, 23); 66 | $this->assertInstanceOf("WideImage\\PaletteImage", $res); 67 | 68 | // preserves transparency 69 | $this->assertTrue($res->isTransparent()); 70 | $this->assertTransparentColorAt($res, 1, 1); 71 | } 72 | 73 | public function testPNGAlpha() 74 | { 75 | $img = WideImage::load(IMG_PATH . '100x100-blue-alpha.png'); 76 | 77 | $gray = $img->asGrayscale(); 78 | $this->assertTrue($gray instanceof TrueColorImage); 79 | $this->assertEquals(100, $gray->getWidth()); 80 | $this->assertEquals(100, $gray->getHeight()); 81 | 82 | $this->assertRGBNear($gray->getRGBAt(25, 25), 29, 29, 29, 32); 83 | $this->assertRGBNear($gray->getRGBAt(75, 25), 29, 29, 29, 64); 84 | $this->assertRGBNear($gray->getRGBAt(75, 75), 29, 29, 29, 96); 85 | $this->assertRGBNear($gray->getRGBAt(25, 75), 0, 0, 0, 127); 86 | 87 | $this->assertFalse($gray->isTransparent()); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /test/WideImage/Operation/AsNegativeTest.php: -------------------------------------------------------------------------------- 1 | skipUnless(function_exists('imagefilter')); 34 | } 35 | 36 | public function testTransparentGIF() 37 | { 38 | $img = $this->load('100x100-color-hole.gif'); 39 | 40 | $res = $img->asNegative(); 41 | 42 | $this->assertDimensions($res, 100, 100); 43 | $this->assertInstanceOf("WideImage\\PaletteImage", $res); 44 | 45 | $this->assertRGBNear($res->getRGBAt(10, 10), 0, 0, 255); 46 | $this->assertRGBNear($res->getRGBAt(90, 10), 255, 255, 0); 47 | $this->assertRGBNear($res->getRGBAt(90, 90), 255, 0, 255); 48 | $this->assertRGBNear($res->getRGBAt(10, 90), 0, 255, 255); 49 | 50 | // preserves transparency 51 | $this->assertTrue($res->isTransparent()); 52 | $this->assertTransparentColorAt($res, 50, 50); 53 | } 54 | 55 | public function testTransparentLogoGIF() 56 | { 57 | $img = $this->load('logo.gif'); 58 | $this->assertTransparentColorAt($img, 1, 1); 59 | 60 | $res = $img->asNegative(); 61 | $this->assertDimensions($res, 150, 23); 62 | $this->assertInstanceOf("WideImage\\PaletteImage", $res); 63 | 64 | // preserves transparency 65 | $this->assertTrue($res->isTransparent()); 66 | $this->assertTransparentColorAt($res, 1, 1); 67 | } 68 | 69 | public function testPNGAlpha() 70 | { 71 | $img = $this->load('100x100-blue-alpha.png'); 72 | 73 | $res = $img->asNegative(); 74 | 75 | $this->assertDimensions($res, 100, 100); 76 | $this->assertInstanceOf("WideImage\\TrueColorImage", $res); 77 | 78 | $this->assertRGBNear($res->getRGBAt(25, 25), 255, 255, 0, 32); 79 | $this->assertRGBNear($res->getRGBAt(75, 25), 255, 255, 0, 64); 80 | $this->assertRGBNear($res->getRGBAt(75, 75), 255, 255, 0, 96); 81 | $this->assertRGBNear($res->getRGBAt(25, 75), 255, 255, 255, 127); 82 | 83 | $this->assertFalse($res->isTransparent()); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /test/WideImage/Operation/AutoCrop.test.php: -------------------------------------------------------------------------------- 1 | autocrop(); 38 | $this->assertTrue($cropped instanceof TrueColorImage); 39 | $this->assertEquals(71, $cropped->getWidth()); 40 | $this->assertEquals(70, $cropped->getHeight()); 41 | 42 | $this->assertRGBNear($cropped->getRGBAt(10, 10), 255, 0, 0); 43 | } 44 | 45 | public function testAutocropHalfImageBug() 46 | { 47 | $img = WideImage::load(IMG_PATH . '100x100-red-spot-half-cut.png'); 48 | 49 | $cropped = $img->autocrop(); 50 | $this->assertTrue($cropped instanceof TrueColorImage); 51 | $this->assertEquals(22, $cropped->getWidth()); 52 | $this->assertEquals(23, $cropped->getHeight()); 53 | 54 | $this->assertRGBNear($cropped->getRGBAt(10, 10), 255, 0, 0); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /test/WideImage/Operation/CorrectGammaTest.php: -------------------------------------------------------------------------------- 1 | correctGamma(1, 2); 38 | 39 | $this->assertTrue($result instanceof PaletteImage); 40 | $this->assertTrue($result->isTransparent()); 41 | 42 | $this->assertEquals(100, $result->getWidth()); 43 | $this->assertEquals(100, $result->getHeight()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /test/WideImage/Operation/CropTest.php: -------------------------------------------------------------------------------- 1 | crop('10%', 15, 50, '40%'); 39 | 40 | $this->assertTrue($cropped instanceof PaletteImage); 41 | $this->assertTrue($cropped->isTransparent()); 42 | $this->assertEquals(50, $cropped->getWidth()); 43 | $this->assertEquals(40, $cropped->getHeight()); 44 | 45 | $this->assertRGBNear($cropped->getRGBAt(39, 9), 255, 255, 0); 46 | $this->assertRGBNear($cropped->getRGBAt(40, 9), 0, 0, 255); 47 | $this->assertRGBNear($cropped->getRGBAt(14, 35), 255, 0, 0); 48 | $this->assertRGBNear($cropped->getRGBAt(16, 11), $cropped->getTransparentColorRGB()); 49 | } 50 | 51 | public function testCropPNGAlpha() 52 | { 53 | $img = WideImage::load(IMG_PATH . '100x100-blue-alpha.png'); 54 | 55 | $cropped = $img->crop(10, 10, 50, 50); 56 | 57 | $this->assertTrue($cropped instanceof TrueColorImage); 58 | $this->assertFalse($cropped->isTransparent()); 59 | $this->assertEquals(50, $cropped->getWidth()); 60 | $this->assertEquals(50, $cropped->getHeight()); 61 | 62 | $this->assertRGBNear($cropped->getRGBAt(39, 39), 0, 0, 255, 32); 63 | $this->assertRGBNear($cropped->getRGBAt(40, 40), 0, 0, 255, 96); 64 | } 65 | 66 | public function testCropHasCorrectSize() 67 | { 68 | $img = WideImage::load(IMG_PATH . '100x100-blue-alpha.png'); 69 | 70 | $cropped = $img->crop(10, 10, 10, 10); 71 | $this->assertEquals(10, $cropped->getWidth()); 72 | $this->assertEquals(10, $cropped->getHeight()); 73 | 74 | $cropped = $img->crop(10, 20, 100, 200); 75 | $this->assertEquals(90, $cropped->getWidth()); 76 | $this->assertEquals(80, $cropped->getHeight()); 77 | } 78 | 79 | public function testCropIsNormalized() 80 | { 81 | $img = WideImage::load(IMG_PATH . '100x100-blue-alpha.png'); 82 | 83 | $cropped = $img->crop(-10, -20, 100, 100); 84 | $this->assertEquals(90, $cropped->getWidth()); 85 | $this->assertEquals(80, $cropped->getHeight()); 86 | 87 | $cropped = $img->crop(10, 20, 140, 170); 88 | $this->assertEquals(90, $cropped->getWidth()); 89 | $this->assertEquals(80, $cropped->getHeight()); 90 | 91 | $cropped = $img->crop(-10, -20, 140, 170); 92 | $this->assertEquals(100, $cropped->getWidth()); 93 | $this->assertEquals(100, $cropped->getHeight()); 94 | } 95 | 96 | public function testCropCutsAreaOutsideBoundaries() 97 | { 98 | $this->expectException(\WideImage\Exception\Exception::class); 99 | $img = WideImage::load(IMG_PATH . '100x100-blue-alpha.png'); 100 | $img->crop(120, 100, 1, 2); 101 | } 102 | 103 | public function testCropCutsAreaNegativePosition() 104 | { 105 | $this->expectException(\WideImage\Exception\Exception::class); 106 | $img = WideImage::load(IMG_PATH . '100x100-blue-alpha.png'); 107 | $img->crop(-150, -200, 50, 50); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /test/WideImage/Operation/CustomOp.php: -------------------------------------------------------------------------------- 1 | copy(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/WideImage/Operation/FlipTest.php: -------------------------------------------------------------------------------- 1 | assertRGBEqual($img->getRGBAt(5, 5), 255, 255, 0); 38 | $this->assertRGBEqual($img->getRGBAt(95, 5), 0, 0, 255); 39 | $this->assertRGBEqual($img->getRGBAt(95, 95), 0, 255, 0); 40 | $this->assertRGBEqual($img->getRGBAt(5, 95), 255, 0, 0); 41 | 42 | $new = $img->flip(); 43 | 44 | $this->assertTrue($new instanceof PaletteImage); 45 | 46 | $this->assertEquals(100, $new->getWidth()); 47 | $this->assertEquals(100, $new->getHeight()); 48 | 49 | $this->assertRGBEqual($new->getRGBAt(5, 95), 255, 255, 0); 50 | $this->assertRGBEqual($new->getRGBAt(95, 95), 0, 0, 255); 51 | $this->assertRGBEqual($new->getRGBAt(95, 5), 0, 255, 0); 52 | $this->assertRGBEqual($new->getRGBAt(5, 5), 255, 0, 0); 53 | 54 | $this->assertTrue($new->isTransparent()); 55 | $this->assertRGBEqual($new->getRGBAt(50, 50), $img->getTransparentColorRGB()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /test/WideImage/Operation/GetMaskTest.php: -------------------------------------------------------------------------------- 1 | getMask(); 38 | $this->assertTrue($mask instanceof TrueColorImage); 39 | 40 | $this->assertFalse($mask->isTransparent()); 41 | $this->assertEquals(100, $mask->getWidth()); 42 | $this->assertEquals(100, $mask->getHeight()); 43 | 44 | $this->assertRGBNear($mask->getRGBAt(10, 10), 255, 255, 255); 45 | $this->assertRGBNear($mask->getRGBAt(90, 90), 255, 255, 255); 46 | $this->assertRGBNear($mask->getRGBAt(50, 50), 0, 0, 0); 47 | } 48 | 49 | public function testGetMaskPNGAlpha() 50 | { 51 | $img = WideImage::load(IMG_PATH . '100x100-blue-alpha.png'); 52 | 53 | $mask = $img->getMask(); 54 | $this->assertTrue($mask instanceof TrueColorImage); 55 | 56 | $this->assertFalse($mask->isTransparent()); 57 | $this->assertEquals(100, $mask->getWidth()); 58 | $this->assertEquals(100, $mask->getHeight()); 59 | 60 | $this->assertRGBNear($mask->getRGBAt(25, 25), 192, 192, 192); 61 | $this->assertRGBNear($mask->getRGBAt(75, 25), 128, 128, 128); 62 | $this->assertRGBNear($mask->getRGBAt(75, 75), 64, 64, 64); 63 | $this->assertRGBNear($mask->getRGBAt(25, 75), 0, 0, 0); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /test/WideImage/Operation/MergeTest.php: -------------------------------------------------------------------------------- 1 | merge($overlay, 0, 0, 0); 39 | 40 | $this->assertEquals(100, $res->getWidth()); 41 | $this->assertEquals(100, $res->getHeight()); 42 | 43 | $this->assertRGBAt($res, 5, 5, ['red' => 255, 'green' => 255, 'blue' => 0, 'alpha' => 0]); 44 | $this->assertRGBAt($res, 40, 40, ['red' => 0, 'green' => 0, 'blue' => 0, 'alpha' => 127]); 45 | $this->assertRGBAt($res, 95, 5, ['red' => 0, 'green' => 0, 'blue' => 255, 'alpha' => 0]); 46 | $this->assertRGBAt($res, 60, 40, ['red' => 0, 'green' => 0, 'blue' => 0, 'alpha' => 127]); 47 | $this->assertRGBAt($res, 95, 95, ['red' => 0, 'green' => 255, 'blue' => 0, 'alpha' => 0]); 48 | $this->assertRGBAt($res, 60, 60, ['red' => 0, 'green' => 0, 'blue' => 0, 'alpha' => 127]); 49 | $this->assertRGBAt($res, 5, 95, ['red' => 255, 'green' => 0, 'blue' => 0, 'alpha' => 0]); 50 | $this->assertRGBAt($res, 40, 60, ['red' => 0, 'green' => 0, 'blue' => 0, 'alpha' => 127]); 51 | } 52 | 53 | public function testMergeOpacityHalf() 54 | { 55 | $img = WideImage::load(IMG_PATH . '100x100-color-hole.png'); 56 | $overlay = WideImage::load(IMG_PATH . '100x100-square-overlay.png'); 57 | 58 | $res = $img->merge($overlay, 0, 0, 50); 59 | 60 | $this->assertEquals(100, $res->getWidth()); 61 | $this->assertEquals(100, $res->getHeight()); 62 | 63 | $this->assertRGBAt($res, 5, 5, ['red' => 255, 'green' => 255, 'blue' => 127, 'alpha' => 0]); 64 | $this->assertRGBAt($res, 40, 40, ['red' => 127, 'green' => 127, 'blue' => 127, 'alpha' => 0]); 65 | $this->assertRGBAt($res, 95, 5, ['red' => 0, 'green' => 0, 'blue' => 255, 'alpha' => 0]); 66 | $this->assertRGBAt($res, 60, 40, ['red' => 0, 'green' => 0, 'blue' => 0, 'alpha' => 127]); 67 | $this->assertRGBAt($res, 95, 95, ['red' => 0, 'green' => 127, 'blue' => 0, 'alpha' => 0]); 68 | 69 | // these two should definitely pass ... 70 | 71 | #$this->assertRGBAt($res, 60, 60, array('red' => 127, 'green' => 127, 'blue' => 127, 'alpha' => 0)); 72 | $this->assertRGBAt($res, 5, 95, ['red' => 255, 'green' => 0, 'blue' => 0, 'alpha' => 0]); 73 | #$this->assertRGBAt($res, 40, 60, array('red' => 255, 'green' => 127, 'blue' => 127, 'alpha' => 0)); 74 | } 75 | 76 | public function testMergeOpacityFull() 77 | { 78 | $img = WideImage::load(IMG_PATH . '100x100-color-hole.png'); 79 | $overlay = WideImage::load(IMG_PATH . '100x100-square-overlay.png'); 80 | 81 | $res = $img->merge($overlay, 0, 0, 100); 82 | 83 | $this->assertEquals(100, $res->getWidth()); 84 | $this->assertEquals(100, $res->getHeight()); 85 | 86 | $this->assertRGBAt($res, 5, 5, ['red' => 255, 'green' => 255, 'blue' => 255, 'alpha' => 0]); 87 | $this->assertRGBAt($res, 40, 40, ['red' => 255, 'green' => 255, 'blue' => 255, 'alpha' => 0]); 88 | $this->assertRGBAt($res, 95, 5, ['red' => 0, 'green' => 0, 'blue' => 255, 'alpha' => 0]); 89 | $this->assertRGBAt($res, 60, 40, ['red' => 0, 'green' => 0, 'blue' => 0, 'alpha' => 127]); 90 | $this->assertRGBAt($res, 95, 95, ['red' => 0, 'green' => 0, 'blue' => 0, 'alpha' => 0]); 91 | $this->assertRGBAt($res, 60, 60, ['red' => 0, 'green' => 0, 'blue' => 0, 'alpha' => 0]); 92 | $this->assertRGBAt($res, 5, 95, ['red' => 255, 'green' => 0, 'blue' => 0, 'alpha' => 0]); 93 | $this->assertRGBAt($res, 40, 60, ['red' => 255, 'green' => 0, 'blue' => 0, 'alpha' => 0]); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /test/WideImage/Operation/MirrorTest.php: -------------------------------------------------------------------------------- 1 | assertRGBEqual($img->getRGBAt(5, 5), 255, 255, 0); 38 | $this->assertRGBEqual($img->getRGBAt(95, 5), 0, 0, 255); 39 | $this->assertRGBEqual($img->getRGBAt(95, 95), 0, 255, 0); 40 | $this->assertRGBEqual($img->getRGBAt(5, 95), 255, 0, 0); 41 | 42 | $new = $img->mirror(); 43 | 44 | $this->assertTrue($new instanceof PaletteImage); 45 | 46 | $this->assertEquals(100, $new->getWidth()); 47 | $this->assertEquals(100, $new->getHeight()); 48 | 49 | $this->assertRGBEqual($new->getRGBAt(95, 5), 255, 255, 0); 50 | $this->assertRGBEqual($new->getRGBAt(5, 5), 0, 0, 255); 51 | $this->assertRGBEqual($new->getRGBAt(5, 95), 0, 255, 0); 52 | $this->assertRGBEqual($new->getRGBAt(95, 95), 255, 0, 0); 53 | 54 | $this->assertTrue($new->isTransparent()); 55 | $this->assertRGBEqual($new->getRGBAt(50, 50), $img->getTransparentColorRGB()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /test/WideImage/Operation/MyOperation.php: -------------------------------------------------------------------------------- 1 | resizeCanvas(180, 180, 0, 0); 38 | $this->assertDimensions($resized, 180, 180); 39 | } 40 | 41 | public function testResizeCanvasDown() 42 | { 43 | $img = WideImage::createTrueColorImage(160, 120); 44 | $resized = $img->resizeCanvas(30, 100, 0, 0); 45 | $this->assertDimensions($resized, 30, 100); 46 | } 47 | 48 | public function testResizeCanvasPositionsCenter() 49 | { 50 | $img = WideImage::createTrueColorImage(20, 20); 51 | $black = $img->allocateColor(0, 0, 0); 52 | $white = $img->allocateColor(255, 255, 255); 53 | $img->fill(0, 0, $black); 54 | 55 | $res = $img->resizeCanvas(40, 40, 'center', 'center', $white); 56 | $this->assertRGBAt($res, 5, 5, $white); 57 | $this->assertRGBAt($res, 35, 35, $white); 58 | $this->assertRGBAt($res, 5, 35, $white); 59 | $this->assertRGBAt($res, 35, 5, $white); 60 | $this->assertRGBAt($res, 20, 20, $black); 61 | } 62 | 63 | public function testResizeCanvasPositionsCorner() 64 | { 65 | $img = WideImage::createTrueColorImage(20, 20); 66 | $black = $img->allocateColor(0, 0, 0); 67 | $white = $img->allocateColor(255, 255, 255); 68 | $img->fill(0, 0, $black); 69 | 70 | $res = $img->resizeCanvas(40, 40, 'bottom', 'right', $white); 71 | $this->assertRGBAt($res, 5, 5, $white); 72 | $this->assertRGBAt($res, 35, 35, $black); 73 | $this->assertRGBAt($res, 5, 35, $white); 74 | $this->assertRGBAt($res, 35, 5, $white); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /test/WideImage/Operation/RotateTest.php: -------------------------------------------------------------------------------- 1 | skipUnless(function_exists('imagerotate')); 35 | } 36 | 37 | public function testRotateAlphaSafe() 38 | { 39 | $img = WideImage::load(IMG_PATH . '100x100-blue-alpha.png'); 40 | $this->assertRGBEqual($img->getRGBAt(25, 25), 0, 0, 255, round(128 / 4)); 41 | $this->assertRGBEqual($img->getRGBAt(75, 25), 0, 0, 255, round(2 * 128 / 4)); 42 | $this->assertRGBEqual($img->getRGBAt(75, 75), 0, 0, 255, round(3 * 128 / 4)); 43 | $this->assertRGBEqual($img->getRGBAt(25, 75), 0, 0, 0, 127); 44 | $new = $img->rotate(90, null); 45 | $this->assertEquals(100, $new->getWidth()); 46 | $this->assertEquals(100, $new->getHeight()); 47 | } 48 | 49 | public function testRotateCounterClockwise90() 50 | { 51 | $img = WideImage::load(IMG_PATH . 'fgnl.jpg'); 52 | $new = $img->rotate(-90); 53 | $this->assertEquals(287, $new->getWidth()); 54 | $this->assertEquals(174, $new->getHeight()); 55 | } 56 | 57 | public function testRotate45() 58 | { 59 | $img = WideImage::load(IMG_PATH . '100x100-rainbow.png'); 60 | $new = $img->rotate(45); 61 | 62 | // TODO: figure out why this fluctuates between 140 and 143 on different PHP versions 63 | $this->assertGreaterThanOrEqual(140, $new->getWidth()); 64 | $this->assertLessThanOrEqual(143, $new->getWidth()); 65 | $this->assertGreaterThanOrEqual(140, $new->getHeight()); 66 | $this->assertLessThanOrEqual(143, $new->getHeight()); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /test/WideImage/Operation/RoundCornersTest.php: -------------------------------------------------------------------------------- 1 | roundCorners(30, $img->allocateColor(255, 255, 255), WideImage::SIDE_ALL); 37 | 38 | $this->assertEquals(100, $res->getWidth()); 39 | $this->assertEquals(100, $res->getHeight()); 40 | 41 | $this->assertRGBAt($res, 5, 5, ['red' => 255, 'green' => 255, 'blue' => 255, 'alpha' => 0]); 42 | $this->assertRGBAt($res, 95, 5, ['red' => 255, 'green' => 255, 'blue' => 255, 'alpha' => 0]); 43 | $this->assertRGBAt($res, 95, 95, ['red' => 255, 'green' => 255, 'blue' => 255, 'alpha' => 0]); 44 | $this->assertRGBAt($res, 5, 95, ['red' => 255, 'green' => 255, 'blue' => 255, 'alpha' => 0]); 45 | } 46 | 47 | public function testTransparentCorner() 48 | { 49 | $img = WideImage::load(IMG_PATH . '100x100-blue-alpha.png'); 50 | $res = $img->roundCorners(30, null, WideImage::SIDE_ALL); 51 | 52 | $this->assertEquals(100, $res->getWidth()); 53 | $this->assertEquals(100, $res->getHeight()); 54 | 55 | $this->assertRGBAt($res, 5, 5, ['red' => 255, 'green' => 255, 'blue' => 255, 'alpha' => 127]); 56 | $this->assertRGBAt($res, 95, 5, ['red' => 255, 'green' => 255, 'blue' => 255, 'alpha' => 127]); 57 | $this->assertRGBAt($res, 95, 95, ['red' => 255, 'green' => 255, 'blue' => 255, 'alpha' => 127]); 58 | $this->assertRGBAt($res, 5, 95, ['red' => 255, 'green' => 255, 'blue' => 255, 'alpha' => 127]); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /test/WideImage/Operation/UnsharpTest.php: -------------------------------------------------------------------------------- 1 | unsharp(10, 5, 1); 38 | 39 | $this->assertTrue($result instanceof PaletteImage); 40 | $this->assertTrue($result->isTransparent()); 41 | 42 | $this->assertEquals(100, $result->getWidth()); 43 | $this->assertEquals(100, $result->getHeight()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /test/WideImage/OperationFactoryTest.php: -------------------------------------------------------------------------------- 1 | assertSame($op1, $op2); 40 | } 41 | 42 | public function testNoOperation() 43 | { 44 | $this->expectException(\WideImage\Exception\UnknownImageOperationException::class); 45 | OperationFactory::get('NoSuchOp'); 46 | } 47 | 48 | public function testUserDefinedOp() 49 | { 50 | $op = OperationFactory::get('MyOperation'); 51 | $this->assertTrue($op instanceof MyOperation); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /test/WideImage/PaletteImageTest.php: -------------------------------------------------------------------------------- 1 | assertTrue($img instanceof PaletteImage); 38 | $this->assertTrue($img->isValid()); 39 | $this->assertFalse($img->isTrueColor()); 40 | } 41 | 42 | public function testCopy() 43 | { 44 | $img = WideImage::load(IMG_PATH . '100x100-color-hole.gif'); 45 | $this->assertTrue($img instanceof PaletteImage); 46 | $this->assertTrue($img->isValid()); 47 | $this->assertFalse($img->isTrueColor()); 48 | $this->assertTrue($img->isTransparent()); 49 | $this->assertRGBEqual($img->getRGBAt(15, 15), 255, 255, 0); 50 | $this->assertRGBEqual($img->getRGBAt(85, 15), 0, 0, 255); 51 | $this->assertRGBEqual($img->getRGBAt(85, 85), 0, 255, 0); 52 | $this->assertRGBEqual($img->getRGBAt(15, 85), 255, 0, 0); 53 | $this->assertTrue($img->getTransparentColor() === $img->getColorAt(50, 50)); 54 | 55 | $copy = $img->copy(); 56 | $this->assertFalse($img->getHandle() === $copy->getHandle()); 57 | 58 | $this->assertTrue($copy instanceof PaletteImage); 59 | $this->assertTrue($copy->isValid()); 60 | $this->assertFalse($copy->isTrueColor()); 61 | $this->assertTrue($copy->isTransparent()); 62 | $this->assertRGBEqual($copy->getRGBAt(15, 15), 255, 255, 0); 63 | $this->assertRGBEqual($copy->getRGBAt(85, 15), 0, 0, 255); 64 | $this->assertRGBEqual($copy->getRGBAt(85, 85), 0, 255, 0); 65 | $this->assertRGBEqual($copy->getRGBAt(15, 85), 255, 0, 0); 66 | $this->assertTrue($copy->getTransparentColor() === $copy->getColorAt(50, 50)); 67 | 68 | $this->assertSame($img->getTransparentColorRGB(), $copy->getTransparentColorRGB()); 69 | } 70 | 71 | public function testCopyNoAlpha() 72 | { 73 | $img = WideImage::load(IMG_PATH . '100x100-color-hole.gif'); 74 | $this->assertRGBEqual($img->getRGBAt(85, 85), 0, 255, 0); 75 | $copy = $img->copyNoAlpha(); 76 | $this->assertFalse($img->getHandle() === $copy->getHandle()); 77 | $this->assertTrue($copy instanceof PaletteImage); 78 | $this->assertTrue($copy->isValid()); 79 | $this->assertFalse($copy->isTrueColor()); 80 | $this->assertRGBEqual($copy->getRGBAt(85, 85), 0, 255, 0); 81 | } 82 | 83 | public function testAsTrueColor() 84 | { 85 | $img = WideImage::load(IMG_PATH . '100x100-color-hole.gif'); 86 | $this->assertTrue($img instanceof PaletteImage); 87 | $this->assertTrue($img->isValid()); 88 | 89 | $copy = $img->asTrueColor(); 90 | $this->assertFalse($img->getHandle() === $copy->getHandle()); 91 | 92 | $this->assertTrue($copy instanceof TrueColorImage); 93 | $this->assertTrue($copy->isValid()); 94 | $this->assertTrue($copy->isTrueColor()); 95 | $this->assertTrue($copy->isTransparent()); 96 | $this->assertRGBEqual($copy->getRGBAt(15, 15), 255, 255, 0); 97 | $this->assertRGBEqual($copy->getRGBAt(85, 15), 0, 0, 255); 98 | $this->assertRGBEqual($copy->getRGBAt(85, 85), 0, 255, 0); 99 | $this->assertRGBEqual($copy->getRGBAt(15, 85), 255, 0, 0); 100 | 101 | $this->assertEquals($copy->getRGBAt(50, 50), $copy->getTransparentColorRGB()); 102 | $rgb = $copy->getTransparentColorRGB(); 103 | $this->assertRGBEqual($img->getTransparentColorRGB(), $rgb['red'], $rgb['green'], $rgb['blue']); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /test/images/100x100-blue-alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/100x100-blue-alpha.png -------------------------------------------------------------------------------- /test/images/100x100-color-hole.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/100x100-color-hole.gif -------------------------------------------------------------------------------- /test/images/100x100-color-hole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/100x100-color-hole.png -------------------------------------------------------------------------------- /test/images/100x100-rainbow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/100x100-rainbow.png -------------------------------------------------------------------------------- /test/images/100x100-red-spot-half-cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/100x100-red-spot-half-cut.png -------------------------------------------------------------------------------- /test/images/100x100-red-spot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/100x100-red-spot.png -------------------------------------------------------------------------------- /test/images/100x100-red-transparent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/100x100-red-transparent.gif -------------------------------------------------------------------------------- /test/images/100x100-rgbyg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/100x100-rgbyg.png -------------------------------------------------------------------------------- /test/images/100x100-square-overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/100x100-square-overlay.png -------------------------------------------------------------------------------- /test/images/100x50-rgbt.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/100x50-rgbt.gif -------------------------------------------------------------------------------- /test/images/75x25-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/75x25-gray.png -------------------------------------------------------------------------------- /test/images/actually-a-png.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/actually-a-png.jpg -------------------------------------------------------------------------------- /test/images/bmp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/bmp/favicon.ico -------------------------------------------------------------------------------- /test/images/bmp/rainbow-16b-x.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/bmp/rainbow-16b-x.bmp -------------------------------------------------------------------------------- /test/images/bmp/rainbow-16b.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/bmp/rainbow-16b.bmp -------------------------------------------------------------------------------- /test/images/bmp/rainbow-24b.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/bmp/rainbow-24b.bmp -------------------------------------------------------------------------------- /test/images/bmp/rainbow-32b.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/bmp/rainbow-32b.bmp -------------------------------------------------------------------------------- /test/images/bmp/rainbow-palette-rle.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/bmp/rainbow-palette-rle.bmp -------------------------------------------------------------------------------- /test/images/fakeimage.png: -------------------------------------------------------------------------------- 1 | NOT AN ACTUAL IMAGE -------------------------------------------------------------------------------- /test/images/fgnl-bmp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/fgnl-bmp.jpg -------------------------------------------------------------------------------- /test/images/fgnl.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/fgnl.bmp -------------------------------------------------------------------------------- /test/images/fgnl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/fgnl.jpg -------------------------------------------------------------------------------- /test/images/image-actually-foo.foo2: -------------------------------------------------------------------------------- 1 | Fake image with custom extension -------------------------------------------------------------------------------- /test/images/image.foo: -------------------------------------------------------------------------------- 1 | Fake image with custom extension -------------------------------------------------------------------------------- /test/images/logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/logo.gif -------------------------------------------------------------------------------- /test/images/splat.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/splat.tga -------------------------------------------------------------------------------- /test/images/temp/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smottt/WideImage/17c1321d10fc876236d82f7a247b6d5f3a32d946/test/images/temp/.gitkeep -------------------------------------------------------------------------------- /test/run.bat: -------------------------------------------------------------------------------- 1 | phpunit --verbose --bootstrap test-init.php %1 %2 %3 %4 %5 %6 WideImage 2 | -------------------------------------------------------------------------------- /test/run.sh: -------------------------------------------------------------------------------- 1 | `dirname $0`/../vendor/bin/simple-phpunit $* --verbose --bootstrap `dirname $0`/test-init.php `dirname $0`/WideImage 2 | -------------------------------------------------------------------------------- /test/test-init.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('WideImage\\Image', $image); 27 | $this->assertTrue($image->isValid()); 28 | } 29 | 30 | public function assertDimensions($image, $width, $height) 31 | { 32 | $this->assertEquals($width, $image->getWidth()); 33 | $this->assertEquals($height, $image->getHeight()); 34 | } 35 | 36 | public function assertTransparentColorMatch($img1, $img2) 37 | { 38 | $tc1 = $img1->getTransparentColorRGB(); 39 | $tc2 = $img2->getTransparentColorRGB(); 40 | $this->assertEquals($tc1, $tc2); 41 | } 42 | 43 | public function assertTransparentColorAt($img, $x, $y) 44 | { 45 | $this->assertEquals($img->getTransparentColor(), $img->getColorAt($x, $y)); 46 | } 47 | 48 | public function assertRGBWithinMargin($rec, $r, $g, $b, $a, $margin) 49 | { 50 | if (is_array($r)) { 51 | $a = $r['alpha']; 52 | $b = $r['blue']; 53 | $g = $r['green']; 54 | $r = $r['red']; 55 | } 56 | 57 | $result = 58 | abs($rec['red'] - $r) <= $margin && 59 | abs($rec['green'] - $g) <= $margin && 60 | abs($rec['blue'] - $b) <= $margin; 61 | 62 | $result = $result && ($a === null || abs($rec['alpha'] - $a) <= $margin); 63 | 64 | $this->assertTrue( 65 | $result, 66 | "RGBA [{$rec['red']}, {$rec['green']}, {$rec['blue']}, {$rec['alpha']}] " . 67 | "doesn't match RGBA [$r, $g, $b, $a] within margin [$margin]." 68 | ); 69 | } 70 | 71 | public function assertRGBAt($img, $x, $y, $rgba) 72 | { 73 | if (is_array($rgba)) { 74 | $cmp = $img->getRGBAt($x, $y); 75 | } else { 76 | $cmp = $img->getColorAt($x, $y); 77 | } 78 | 79 | $this->assertSame($cmp, $rgba); 80 | } 81 | 82 | public function assertRGBNear($rec, $r, $g = null, $b = null, $a = null) 83 | { 84 | $this->assertRGBWithinMargin($rec, $r, $g, $b, $a, 2); 85 | } 86 | 87 | public function assertRGBEqual($rec, $r, $g = null, $b = null, $a = null) 88 | { 89 | $this->assertRGBWithinMargin($rec, $r, $g, $b, $a, 0); 90 | } 91 | } 92 | --------------------------------------------------------------------------------