|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
##DOC-SIGNATURE## |
|
4
|
|
|
|
|
5
|
|
|
This file is part of WideImage. |
|
6
|
|
|
|
|
7
|
|
|
WideImage is free software; you can redistribute it and/or modify |
|
8
|
|
|
it under the terms of the GNU Lesser General Public License as published by |
|
9
|
|
|
the Free Software Foundation; either version 2.1 of the License, or |
|
10
|
|
|
(at your option) any later version. |
|
11
|
|
|
|
|
12
|
|
|
WideImage is distributed in the hope that it will be useful, |
|
13
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
15
|
|
|
GNU Lesser General Public License for more details. |
|
16
|
|
|
|
|
17
|
|
|
You should have received a copy of the GNU Lesser General Public License |
|
18
|
|
|
along with WideImage; if not, write to the Free Software |
|
19
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|
20
|
|
|
|
|
21
|
|
|
* @package WideImage |
|
22
|
|
|
**/ |
|
23
|
|
|
|
|
24
|
|
|
namespace WideImage; |
|
25
|
|
|
|
|
26
|
|
|
use WideImage\Exception\UnknownErrorWhileMappingException; |
|
27
|
|
|
use WideImage\Exception\GDFunctionResultException; |
|
28
|
|
|
|
|
29
|
|
|
/** |
|
30
|
|
|
* Base class for images |
|
31
|
|
|
* |
|
32
|
|
|
* @package WideImage |
|
33
|
|
|
*/ |
|
34
|
|
|
abstract class Image |
|
35
|
|
|
{ |
|
36
|
|
|
/** |
|
37
|
|
|
* Holds the image resource |
|
38
|
|
|
* @var resource |
|
39
|
|
|
*/ |
|
40
|
|
|
protected $handle = null; |
|
41
|
|
|
|
|
42
|
|
|
/** |
|
43
|
|
|
* Flag that determines if WideImage should call imagedestroy() upon object destruction |
|
44
|
|
|
* @var bool |
|
45
|
|
|
*/ |
|
46
|
|
|
protected $handleReleased = false; |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* Canvas object |
|
50
|
|
|
* @var \WideImage\Canvas |
|
51
|
|
|
*/ |
|
52
|
|
|
protected $canvas = null; |
|
53
|
|
|
|
|
54
|
|
|
/** |
|
55
|
|
|
* @var string |
|
56
|
|
|
*/ |
|
57
|
|
|
protected $sdata = null; |
|
58
|
|
|
|
|
59
|
|
|
/** |
|
60
|
|
|
* The base class constructor |
|
61
|
|
|
* |
|
62
|
|
|
* @param resource $handle Image handle (GD2 resource) |
|
63
|
|
|
*/ |
|
64
|
|
|
public function __construct($handle) |
|
65
|
|
|
{ |
|
66
|
|
|
WideImage::assertValidImageHandle($handle); |
|
67
|
|
|
$this->handle = $handle; |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
|
|
/** |
|
71
|
|
|
* Cleanup |
|
72
|
|
|
* |
|
73
|
|
|
* Destroys the handle via \WideImage\Image::destroy() when called by the GC. |
|
74
|
|
|
*/ |
|
75
|
|
|
public function __destruct() |
|
76
|
|
|
{ |
|
77
|
|
|
$this->destroy(); |
|
78
|
|
|
} |
|
79
|
|
|
|
|
80
|
|
|
/** |
|
81
|
|
|
* This method destroy the image handle, and releases the image resource. |
|
82
|
|
|
* |
|
83
|
|
|
* After this is called, the object doesn't hold a valid image any more. |
|
84
|
|
|
* No operation should be called after that. |
|
85
|
|
|
*/ |
|
86
|
|
|
public function destroy() |
|
87
|
|
|
{ |
|
88
|
|
|
if ($this->isValid() && !$this->handleReleased) { |
|
89
|
|
|
imagedestroy($this->handle); |
|
90
|
|
|
} |
|
91
|
|
|
|
|
92
|
|
|
$this->handle = null; |
|
93
|
|
|
} |
|
94
|
|
|
|
|
95
|
|
|
/** |
|
96
|
|
|
* Returns the GD image resource |
|
97
|
|
|
* |
|
98
|
|
|
* @return resource GD image resource |
|
99
|
|
|
*/ |
|
100
|
|
|
public function getHandle() |
|
101
|
|
|
{ |
|
102
|
|
|
return $this->handle; |
|
103
|
|
|
} |
|
104
|
|
|
|
|
105
|
|
|
/** |
|
106
|
|
|
* @return bool True, if the image object holds a valid GD image, false otherwise |
|
107
|
|
|
*/ |
|
108
|
|
|
public function isValid() |
|
109
|
|
|
{ |
|
110
|
|
|
return WideImage::isValidImageHandle($this->handle); |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
/** |
|
114
|
|
|
* Releases the handle |
|
115
|
|
|
*/ |
|
116
|
|
|
public function releaseHandle() |
|
117
|
|
|
{ |
|
118
|
|
|
$this->handleReleased = true; |
|
119
|
|
|
} |
|
120
|
|
|
|
|
121
|
|
|
/** |
|
122
|
|
|
* Saves an image to a file |
|
123
|
|
|
* |
|
124
|
|
|
* The file type is recognized from the $uri. If you save to a GIF8, truecolor images |
|
125
|
|
|
* are automatically converted to palette. |
|
126
|
|
|
* |
|
127
|
|
|
* This method supports additional parameters: quality (for jpeg images) and |
|
128
|
|
|
* compression quality and filters (for png images). See http://www.php.net/imagejpeg and |
|
129
|
|
|
* http://www.php.net/imagepng for details. |
|
130
|
|
|
* |
|
131
|
|
|
* Examples: |
|
132
|
|
|
* <code> |
|
133
|
|
|
* // save to a GIF |
|
134
|
|
|
* $image->saveToFile('image.gif'); |
|
135
|
|
|
* |
|
136
|
|
|
* // save to a PNG with compression=7 and no filters |
|
137
|
|
|
* $image->saveToFile('image.png', 7, PNG_NO_FILTER); |
|
138
|
|
|
* |
|
139
|
|
|
* // save to a JPEG with quality=80 |
|
140
|
|
|
* $image->saveToFile('image.jpg', 80); |
|
141
|
|
|
* |
|
142
|
|
|
* // save to a JPEG with default quality=100 |
|
143
|
|
|
* $image->saveToFile('image.jpg'); |
|
144
|
|
|
* </code> |
|
145
|
|
|
* |
|
146
|
|
|
* @param string $uri File location |
|
147
|
|
|
*/ |
|
148
|
|
|
public function saveToFile($uri) |
|
149
|
|
|
{ |
|
150
|
|
|
$mapper = MapperFactory::selectMapper($uri, null); |
|
151
|
|
|
$args = func_get_args(); |
|
152
|
|
|
array_unshift($args, $this->getHandle()); |
|
153
|
|
|
$res = call_user_func_array(array($mapper, 'save'), $args); |
|
154
|
|
|
|
|
155
|
|
|
if (!$res) { |
|
156
|
|
|
throw new UnknownErrorWhileMappingException(get_class($mapper) . " returned an invalid result while saving to $uri"); |
|
157
|
|
|
} |
|
158
|
|
|
} |
|
159
|
|
|
|
|
160
|
|
|
/** |
|
161
|
|
|
* Returns binary string with image data in format specified by $format |
|
162
|
|
|
* |
|
163
|
|
|
* Additional parameters may be passed to the function. See \WideImage\Image::saveToFile() for more details. |
|
164
|
|
|
* |
|
165
|
|
|
* @param string $format The format of the image |
|
166
|
|
|
* @return string The binary image data in specified format |
|
167
|
|
|
*/ |
|
168
|
|
|
public function asString($format) |
|
169
|
|
|
{ |
|
170
|
|
|
ob_start(); |
|
171
|
|
|
$args = func_get_args(); |
|
172
|
|
|
$args[0] = null; |
|
173
|
|
|
array_unshift($args, $this->getHandle()); |
|
174
|
|
|
|
|
175
|
|
|
$mapper = MapperFactory::selectMapper(null, $format); |
|
176
|
|
|
$res = call_user_func_array(array($mapper, 'save'), $args); |
|
177
|
|
|
|
|
178
|
|
|
if (!$res) { |
|
179
|
|
|
throw new UnknownErrorWhileMappingException(get_class($mapper) . " returned an invalid result while writing the image data"); |
|
180
|
|
|
} |
|
181
|
|
|
|
|
182
|
|
|
return ob_get_clean(); |
|
183
|
|
|
} |
|
184
|
|
|
|
|
185
|
|
|
/** |
|
186
|
|
|
* Output a header to browser. |
|
187
|
|
|
* |
|
188
|
|
|
* @param $name Name of the header |
|
|
|
|
|
|
189
|
|
|
* @param $data Data |
|
|
|
|
|
|
190
|
|
|
*/ |
|
191
|
|
|
protected function writeHeader($name, $data) |
|
192
|
|
|
{ |
|
193
|
|
|
header($name . ": " . $data); |
|
194
|
|
|
} |
|
195
|
|
|
|
|
196
|
|
|
/** |
|
197
|
|
|
* Outputs the image to browser |
|
198
|
|
|
* |
|
199
|
|
|
* Sets headers Content-length and Content-type, and echoes the image in the specified format. |
|
200
|
|
|
* All other headers (such as Content-disposition) must be added manually. |
|
201
|
|
|
* |
|
202
|
|
|
* Example: |
|
203
|
|
|
* <code> |
|
204
|
|
|
* WideImage::load('image1.png')->resize(100, 100)->output('gif'); |
|
205
|
|
|
* </code> |
|
206
|
|
|
* |
|
207
|
|
|
* @param string $format Image format |
|
208
|
|
|
*/ |
|
209
|
|
|
public function output($format) |
|
210
|
|
|
{ |
|
211
|
|
|
$args = func_get_args(); |
|
212
|
|
|
$data = call_user_func_array(array($this, 'asString'), $args); |
|
213
|
|
|
|
|
214
|
|
|
$this->writeHeader('Content-length', strlen($data)); |
|
215
|
|
|
$this->writeHeader('Content-type', MapperFactory::mimeType($format)); |
|
216
|
|
|
echo $data; |
|
217
|
|
|
} |
|
218
|
|
|
|
|
219
|
|
|
/** |
|
220
|
|
|
* @return int Image width |
|
221
|
|
|
*/ |
|
222
|
|
|
public function getWidth() |
|
223
|
|
|
{ |
|
224
|
|
|
return imagesx($this->handle); |
|
225
|
|
|
} |
|
226
|
|
|
|
|
227
|
|
|
/** |
|
228
|
|
|
* @return int Image height |
|
229
|
|
|
*/ |
|
230
|
|
|
public function getHeight() |
|
231
|
|
|
{ |
|
232
|
|
|
return imagesy($this->handle); |
|
233
|
|
|
} |
|
234
|
|
|
|
|
235
|
|
|
/** |
|
236
|
|
|
* Allocate a color by RGB values. |
|
237
|
|
|
* |
|
238
|
|
|
* @param mixed $R Red-component value or an RGB array (with red, green, blue keys) |
|
239
|
|
|
* @param int $G If $R is int, this is the green component |
|
240
|
|
|
* @param int $B If $R is int, this is the blue component |
|
241
|
|
|
* @return int Image color index |
|
242
|
|
|
*/ |
|
243
|
|
|
public function allocateColor($R, $G = null, $B = null) |
|
244
|
|
|
{ |
|
245
|
|
|
if (is_array($R)) { |
|
246
|
|
|
return imageColorAllocate($this->handle, $R['red'], $R['green'], $R['blue']); |
|
247
|
|
|
} |
|
248
|
|
|
|
|
249
|
|
|
return imageColorAllocate($this->handle, $R, $G, $B); |
|
250
|
|
|
} |
|
251
|
|
|
|
|
252
|
|
|
/** |
|
253
|
|
|
* @return bool True if the image is transparent, false otherwise |
|
254
|
|
|
*/ |
|
255
|
|
|
public function isTransparent() |
|
256
|
|
|
{ |
|
257
|
|
|
return $this->getTransparentColor() >= 0; |
|
258
|
|
|
} |
|
259
|
|
|
|
|
260
|
|
|
/** |
|
261
|
|
|
* @return int Transparent color index |
|
262
|
|
|
*/ |
|
263
|
|
|
public function getTransparentColor() |
|
264
|
|
|
{ |
|
265
|
|
|
return imagecolortransparent($this->handle); |
|
266
|
|
|
} |
|
267
|
|
|
|
|
268
|
|
|
/** |
|
269
|
|
|
* Sets the current transparent color index. Only makes sense for palette images (8-bit). |
|
270
|
|
|
* |
|
271
|
|
|
* @param int $color Transparent color index |
|
272
|
|
|
*/ |
|
273
|
|
|
public function setTransparentColor($color) |
|
274
|
|
|
{ |
|
275
|
|
|
return imagecolortransparent($this->handle, $color); |
|
276
|
|
|
} |
|
277
|
|
|
|
|
278
|
|
|
/** |
|
279
|
|
|
* Returns a RGB array of the transparent color or null if none. |
|
280
|
|
|
* |
|
281
|
|
|
* @return mixed Transparent color RGBA array |
|
282
|
|
|
*/ |
|
283
|
|
|
public function getTransparentColorRGB() |
|
284
|
|
|
{ |
|
285
|
|
|
$total = imagecolorstotal($this->handle); |
|
286
|
|
|
$tc = $this->getTransparentColor(); |
|
287
|
|
|
|
|
288
|
|
|
if ($tc >= $total && $total > 0) { |
|
289
|
|
|
return null; |
|
290
|
|
|
} |
|
291
|
|
|
|
|
292
|
|
|
return $this->getColorRGB($tc); |
|
293
|
|
|
} |
|
294
|
|
|
|
|
295
|
|
|
/** |
|
296
|
|
|
* Returns a RGBA array for pixel at $x, $y |
|
297
|
|
|
* |
|
298
|
|
|
* @param int $x |
|
299
|
|
|
* @param int $y |
|
300
|
|
|
* @return array RGB array |
|
301
|
|
|
*/ |
|
302
|
|
|
public function getRGBAt($x, $y) |
|
303
|
|
|
{ |
|
304
|
|
|
return $this->getColorRGB($this->getColorAt($x, $y)); |
|
305
|
|
|
} |
|
306
|
|
|
|
|
307
|
|
|
/** |
|
308
|
|
|
* Writes a pixel at the designated coordinates |
|
309
|
|
|
* |
|
310
|
|
|
* Takes an associative array of colours and uses getExactColor() to |
|
311
|
|
|
* retrieve the exact index color to write to the image with. |
|
312
|
|
|
* |
|
313
|
|
|
* @param int $x |
|
314
|
|
|
* @param int $y |
|
315
|
|
|
* @param array $color |
|
316
|
|
|
*/ |
|
317
|
|
|
public function setRGBAt($x, $y, $color) |
|
318
|
|
|
{ |
|
319
|
|
|
$this->setColorAt($x, $y, $this->getExactColor($color)); |
|
320
|
|
|
} |
|
321
|
|
|
|
|
322
|
|
|
/** |
|
323
|
|
|
* Returns a color's RGB |
|
324
|
|
|
* |
|
325
|
|
|
* @param int $colorIndex Color index |
|
326
|
|
|
* @return mixed RGBA array for a color with index $colorIndex |
|
327
|
|
|
*/ |
|
328
|
|
|
public function getColorRGB($colorIndex) |
|
329
|
|
|
{ |
|
330
|
|
|
return imageColorsForIndex($this->handle, $colorIndex); |
|
331
|
|
|
} |
|
332
|
|
|
|
|
333
|
|
|
/** |
|
334
|
|
|
* Returns an index of the color at $x, $y |
|
335
|
|
|
* |
|
336
|
|
|
* @param int $x |
|
337
|
|
|
* @param int $y |
|
338
|
|
|
* @return int Color index for a pixel at $x, $y |
|
339
|
|
|
*/ |
|
340
|
|
|
public function getColorAt($x, $y) |
|
341
|
|
|
{ |
|
342
|
|
|
return imagecolorat($this->handle, $x, $y); |
|
343
|
|
|
} |
|
344
|
|
|
|
|
345
|
|
|
/** |
|
346
|
|
|
* Set the color index $color to a pixel at $x, $y |
|
347
|
|
|
* |
|
348
|
|
|
* @param int $x |
|
349
|
|
|
* @param int $y |
|
350
|
|
|
* @param int $color Color index |
|
351
|
|
|
*/ |
|
352
|
|
|
public function setColorAt($x, $y, $color) |
|
353
|
|
|
{ |
|
354
|
|
|
return imagesetpixel($this->handle, $x, $y, $color); |
|
355
|
|
|
} |
|
356
|
|
|
|
|
357
|
|
|
/** |
|
358
|
|
|
* Returns closest color index that matches the given RGB value. Uses |
|
359
|
|
|
* PHP's imagecolorclosest() |
|
360
|
|
|
* |
|
361
|
|
|
* @param mixed $R Red or RGBA array |
|
362
|
|
|
* @param int $G Green component (or null if $R is an RGB array) |
|
363
|
|
|
* @param int $B Blue component (or null if $R is an RGB array) |
|
364
|
|
|
* @return int Color index |
|
365
|
|
|
*/ |
|
366
|
|
|
public function getClosestColor($R, $G = null, $B = null) |
|
367
|
|
|
{ |
|
368
|
|
|
if (is_array($R)) { |
|
369
|
|
|
return imagecolorclosest($this->handle, $R['red'], $R['green'], $R['blue']); |
|
370
|
|
|
} |
|
371
|
|
|
|
|
372
|
|
|
return imagecolorclosest($this->handle, $R, $G, $B); |
|
373
|
|
|
} |
|
374
|
|
|
|
|
375
|
|
|
/** |
|
376
|
|
|
* Returns the color index that exactly matches the given RGB value. Uses |
|
377
|
|
|
* PHP's imagecolorexact() |
|
378
|
|
|
* |
|
379
|
|
|
* @param mixed $R Red or RGBA array |
|
380
|
|
|
* @param int $G Green component (or null if $R is an RGB array) |
|
381
|
|
|
* @param int $B Blue component (or null if $R is an RGB array) |
|
382
|
|
|
* @return int Color index |
|
383
|
|
|
*/ |
|
384
|
|
|
public function getExactColor($R, $G = null, $B = null) |
|
385
|
|
|
{ |
|
386
|
|
|
if (is_array($R)) { |
|
387
|
|
|
return imagecolorexact($this->handle, $R['red'], $R['green'], $R['blue']); |
|
388
|
|
|
} |
|
389
|
|
|
|
|
390
|
|
|
return imagecolorexact($this->handle, $R, $G, $B); |
|
391
|
|
|
} |
|
392
|
|
|
|
|
393
|
|
|
/** |
|
394
|
|
|
* Copies transparency information from $sourceImage. Optionally fills |
|
395
|
|
|
* the image with the transparent color at (0, 0). |
|
396
|
|
|
* |
|
397
|
|
|
* @param object $sourceImage |
|
398
|
|
|
* @param bool $fill True if you want to fill the image with transparent color |
|
399
|
|
|
*/ |
|
400
|
|
|
public function copyTransparencyFrom($sourceImage, $fill = true) |
|
401
|
|
|
{ |
|
402
|
|
|
if ($sourceImage->isTransparent()) { |
|
403
|
|
|
$rgba = $sourceImage->getTransparentColorRGB(); |
|
404
|
|
|
|
|
405
|
|
|
if ($rgba === null) { |
|
406
|
|
|
return; |
|
407
|
|
|
} |
|
408
|
|
|
|
|
409
|
|
|
if ($this->isTrueColor()) { |
|
410
|
|
|
$rgba['alpha'] = 127; |
|
411
|
|
|
$color = $this->allocateColorAlpha($rgba); |
|
|
|
|
|
|
412
|
|
|
} else { |
|
413
|
|
|
$color = $this->allocateColor($rgba); |
|
414
|
|
|
} |
|
415
|
|
|
|
|
416
|
|
|
$this->setTransparentColor($color); |
|
|
|
|
|
|
417
|
|
|
|
|
418
|
|
|
if ($fill) { |
|
419
|
|
|
$this->fill(0, 0, $color); |
|
|
|
|
|
|
420
|
|
|
} |
|
421
|
|
|
} |
|
422
|
|
|
} |
|
423
|
|
|
|
|
424
|
|
|
/** |
|
425
|
|
|
* Fill the image at ($x, $y) with color index $color |
|
426
|
|
|
* |
|
427
|
|
|
* @param int $x |
|
428
|
|
|
* @param int $y |
|
429
|
|
|
* @param int $color |
|
430
|
|
|
*/ |
|
431
|
|
|
public function fill($x, $y, $color) |
|
432
|
|
|
{ |
|
433
|
|
|
return imagefill($this->handle, $x, $y, $color); |
|
434
|
|
|
} |
|
435
|
|
|
|
|
436
|
|
|
/** |
|
437
|
|
|
* Used internally to create Operation objects |
|
438
|
|
|
* |
|
439
|
|
|
* @param string $name |
|
440
|
|
|
* @return object |
|
441
|
|
|
*/ |
|
442
|
|
|
protected function getOperation($name) |
|
443
|
|
|
{ |
|
444
|
|
|
return OperationFactory::get($name); |
|
445
|
|
|
} |
|
446
|
|
|
|
|
447
|
|
|
/** |
|
448
|
|
|
* Returns the image's mask |
|
449
|
|
|
* |
|
450
|
|
|
* Mask is a greyscale image where the shade defines the alpha channel (black = transparent, white = opaque). |
|
451
|
|
|
* |
|
452
|
|
|
* For opaque images (JPEG), the result will be white. For images with single-color transparency (GIF, 8-bit PNG), |
|
453
|
|
|
* the areas with the transparent color will be black. For images with alpha channel transparenct, |
|
454
|
|
|
* the result will be alpha channel. |
|
455
|
|
|
* |
|
456
|
|
|
* @return \WideImage\Image An image mask |
|
457
|
|
|
**/ |
|
458
|
|
|
public function getMask() |
|
459
|
|
|
{ |
|
460
|
|
|
return $this->getOperation('GetMask')->execute($this); |
|
461
|
|
|
} |
|
462
|
|
|
|
|
463
|
|
|
/** |
|
464
|
|
|
* Resize the image to given dimensions. |
|
465
|
|
|
* |
|
466
|
|
|
* $width and $height are both smart coordinates. This means that you can pass any of these values in: |
|
467
|
|
|
* - positive or negative integer (100, -20, ...) |
|
468
|
|
|
* - positive or negative percent string (30%, -15%, ...) |
|
469
|
|
|
* - complex coordinate (50% - 20, 15 + 30%, ...) |
|
470
|
|
|
* - null: if one dimension is null, it's calculated proportionally from the other. |
|
471
|
|
|
* |
|
472
|
|
|
* $fit parameter can be set to one of these three values: |
|
473
|
|
|
* - 'inside': resize proportionally and fit the resulting image tightly in the $width x $height box |
|
474
|
|
|
* - 'outside': resize proportionally and fit the resulting image tighly outside the box |
|
475
|
|
|
* - 'fill': resize the image to fill the $width x $height box exactly |
|
476
|
|
|
* |
|
477
|
|
|
* $scale parameter can be: |
|
478
|
|
|
* - 'down': only resize the image if it's larger than the $width x $height box |
|
479
|
|
|
* - 'up': only resize the image if it's smaller than the $width x $height box |
|
480
|
|
|
* - 'any': resize the image |
|
481
|
|
|
* |
|
482
|
|
|
* Example (resize to half-size): |
|
483
|
|
|
* <code> |
|
484
|
|
|
* $smaller = $image->resize('50%'); |
|
485
|
|
|
* |
|
486
|
|
|
* $smaller = $image->resize('100', '100', 'inside', 'down'); |
|
487
|
|
|
* is the same as |
|
488
|
|
|
* $smaller = $image->resizeDown(100, 100, 'inside'); |
|
489
|
|
|
* </code> |
|
490
|
|
|
* |
|
491
|
|
|
* @param mixed $width The new width (smart coordinate), or null. |
|
492
|
|
|
* @param mixed $height The new height (smart coordinate), or null. |
|
493
|
|
|
* @param string $fit 'inside', 'outside', 'fill' |
|
494
|
|
|
* @param string $scale 'down', 'up', 'any' |
|
495
|
|
|
* @return \WideImage\Image The resized image |
|
496
|
|
|
*/ |
|
497
|
|
|
public function resize($width = null, $height = null, $fit = 'inside', $scale = 'any') |
|
498
|
|
|
{ |
|
499
|
|
|
return $this->getOperation('Resize')->execute($this, $width, $height, $fit, $scale); |
|
500
|
|
|
} |
|
501
|
|
|
|
|
502
|
|
|
/** |
|
503
|
|
|
* Same as \WideImage\Image::resize(), but the image is only applied if it is larger then the given dimensions. |
|
504
|
|
|
* Otherwise, the resulting image retains the source's dimensions. |
|
505
|
|
|
* |
|
506
|
|
|
* @param int $width New width, smart coordinate |
|
507
|
|
|
* @param int $height New height, smart coordinate |
|
508
|
|
|
* @param string $fit 'inside', 'outside', 'fill' |
|
509
|
|
|
* @return \WideImage\Image resized image |
|
510
|
|
|
*/ |
|
511
|
|
|
public function resizeDown($width = null, $height = null, $fit = 'inside') |
|
512
|
|
|
{ |
|
513
|
|
|
return $this->resize($width, $height, $fit, 'down'); |
|
514
|
|
|
} |
|
515
|
|
|
|
|
516
|
|
|
/** |
|
517
|
|
|
* Same as \WideImage\Image::resize(), but the image is only applied if it is smaller then the given dimensions. |
|
518
|
|
|
* Otherwise, the resulting image retains the source's dimensions. |
|
519
|
|
|
* |
|
520
|
|
|
* @param int $width New width, smart coordinate |
|
521
|
|
|
* @param int $height New height, smart coordinate |
|
522
|
|
|
* @param string $fit 'inside', 'outside', 'fill' |
|
523
|
|
|
* @return \WideImage\Image resized image |
|
524
|
|
|
*/ |
|
525
|
|
|
public function resizeUp($width = null, $height = null, $fit = 'inside') |
|
526
|
|
|
{ |
|
527
|
|
|
return $this->resize($width, $height, $fit, 'up'); |
|
528
|
|
|
} |
|
529
|
|
|
|
|
530
|
|
|
/** |
|
531
|
|
|
* Rotate the image for angle $angle clockwise. |
|
532
|
|
|
* |
|
533
|
|
|
* Preserves transparency. Has issues when saving to a BMP. |
|
534
|
|
|
* |
|
535
|
|
|
* @param int $angle Angle in degrees, clock-wise |
|
536
|
|
|
* @param int $bgColor color of the new background |
|
537
|
|
|
* @param bool $ignoreTransparent |
|
538
|
|
|
* @return \WideImage\Image The rotated image |
|
539
|
|
|
*/ |
|
540
|
|
|
public function rotate($angle, $bgColor = null, $ignoreTransparent = true) |
|
541
|
|
|
{ |
|
542
|
|
|
return $this->getOperation('Rotate')->execute($this, $angle, $bgColor, $ignoreTransparent); |
|
543
|
|
|
} |
|
544
|
|
|
|
|
545
|
|
|
/** |
|
546
|
|
|
* This method lays the overlay (watermark) on the image. |
|
547
|
|
|
* |
|
548
|
|
|
* Hint: if the overlay is a truecolor image with alpha channel, you should leave $pct at 100. |
|
549
|
|
|
* |
|
550
|
|
|
* This operation supports alignment notation in coordinates: |
|
551
|
|
|
* <code> |
|
552
|
|
|
* $watermark = WideImage::load('logo.gif'); |
|
553
|
|
|
* $base = WideImage::load('picture.jpg'); |
|
554
|
|
|
* $result = $base->merge($watermark, "right - 10", "bottom - 10", 50); |
|
555
|
|
|
* // applies a logo aligned to bottom-right corner with a 10 pixel margin |
|
556
|
|
|
* </code> |
|
557
|
|
|
* |
|
558
|
|
|
* @param \WideImage\Image $overlay The overlay image |
|
559
|
|
|
* @param mixed $left Left position of the overlay, smart coordinate |
|
560
|
|
|
* @param mixed $top Top position of the overlay, smart coordinate |
|
561
|
|
|
* @param int $pct The opacity of the overlay |
|
562
|
|
|
* @return \WideImage\Image The merged image |
|
563
|
|
|
*/ |
|
564
|
|
|
public function merge($overlay, $left = 0, $top = 0, $pct = 100) |
|
565
|
|
|
{ |
|
566
|
|
|
return $this->getOperation('Merge')->execute($this, $overlay, $left, $top, $pct); |
|
567
|
|
|
} |
|
568
|
|
|
|
|
569
|
|
|
/** |
|
570
|
|
|
* Resizes the canvas of the image, but doesn't scale the content of the image |
|
571
|
|
|
* |
|
572
|
|
|
* This operation creates an empty canvas with dimensions $width x $height, filled with |
|
573
|
|
|
* background color $bg_color and draws the original image onto it at position [$pos_x, $pos_y]. |
|
574
|
|
|
* |
|
575
|
|
|
* Arguments $width, $height, $pos_x and $pos_y are all smart coordinates. $width and $height are |
|
576
|
|
|
* relative to the current image size, $pos_x and $pos_y are relative to the newly calculated |
|
577
|
|
|
* canvas size. This can be confusing, but it makes sense. See the example below. |
|
578
|
|
|
* |
|
579
|
|
|
* The example below loads a 100x150 image and then resizes its canvas to 200% x 100%+20 |
|
580
|
|
|
* (which evaluates to 200x170). The image is placed at position [10, center+20], which evaluates to [10, 30]. |
|
581
|
|
|
* <code> |
|
582
|
|
|
* $image = WideImage::load('someimage.jpg'); // 100x150 |
|
583
|
|
|
* $white = $image->allocateColor(255, 255, 255); |
|
584
|
|
|
* $image->resizeCanvas('200%', '100% + 20', 10, 'center+20', $white); |
|
585
|
|
|
* </code> |
|
586
|
|
|
* |
|
587
|
|
|
* The parameter $merge defines whether the original image should be merged onto the new canvas. |
|
588
|
|
|
* This means it blends transparent color and alpha colors into the background color. If set to false, |
|
589
|
|
|
* the original image is just copied over, preserving the transparency/alpha information. |
|
590
|
|
|
* |
|
591
|
|
|
* You can set the $scale parameter to limit when to resize the canvas. For example, if you want |
|
592
|
|
|
* to resize the canvas only if the image is smaller than the new size, but leave the image intact |
|
593
|
|
|
* if it's larger, set it to 'up'. Likewise, if you want to shrink the canvas, but don't want to |
|
594
|
|
|
* change images that are already smaller, set it to 'down'. |
|
595
|
|
|
* |
|
596
|
|
|
* @param mixed $width Width of the new canvas (smart coordinate, relative to current image width) |
|
597
|
|
|
* @param mixed $height Height of the new canvas (smart coordinate, relative to current image height) |
|
598
|
|
|
* @param mixed $pos_x x-position of the image (smart coordinate, relative to the new width) |
|
599
|
|
|
* @param mixed $pos_y y-position of the image (smart coordinate, relative to the new height) |
|
600
|
|
|
* @param int $bg_color Background color (created with allocateColor or allocateColorAlpha), defaults to null (tries to use a transparent color) |
|
601
|
|
|
* @param string $scale Possible values: 'up' (enlarge only), 'down' (downsize only), 'any' (resize precisely to $width x $height). Defaults to 'any'. |
|
602
|
|
|
* @param bool $merge Merge the original image (flatten alpha channel and transparency) or copy it over (preserve). Defaults to false. |
|
603
|
|
|
* @return \WideImage\Image The resulting image with resized canvas |
|
604
|
|
|
*/ |
|
605
|
|
|
public function resizeCanvas($width, $height, $pos_x, $pos_y, $bg_color = null, $scale = 'any', $merge = false) |
|
606
|
|
|
{ |
|
607
|
|
|
return $this->getOperation('ResizeCanvas')->execute($this, $width, $height, $pos_x, $pos_y, $bg_color, $scale, $merge); |
|
608
|
|
|
} |
|
609
|
|
|
|
|
610
|
|
|
/** |
|
611
|
|
|
* Returns an image with round corners |
|
612
|
|
|
* |
|
613
|
|
|
* You can either set the corners' color or set them transparent. |
|
614
|
|
|
* |
|
615
|
|
|
* Note on $smoothness: 1 means jagged edges, 2 is much better, more than 4 doesn't noticeably improve the quality. |
|
616
|
|
|
* Rendering becomes increasingly slower if you increase smoothness. |
|
617
|
|
|
* |
|
618
|
|
|
* Example: |
|
619
|
|
|
* <code> |
|
620
|
|
|
* $nice = $ugly->roundCorners(20, $ugly->allocateColor(255, 0, 0), 2); |
|
621
|
|
|
* </code> |
|
622
|
|
|
* |
|
623
|
|
|
* Use $corners parameter to specify which corners to draw rounded. Possible values are |
|
624
|
|
|
* WideImage::SIDE_TOP_LEFT, WideImage::SIDE_TOP, |
|
625
|
|
|
* WideImage::SIDE_TOP_RIGHT, WideImage::SIDE_RIGHT, |
|
626
|
|
|
* WideImage::SIDE_BOTTOM_RIGHT, WideImage::SIDE_BOTTOM, |
|
627
|
|
|
* WideImage::SIDE_BOTTOM_LEFT, WideImage::SIDE_LEFT, and WideImage::SIDE_ALL. |
|
628
|
|
|
* You can specify any combination of corners with a + operation, see example below. |
|
629
|
|
|
* |
|
630
|
|
|
* Example: |
|
631
|
|
|
* <code> |
|
632
|
|
|
* $white = $image->allocateColor(255, 255, 255); |
|
633
|
|
|
* $diagonal_corners = $image->roundCorners(15, $white, 2, WideImage::SIDE_TOP_LEFT + WideImage::SIDE_BOTTOM_RIGHT); |
|
634
|
|
|
* $right_corners = $image->roundCorners(15, $white, 2, WideImage::SIDE_RIGHT); |
|
635
|
|
|
* </code> |
|
636
|
|
|
* |
|
637
|
|
|
* @param int $radius Radius of the corners |
|
638
|
|
|
* @param int $color The color of corners. If null, corners are rendered transparent (slower than using a solid color). |
|
639
|
|
|
* @param int $smoothness Specify the level of smoothness. Suggested values from 1 to 4. |
|
640
|
|
|
* @param int $corners Specify which corners to draw (defaults to WideImage::SIDE_ALL = all corners) |
|
641
|
|
|
* @return \WideImage\Image The resulting image with round corners |
|
642
|
|
|
*/ |
|
643
|
|
|
public function roundCorners($radius, $color = null, $smoothness = 2, $corners = 255) |
|
644
|
|
|
{ |
|
645
|
|
|
return $this->getOperation('RoundCorners')->execute($this, $radius, $color, $smoothness, $corners); |
|
646
|
|
|
} |
|
647
|
|
|
|
|
648
|
|
|
/** |
|
649
|
|
|
* Returns an image with applied mask |
|
650
|
|
|
* |
|
651
|
|
|
* A mask is a grayscale image, where the shade determines the alpha channel. Black is fully transparent |
|
652
|
|
|
* and white is fully opaque. |
|
653
|
|
|
* |
|
654
|
|
|
* @param \WideImage\Image $mask The mask image, greyscale |
|
655
|
|
|
* @param mixed $left Left coordinate, smart coordinate |
|
656
|
|
|
* @param mixed $top Top coordinate, smart coordinate |
|
657
|
|
|
* @return \WideImage\Image The resulting image |
|
658
|
|
|
**/ |
|
659
|
|
|
public function applyMask($mask, $left = 0, $top = 0) |
|
660
|
|
|
{ |
|
661
|
|
|
return $this->getOperation('ApplyMask')->execute($this, $mask, $left, $top); |
|
662
|
|
|
} |
|
663
|
|
|
|
|
664
|
|
|
/** |
|
665
|
|
|
* Applies a filter |
|
666
|
|
|
* |
|
667
|
|
|
* @param int $filter One of the IMG_FILTER_* constants |
|
668
|
|
|
* @param int $arg1 |
|
669
|
|
|
* @param int $arg2 |
|
670
|
|
|
* @param int $arg3 |
|
671
|
|
|
* @param int $arg4 |
|
672
|
|
|
* @return \WideImage\Image |
|
673
|
|
|
*/ |
|
674
|
|
|
public function applyFilter($filter, $arg1 = null, $arg2 = null, $arg3 = null, $arg4 = null) |
|
675
|
|
|
{ |
|
676
|
|
|
return $this->getOperation('ApplyFilter')->execute($this, $filter, $arg1, $arg2, $arg3, $arg4); |
|
677
|
|
|
} |
|
678
|
|
|
|
|
679
|
|
|
/** |
|
680
|
|
|
* Applies convolution matrix with imageconvolution() |
|
681
|
|
|
* |
|
682
|
|
|
* @param array $matrix |
|
683
|
|
|
* @param float $div |
|
684
|
|
|
* @param float $offset |
|
685
|
|
|
* @return \WideImage\Image |
|
686
|
|
|
*/ |
|
687
|
|
|
public function applyConvolution($matrix, $div, $offset) |
|
688
|
|
|
{ |
|
689
|
|
|
return $this->getOperation('ApplyConvolution')->execute($this, $matrix, $div, $offset); |
|
690
|
|
|
} |
|
691
|
|
|
|
|
692
|
|
|
/** |
|
693
|
|
|
* Returns a cropped rectangular portion of the image |
|
694
|
|
|
* |
|
695
|
|
|
* If the rectangle specifies area that is out of bounds, it's limited to the current image bounds. |
|
696
|
|
|
* |
|
697
|
|
|
* Examples: |
|
698
|
|
|
* <code> |
|
699
|
|
|
* $cropped = $img->crop(10, 10, 150, 200); // crops a 150x200 rect at (10, 10) |
|
700
|
|
|
* $cropped = $img->crop(-100, -50, 100, 50); // crops a 100x50 rect at the right-bottom of the image |
|
701
|
|
|
* $cropped = $img->crop('25%', '25%', '50%', '50%'); // crops a 50%x50% rect from the center of the image |
|
702
|
|
|
* </code> |
|
703
|
|
|
* |
|
704
|
|
|
* This operation supports alignment notation in left/top coordinates. |
|
705
|
|
|
* Example: |
|
706
|
|
|
* <code> |
|
707
|
|
|
* $cropped = $img->crop("right", "bottom", 100, 200); // crops a 100x200 rect from right bottom |
|
708
|
|
|
* $cropped = $img->crop("center", "middle", 50, 30); // crops a 50x30 from the center of the image |
|
709
|
|
|
* </code> |
|
710
|
|
|
* |
|
711
|
|
|
* @param mixed $left Left-coordinate of the crop rect, smart coordinate |
|
712
|
|
|
* @param mixed $top Top-coordinate of the crop rect, smart coordinate |
|
713
|
|
|
* @param mixed $width Width of the crop rect, smart coordinate |
|
714
|
|
|
* @param mixed $height Height of the crop rect, smart coordinate |
|
715
|
|
|
* @return \WideImage\Image The cropped image |
|
716
|
|
|
**/ |
|
717
|
|
|
public function crop($left = 0, $top = 0, $width = '100%', $height = '100%') |
|
718
|
|
|
{ |
|
719
|
|
|
return $this->getOperation('Crop')->execute($this, $left, $top, $width, $height); |
|
720
|
|
|
} |
|
721
|
|
|
|
|
722
|
|
|
/** |
|
723
|
|
|
* Performs an auto-crop on the image |
|
724
|
|
|
* |
|
725
|
|
|
* The image is auto-cropped from each of four sides. All sides are |
|
726
|
|
|
* scanned for pixels that differ from $base_color for more than |
|
727
|
|
|
* $rgb_threshold in absolute RGB difference. If more than $pixel_cutoff |
|
728
|
|
|
* differentiating pixels are found, that line is considered to be the crop line for the side. |
|
729
|
|
|
* If the line isn't different enough, the algorithm procedes to the next line |
|
730
|
|
|
* towards the other edge of the image. |
|
731
|
|
|
* |
|
732
|
|
|
* When the crop rectangle is found, it's enlarged by the $margin value on each of the four sides. |
|
733
|
|
|
* |
|
734
|
|
|
* @param int $margin Margin for the crop rectangle, can be negative. |
|
735
|
|
|
* @param int $rgb_threshold RGB difference which still counts as "same color". |
|
736
|
|
|
* @param int $pixel_cutoff How many pixels need to be different to mark a cut line. |
|
737
|
|
|
* @param int $base_color The base color index. If none specified (or null given), left-top pixel is used. |
|
738
|
|
|
* @return \WideImage\Image The cropped image |
|
739
|
|
|
*/ |
|
740
|
|
|
public function autoCrop($margin = 0, $rgb_threshold = 0, $pixel_cutoff = 1, $base_color = null) |
|
741
|
|
|
{ |
|
742
|
|
|
return $this->getOperation('AutoCrop')->execute($this, $margin, $rgb_threshold, $pixel_cutoff, $base_color); |
|
743
|
|
|
} |
|
744
|
|
|
|
|
745
|
|
|
/** |
|
746
|
|
|
* Returns a negative of the image |
|
747
|
|
|
* |
|
748
|
|
|
* This operation differs from calling \WideImage\Image::applyFilter(IMG_FILTER_NEGATIVE), because it's 8-bit and transparency safe. |
|
749
|
|
|
* This means it will return an 8-bit image, if the source image is 8-bit. If that 8-bit image has a palette transparency, |
|
750
|
|
|
* the resulting image will keep transparency. |
|
751
|
|
|
* |
|
752
|
|
|
* @return \WideImage\Image negative of the image |
|
753
|
|
|
*/ |
|
754
|
|
|
public function asNegative() |
|
755
|
|
|
{ |
|
756
|
|
|
return $this->getOperation('AsNegative')->execute($this); |
|
757
|
|
|
} |
|
758
|
|
|
|
|
759
|
|
|
/** |
|
760
|
|
|
* Returns a grayscale copy of the image |
|
761
|
|
|
* |
|
762
|
|
|
* @return \WideImage\Image grayscale copy |
|
763
|
|
|
**/ |
|
764
|
|
|
public function asGrayscale() |
|
765
|
|
|
{ |
|
766
|
|
|
return $this->getOperation('AsGrayscale')->execute($this); |
|
767
|
|
|
} |
|
768
|
|
|
|
|
769
|
|
|
/** |
|
770
|
|
|
* Returns a mirrored copy of the image |
|
771
|
|
|
* |
|
772
|
|
|
* @return \WideImage\Image Mirrored copy |
|
773
|
|
|
**/ |
|
774
|
|
|
public function mirror() |
|
775
|
|
|
{ |
|
776
|
|
|
return $this->getOperation('Mirror')->execute($this); |
|
777
|
|
|
} |
|
778
|
|
|
|
|
779
|
|
|
/** |
|
780
|
|
|
* Applies the unsharp filter |
|
781
|
|
|
* |
|
782
|
|
|
* @param float $amount |
|
783
|
|
|
* @param float $radius |
|
784
|
|
|
* @param float $threshold |
|
785
|
|
|
* @return \WideImage\Image Unsharpened copy of the image |
|
786
|
|
|
**/ |
|
787
|
|
|
public function unsharp($amount, $radius, $threshold) |
|
788
|
|
|
{ |
|
789
|
|
|
return $this->getOperation('Unsharp')->execute($this, $amount, $radius, $threshold); |
|
790
|
|
|
} |
|
791
|
|
|
|
|
792
|
|
|
/** |
|
793
|
|
|
* Returns a flipped (mirrored over horizontal line) copy of the image |
|
794
|
|
|
* |
|
795
|
|
|
* @return \WideImage\Image Flipped copy |
|
796
|
|
|
**/ |
|
797
|
|
|
public function flip() |
|
798
|
|
|
{ |
|
799
|
|
|
return $this->getOperation('Flip')->execute($this); |
|
800
|
|
|
} |
|
801
|
|
|
|
|
802
|
|
|
/** |
|
803
|
|
|
* Corrects gamma on the image |
|
804
|
|
|
* |
|
805
|
|
|
* @param float $inputGamma |
|
806
|
|
|
* @param float $outputGamma |
|
807
|
|
|
* @return \WideImage\Image Image with corrected gamma |
|
808
|
|
|
**/ |
|
809
|
|
|
public function correctGamma($inputGamma, $outputGamma) |
|
810
|
|
|
{ |
|
811
|
|
|
return $this->getOperation('CorrectGamma')->execute($this, $inputGamma, $outputGamma); |
|
812
|
|
|
} |
|
813
|
|
|
|
|
814
|
|
|
/** |
|
815
|
|
|
* Adds noise to the image |
|
816
|
|
|
* |
|
817
|
|
|
* @author Tomasz Kapusta |
|
818
|
|
|
* |
|
819
|
|
|
* @param int $amount Number of noise pixels to add |
|
820
|
|
|
* @param string $type Type of noise 'salt&pepper', 'color' or 'mono' |
|
821
|
|
|
* @return \WideImage\Image Image with noise added |
|
822
|
|
|
**/ |
|
823
|
|
|
public function addNoise($amount, $type) |
|
824
|
|
|
{ |
|
825
|
|
|
return $this->getOperation('AddNoise')->execute($this, $amount, $type); |
|
826
|
|
|
} |
|
827
|
|
|
|
|
828
|
|
|
/** |
|
829
|
|
|
* Used internally to execute operations |
|
830
|
|
|
* |
|
831
|
|
|
* @param string $name |
|
832
|
|
|
* @param array $args |
|
833
|
|
|
* @return \WideImage\Image |
|
834
|
|
|
*/ |
|
835
|
|
|
public function __call($name, $args) |
|
836
|
|
|
{ |
|
837
|
|
|
$op = $this->getOperation($name); |
|
838
|
|
|
array_unshift($args, $this); |
|
839
|
|
|
return call_user_func_array(array($op, 'execute'), $args); |
|
840
|
|
|
} |
|
841
|
|
|
|
|
842
|
|
|
/** |
|
843
|
|
|
* Returns an image in GIF or PNG format |
|
844
|
|
|
* |
|
845
|
|
|
* @return string |
|
846
|
|
|
*/ |
|
847
|
|
|
public function __toString() |
|
848
|
|
|
{ |
|
849
|
|
|
if ($this->isTransparent()) { |
|
850
|
|
|
return $this->asString('gif'); |
|
851
|
|
|
} |
|
852
|
|
|
|
|
853
|
|
|
return $this->asString('png'); |
|
854
|
|
|
} |
|
855
|
|
|
|
|
856
|
|
|
/** |
|
857
|
|
|
* Returns a copy of the image object |
|
858
|
|
|
* |
|
859
|
|
|
* @return \WideImage\Image The copy |
|
860
|
|
|
**/ |
|
861
|
|
|
public function copy() |
|
862
|
|
|
{ |
|
863
|
|
|
$dest = $this->doCreate($this->getWidth(), $this->getHeight()); |
|
|
|
|
|
|
864
|
|
|
$dest->copyTransparencyFrom($this, true); |
|
865
|
|
|
$this->copyTo($dest, 0, 0); |
|
866
|
|
|
return $dest; |
|
867
|
|
|
} |
|
868
|
|
|
|
|
869
|
|
|
/** |
|
870
|
|
|
* Copies this image onto another image |
|
871
|
|
|
* |
|
872
|
|
|
* @param \WideImage\Image $dest |
|
873
|
|
|
* @param int $left |
|
874
|
|
|
* @param int $top |
|
875
|
|
|
**/ |
|
876
|
|
|
public function copyTo($dest, $left = 0, $top = 0) |
|
877
|
|
|
{ |
|
878
|
|
|
if (!imagecopy($dest->getHandle(), $this->handle, $left, $top, 0, 0, $this->getWidth(), $this->getHeight())) { |
|
879
|
|
|
throw new GDFunctionResultException("imagecopy() returned false"); |
|
880
|
|
|
} |
|
881
|
|
|
} |
|
882
|
|
|
|
|
883
|
|
|
/** |
|
884
|
|
|
* Returns the canvas object |
|
885
|
|
|
* |
|
886
|
|
|
* The Canvas object can be used to draw text and shapes on the image |
|
887
|
|
|
* |
|
888
|
|
|
* Examples: |
|
889
|
|
|
* <code> |
|
890
|
|
|
* $img = WideImage::load('pic.jpg); |
|
891
|
|
|
* $canvas = $img->getCanvas(); |
|
892
|
|
|
* $canvas->useFont('arial.ttf', 15, $img->allocateColor(200, 220, 255)); |
|
893
|
|
|
* $canvas->writeText(10, 50, "Hello world!"); |
|
894
|
|
|
* |
|
895
|
|
|
* $canvas->filledRectangle(10, 10, 80, 40, $img->allocateColor(255, 127, 255)); |
|
896
|
|
|
* $canvas->line(60, 80, 30, 100, $img->allocateColor(255, 0, 0)); |
|
897
|
|
|
* $img->saveToFile('new.png'); |
|
898
|
|
|
* </code> |
|
899
|
|
|
* |
|
900
|
|
|
* @return \WideImage\Canvas The Canvas object |
|
901
|
|
|
**/ |
|
902
|
|
|
function getCanvas() |
|
|
|
|
|
|
903
|
|
|
{ |
|
904
|
|
|
if ($this->canvas == null) { |
|
905
|
|
|
$this->canvas = new Canvas($this); |
|
906
|
|
|
} |
|
907
|
|
|
|
|
908
|
|
|
return $this->canvas; |
|
909
|
|
|
} |
|
910
|
|
|
|
|
911
|
|
|
/** |
|
912
|
|
|
* Returns true if the image is true-color, false otherwise |
|
913
|
|
|
* |
|
914
|
|
|
* @return bool |
|
915
|
|
|
**/ |
|
916
|
|
|
abstract public function isTrueColor(); |
|
917
|
|
|
|
|
918
|
|
|
/** |
|
919
|
|
|
* Returns a true-color copy of the image |
|
920
|
|
|
* |
|
921
|
|
|
* @return \WideImage\TrueColorImage |
|
922
|
|
|
**/ |
|
923
|
|
|
abstract public function asTrueColor(); |
|
924
|
|
|
|
|
925
|
|
|
/** |
|
926
|
|
|
* Returns a palette copy (8bit) of the image |
|
927
|
|
|
* |
|
928
|
|
|
* @param int $nColors Number of colors in the resulting image, more than 0, less or equal to 255 |
|
929
|
|
|
* @param bool $dither Use dithering or not |
|
930
|
|
|
* @param bool $matchPalette Set to true to use imagecolormatch() to match the resulting palette more closely to the original image |
|
931
|
|
|
* @return \WideImage\Image |
|
932
|
|
|
**/ |
|
933
|
|
|
abstract public function asPalette($nColors = 255, $dither = null, $matchPalette = true); |
|
934
|
|
|
|
|
935
|
|
|
/** |
|
936
|
|
|
* Retrieve an image with selected channels |
|
937
|
|
|
* |
|
938
|
|
|
* Examples: |
|
939
|
|
|
* <code> |
|
940
|
|
|
* $channels = $img->getChannels('red', 'blue'); |
|
941
|
|
|
* $channels = $img->getChannels('alpha', 'green'); |
|
942
|
|
|
* $channels = $img->getChannels(array('green', 'blue')); |
|
943
|
|
|
* </code> |
|
944
|
|
|
* |
|
945
|
|
|
* @return \WideImage\Image |
|
946
|
|
|
**/ |
|
947
|
|
|
abstract public function getChannels(); |
|
948
|
|
|
|
|
949
|
|
|
/** |
|
950
|
|
|
* Returns an image without an alpha channel |
|
951
|
|
|
* |
|
952
|
|
|
* @return \WideImage\Image |
|
953
|
|
|
**/ |
|
954
|
|
|
abstract public function copyNoAlpha(); |
|
955
|
|
|
|
|
956
|
|
|
/** |
|
957
|
|
|
* Returns an array of serializable protected variables. Called automatically upon serialize(). |
|
958
|
|
|
* |
|
959
|
|
|
* @return array |
|
960
|
|
|
*/ |
|
961
|
|
|
public function __sleep() |
|
962
|
|
|
{ |
|
963
|
|
|
$this->sdata = $this->asString('png'); |
|
964
|
|
|
|
|
965
|
|
|
return array('sdata', 'handleReleased'); |
|
966
|
|
|
} |
|
967
|
|
|
|
|
968
|
|
|
/** |
|
969
|
|
|
* Restores an image from serialization. Called automatically upon unserialize(). |
|
970
|
|
|
*/ |
|
971
|
|
|
public function __wakeup() |
|
972
|
|
|
{ |
|
973
|
|
|
$temp_image = WideImage::loadFromString($this->sdata); |
|
974
|
|
|
$temp_image->releaseHandle(); |
|
975
|
|
|
$this->handle = $temp_image->handle; |
|
976
|
|
|
$temp_image = null; |
|
|
|
|
|
|
977
|
|
|
$this->sdata = null; |
|
978
|
|
|
} |
|
979
|
|
|
} |
|
980
|
|
|
|
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths