|
1
|
|
|
<?php |
|
2
|
|
|
////////////////////////////////////////////////////////////// |
|
3
|
|
|
// phpThumb() by James Heinrich <[email protected]> // |
|
4
|
|
|
// available at http://phpthumb.sourceforge.net // |
|
5
|
|
|
// and/or https://github.com/JamesHeinrich/phpThumb // |
|
6
|
|
|
////////////////////////////////////////////////////////////// |
|
7
|
|
|
/// // |
|
8
|
|
|
// phpthumb.filters.php - image processing filter functions // |
|
9
|
|
|
// /// |
|
10
|
|
|
////////////////////////////////////////////////////////////// |
|
11
|
|
|
|
|
12
|
|
|
class phpthumb_filters |
|
13
|
|
|
{ |
|
14
|
|
|
/** |
|
15
|
|
|
* @var phpthumb |
|
16
|
|
|
*/ |
|
17
|
|
|
|
|
18
|
|
|
public $phpThumbObject = null; |
|
19
|
|
|
|
|
20
|
|
|
public function DebugMessage($message, $file = '', $line = '') |
|
21
|
|
|
{ |
|
22
|
|
|
if (is_object($this->phpThumbObject)) { |
|
23
|
|
|
return $this->phpThumbObject->DebugMessage($message, $file, $line); |
|
24
|
|
|
} |
|
25
|
|
|
return false; |
|
26
|
|
|
} |
|
27
|
|
|
|
|
28
|
|
|
public function ApplyMask(&$gdimg_mask, &$gdimg_image) |
|
29
|
|
|
{ |
|
30
|
|
|
if (phpthumb_functions::gd_version() < 2) { |
|
31
|
|
|
$this->DebugMessage('Skipping ApplyMask() because gd_version is "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
|
32
|
|
|
return false; |
|
33
|
|
|
} |
|
34
|
|
|
if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '4.3.2', '>=')) { |
|
35
|
|
|
$this->DebugMessage('Using alpha ApplyMask() technique', __FILE__, __LINE__); |
|
36
|
|
|
if ($gdimg_mask_resized = phpthumb_functions::ImageCreateFunction(imagesx($gdimg_image), imagesy($gdimg_image))) { |
|
37
|
|
|
imagecopyresampled($gdimg_mask_resized, $gdimg_mask, 0, 0, 0, 0, imagesx($gdimg_image), imagesy($gdimg_image), imagesx($gdimg_mask), imagesy($gdimg_mask)); |
|
38
|
|
|
if ($gdimg_mask_blendtemp = phpthumb_functions::ImageCreateFunction(imagesx($gdimg_image), imagesy($gdimg_image))) { |
|
39
|
|
|
$color_background = imagecolorallocate($gdimg_mask_blendtemp, 0, 0, 0); |
|
40
|
|
|
imagefilledrectangle($gdimg_mask_blendtemp, 0, 0, imagesx($gdimg_mask_blendtemp), imagesy($gdimg_mask_blendtemp), $color_background); |
|
41
|
|
|
imagealphablending($gdimg_mask_blendtemp, false); |
|
42
|
|
|
imagesavealpha($gdimg_mask_blendtemp, true); |
|
43
|
|
|
for ($x = 0, $xMax = imagesx($gdimg_image); $x < $xMax; $x++) { |
|
44
|
|
|
for ($y = 0, $yMax = imagesy($gdimg_image); $y < $yMax; $y++) { |
|
45
|
|
|
//$RealPixel = phpthumb_functions::GetPixelColor($gdimg_mask_blendtemp, $x, $y); |
|
46
|
|
|
$RealPixel = phpthumb_functions::GetPixelColor($gdimg_image, $x, $y); |
|
47
|
|
|
$MaskPixel = phpthumb_functions::GrayscalePixel(phpthumb_functions::GetPixelColor($gdimg_mask_resized, $x, $y)); |
|
48
|
|
|
$MaskAlpha = 127 - (floor($MaskPixel['red'] / 2) * (1 - ($RealPixel['alpha'] / 127))); |
|
49
|
|
|
$newcolor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_mask_blendtemp, $RealPixel['red'], $RealPixel['green'], $RealPixel['blue'], $MaskAlpha); |
|
50
|
|
|
imagesetpixel($gdimg_mask_blendtemp, $x, $y, $newcolor); |
|
51
|
|
|
} |
|
52
|
|
|
} |
|
53
|
|
|
imagealphablending($gdimg_image, false); |
|
54
|
|
|
imagesavealpha($gdimg_image, true); |
|
55
|
|
|
imagecopy($gdimg_image, $gdimg_mask_blendtemp, 0, 0, 0, 0, imagesx($gdimg_mask_blendtemp), imagesy($gdimg_mask_blendtemp)); |
|
56
|
|
|
imagedestroy($gdimg_mask_blendtemp); |
|
57
|
|
|
} else { |
|
58
|
|
|
$this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); |
|
59
|
|
|
} |
|
60
|
|
|
imagedestroy($gdimg_mask_resized); |
|
61
|
|
|
} else { |
|
62
|
|
|
$this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); |
|
63
|
|
|
} |
|
64
|
|
|
} else { |
|
65
|
|
|
// alpha merging requires PHP v4.3.2+ |
|
66
|
|
|
$this->DebugMessage('Skipping ApplyMask() technique because PHP is v"' . PHP_VERSION . '"', __FILE__, __LINE__); |
|
67
|
|
|
} |
|
68
|
|
|
return true; |
|
69
|
|
|
} |
|
70
|
|
|
|
|
71
|
|
|
public function Bevel(&$gdimg, $width, $hexcolor1, $hexcolor2) |
|
72
|
|
|
{ |
|
73
|
|
|
$width = ($width ? $width : 5); |
|
74
|
|
|
$hexcolor1 = ($hexcolor1 ? $hexcolor1 : 'FFFFFF'); |
|
75
|
|
|
$hexcolor2 = ($hexcolor2 ? $hexcolor2 : '000000'); |
|
76
|
|
|
|
|
77
|
|
|
imagealphablending($gdimg, true); |
|
78
|
|
|
for ($i = 0; $i < $width; $i++) { |
|
79
|
|
|
$alpha = round(($i / $width) * 127); |
|
80
|
|
|
$color1 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1, false, $alpha); |
|
81
|
|
|
$color2 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2, false, $alpha); |
|
82
|
|
|
|
|
83
|
|
|
imageline($gdimg, $i, $i + 1, $i, imagesy($gdimg) - $i - 1, $color1); // left |
|
84
|
|
|
imageline($gdimg, $i, $i, imagesx($gdimg) - $i, $i, $color1); // top |
|
85
|
|
|
imageline($gdimg, imagesx($gdimg) - $i, imagesy($gdimg) - $i - 1, imagesx($gdimg) - $i, $i + 1, $color2); // right |
|
86
|
|
|
imageline($gdimg, imagesx($gdimg) - $i, imagesy($gdimg) - $i, $i, imagesy($gdimg) - $i, $color2); // bottom |
|
87
|
|
|
} |
|
88
|
|
|
return true; |
|
89
|
|
|
} |
|
90
|
|
|
|
|
91
|
|
|
public function Blur(&$gdimg, $radius = 0.5) |
|
92
|
|
|
{ |
|
93
|
|
|
// Taken from Torstein Hønsi's phpUnsharpMask (see phpthumb.unsharp.php) |
|
94
|
|
|
|
|
95
|
|
|
$radius = round(max(0, min($radius, 50)) * 2); |
|
96
|
|
|
if (!$radius) { |
|
97
|
|
|
return false; |
|
98
|
|
|
} |
|
99
|
|
|
|
|
100
|
|
|
$w = imagesx($gdimg); |
|
101
|
|
|
$h = imagesy($gdimg); |
|
102
|
|
|
if ($imgBlur = imagecreatetruecolor($w, $h)) { |
|
103
|
|
|
// Gaussian blur matrix: |
|
104
|
|
|
// 1 2 1 |
|
105
|
|
|
// 2 4 2 |
|
106
|
|
|
// 1 2 1 |
|
107
|
|
|
|
|
108
|
|
|
// Move copies of the image around one pixel at the time and merge them with weight |
|
109
|
|
|
// according to the matrix. The same matrix is simply repeated for higher radii. |
|
110
|
|
|
for ($i = 0; $i < $radius; $i++) { |
|
111
|
|
|
imagecopy($imgBlur, $gdimg, 0, 0, 1, 1, $w - 1, $h - 1); // up left |
|
112
|
|
|
imagecopymerge($imgBlur, $gdimg, 1, 1, 0, 0, $w, $h, 50.00000); // down right |
|
113
|
|
|
imagecopymerge($imgBlur, $gdimg, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left |
|
|
|
|
|
|
114
|
|
|
imagecopymerge($imgBlur, $gdimg, 1, 0, 0, 1, $w, $h - 1, 25.00000); // up right |
|
115
|
|
|
imagecopymerge($imgBlur, $gdimg, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left |
|
116
|
|
|
imagecopymerge($imgBlur, $gdimg, 1, 0, 0, 0, $w, $h, 25.00000); // right |
|
117
|
|
|
imagecopymerge($imgBlur, $gdimg, 0, 0, 0, 1, $w, $h - 1, 20.00000); // up |
|
118
|
|
|
imagecopymerge($imgBlur, $gdimg, 0, 1, 0, 0, $w, $h, 16.666667); // down |
|
119
|
|
|
imagecopymerge($imgBlur, $gdimg, 0, 0, 0, 0, $w, $h, 50.000000); // center |
|
120
|
|
|
imagecopy($gdimg, $imgBlur, 0, 0, 0, 0, $w, $h); |
|
121
|
|
|
} |
|
122
|
|
|
return true; |
|
123
|
|
|
} |
|
124
|
|
|
return false; |
|
125
|
|
|
} |
|
126
|
|
|
|
|
127
|
|
|
public function BlurGaussian(&$gdimg) |
|
128
|
|
|
{ |
|
129
|
|
|
if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { |
|
130
|
|
|
if (imagefilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)) { |
|
131
|
|
|
return true; |
|
132
|
|
|
} |
|
133
|
|
|
$this->DebugMessage('FAILED: imagefilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)', __FILE__, __LINE__); |
|
134
|
|
|
// fall through and try it the hard way |
|
135
|
|
|
} |
|
136
|
|
|
$this->DebugMessage('FAILED: phpthumb_filters::BlurGaussian($gdimg) [using phpthumb_filters::Blur() instead]', __FILE__, __LINE__); |
|
137
|
|
|
return $this->Blur($gdimg, 0.5); |
|
138
|
|
|
} |
|
139
|
|
|
|
|
140
|
|
|
public function BlurSelective(&$gdimg) |
|
141
|
|
|
{ |
|
142
|
|
|
if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { |
|
143
|
|
|
if (imagefilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)) { |
|
144
|
|
|
return true; |
|
145
|
|
|
} |
|
146
|
|
|
$this->DebugMessage('FAILED: imagefilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)', __FILE__, __LINE__); |
|
147
|
|
|
// fall through and try it the hard way |
|
148
|
|
|
} |
|
149
|
|
|
// currently not implemented "the hard way" |
|
150
|
|
|
$this->DebugMessage('FAILED: phpthumb_filters::BlurSelective($gdimg) [function not implemented]', __FILE__, __LINE__); |
|
151
|
|
|
return false; |
|
152
|
|
|
} |
|
153
|
|
|
|
|
154
|
|
|
public function Brightness(&$gdimg, $amount = 0) |
|
155
|
|
|
{ |
|
156
|
|
|
if ($amount == 0) { |
|
157
|
|
|
return true; |
|
158
|
|
|
} |
|
159
|
|
|
$amount = max(-255, min(255, $amount)); |
|
160
|
|
|
|
|
161
|
|
|
if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { |
|
162
|
|
|
if (imagefilter($gdimg, IMG_FILTER_BRIGHTNESS, $amount)) { |
|
163
|
|
|
return true; |
|
164
|
|
|
} |
|
165
|
|
|
$this->DebugMessage('FAILED: imagefilter($gdimg, IMG_FILTER_BRIGHTNESS, ' . $amount . ')', __FILE__, __LINE__); |
|
166
|
|
|
// fall through and try it the hard way |
|
167
|
|
|
} |
|
168
|
|
|
|
|
169
|
|
|
$scaling = (255 - abs($amount)) / 255; |
|
170
|
|
|
$baseamount = (($amount > 0) ? $amount : 0); |
|
171
|
|
|
for ($x = 0, $xMax = imagesx($gdimg); $x < $xMax; $x++) { |
|
172
|
|
|
for ($y = 0, $yMax = imagesy($gdimg); $y < $yMax; $y++) { |
|
173
|
|
|
$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); |
|
174
|
|
|
$NewPixel = []; |
|
175
|
|
|
foreach ($OriginalPixel as $key => $value) { |
|
176
|
|
|
$NewPixel[$key] = round($baseamount + ($OriginalPixel[$key] * $scaling)); |
|
177
|
|
|
} |
|
178
|
|
|
$newColor = imagecolorallocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); |
|
179
|
|
|
imagesetpixel($gdimg, $x, $y, $newColor); |
|
180
|
|
|
} |
|
181
|
|
|
} |
|
182
|
|
|
return true; |
|
183
|
|
|
} |
|
184
|
|
|
|
|
185
|
|
|
public function Contrast(&$gdimg, $amount = 0) |
|
186
|
|
|
{ |
|
187
|
|
|
if ($amount == 0) { |
|
188
|
|
|
return true; |
|
189
|
|
|
} |
|
190
|
|
|
$amount = max(-255, min(255, $amount)); |
|
191
|
|
|
|
|
192
|
|
|
if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { |
|
193
|
|
|
// imagefilter(IMG_FILTER_CONTRAST) has range +100 to -100 (positive numbers make it darker!) |
|
194
|
|
|
$amount = ($amount / 255) * -100; |
|
195
|
|
|
if (imagefilter($gdimg, IMG_FILTER_CONTRAST, $amount)) { |
|
196
|
|
|
return true; |
|
197
|
|
|
} |
|
198
|
|
|
$this->DebugMessage('FAILED: imagefilter($gdimg, IMG_FILTER_CONTRAST, ' . $amount . ')', __FILE__, __LINE__); |
|
199
|
|
|
// fall through and try it the hard way |
|
200
|
|
|
} |
|
201
|
|
|
|
|
202
|
|
|
if ($amount > 0) { |
|
203
|
|
|
$scaling = 1 + ($amount / 255); |
|
204
|
|
|
} else { |
|
205
|
|
|
$scaling = (255 - abs($amount)) / 255; |
|
206
|
|
|
} |
|
207
|
|
|
for ($x = 0, $xMax = imagesx($gdimg); $x < $xMax; $x++) { |
|
208
|
|
|
for ($y = 0, $yMax = imagesy($gdimg); $y < $yMax; $y++) { |
|
209
|
|
|
$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); |
|
210
|
|
|
$NewPixel = []; |
|
211
|
|
|
foreach ($OriginalPixel as $key => $value) { |
|
212
|
|
|
$NewPixel[$key] = min(255, max(0, round($OriginalPixel[$key] * $scaling))); |
|
213
|
|
|
} |
|
214
|
|
|
$newColor = imagecolorallocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); |
|
215
|
|
|
imagesetpixel($gdimg, $x, $y, $newColor); |
|
216
|
|
|
} |
|
217
|
|
|
} |
|
218
|
|
|
return true; |
|
219
|
|
|
} |
|
220
|
|
|
|
|
221
|
|
|
public function Colorize(&$gdimg, $amount, $targetColor) |
|
222
|
|
|
{ |
|
223
|
|
|
$amount = (is_numeric($amount) ? $amount : 25); |
|
224
|
|
|
$amountPct = $amount / 100; |
|
225
|
|
|
$targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'gray'); |
|
226
|
|
|
|
|
227
|
|
|
if ($amount == 0) { |
|
228
|
|
|
return true; |
|
229
|
|
|
} |
|
230
|
|
|
|
|
231
|
|
|
if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { |
|
232
|
|
|
if ($targetColor == 'gray') { |
|
233
|
|
|
$targetColor = '808080'; |
|
234
|
|
|
} |
|
235
|
|
|
$r = round($amountPct * hexdec(substr($targetColor, 0, 2))); |
|
236
|
|
|
$g = round($amountPct * hexdec(substr($targetColor, 2, 2))); |
|
237
|
|
|
$b = round($amountPct * hexdec(substr($targetColor, 4, 2))); |
|
238
|
|
|
if (imagefilter($gdimg, IMG_FILTER_COLORIZE, $r, $g, $b)) { |
|
|
|
|
|
|
239
|
|
|
return true; |
|
240
|
|
|
} |
|
241
|
|
|
$this->DebugMessage('FAILED: imagefilter($gdimg, IMG_FILTER_COLORIZE)', __FILE__, __LINE__); |
|
242
|
|
|
// fall through and try it the hard way |
|
243
|
|
|
} |
|
244
|
|
|
|
|
245
|
|
|
// overridden below for grayscale |
|
246
|
|
|
$TargetPixel = []; |
|
247
|
|
|
if ($targetColor != 'gray') { |
|
248
|
|
|
$TargetPixel['red'] = hexdec(substr($targetColor, 0, 2)); |
|
249
|
|
|
$TargetPixel['green'] = hexdec(substr($targetColor, 2, 2)); |
|
250
|
|
|
$TargetPixel['blue'] = hexdec(substr($targetColor, 4, 2)); |
|
251
|
|
|
} |
|
252
|
|
|
|
|
253
|
|
|
for ($x = 0, $xMax = imagesx($gdimg); $x < $xMax; $x++) { |
|
254
|
|
|
for ($y = 0, $yMax = imagesy($gdimg); $y < $yMax; $y++) { |
|
255
|
|
|
$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); |
|
256
|
|
|
if ($targetColor == 'gray') { |
|
257
|
|
|
$TargetPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); |
|
258
|
|
|
} |
|
259
|
|
|
$NewPixel = []; |
|
260
|
|
|
foreach ($TargetPixel as $key => $value) { |
|
261
|
|
|
$NewPixel[$key] = round(max(0, min(255, ($OriginalPixel[$key] * ((100 - $amount) / 100)) + ($TargetPixel[$key] * $amountPct)))); |
|
262
|
|
|
} |
|
263
|
|
|
//$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']); |
|
264
|
|
|
$newColor = imagecolorallocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); |
|
265
|
|
|
imagesetpixel($gdimg, $x, $y, $newColor); |
|
266
|
|
|
} |
|
267
|
|
|
} |
|
268
|
|
|
return true; |
|
269
|
|
|
} |
|
270
|
|
|
|
|
271
|
|
|
public function Crop(&$gdimg, $left = 0, $right = 0, $top = 0, $bottom = 0) |
|
272
|
|
|
{ |
|
273
|
|
|
if (!$left && !$right && !$top && !$bottom) { |
|
274
|
|
|
return true; |
|
275
|
|
|
} |
|
276
|
|
|
$oldW = imagesx($gdimg); |
|
277
|
|
|
$oldH = imagesy($gdimg); |
|
278
|
|
|
if (($left > 0) && ($left < 1)) { |
|
279
|
|
|
$left = round($left * $oldW); |
|
280
|
|
|
} |
|
281
|
|
|
if (($right > 0) && ($right < 1)) { |
|
282
|
|
|
$right = round($right * $oldW); |
|
283
|
|
|
} |
|
284
|
|
|
if (($top > 0) && ($top < 1)) { |
|
285
|
|
|
$top = round($top * $oldH); |
|
286
|
|
|
} |
|
287
|
|
|
if (($bottom > 0) && ($bottom < 1)) { |
|
288
|
|
|
$bottom = round($bottom * $oldH); |
|
289
|
|
|
} |
|
290
|
|
|
$right = min($oldW - $left - 1, $right); |
|
291
|
|
|
$bottom = min($oldH - $top - 1, $bottom); |
|
292
|
|
|
$newW = $oldW - $left - $right; |
|
293
|
|
|
$newH = $oldH - $top - $bottom; |
|
294
|
|
|
|
|
295
|
|
|
if ($imgCropped = imagecreatetruecolor($newW, $newH)) { |
|
296
|
|
|
imagecopy($imgCropped, $gdimg, 0, 0, $left, $top, $newW, $newH); |
|
297
|
|
|
if ($gdimg = imagecreatetruecolor($newW, $newH)) { |
|
298
|
|
|
imagecopy($gdimg, $imgCropped, 0, 0, 0, 0, $newW, $newH); |
|
299
|
|
|
imagedestroy($imgCropped); |
|
300
|
|
|
return true; |
|
301
|
|
|
} |
|
302
|
|
|
imagedestroy($imgCropped); |
|
303
|
|
|
} |
|
304
|
|
|
return false; |
|
305
|
|
|
} |
|
306
|
|
|
|
|
307
|
|
|
public function Desaturate(&$gdimg, $amount, $color = '') |
|
308
|
|
|
{ |
|
309
|
|
|
if ($amount == 0) { |
|
310
|
|
|
return true; |
|
311
|
|
|
} |
|
312
|
|
|
return $this->Colorize($gdimg, $amount, (phpthumb_functions::IsHexColor($color) ? $color : 'gray')); |
|
313
|
|
|
} |
|
314
|
|
|
|
|
315
|
|
|
public function DropShadow(&$gdimg, $distance, $width, $hexcolor, $angle, $alpha) |
|
316
|
|
|
{ |
|
317
|
|
|
if (phpthumb_functions::gd_version() < 2) { |
|
318
|
|
|
return false; |
|
319
|
|
|
} |
|
320
|
|
|
$distance = ($distance ? $distance : 10); |
|
321
|
|
|
$width = ($width ? $width : 10); |
|
322
|
|
|
$hexcolor = ($hexcolor ? $hexcolor : '000000'); |
|
323
|
|
|
$angle = ($angle ? $angle : 225) % 360; |
|
324
|
|
|
$alpha = max(0, min(100, ($alpha ? $alpha : 100))); |
|
325
|
|
|
|
|
326
|
|
|
if ($alpha <= 0) { |
|
327
|
|
|
// invisible shadow, nothing to do |
|
328
|
|
|
return true; |
|
329
|
|
|
} |
|
330
|
|
|
if ($distance <= 0) { |
|
331
|
|
|
// shadow completely obscured by source image, nothing to do |
|
332
|
|
|
return true; |
|
333
|
|
|
} |
|
334
|
|
|
|
|
335
|
|
|
//$width_shadow = cos(deg2rad($angle)) * ($distance + $width); |
|
336
|
|
|
//$height_shadow = sin(deg2rad($angle)) * ($distance + $width); |
|
337
|
|
|
//$scaling = min(imagesx($gdimg) / (imagesx($gdimg) + abs($width_shadow)), imagesy($gdimg) / (imagesy($gdimg) + abs($height_shadow))); |
|
338
|
|
|
|
|
339
|
|
|
$Offset = []; |
|
340
|
|
|
for ($i = 0; $i < $width; $i++) { |
|
341
|
|
|
$WidthAlpha[$i] = (abs(($width / 2) - $i) / $width); |
|
342
|
|
|
$Offset['x'] = cos(deg2rad($angle)) * ($distance + $i); |
|
343
|
|
|
$Offset['y'] = sin(deg2rad($angle)) * ($distance + $i); |
|
344
|
|
|
} |
|
345
|
|
|
|
|
346
|
|
|
$tempImageWidth = imagesx($gdimg) + abs($Offset['x']); |
|
347
|
|
|
$tempImageHeight = imagesy($gdimg) + abs($Offset['y']); |
|
348
|
|
|
|
|
349
|
|
|
if ($gdimg_dropshadow_temp = phpthumb_functions::ImageCreateFunction($tempImageWidth, $tempImageHeight)) { |
|
350
|
|
|
imagealphablending($gdimg_dropshadow_temp, false); |
|
351
|
|
|
imagesavealpha($gdimg_dropshadow_temp, true); |
|
352
|
|
|
$transparent1 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, 0, 0, 0, 127); |
|
353
|
|
|
imagefill($gdimg_dropshadow_temp, 0, 0, $transparent1); |
|
354
|
|
|
|
|
355
|
|
|
$PixelMap = []; |
|
356
|
|
|
for ($x = 0, $xMax = imagesx($gdimg); $x < $xMax; $x++) { |
|
357
|
|
|
for ($y = 0, $yMax = imagesy($gdimg); $y < $yMax; $y++) { |
|
358
|
|
|
$PixelMap[$x][$y] = phpthumb_functions::GetPixelColor($gdimg, $x, $y); |
|
359
|
|
|
} |
|
360
|
|
|
} |
|
361
|
|
|
for ($x = 0; $x < $tempImageWidth; $x++) { |
|
362
|
|
|
for ($y = 0; $y < $tempImageHeight; $y++) { |
|
363
|
|
|
//for ($i = 0; $i < $width; $i++) { |
|
364
|
|
|
for ($i = 0; $i < 1; $i++) { |
|
365
|
|
|
if (!isset($PixelMap[$x][$y]['alpha']) || ($PixelMap[$x][$y]['alpha'] > 0)) { |
|
366
|
|
|
if (isset($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']) && ($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha'] < 127)) { |
|
367
|
|
|
$thisColor = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor, false, $PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']); |
|
368
|
|
|
imagesetpixel($gdimg_dropshadow_temp, $x, $y, $thisColor); |
|
369
|
|
|
} |
|
370
|
|
|
} |
|
371
|
|
|
} |
|
372
|
|
|
} |
|
373
|
|
|
} |
|
374
|
|
|
|
|
375
|
|
|
imagealphablending($gdimg_dropshadow_temp, true); |
|
376
|
|
|
for ($x = 0, $xMax = imagesx($gdimg); $x < $xMax; $x++) { |
|
377
|
|
|
for ($y = 0, $yMax = imagesy($gdimg); $y < $yMax; $y++) { |
|
378
|
|
|
if ($PixelMap[$x][$y]['alpha'] < 127) { |
|
379
|
|
|
$thisColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, $PixelMap[$x][$y]['red'], $PixelMap[$x][$y]['green'], $PixelMap[$x][$y]['blue'], $PixelMap[$x][$y]['alpha']); |
|
380
|
|
|
imagesetpixel($gdimg_dropshadow_temp, $x, $y, $thisColor); |
|
381
|
|
|
} |
|
382
|
|
|
} |
|
383
|
|
|
} |
|
384
|
|
|
|
|
385
|
|
|
imagesavealpha($gdimg, true); |
|
386
|
|
|
imagealphablending($gdimg, false); |
|
387
|
|
|
//$this->is_alpha = true; |
|
388
|
|
|
$transparent2 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0, 0, 0, 127); |
|
389
|
|
|
imagefilledrectangle($gdimg, 0, 0, imagesx($gdimg), imagesy($gdimg), $transparent2); |
|
390
|
|
|
imagecopyresampled($gdimg, $gdimg_dropshadow_temp, 0, 0, 0, 0, imagesx($gdimg), imagesy($gdimg), imagesx($gdimg_dropshadow_temp), imagesy($gdimg_dropshadow_temp)); |
|
391
|
|
|
|
|
392
|
|
|
imagedestroy($gdimg_dropshadow_temp); |
|
393
|
|
|
} |
|
394
|
|
|
return true; |
|
395
|
|
|
} |
|
396
|
|
|
|
|
397
|
|
|
public function EdgeDetect(&$gdimg) |
|
398
|
|
|
{ |
|
399
|
|
|
if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { |
|
400
|
|
|
if (imagefilter($gdimg, IMG_FILTER_EDGEDETECT)) { |
|
401
|
|
|
return true; |
|
402
|
|
|
} |
|
403
|
|
|
$this->DebugMessage('FAILED: imagefilter($gdimg, IMG_FILTER_EDGEDETECT)', __FILE__, __LINE__); |
|
404
|
|
|
// fall through and try it the hard way |
|
405
|
|
|
} |
|
406
|
|
|
// currently not implemented "the hard way" |
|
407
|
|
|
$this->DebugMessage('FAILED: phpthumb_filters::EdgeDetect($gdimg) [function not implemented]', __FILE__, __LINE__); |
|
408
|
|
|
return false; |
|
409
|
|
|
} |
|
410
|
|
|
|
|
411
|
|
|
public function Ellipse($gdimg) |
|
412
|
|
|
{ |
|
413
|
|
|
if (phpthumb_functions::gd_version() < 2) { |
|
414
|
|
|
return false; |
|
415
|
|
|
} |
|
416
|
|
|
// generate mask at twice desired resolution and downsample afterwards for easy antialiasing |
|
417
|
|
|
if ($gdimg_ellipsemask_double = phpthumb_functions::ImageCreateFunction(imagesx($gdimg) * 2, imagesy($gdimg) * 2)) { |
|
418
|
|
|
if ($gdimg_ellipsemask = phpthumb_functions::ImageCreateFunction(imagesx($gdimg), imagesy($gdimg))) { |
|
419
|
|
|
$color_transparent = imagecolorallocate($gdimg_ellipsemask_double, 255, 255, 255); |
|
420
|
|
|
imagefilledellipse($gdimg_ellipsemask_double, imagesx($gdimg), imagesy($gdimg), (imagesx($gdimg) - 1) * 2, (imagesy($gdimg) - 1) * 2, $color_transparent); |
|
421
|
|
|
imagecopyresampled($gdimg_ellipsemask, $gdimg_ellipsemask_double, 0, 0, 0, 0, imagesx($gdimg), imagesy($gdimg), imagesx($gdimg) * 2, imagesy($gdimg) * 2); |
|
422
|
|
|
|
|
423
|
|
|
$this->ApplyMask($gdimg_ellipsemask, $gdimg); |
|
424
|
|
|
imagedestroy($gdimg_ellipsemask); |
|
425
|
|
|
return true; |
|
426
|
|
|
} else { |
|
427
|
|
|
$this->DebugMessage('$gdimg_ellipsemask = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__); |
|
428
|
|
|
} |
|
429
|
|
|
imagedestroy($gdimg_ellipsemask_double); |
|
430
|
|
|
} else { |
|
431
|
|
|
$this->DebugMessage('$gdimg_ellipsemask_double = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__); |
|
432
|
|
|
} |
|
433
|
|
|
return false; |
|
434
|
|
|
} |
|
435
|
|
|
|
|
436
|
|
|
public function Emboss(&$gdimg) |
|
437
|
|
|
{ |
|
438
|
|
|
if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { |
|
439
|
|
|
if (imagefilter($gdimg, IMG_FILTER_EMBOSS)) { |
|
440
|
|
|
return true; |
|
441
|
|
|
} |
|
442
|
|
|
$this->DebugMessage('FAILED: imagefilter($gdimg, IMG_FILTER_EMBOSS)', __FILE__, __LINE__); |
|
443
|
|
|
// fall through and try it the hard way |
|
444
|
|
|
} |
|
445
|
|
|
// currently not implemented "the hard way" |
|
446
|
|
|
$this->DebugMessage('FAILED: phpthumb_filters::Emboss($gdimg) [function not implemented]', __FILE__, __LINE__); |
|
447
|
|
|
return false; |
|
448
|
|
|
} |
|
449
|
|
|
|
|
450
|
|
|
public function Flip(&$gdimg, $x = false, $y = false) |
|
451
|
|
|
{ |
|
452
|
|
|
if (!$x && !$y) { |
|
453
|
|
|
return false; |
|
454
|
|
|
} |
|
455
|
|
|
if ($tempImage = phpthumb_functions::ImageCreateFunction(imagesx($gdimg), imagesy($gdimg))) { |
|
456
|
|
|
if ($x) { |
|
457
|
|
|
imagecopy($tempImage, $gdimg, 0, 0, 0, 0, imagesx($gdimg), imagesy($gdimg)); |
|
458
|
|
|
for ($x = 0, $xMax = imagesx($gdimg); $x < $xMax; $x++) { |
|
459
|
|
|
imagecopy($gdimg, $tempImage, imagesx($gdimg) - 1 - $x, 0, $x, 0, 1, imagesy($gdimg)); |
|
460
|
|
|
} |
|
461
|
|
|
} |
|
462
|
|
|
if ($y) { |
|
463
|
|
|
imagecopy($tempImage, $gdimg, 0, 0, 0, 0, imagesx($gdimg), imagesy($gdimg)); |
|
464
|
|
|
for ($y = 0, $yMax = imagesy($gdimg); $y < $yMax; $y++) { |
|
465
|
|
|
imagecopy($gdimg, $tempImage, 0, imagesy($gdimg) - 1 - $y, 0, $y, imagesx($gdimg), 1); |
|
466
|
|
|
} |
|
467
|
|
|
} |
|
468
|
|
|
imagedestroy($tempImage); |
|
469
|
|
|
} |
|
470
|
|
|
return true; |
|
471
|
|
|
} |
|
472
|
|
|
|
|
473
|
|
|
public function Frame(&$gdimg, $frame_width, $edge_width, $hexcolor_frame, $hexcolor1, $hexcolor2) |
|
474
|
|
|
{ |
|
475
|
|
|
$frame_width = ($frame_width ? $frame_width : 5); |
|
476
|
|
|
$edge_width = ($edge_width ? $edge_width : 1); |
|
477
|
|
|
$hexcolor_frame = ($hexcolor_frame ? $hexcolor_frame : 'CCCCCC'); |
|
478
|
|
|
$hexcolor1 = ($hexcolor1 ? $hexcolor1 : 'FFFFFF'); |
|
479
|
|
|
$hexcolor2 = ($hexcolor2 ? $hexcolor2 : '000000'); |
|
480
|
|
|
|
|
481
|
|
|
$color_frame = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor_frame); |
|
482
|
|
|
$color1 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1); |
|
483
|
|
|
$color2 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2); |
|
484
|
|
|
for ($i = 0; $i < $edge_width; $i++) { |
|
485
|
|
|
// outer bevel |
|
486
|
|
|
imageline($gdimg, $i, $i, $i, imagesy($gdimg) - $i, $color1); // left |
|
487
|
|
|
imageline($gdimg, $i, $i, imagesx($gdimg) - $i, $i, $color1); // top |
|
488
|
|
|
imageline($gdimg, imagesx($gdimg) - $i, imagesy($gdimg) - $i, imagesx($gdimg) - $i, $i, $color2); // right |
|
489
|
|
|
imageline($gdimg, imagesx($gdimg) - $i, imagesy($gdimg) - $i, $i, imagesy($gdimg) - $i, $color2); // bottom |
|
490
|
|
|
} |
|
491
|
|
|
for ($i = 0; $i < $frame_width; $i++) { |
|
492
|
|
|
// actual frame |
|
493
|
|
|
imagerectangle($gdimg, $edge_width + $i, $edge_width + $i, imagesx($gdimg) - $edge_width - $i, imagesy($gdimg) - $edge_width - $i, $color_frame); |
|
494
|
|
|
} |
|
495
|
|
|
for ($i = 0; $i < $edge_width; $i++) { |
|
496
|
|
|
// inner bevel |
|
497
|
|
|
imageline($gdimg, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, imagesy($gdimg) - $frame_width - $edge_width - $i, $color2); // left |
|
498
|
|
|
imageline($gdimg, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, imagesx($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, $color2); // top |
|
499
|
|
|
imageline($gdimg, imagesx($gdimg) - $frame_width - $edge_width - $i, imagesy($gdimg) - $frame_width - $edge_width - $i, imagesx($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, $color1); // right |
|
500
|
|
|
imageline($gdimg, imagesx($gdimg) - $frame_width - $edge_width - $i, imagesy($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, imagesy($gdimg) - $frame_width - $edge_width - $i, $color1); // bottom |
|
501
|
|
|
} |
|
502
|
|
|
return true; |
|
503
|
|
|
} |
|
504
|
|
|
|
|
505
|
|
|
public function Gamma(&$gdimg, $amount) |
|
506
|
|
|
{ |
|
507
|
|
|
if (number_format($amount, 4) == '1.0000') { |
|
508
|
|
|
return true; |
|
509
|
|
|
} |
|
510
|
|
|
return imagegammacorrect($gdimg, 1.0, $amount); |
|
511
|
|
|
} |
|
512
|
|
|
|
|
513
|
|
|
public function Grayscale(&$gdimg) |
|
514
|
|
|
{ |
|
515
|
|
|
if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { |
|
516
|
|
|
if (imagefilter($gdimg, IMG_FILTER_GRAYSCALE)) { |
|
517
|
|
|
return true; |
|
518
|
|
|
} |
|
519
|
|
|
$this->DebugMessage('FAILED: imagefilter($gdimg, IMG_FILTER_GRAYSCALE)', __FILE__, __LINE__); |
|
520
|
|
|
// fall through and try it the hard way |
|
521
|
|
|
} |
|
522
|
|
|
return $this->Colorize($gdimg, 100, 'gray'); |
|
523
|
|
|
} |
|
524
|
|
|
|
|
525
|
|
|
public function HistogramAnalysis(&$gdimg, $calculateGray = false) |
|
526
|
|
|
{ |
|
527
|
|
|
$ImageSX = imagesx($gdimg); |
|
528
|
|
|
$ImageSY = imagesy($gdimg); |
|
529
|
|
|
$Analysis = []; |
|
530
|
|
|
for ($x = 0; $x < $ImageSX; $x++) { |
|
531
|
|
|
for ($y = 0; $y < $ImageSY; $y++) { |
|
532
|
|
|
$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); |
|
533
|
|
|
@$Analysis['red'][$OriginalPixel['red']]++; |
|
534
|
|
|
@$Analysis['green'][$OriginalPixel['green']]++; |
|
535
|
|
|
@$Analysis['blue'][$OriginalPixel['blue']]++; |
|
536
|
|
|
@$Analysis['alpha'][$OriginalPixel['alpha']]++; |
|
537
|
|
|
if ($calculateGray) { |
|
538
|
|
|
$GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); |
|
539
|
|
|
@$Analysis['gray'][$GrayPixel['red']]++; |
|
540
|
|
|
} |
|
541
|
|
|
} |
|
542
|
|
|
} |
|
543
|
|
|
$keys = ['red', 'green', 'blue', 'alpha']; |
|
544
|
|
|
if ($calculateGray) { |
|
545
|
|
|
$keys[] = 'gray'; |
|
546
|
|
|
} |
|
547
|
|
|
foreach ($keys as $dummy => $key) { |
|
548
|
|
|
ksort($Analysis[$key]); |
|
549
|
|
|
} |
|
550
|
|
|
return $Analysis; |
|
551
|
|
|
} |
|
552
|
|
|
|
|
553
|
|
|
public function HistogramStretch(&$gdimg, $band = '*', $method = 0, $threshold = 0.1) |
|
554
|
|
|
{ |
|
555
|
|
|
// equivalent of "Auto Contrast" in Adobe Photoshop |
|
556
|
|
|
// method 0 stretches according to RGB colors. Gives a more conservative stretch. |
|
557
|
|
|
// method 1 band stretches according to grayscale which is color-biased (59% green, 30% red, 11% blue). May give a punchier / more aggressive stretch, possibly appearing over-saturated |
|
558
|
|
|
$Analysis = $this->HistogramAnalysis($gdimg, true); |
|
559
|
|
|
$keys = ['r' => 'red', 'g' => 'green', 'b' => 'blue', 'a' => 'alpha', '*' => ($method == 0) ? 'all' : 'gray']; |
|
560
|
|
|
$band = $band[0]; |
|
561
|
|
|
if (!isset($keys[$band])) { |
|
562
|
|
|
return false; |
|
563
|
|
|
} |
|
564
|
|
|
$key = $keys[$band]; |
|
565
|
|
|
|
|
566
|
|
|
// If the absolute brightest and darkest pixels are used then one random |
|
567
|
|
|
// pixel in the image could throw off the whole system. Instead, count up/down |
|
568
|
|
|
// from the limit and allow <threshold> (default = 0.1%) of brightest/darkest |
|
569
|
|
|
// pixels to be clipped to min/max |
|
570
|
|
|
$threshold = (float)$threshold / 100; |
|
571
|
|
|
$clip_threshold = imagesx($gdimg) * imagesx($gdimg) * $threshold; |
|
572
|
|
|
|
|
573
|
|
|
$countsum = 0; |
|
574
|
|
|
$range_min = 0; |
|
575
|
|
|
for ($i = 0; $i <= 255; $i++) { |
|
576
|
|
|
if ($method == 0) { |
|
577
|
|
|
$countsum = max(@$Analysis['red'][$i], @$Analysis['green'][$i], @$Analysis['blue'][$i]); |
|
578
|
|
|
} else { |
|
579
|
|
|
$countsum += @$Analysis[$key][$i]; |
|
580
|
|
|
} |
|
581
|
|
|
if ($countsum >= $clip_threshold) { |
|
582
|
|
|
$range_min = $i - 1; |
|
583
|
|
|
break; |
|
584
|
|
|
} |
|
585
|
|
|
} |
|
586
|
|
|
$range_min = max($range_min, 0); |
|
587
|
|
|
|
|
588
|
|
|
$countsum = 0; |
|
589
|
|
|
$range_max = 255; |
|
590
|
|
|
for ($i = 255; $i >= 0; $i--) { |
|
591
|
|
|
if ($method == 0) { |
|
592
|
|
|
$countsum = max(@$Analysis['red'][$i], @$Analysis['green'][$i], @$Analysis['blue'][$i]); |
|
593
|
|
|
} else { |
|
594
|
|
|
$countsum += @$Analysis[$key][$i]; |
|
595
|
|
|
} |
|
596
|
|
|
if ($countsum >= $clip_threshold) { |
|
597
|
|
|
$range_max = $i + 1; |
|
598
|
|
|
break; |
|
599
|
|
|
} |
|
600
|
|
|
} |
|
601
|
|
|
$range_max = min($range_max, 255); |
|
602
|
|
|
|
|
603
|
|
|
$range_scale = (($range_max == $range_min) ? 1 : (255 / ($range_max - $range_min))); |
|
604
|
|
|
if (($range_min == 0) && ($range_max == 255)) { |
|
605
|
|
|
// no adjustment necessary - don't waste CPU time! |
|
606
|
|
|
return true; |
|
607
|
|
|
} |
|
608
|
|
|
|
|
609
|
|
|
$ImageSX = imagesx($gdimg); |
|
610
|
|
|
$ImageSY = imagesy($gdimg); |
|
611
|
|
|
for ($x = 0; $x < $ImageSX; $x++) { |
|
612
|
|
|
for ($y = 0; $y < $ImageSY; $y++) { |
|
613
|
|
|
$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); |
|
614
|
|
|
if ($band == '*') { |
|
615
|
|
|
$new['red'] = min(255, max(0, ($OriginalPixel['red'] - $range_min) * $range_scale)); |
|
616
|
|
|
$new['green'] = min(255, max(0, ($OriginalPixel['green'] - $range_min) * $range_scale)); |
|
617
|
|
|
$new['blue'] = min(255, max(0, ($OriginalPixel['blue'] - $range_min) * $range_scale)); |
|
618
|
|
|
$new['alpha'] = min(255, max(0, ($OriginalPixel['alpha'] - $range_min) * $range_scale)); |
|
619
|
|
|
} else { |
|
620
|
|
|
$new = $OriginalPixel; |
|
621
|
|
|
$new[$key] = min(255, max(0, ($OriginalPixel[$key] - $range_min) * $range_scale)); |
|
622
|
|
|
} |
|
623
|
|
|
$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $new['red'], $new['green'], $new['blue'], $new['alpha']); |
|
624
|
|
|
imagesetpixel($gdimg, $x, $y, $newColor); |
|
625
|
|
|
} |
|
626
|
|
|
} |
|
627
|
|
|
|
|
628
|
|
|
return true; |
|
629
|
|
|
} |
|
630
|
|
|
|
|
631
|
|
|
public function HistogramOverlay(&$gdimg, $bands = '*', $colors = '', $width = 0.25, $height = 0.25, $alignment = 'BR', $opacity = 50, $margin_x = 5, $margin_y = null) |
|
|
|
|
|
|
632
|
|
|
{ |
|
633
|
|
|
$margin_y = (null === $margin_y ? $margin_x : $margin_y); |
|
634
|
|
|
|
|
635
|
|
|
$Analysis = $this->HistogramAnalysis($gdimg, true); |
|
636
|
|
|
$histW = round(($width > 1) ? min($width, imagesx($gdimg)) : imagesx($gdimg) * $width); |
|
637
|
|
|
$histH = round(($width > 1) ? min($width, imagesx($gdimg)) : imagesx($gdimg) * $width); |
|
638
|
|
|
if ($gdHist = imagecreatetruecolor($histW, $histH)) { |
|
|
|
|
|
|
639
|
|
|
$color_back = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHist, 0, 0, 0, 127); |
|
640
|
|
|
imagefilledrectangle($gdHist, 0, 0, $histW, $histH, $color_back); |
|
|
|
|
|
|
641
|
|
|
imagealphablending($gdHist, false); |
|
642
|
|
|
imagesavealpha($gdHist, true); |
|
643
|
|
|
|
|
644
|
|
|
$HistogramTempWidth = 256; |
|
645
|
|
|
$HistogramTempHeight = 100; |
|
646
|
|
|
if ($gdHistTemp = imagecreatetruecolor($HistogramTempWidth, $HistogramTempHeight)) { |
|
647
|
|
|
$color_back_temp = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHistTemp, 255, 0, 255, 127); |
|
648
|
|
|
imagealphablending($gdHistTemp, false); |
|
649
|
|
|
imagesavealpha($gdHistTemp, true); |
|
650
|
|
|
imagefilledrectangle($gdHistTemp, 0, 0, imagesx($gdHistTemp), imagesy($gdHistTemp), $color_back_temp); |
|
651
|
|
|
|
|
652
|
|
|
$DefaultColors = ['r' => 'FF0000', 'g' => '00FF00', 'b' => '0000FF', 'a' => '999999', '*' => 'FFFFFF']; |
|
653
|
|
|
$Colors = explode(';', $colors); |
|
654
|
|
|
$BandsToGraph = array_unique(preg_split('##', $bands)); |
|
655
|
|
|
$keys = ['r' => 'red', 'g' => 'green', 'b' => 'blue', 'a' => 'alpha', '*' => 'gray']; |
|
656
|
|
|
foreach ($BandsToGraph as $key => $band) { |
|
657
|
|
|
if (!isset($keys[$band])) { |
|
658
|
|
|
continue; |
|
659
|
|
|
} |
|
660
|
|
|
$PeakValue = max($Analysis[$keys[$band]]); |
|
661
|
|
|
$thisColor = phpthumb_functions::ImageHexColorAllocate($gdHistTemp, phpthumb_functions::IsHexColor(@$Colors[$key]) ? $Colors[$key] : $DefaultColors[$band]); |
|
662
|
|
|
for ($x = 0; $x < $HistogramTempWidth; $x++) { |
|
663
|
|
|
imageline($gdHistTemp, $x, $HistogramTempHeight - 1, $x, $HistogramTempHeight - 1 - round(@$Analysis[$keys[$band]][$x] / $PeakValue * $HistogramTempHeight), $thisColor); |
|
664
|
|
|
} |
|
665
|
|
|
imageline($gdHistTemp, 0, $HistogramTempHeight - 1, $HistogramTempWidth - 1, $HistogramTempHeight - 1, $thisColor); |
|
666
|
|
|
imageline($gdHistTemp, 0, $HistogramTempHeight - 2, $HistogramTempWidth - 1, $HistogramTempHeight - 2, $thisColor); |
|
667
|
|
|
} |
|
668
|
|
|
imagecopyresampled($gdHist, $gdHistTemp, 0, 0, 0, 0, imagesx($gdHist), imagesy($gdHist), imagesx($gdHistTemp), imagesy($gdHistTemp)); |
|
669
|
|
|
imagedestroy($gdHistTemp); |
|
670
|
|
|
} else { |
|
671
|
|
|
return false; |
|
672
|
|
|
} |
|
673
|
|
|
|
|
674
|
|
|
$this->WatermarkOverlay($gdimg, $gdHist, $alignment, $opacity, $margin_x, $margin_y); |
|
675
|
|
|
imagedestroy($gdHist); |
|
676
|
|
|
return true; |
|
677
|
|
|
} |
|
678
|
|
|
return false; |
|
679
|
|
|
} |
|
680
|
|
|
|
|
681
|
|
|
public function ImageBorder(&$gdimg, $border_width, $radius_x, $radius_y, $hexcolor_border) |
|
682
|
|
|
{ |
|
683
|
|
|
$border_width = ($border_width ? $border_width : 1); |
|
684
|
|
|
$radius_x = ($radius_x ? $radius_x : 0); |
|
685
|
|
|
$radius_y = ($radius_y ? $radius_y : 0); |
|
686
|
|
|
|
|
687
|
|
|
$output_width = imagesx($gdimg); |
|
688
|
|
|
$output_height = imagesy($gdimg); |
|
689
|
|
|
|
|
690
|
|
|
[$new_width, $new_height] = phpthumb_functions::ProportionalResize($output_width, $output_height, $output_width - max($border_width * 2, $radius_x), $output_height - max($border_width * 2, $radius_y)); |
|
691
|
|
|
$offset_x = ($radius_x ? $output_width - $new_width - $radius_x : 0); |
|
692
|
|
|
|
|
693
|
|
|
if ($gd_border_canvas = phpthumb_functions::ImageCreateFunction($output_width, $output_height)) { |
|
694
|
|
|
imagesavealpha($gd_border_canvas, true); |
|
695
|
|
|
imagealphablending($gd_border_canvas, false); |
|
696
|
|
|
$color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gd_border_canvas, 255, 255, 255, 127); |
|
697
|
|
|
imagefilledrectangle($gd_border_canvas, 0, 0, $output_width, $output_height, $color_background); |
|
698
|
|
|
|
|
699
|
|
|
$color_border = phpthumb_functions::ImageHexColorAllocate($gd_border_canvas, (phpthumb_functions::IsHexColor($hexcolor_border) ? $hexcolor_border : '000000')); |
|
700
|
|
|
|
|
701
|
|
|
for ($i = 0; $i < $border_width; $i++) { |
|
702
|
|
|
imageline($gd_border_canvas, floor($offset_x / 2) + $radius_x, $i, $output_width - $radius_x - ceil($offset_x / 2), $i, $color_border); // top |
|
703
|
|
|
imageline($gd_border_canvas, floor($offset_x / 2) + $radius_x, $output_height - 1 - $i, $output_width - $radius_x - ceil($offset_x / 2), $output_height - 1 - $i, $color_border); // bottom |
|
704
|
|
|
imageline($gd_border_canvas, floor($offset_x / 2) + $i, $radius_y, floor($offset_x / 2) + $i, $output_height - $radius_y, $color_border); // left |
|
705
|
|
|
imageline($gd_border_canvas, $output_width - 1 - $i - ceil($offset_x / 2), $radius_y, $output_width - 1 - $i - ceil($offset_x / 2), $output_height - $radius_y, $color_border); // right |
|
706
|
|
|
} |
|
707
|
|
|
|
|
708
|
|
|
if ($radius_x && $radius_y) { |
|
709
|
|
|
// PHP bug: imagearc() with thicknesses > 1 give bad/undesirable/unpredicatable results |
|
710
|
|
|
// Solution: Draw multiple 1px arcs side-by-side. |
|
711
|
|
|
|
|
712
|
|
|
// Problem: parallel arcs give strange/ugly antialiasing problems |
|
713
|
|
|
// Solution: draw non-parallel arcs, from one side of the line thickness at the start angle |
|
714
|
|
|
// to the opposite edge of the line thickness at the terminating angle |
|
715
|
|
|
for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) { |
|
716
|
|
|
imagearc($gd_border_canvas, floor($offset_x / 2) + 1 + $radius_x, $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left |
|
717
|
|
|
imagearc($gd_border_canvas, $output_width - $radius_x - 1 - ceil($offset_x / 2), $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right |
|
718
|
|
|
imagearc($gd_border_canvas, $output_width - $radius_x - 1 - ceil($offset_x / 2), $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2, 0, 90, $color_border); // bottom-right |
|
719
|
|
|
imagearc($gd_border_canvas, floor($offset_x / 2) + 1 + $radius_x, $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2, 90, 180, $color_border); // bottom-left |
|
720
|
|
|
} |
|
721
|
|
|
if ($border_width > 1) { |
|
722
|
|
|
for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) { |
|
723
|
|
|
imagearc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x, $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left |
|
724
|
|
|
imagearc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2), $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right |
|
725
|
|
|
imagearc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2), $output_height - $radius_y, $radius_x * 2, $radius_y * 2, 0, 90, $color_border); // bottom-right |
|
726
|
|
|
imagearc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x, $output_height - $radius_y, $radius_x * 2, $radius_y * 2, 90, 180, $color_border); // bottom-left |
|
727
|
|
|
} |
|
728
|
|
|
} |
|
729
|
|
|
} |
|
730
|
|
|
$this->phpThumbObject->ImageResizeFunction($gd_border_canvas, $gdimg, floor(($output_width - $new_width) / 2), round(($output_height - $new_height) / 2), 0, 0, $new_width, $new_height, $output_width, $output_height); |
|
731
|
|
|
|
|
732
|
|
|
imagedestroy($gdimg); |
|
733
|
|
|
$gdimg = phpthumb_functions::ImageCreateFunction($output_width, $output_height); |
|
734
|
|
|
imagesavealpha($gdimg, true); |
|
735
|
|
|
imagealphablending($gdimg, false); |
|
736
|
|
|
$gdimg_color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 255, 255, 255, 127); |
|
737
|
|
|
imagefilledrectangle($gdimg, 0, 0, $output_width, $output_height, $gdimg_color_background); |
|
738
|
|
|
|
|
739
|
|
|
imagecopy($gdimg, $gd_border_canvas, 0, 0, 0, 0, $output_width, $output_height); |
|
740
|
|
|
imagedestroy($gd_border_canvas); |
|
741
|
|
|
return true; |
|
742
|
|
|
} else { |
|
743
|
|
|
$this->DebugMessage('FAILED: $gd_border_canvas = phpthumb_functions::ImageCreateFunction(' . $output_width . ', ' . $output_height . ')', __FILE__, __LINE__); |
|
744
|
|
|
} |
|
745
|
|
|
return false; |
|
746
|
|
|
} |
|
747
|
|
|
|
|
748
|
|
|
public static function ImprovedImageRotate(&$gdimg_source, $rotate_angle = 0, $config_background_hexcolor = 'FFFFFF', $bg = null, &$phpThumbObject) |
|
749
|
|
|
{ |
|
750
|
|
|
while ($rotate_angle < 0) { |
|
751
|
|
|
$rotate_angle += 360; |
|
752
|
|
|
} |
|
753
|
|
|
$rotate_angle %= 360; |
|
754
|
|
|
if ($rotate_angle != 0) { |
|
755
|
|
|
$background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_source, $config_background_hexcolor); |
|
756
|
|
|
|
|
757
|
|
|
if ((phpthumb_functions::gd_version() >= 2) && !$bg && ($rotate_angle % 90)) { |
|
758
|
|
|
//$this->DebugMessage('Using alpha rotate', __FILE__, __LINE__); |
|
759
|
|
|
if ($gdimg_rotate_mask = phpthumb_functions::ImageCreateFunction(imagesx($gdimg_source), imagesy($gdimg_source))) { |
|
760
|
|
|
$color_mask = []; |
|
761
|
|
|
for ($i = 0; $i <= 255; $i++) { |
|
762
|
|
|
$color_mask[$i] = imagecolorallocate($gdimg_rotate_mask, $i, $i, $i); |
|
763
|
|
|
} |
|
764
|
|
|
imagefilledrectangle($gdimg_rotate_mask, 0, 0, imagesx($gdimg_rotate_mask), imagesy($gdimg_rotate_mask), $color_mask[255]); |
|
765
|
|
|
$imageX = imagesx($gdimg_source); |
|
766
|
|
|
$imageY = imagesy($gdimg_source); |
|
767
|
|
|
for ($x = 0; $x < $imageX; $x++) { |
|
768
|
|
|
for ($y = 0; $y < $imageY; $y++) { |
|
769
|
|
|
$pixelcolor = phpthumb_functions::GetPixelColor($gdimg_source, $x, $y); |
|
770
|
|
|
imagesetpixel($gdimg_rotate_mask, $x, $y, $color_mask[255 - round($pixelcolor['alpha'] * 255 / 127)]); |
|
771
|
|
|
} |
|
772
|
|
|
} |
|
773
|
|
|
$gdimg_rotate_mask = imagerotate($gdimg_rotate_mask, $rotate_angle, $color_mask[0]); |
|
774
|
|
|
$gdimg_source = imagerotate($gdimg_source, $rotate_angle, $background_color); |
|
775
|
|
|
|
|
776
|
|
|
imagealphablending($gdimg_source, false); |
|
777
|
|
|
imagesavealpha($gdimg_source, true); |
|
778
|
|
|
//$this->is_alpha = true; |
|
779
|
|
|
$phpThumbFilters = new self(); |
|
780
|
|
|
//$phpThumbFilters->phpThumbObject = $this; |
|
781
|
|
|
$phpThumbFilters->phpThumbObject = $phpThumbObject; |
|
782
|
|
|
$phpThumbFilters->ApplyMask($gdimg_rotate_mask, $gdimg_source); |
|
783
|
|
|
|
|
784
|
|
|
imagedestroy($gdimg_rotate_mask); |
|
785
|
|
|
} else { |
|
786
|
|
|
//$this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); |
|
787
|
|
|
} |
|
788
|
|
|
} else { |
|
789
|
|
|
if (phpthumb_functions::gd_version() < 2) { |
|
790
|
|
|
//$this->DebugMessage('Using non-alpha rotate because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); |
|
791
|
|
|
} elseif ($bg) { |
|
792
|
|
|
//$this->DebugMessage('Using non-alpha rotate because $this->bg is "'.$bg.'"', __FILE__, __LINE__); |
|
793
|
|
|
} elseif ($rotate_angle % 90) { |
|
794
|
|
|
//$this->DebugMessage('Using non-alpha rotate because ($rotate_angle % 90) = "'.($rotate_angle % 90).'"', __FILE__, __LINE__); |
|
795
|
|
|
} else { |
|
796
|
|
|
//$this->DebugMessage('Using non-alpha rotate because $this->thumbnailFormat is "'.$this->thumbnailFormat.'"', __FILE__, __LINE__); |
|
797
|
|
|
} |
|
798
|
|
|
|
|
799
|
|
|
if (imagecolortransparent($gdimg_source) >= 0) { |
|
800
|
|
|
// imagerotate() forgets all about an image's transparency and sets the transparent color to black |
|
801
|
|
|
// To compensate, flood-fill the transparent color of the source image with the specified background color first |
|
802
|
|
|
// then rotate and the colors should match |
|
803
|
|
|
|
|
804
|
|
|
if (!function_exists('imageistruecolor') || !imageistruecolor($gdimg_source)) { |
|
805
|
|
|
// convert paletted image to true-color before rotating to prevent nasty aliasing artifacts |
|
806
|
|
|
|
|
807
|
|
|
//$this->source_width = imagesx($gdimg_source); |
|
808
|
|
|
//$this->source_height = imagesy($gdimg_source); |
|
809
|
|
|
$gdimg_newsrc = phpthumb_functions::ImageCreateFunction(imagesx($gdimg_source), imagesy($gdimg_source)); |
|
810
|
|
|
$background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $config_background_hexcolor); |
|
811
|
|
|
imagefilledrectangle($gdimg_newsrc, 0, 0, imagesx($gdimg_source), imagesy($gdimg_source), phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $config_background_hexcolor)); |
|
812
|
|
|
imagecopy($gdimg_newsrc, $gdimg_source, 0, 0, 0, 0, imagesx($gdimg_source), imagesy($gdimg_source)); |
|
813
|
|
|
imagedestroy($gdimg_source); |
|
814
|
|
|
unset($gdimg_source); |
|
815
|
|
|
$gdimg_source = $gdimg_newsrc; |
|
816
|
|
|
unset($gdimg_newsrc); |
|
817
|
|
|
} else { |
|
818
|
|
|
imagecolorset( |
|
819
|
|
|
$gdimg_source, |
|
820
|
|
|
imagecolortransparent($gdimg_source), |
|
821
|
|
|
hexdec(substr($config_background_hexcolor, 0, 2)), |
|
822
|
|
|
hexdec(substr($config_background_hexcolor, 2, 2)), |
|
823
|
|
|
hexdec(substr($config_background_hexcolor, 4, 2)) |
|
824
|
|
|
); |
|
825
|
|
|
|
|
826
|
|
|
imagecolortransparent($gdimg_source, -1); |
|
827
|
|
|
} |
|
828
|
|
|
} |
|
829
|
|
|
|
|
830
|
|
|
$gdimg_source = imagerotate($gdimg_source, $rotate_angle, $background_color); |
|
831
|
|
|
} |
|
832
|
|
|
} |
|
833
|
|
|
return true; |
|
834
|
|
|
} |
|
835
|
|
|
|
|
836
|
|
|
public function MeanRemoval(&$gdimg) |
|
837
|
|
|
{ |
|
838
|
|
|
if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { |
|
839
|
|
|
if (imagefilter($gdimg, IMG_FILTER_MEAN_REMOVAL)) { |
|
840
|
|
|
return true; |
|
841
|
|
|
} |
|
842
|
|
|
$this->DebugMessage('FAILED: imagefilter($gdimg, IMG_FILTER_MEAN_REMOVAL)', __FILE__, __LINE__); |
|
843
|
|
|
// fall through and try it the hard way |
|
844
|
|
|
} |
|
845
|
|
|
// currently not implemented "the hard way" |
|
846
|
|
|
$this->DebugMessage('FAILED: phpthumb_filters::MeanRemoval($gdimg) [function not implemented]', __FILE__, __LINE__); |
|
847
|
|
|
return false; |
|
848
|
|
|
} |
|
849
|
|
|
|
|
850
|
|
|
public function Negative(&$gdimg) |
|
851
|
|
|
{ |
|
852
|
|
|
if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { |
|
853
|
|
|
if (imagefilter($gdimg, IMG_FILTER_NEGATE)) { |
|
854
|
|
|
return true; |
|
855
|
|
|
} |
|
856
|
|
|
$this->DebugMessage('FAILED: imagefilter($gdimg, IMG_FILTER_NEGATE)', __FILE__, __LINE__); |
|
857
|
|
|
// fall through and try it the hard way |
|
858
|
|
|
} |
|
859
|
|
|
$ImageSX = imagesx($gdimg); |
|
860
|
|
|
$ImageSY = imagesy($gdimg); |
|
861
|
|
|
for ($x = 0; $x < $ImageSX; $x++) { |
|
862
|
|
|
for ($y = 0; $y < $ImageSY; $y++) { |
|
863
|
|
|
$currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); |
|
864
|
|
|
$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, ~$currentPixel['red'] & 0xFF, ~$currentPixel['green'] & 0xFF, ~$currentPixel['blue'] & 0xFF, $currentPixel['alpha']); |
|
865
|
|
|
imagesetpixel($gdimg, $x, $y, $newColor); |
|
866
|
|
|
} |
|
867
|
|
|
} |
|
868
|
|
|
return true; |
|
869
|
|
|
} |
|
870
|
|
|
|
|
871
|
|
|
public function RoundedImageCorners(&$gdimg, $radius_x, $radius_y) |
|
872
|
|
|
{ |
|
873
|
|
|
// generate mask at twice desired resolution and downsample afterwards for easy antialiasing |
|
874
|
|
|
// mask is generated as a white double-size ellipse on a triple-size black background and copy-paste-resampled |
|
875
|
|
|
// onto a correct-size mask image as 4 corners due to errors when the entire mask is resampled at once (gray edges) |
|
876
|
|
|
if ($gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction($radius_x * 6, $radius_y * 6)) { |
|
877
|
|
|
if ($gdimg_cornermask = phpthumb_functions::ImageCreateFunction(imagesx($gdimg), imagesy($gdimg))) { |
|
878
|
|
|
$color_transparent = imagecolorallocate($gdimg_cornermask_triple, 255, 255, 255); |
|
879
|
|
|
imagefilledellipse($gdimg_cornermask_triple, $radius_x * 3, $radius_y * 3, $radius_x * 4, $radius_y * 4, $color_transparent); |
|
880
|
|
|
|
|
881
|
|
|
imagefilledrectangle($gdimg_cornermask, 0, 0, imagesx($gdimg), imagesy($gdimg), $color_transparent); |
|
882
|
|
|
|
|
883
|
|
|
imagecopyresampled($gdimg_cornermask, $gdimg_cornermask_triple, 0, 0, $radius_x, $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); |
|
884
|
|
|
imagecopyresampled($gdimg_cornermask, $gdimg_cornermask_triple, 0, imagesy($gdimg) - $radius_y, $radius_x, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); |
|
885
|
|
|
imagecopyresampled($gdimg_cornermask, $gdimg_cornermask_triple, imagesx($gdimg) - $radius_x, imagesy($gdimg) - $radius_y, $radius_x * 3, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); |
|
886
|
|
|
imagecopyresampled($gdimg_cornermask, $gdimg_cornermask_triple, imagesx($gdimg) - $radius_x, 0, $radius_x * 3, $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); |
|
887
|
|
|
|
|
888
|
|
|
$this->ApplyMask($gdimg_cornermask, $gdimg); |
|
889
|
|
|
imagedestroy($gdimg_cornermask); |
|
890
|
|
|
$this->DebugMessage('RoundedImageCorners(' . $radius_x . ', ' . $radius_y . ') succeeded', __FILE__, __LINE__); |
|
891
|
|
|
return true; |
|
892
|
|
|
} else { |
|
893
|
|
|
$this->DebugMessage('FAILED: $gdimg_cornermask = phpthumb_functions::ImageCreateFunction(' . imagesx($gdimg) . ', ' . imagesy($gdimg) . ')', __FILE__, __LINE__); |
|
894
|
|
|
} |
|
895
|
|
|
imagedestroy($gdimg_cornermask_triple); |
|
896
|
|
|
} else { |
|
897
|
|
|
$this->DebugMessage('FAILED: $gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction(' . ($radius_x * 6) . ', ' . ($radius_y * 6) . ')', __FILE__, __LINE__); |
|
898
|
|
|
} |
|
899
|
|
|
return false; |
|
900
|
|
|
} |
|
901
|
|
|
|
|
902
|
|
|
public function Saturation(&$gdimg, $amount, $color = '') |
|
903
|
|
|
{ |
|
904
|
|
|
if ($amount == 0) { |
|
905
|
|
|
return true; |
|
906
|
|
|
} elseif ($amount > 0) { |
|
907
|
|
|
$amount = 0 - $amount; |
|
908
|
|
|
} else { |
|
909
|
|
|
$amount = abs($amount); |
|
910
|
|
|
} |
|
911
|
|
|
return $this->Desaturate($gdimg, $amount, $color); |
|
912
|
|
|
} |
|
913
|
|
|
|
|
914
|
|
|
public function Sepia(&$gdimg, $amount, $targetColor) |
|
915
|
|
|
{ |
|
916
|
|
|
$amount = (is_numeric($amount) ? max(0, min(100, $amount)) : 50); |
|
917
|
|
|
$amountPct = $amount / 100; |
|
918
|
|
|
$targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'A28065'); |
|
919
|
|
|
|
|
920
|
|
|
if ($amount == 0) { |
|
921
|
|
|
return true; |
|
922
|
|
|
} |
|
923
|
|
|
|
|
924
|
|
|
if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { |
|
925
|
|
|
if (imagefilter($gdimg, IMG_FILTER_GRAYSCALE)) { |
|
926
|
|
|
$r = round($amountPct * hexdec(substr($targetColor, 0, 2))); |
|
927
|
|
|
$g = round($amountPct * hexdec(substr($targetColor, 2, 2))); |
|
928
|
|
|
$b = round($amountPct * hexdec(substr($targetColor, 4, 2))); |
|
929
|
|
|
if (imagefilter($gdimg, IMG_FILTER_COLORIZE, $r, $g, $b)) { |
|
|
|
|
|
|
930
|
|
|
return true; |
|
931
|
|
|
} |
|
932
|
|
|
$this->DebugMessage('FAILED: imagefilter($gdimg, IMG_FILTER_COLORIZE)', __FILE__, __LINE__); |
|
933
|
|
|
// fall through and try it the hard way |
|
934
|
|
|
|
|
935
|
|
|
} else { |
|
936
|
|
|
$this->DebugMessage('FAILED: imagefilter($gdimg, IMG_FILTER_GRAYSCALE)', __FILE__, __LINE__); |
|
937
|
|
|
// fall through and try it the hard way |
|
938
|
|
|
|
|
939
|
|
|
} |
|
940
|
|
|
} |
|
941
|
|
|
|
|
942
|
|
|
$TargetPixel['red'] = hexdec(substr($targetColor, 0, 2)); |
|
|
|
|
|
|
943
|
|
|
$TargetPixel['green'] = hexdec(substr($targetColor, 2, 2)); |
|
944
|
|
|
$TargetPixel['blue'] = hexdec(substr($targetColor, 4, 2)); |
|
945
|
|
|
|
|
946
|
|
|
$ImageSX = imagesx($gdimg); |
|
947
|
|
|
$ImageSY = imagesy($gdimg); |
|
948
|
|
|
for ($x = 0; $x < $ImageSX; $x++) { |
|
949
|
|
|
for ($y = 0; $y < $ImageSY; $y++) { |
|
950
|
|
|
$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); |
|
951
|
|
|
$GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); |
|
952
|
|
|
|
|
953
|
|
|
// http://www.gimpguru.org/Tutorials/SepiaToning/ |
|
954
|
|
|
// "In the traditional sepia toning process, the tinting occurs most in |
|
955
|
|
|
// the mid-tones: the lighter and darker areas appear to be closer to B&W." |
|
956
|
|
|
$SepiaAmount = ((128 - abs($GrayPixel['red'] - 128)) / 128) * $amountPct; |
|
957
|
|
|
|
|
958
|
|
|
$NewPixel = []; |
|
959
|
|
|
foreach ($TargetPixel as $key => $value) { |
|
960
|
|
|
$NewPixel[$key] = round(max(0, min(255, $GrayPixel[$key] * (1 - $SepiaAmount) + ($TargetPixel[$key] * $SepiaAmount)))); |
|
961
|
|
|
} |
|
962
|
|
|
$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']); |
|
963
|
|
|
imagesetpixel($gdimg, $x, $y, $newColor); |
|
964
|
|
|
} |
|
965
|
|
|
} |
|
966
|
|
|
return true; |
|
967
|
|
|
} |
|
968
|
|
|
|
|
969
|
|
|
public function Smooth(&$gdimg, $amount = 6) |
|
970
|
|
|
{ |
|
971
|
|
|
$amount = min(25, max(0, $amount)); |
|
972
|
|
|
if ($amount == 0) { |
|
973
|
|
|
return true; |
|
974
|
|
|
} |
|
975
|
|
|
if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { |
|
976
|
|
|
if (imagefilter($gdimg, IMG_FILTER_SMOOTH, $amount)) { |
|
977
|
|
|
return true; |
|
978
|
|
|
} |
|
979
|
|
|
$this->DebugMessage('FAILED: imagefilter($gdimg, IMG_FILTER_SMOOTH, ' . $amount . ')', __FILE__, __LINE__); |
|
980
|
|
|
// fall through and try it the hard way |
|
981
|
|
|
} |
|
982
|
|
|
// currently not implemented "the hard way" |
|
983
|
|
|
$this->DebugMessage('FAILED: phpthumb_filters::Smooth($gdimg, ' . $amount . ') [function not implemented]', __FILE__, __LINE__); |
|
984
|
|
|
return false; |
|
985
|
|
|
} |
|
986
|
|
|
|
|
987
|
|
|
public function SourceTransparentColorMask(&$gdimg, $hexcolor, $min_limit = 5, $max_limit = 10) |
|
988
|
|
|
{ |
|
989
|
|
|
$width = imagesx($gdimg); |
|
990
|
|
|
$height = imagesy($gdimg); |
|
991
|
|
|
if ($gdimg_mask = imagecreatetruecolor($width, $height)) { |
|
992
|
|
|
$R = hexdec(substr($hexcolor, 0, 2)); |
|
993
|
|
|
$G = hexdec(substr($hexcolor, 2, 2)); |
|
994
|
|
|
$B = hexdec(substr($hexcolor, 4, 2)); |
|
995
|
|
|
$targetPixel = ['red' => $R, 'green' => $G, 'blue' => $B]; |
|
996
|
|
|
$cutoffRange = $max_limit - $min_limit; |
|
997
|
|
|
for ($x = 0; $x < $width; $x++) { |
|
998
|
|
|
for ($y = 0; $y < $height; $y++) { |
|
999
|
|
|
$currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); |
|
1000
|
|
|
$colorDiff = phpthumb_functions::PixelColorDifferencePercent($currentPixel, $targetPixel); |
|
1001
|
|
|
$grayLevel = min($cutoffRange, max(0, -$min_limit + $colorDiff)) * (255 / max(1, $cutoffRange)); |
|
1002
|
|
|
$newColor = imagecolorallocate($gdimg_mask, $grayLevel, $grayLevel, $grayLevel); |
|
1003
|
|
|
imagesetpixel($gdimg_mask, $x, $y, $newColor); |
|
1004
|
|
|
} |
|
1005
|
|
|
} |
|
1006
|
|
|
return $gdimg_mask; |
|
1007
|
|
|
} |
|
1008
|
|
|
return false; |
|
1009
|
|
|
} |
|
1010
|
|
|
|
|
1011
|
|
|
public function Threshold(&$gdimg, $cutoff) |
|
1012
|
|
|
{ |
|
1013
|
|
|
$width = imagesx($gdimg); |
|
1014
|
|
|
$height = imagesy($gdimg); |
|
1015
|
|
|
$cutoff = min(255, max(0, ($cutoff ? $cutoff : 128))); |
|
1016
|
|
|
for ($x = 0; $x < $width; $x++) { |
|
1017
|
|
|
for ($y = 0; $y < $height; $y++) { |
|
1018
|
|
|
$currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); |
|
1019
|
|
|
$grayPixel = phpthumb_functions::GrayscalePixel($currentPixel); |
|
1020
|
|
|
if ($grayPixel['red'] < $cutoff) { |
|
1021
|
|
|
$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0x00, 0x00, 0x00, $currentPixel['alpha']); |
|
1022
|
|
|
} else { |
|
1023
|
|
|
$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0xFF, 0xFF, 0xFF, $currentPixel['alpha']); |
|
1024
|
|
|
} |
|
1025
|
|
|
imagesetpixel($gdimg, $x, $y, $newColor); |
|
1026
|
|
|
} |
|
1027
|
|
|
} |
|
1028
|
|
|
return true; |
|
1029
|
|
|
} |
|
1030
|
|
|
|
|
1031
|
|
|
public function ImageTrueColorToPalette2(&$image, $dither, $ncolors) |
|
1032
|
|
|
{ |
|
1033
|
|
|
// http://www.php.net/manual/en/function.imagetruecolortopalette.php |
|
1034
|
|
|
// zmorris at zsculpt dot com (17-Aug-2004 06:58) |
|
1035
|
|
|
$width = imagesx($image); |
|
1036
|
|
|
$height = imagesy($image); |
|
1037
|
|
|
$image_copy = imagecreatetruecolor($width, $height); |
|
1038
|
|
|
//imagecopymerge($image_copy, $image, 0, 0, 0, 0, $width, $height, 100); |
|
1039
|
|
|
imagecopy($image_copy, $image, 0, 0, 0, 0, $width, $height); |
|
1040
|
|
|
imagetruecolortopalette($image, $dither, $ncolors); |
|
1041
|
|
|
imagecolormatch($image_copy, $image); |
|
1042
|
|
|
imagedestroy($image_copy); |
|
1043
|
|
|
return true; |
|
1044
|
|
|
} |
|
1045
|
|
|
|
|
1046
|
|
|
public function ReduceColorDepth(&$gdimg, $colors = 256, $dither = true) |
|
1047
|
|
|
{ |
|
1048
|
|
|
$colors = max(min($colors, 256), 2); |
|
1049
|
|
|
// imagetruecolortopalette usually makes ugly colors, the replacement is a bit better |
|
1050
|
|
|
//imagetruecolortopalette($gdimg, $dither, $colors); |
|
1051
|
|
|
$this->ImageTrueColorToPalette2($gdimg, $dither, $colors); |
|
1052
|
|
|
return true; |
|
1053
|
|
|
} |
|
1054
|
|
|
|
|
1055
|
|
|
public function WhiteBalance(&$gdimg, $targetColor = '') |
|
1056
|
|
|
{ |
|
1057
|
|
|
if (phpthumb_functions::IsHexColor($targetColor)) { |
|
1058
|
|
|
$targetPixel = [ |
|
1059
|
|
|
'red' => hexdec(substr($targetColor, 0, 2)), |
|
1060
|
|
|
'green' => hexdec(substr($targetColor, 2, 2)), |
|
1061
|
|
|
'blue' => hexdec(substr($targetColor, 4, 2)), |
|
1062
|
|
|
]; |
|
1063
|
|
|
} else { |
|
1064
|
|
|
$Analysis = $this->HistogramAnalysis($gdimg, false); |
|
1065
|
|
|
$targetPixel = [ |
|
1066
|
|
|
'red' => max(array_keys($Analysis['red'])), |
|
1067
|
|
|
'green' => max(array_keys($Analysis['green'])), |
|
1068
|
|
|
'blue' => max(array_keys($Analysis['blue'])), |
|
1069
|
|
|
]; |
|
1070
|
|
|
} |
|
1071
|
|
|
$grayValue = phpthumb_functions::GrayscaleValue($targetPixel['red'], $targetPixel['green'], $targetPixel['blue']); |
|
1072
|
|
|
$scaleR = $grayValue / $targetPixel['red']; |
|
1073
|
|
|
$scaleG = $grayValue / $targetPixel['green']; |
|
1074
|
|
|
$scaleB = $grayValue / $targetPixel['blue']; |
|
1075
|
|
|
|
|
1076
|
|
|
for ($x = 0, $xMax = imagesx($gdimg); $x < $xMax; $x++) { |
|
1077
|
|
|
for ($y = 0, $yMax = imagesy($gdimg); $y < $yMax; $y++) { |
|
1078
|
|
|
$currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); |
|
1079
|
|
|
$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe( |
|
1080
|
|
|
$gdimg, |
|
1081
|
|
|
max(0, min(255, round($currentPixel['red'] * $scaleR))), |
|
1082
|
|
|
max(0, min(255, round($currentPixel['green'] * $scaleG))), |
|
1083
|
|
|
max(0, min(255, round($currentPixel['blue'] * $scaleB))), |
|
1084
|
|
|
$currentPixel['alpha'] |
|
1085
|
|
|
); |
|
1086
|
|
|
imagesetpixel($gdimg, $x, $y, $newColor); |
|
1087
|
|
|
} |
|
1088
|
|
|
} |
|
1089
|
|
|
return true; |
|
1090
|
|
|
} |
|
1091
|
|
|
|
|
1092
|
|
|
public function WatermarkText(&$gdimg, $text, $size, $alignment, $hex_color = '000000', $ttffont = '', $opacity = 100, $margin = 5, $angle = 0, $bg_color = false, $bg_opacity = 0, $fillextend = '', $lineheight = 1.0) |
|
1093
|
|
|
{ |
|
1094
|
|
|
// text watermark requested |
|
1095
|
|
|
if (!$text) { |
|
1096
|
|
|
return false; |
|
1097
|
|
|
} |
|
1098
|
|
|
imagealphablending($gdimg, true); |
|
1099
|
|
|
|
|
1100
|
|
|
if (preg_match('#^([0-9\\.\\-]*)x([0-9\\.\\-]*)(@[LCR])?$#i', $alignment, $matches)) { |
|
1101
|
|
|
$originOffsetX = (int)$matches[1]; |
|
1102
|
|
|
$originOffsetY = (int)$matches[2]; |
|
1103
|
|
|
$alignment = (@$matches[4] ? $matches[4] : 'L'); |
|
1104
|
|
|
$margin = 0; |
|
1105
|
|
|
} else { |
|
1106
|
|
|
$originOffsetX = 0; |
|
1107
|
|
|
$originOffsetY = 0; |
|
1108
|
|
|
} |
|
1109
|
|
|
$lineheight = min(100.0, max(0.01, (float)$lineheight)); |
|
1110
|
|
|
|
|
1111
|
|
|
$metaTextArray = [ |
|
1112
|
|
|
'^Fb' => $this->phpThumbObject->getimagesizeinfo['filesize'], |
|
1113
|
|
|
'^Fk' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1024), |
|
1114
|
|
|
'^Fm' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1048576), |
|
1115
|
|
|
'^X' => $this->phpThumbObject->getimagesizeinfo[0], |
|
1116
|
|
|
'^Y' => $this->phpThumbObject->getimagesizeinfo[1], |
|
1117
|
|
|
'^x' => imagesx($gdimg), |
|
1118
|
|
|
'^y' => imagesy($gdimg), |
|
1119
|
|
|
'^^' => '^', |
|
1120
|
|
|
]; |
|
1121
|
|
|
$text = strtr($text, $metaTextArray); |
|
1122
|
|
|
|
|
1123
|
|
|
$text = str_replace([ |
|
1124
|
|
|
"\r\n", |
|
1125
|
|
|
"\r", |
|
1126
|
|
|
], "\n", $text); |
|
1127
|
|
|
$textlines = explode("\n", $text); |
|
1128
|
|
|
$this->DebugMessage('Processing ' . count($textlines) . ' lines of text', __FILE__, __LINE__); |
|
1129
|
|
|
|
|
1130
|
|
|
if (@is_readable($ttffont) && is_file($ttffont)) { |
|
1131
|
|
|
$opacity = 100 - (int)max(min($opacity, 100), 0); |
|
1132
|
|
|
$letter_color_text = phpthumb_functions::ImageHexColorAllocate($gdimg, $hex_color, false, $opacity * 1.27); |
|
1133
|
|
|
|
|
1134
|
|
|
$this->DebugMessage('Using TTF font "' . $ttffont . '"', __FILE__, __LINE__); |
|
1135
|
|
|
|
|
1136
|
|
|
$TTFbox = imagettfbbox($size, $angle, $ttffont, $text); |
|
1137
|
|
|
|
|
1138
|
|
|
$min_x = min($TTFbox[0], $TTFbox[2], $TTFbox[4], $TTFbox[6]); |
|
1139
|
|
|
$max_x = max($TTFbox[0], $TTFbox[2], $TTFbox[4], $TTFbox[6]); |
|
1140
|
|
|
//$text_width = round($max_x - $min_x + ($size * 0.5)); |
|
1141
|
|
|
$text_width = round($max_x - $min_x); |
|
1142
|
|
|
|
|
1143
|
|
|
$min_y = min($TTFbox[1], $TTFbox[3], $TTFbox[5], $TTFbox[7]); |
|
1144
|
|
|
$max_y = max($TTFbox[1], $TTFbox[3], $TTFbox[5], $TTFbox[7]); |
|
1145
|
|
|
//$text_height = round($max_y - $min_y + ($size * 0.5)); |
|
1146
|
|
|
$text_height = round($max_y - $min_y); |
|
1147
|
|
|
|
|
1148
|
|
|
$TTFboxChar = imagettfbbox($size, $angle, $ttffont, 'jH'); |
|
1149
|
|
|
$char_min_y = min($TTFboxChar[1], $TTFboxChar[3], $TTFboxChar[5], $TTFboxChar[7]); |
|
1150
|
|
|
$char_max_y = max($TTFboxChar[1], $TTFboxChar[3], $TTFboxChar[5], $TTFboxChar[7]); |
|
1151
|
|
|
$char_height = round($char_max_y - $char_min_y); |
|
1152
|
|
|
|
|
1153
|
|
|
if ($alignment == '*') { |
|
1154
|
|
|
$text_origin_y = $char_height + $margin; |
|
1155
|
|
|
while (($text_origin_y - $text_height) < imagesy($gdimg)) { |
|
1156
|
|
|
$text_origin_x = $margin; |
|
1157
|
|
|
while ($text_origin_x < imagesx($gdimg)) { |
|
1158
|
|
|
imagettftext($gdimg, $size, $angle, $text_origin_x, $text_origin_y, $letter_color_text, $ttffont, $text); |
|
1159
|
|
|
$text_origin_x += ($text_width + $margin); |
|
1160
|
|
|
} |
|
1161
|
|
|
$text_origin_y += ($text_height + $margin) * $lineheight; |
|
1162
|
|
|
} |
|
1163
|
|
|
} else { |
|
1164
|
|
|
// this block for background color only |
|
1165
|
|
|
|
|
1166
|
|
|
$text_origin_x = 0; |
|
1167
|
|
|
$text_origin_y = 0; |
|
1168
|
|
|
switch ($alignment) { |
|
1169
|
|
|
case '*': |
|
1170
|
|
|
// handled separately |
|
1171
|
|
|
break; |
|
1172
|
|
|
|
|
1173
|
|
|
case 'T': |
|
1174
|
|
|
$text_origin_x = ($originOffsetX ? $originOffsetX - round($text_width / 2) : round((imagesx($gdimg) - $text_width) / 2)); |
|
1175
|
|
|
$text_origin_y = $char_height + $margin + $originOffsetY; |
|
1176
|
|
|
break; |
|
1177
|
|
|
|
|
1178
|
|
|
case 'B': |
|
1179
|
|
|
$text_origin_x = ($originOffsetX ? $originOffsetX - round($text_width / 2) : round((imagesx($gdimg) - $text_width) / 2)); |
|
1180
|
|
|
$text_origin_y = imagesy($gdimg) + $TTFbox[1] - $margin + $originOffsetY; |
|
1181
|
|
|
break; |
|
1182
|
|
|
|
|
1183
|
|
|
case 'L': |
|
1184
|
|
|
$text_origin_x = $margin + $originOffsetX; |
|
1185
|
|
|
$text_origin_y = ($originOffsetY ? $originOffsetY : round((imagesy($gdimg) - $text_height) / 2) + $char_height); |
|
1186
|
|
|
break; |
|
1187
|
|
|
|
|
1188
|
|
|
case 'R': |
|
1189
|
|
|
$text_origin_x = ($originOffsetX ? $originOffsetX - $text_width : imagesx($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin); |
|
1190
|
|
|
$text_origin_y = ($originOffsetY ? $originOffsetY : round((imagesy($gdimg) - $text_height) / 2) + $char_height); |
|
1191
|
|
|
break; |
|
1192
|
|
|
|
|
1193
|
|
|
case 'C': |
|
1194
|
|
|
$text_origin_x = ($originOffsetX ? $originOffsetX - round($text_width / 2) : round((imagesx($gdimg) - $text_width) / 2)); |
|
1195
|
|
|
$text_origin_y = ($originOffsetY ? $originOffsetY : round((imagesy($gdimg) - $text_height) / 2) + $char_height); |
|
1196
|
|
|
break; |
|
1197
|
|
|
|
|
1198
|
|
|
case 'TL': |
|
1199
|
|
|
$text_origin_x = $margin + $originOffsetX; |
|
1200
|
|
|
$text_origin_y = $char_height + $margin + $originOffsetY; |
|
1201
|
|
|
break; |
|
1202
|
|
|
|
|
1203
|
|
|
case 'TR': |
|
1204
|
|
|
$text_origin_x = ($originOffsetX ? $originOffsetX - $text_width : imagesx($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin); |
|
1205
|
|
|
$text_origin_y = $char_height + $margin + $originOffsetY; |
|
1206
|
|
|
break; |
|
1207
|
|
|
|
|
1208
|
|
|
case 'BL': |
|
1209
|
|
|
$text_origin_x = $margin + $originOffsetX; |
|
1210
|
|
|
$text_origin_y = imagesy($gdimg) + $TTFbox[1] - $margin + $originOffsetY; |
|
1211
|
|
|
break; |
|
1212
|
|
|
|
|
1213
|
|
|
case 'BR': |
|
1214
|
|
|
default: |
|
1215
|
|
|
$text_origin_x = ($originOffsetX ? $originOffsetX - $text_width : imagesx($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin); |
|
1216
|
|
|
$text_origin_y = imagesy($gdimg) + $TTFbox[1] - $margin + $originOffsetY; |
|
1217
|
|
|
break; |
|
1218
|
|
|
} |
|
1219
|
|
|
|
|
1220
|
|
|
if (phpthumb_functions::IsHexColor($bg_color)) { |
|
1221
|
|
|
$text_background_alpha = round(127 * ((100 - min(max(0, $bg_opacity), 100)) / 100)); |
|
1222
|
|
|
$text_color_background = phpthumb_functions::ImageHexColorAllocate($gdimg, $bg_color, false, $text_background_alpha); |
|
1223
|
|
|
} else { |
|
1224
|
|
|
$text_color_background = phpthumb_functions::ImageHexColorAllocate($gdimg, 'FFFFFF', false, 127); |
|
1225
|
|
|
} |
|
1226
|
|
|
$x1 = $text_origin_x + $min_x; |
|
1227
|
|
|
$y1 = $text_origin_y + $TTFbox[1]; |
|
1228
|
|
|
$x2 = $text_origin_x + $min_x + $text_width; |
|
1229
|
|
|
$y2 = $text_origin_y + $TTFbox[1] - $text_height; |
|
1230
|
|
|
$x_TL = false !== stripos($fillextend, 'x') ? 0 : min($x1, $x2); |
|
1231
|
|
|
$y_TL = false !== stripos($fillextend, 'y') ? 0 : min($y1, $y2); |
|
1232
|
|
|
$x_BR = false !== stripos($fillextend, 'x') ? imagesx($gdimg) : max($x1, $x2); |
|
1233
|
|
|
$y_BR = false !== stripos($fillextend, 'y') ? imagesy($gdimg) : max($y1, $y2); |
|
1234
|
|
|
$this->DebugMessage('WatermarkText() calling imagefilledrectangle($gdimg, ' . $x_TL . ', ' . $y_TL . ', ' . $x_BR . ', ' . $y_BR . ', $text_color_background)', __FILE__, __LINE__); |
|
1235
|
|
|
imagefilledrectangle($gdimg, $x_TL, $y_TL, $x_BR, $y_BR, $text_color_background); |
|
1236
|
|
|
|
|
1237
|
|
|
// end block for background color only |
|
1238
|
|
|
|
|
1239
|
|
|
$y_offset = 0; |
|
1240
|
|
|
foreach ($textlines as $dummy => $line) { |
|
1241
|
|
|
$TTFboxLine = imagettfbbox($size, $angle, $ttffont, $line); |
|
1242
|
|
|
$min_x_line = min($TTFboxLine[0], $TTFboxLine[2], $TTFboxLine[4], $TTFboxLine[6]); |
|
1243
|
|
|
$max_x_line = max($TTFboxLine[0], $TTFboxLine[2], $TTFboxLine[4], $TTFboxLine[6]); |
|
1244
|
|
|
$text_width_line = round($max_x_line - $min_x_line); |
|
1245
|
|
|
|
|
1246
|
|
|
switch ($alignment) { |
|
1247
|
|
|
// $text_origin_y set above, just re-set $text_origin_x here as needed |
|
1248
|
|
|
|
|
1249
|
|
|
case 'L': |
|
1250
|
|
|
case 'TL': |
|
1251
|
|
|
case 'BL': |
|
1252
|
|
|
// no change necessary |
|
1253
|
|
|
break; |
|
1254
|
|
|
|
|
1255
|
|
|
case 'C': |
|
1256
|
|
|
case 'T': |
|
1257
|
|
|
case 'B': |
|
1258
|
|
|
$text_origin_x = ($originOffsetX ? $originOffsetX - round($text_width_line / 2) : round((imagesx($gdimg) - $text_width_line) / 2)); |
|
1259
|
|
|
break; |
|
1260
|
|
|
|
|
1261
|
|
|
case 'R': |
|
1262
|
|
|
case 'TR': |
|
1263
|
|
|
case 'BR': |
|
1264
|
|
|
$text_origin_x = ($originOffsetX ? $originOffsetX - $text_width_line : imagesx($gdimg) - $text_width_line + $TTFbox[0] - $min_x + round($size * 0.25) - $margin); |
|
1265
|
|
|
break; |
|
1266
|
|
|
} |
|
1267
|
|
|
|
|
1268
|
|
|
//imagettftext($gdimg, $size, $angle, $text_origin_x, $text_origin_y, $letter_color_text, $ttffont, $text); |
|
1269
|
|
|
$this->DebugMessage('WatermarkText() calling imagettftext($gdimg, ' . $size . ', ' . $angle . ', ' . $text_origin_x . ', ' . ($text_origin_y + $y_offset) . ', $letter_color_text, ' . $ttffont . ', ' . $line . ')', __FILE__, __LINE__); |
|
1270
|
|
|
imagettftext($gdimg, $size, $angle, $text_origin_x, $text_origin_y + $y_offset, $letter_color_text, $ttffont, $line); |
|
1271
|
|
|
|
|
1272
|
|
|
$y_offset += $char_height * $lineheight; |
|
1273
|
|
|
} |
|
1274
|
|
|
} |
|
1275
|
|
|
return true; |
|
1276
|
|
|
} else { |
|
1277
|
|
|
$size = min(5, max(1, $size)); |
|
1278
|
|
|
$this->DebugMessage('Using built-in font (size=' . $size . ') for text watermark' . ($ttffont ? ' because $ttffont !is_readable(' . $ttffont . ')' : ''), __FILE__, __LINE__); |
|
1279
|
|
|
|
|
1280
|
|
|
$text_width = 0; |
|
1281
|
|
|
$text_height = 0; |
|
1282
|
|
|
foreach ($textlines as $dummy => $line) { |
|
1283
|
|
|
$text_width = max($text_width, imagefontwidth($size) * strlen($line)); |
|
1284
|
|
|
$text_height += imagefontheight($size); |
|
1285
|
|
|
} |
|
1286
|
|
|
if ($img_watermark = phpthumb_functions::ImageCreateFunction($text_width, $text_height)) { |
|
1287
|
|
|
imagealphablending($img_watermark, false); |
|
1288
|
|
|
if (phpthumb_functions::IsHexColor($bg_color)) { |
|
1289
|
|
|
$text_background_alpha = round(127 * ((100 - min(max(0, $bg_opacity), 100)) / 100)); |
|
1290
|
|
|
$text_color_background = phpthumb_functions::ImageHexColorAllocate($img_watermark, $bg_color, false, $text_background_alpha); |
|
1291
|
|
|
} else { |
|
1292
|
|
|
$text_color_background = phpthumb_functions::ImageHexColorAllocate($img_watermark, 'FFFFFF', false, 127); |
|
1293
|
|
|
} |
|
1294
|
|
|
$this->DebugMessage('WatermarkText() calling imagefilledrectangle($img_watermark, 0, 0, ' . imagesx($img_watermark) . ', ' . imagesy($img_watermark) . ', $text_color_background)', __FILE__, __LINE__); |
|
1295
|
|
|
imagefilledrectangle($img_watermark, 0, 0, imagesx($img_watermark), imagesy($img_watermark), $text_color_background); |
|
1296
|
|
|
|
|
1297
|
|
|
$img_watermark_mask = false; |
|
1298
|
|
|
$mask_color_background = false; |
|
1299
|
|
|
$mask_color_watermark = false; |
|
1300
|
|
|
if ($angle && function_exists('imagerotate')) { |
|
1301
|
|
|
// using $img_watermark_mask is pointless if imagerotate function isn't available |
|
1302
|
|
|
if ($img_watermark_mask = phpthumb_functions::ImageCreateFunction($text_width, $text_height)) { |
|
1303
|
|
|
$mask_color_background = imagecolorallocate($img_watermark_mask, 0, 0, 0); |
|
1304
|
|
|
imagealphablending($img_watermark_mask, false); |
|
1305
|
|
|
imagefilledrectangle($img_watermark_mask, 0, 0, imagesx($img_watermark_mask), imagesy($img_watermark_mask), $mask_color_background); |
|
1306
|
|
|
$mask_color_watermark = imagecolorallocate($img_watermark_mask, 255, 255, 255); |
|
1307
|
|
|
} |
|
1308
|
|
|
} |
|
1309
|
|
|
|
|
1310
|
|
|
$text_color_watermark = phpthumb_functions::ImageHexColorAllocate($img_watermark, $hex_color); |
|
1311
|
|
|
$x_offset = 0; |
|
1312
|
|
|
foreach ($textlines as $key => $line) { |
|
1313
|
|
|
switch ($alignment) { |
|
1314
|
|
|
case 'C': |
|
1315
|
|
|
$x_offset = round(($text_width - (imagefontwidth($size) * strlen($line))) / 2); |
|
1316
|
|
|
$originOffsetX = (imagesx($gdimg) - imagesx($img_watermark)) / 2; |
|
1317
|
|
|
$originOffsetY = (imagesy($gdimg) - imagesy($img_watermark)) / 2; |
|
1318
|
|
|
break; |
|
1319
|
|
|
|
|
1320
|
|
|
case 'T': |
|
1321
|
|
|
$x_offset = round(($text_width - (imagefontwidth($size) * strlen($line))) / 2); |
|
1322
|
|
|
$originOffsetX = (imagesx($gdimg) - imagesx($img_watermark)) / 2; |
|
1323
|
|
|
$originOffsetY = $margin; |
|
1324
|
|
|
break; |
|
1325
|
|
|
|
|
1326
|
|
|
case 'B': |
|
1327
|
|
|
$x_offset = round(($text_width - (imagefontwidth($size) * strlen($line))) / 2); |
|
1328
|
|
|
$originOffsetX = (imagesx($gdimg) - imagesx($img_watermark)) / 2; |
|
1329
|
|
|
$originOffsetY = imagesy($gdimg) - imagesy($img_watermark) - $margin; |
|
1330
|
|
|
break; |
|
1331
|
|
|
|
|
1332
|
|
|
case 'L': |
|
1333
|
|
|
$x_offset = 0; |
|
1334
|
|
|
$originOffsetX = $margin; |
|
1335
|
|
|
$originOffsetY = (imagesy($gdimg) - imagesy($img_watermark)) / 2; |
|
1336
|
|
|
break; |
|
1337
|
|
|
|
|
1338
|
|
|
case 'TL': |
|
1339
|
|
|
$x_offset = 0; |
|
1340
|
|
|
$originOffsetX = $margin; |
|
1341
|
|
|
$originOffsetY = $margin; |
|
1342
|
|
|
break; |
|
1343
|
|
|
|
|
1344
|
|
|
case 'BL': |
|
1345
|
|
|
$x_offset = 0; |
|
1346
|
|
|
$originOffsetX = $margin; |
|
1347
|
|
|
$originOffsetY = imagesy($gdimg) - imagesy($img_watermark) - $margin; |
|
1348
|
|
|
break; |
|
1349
|
|
|
|
|
1350
|
|
|
case 'R': |
|
1351
|
|
|
$x_offset = $text_width - (imagefontwidth($size) * strlen($line)); |
|
1352
|
|
|
$originOffsetX = imagesx($gdimg) - imagesx($img_watermark) - $margin; |
|
1353
|
|
|
$originOffsetY = (imagesy($gdimg) - imagesy($img_watermark)) / 2; |
|
1354
|
|
|
break; |
|
1355
|
|
|
|
|
1356
|
|
|
case 'TR': |
|
1357
|
|
|
$x_offset = $text_width - (imagefontwidth($size) * strlen($line)); |
|
1358
|
|
|
$originOffsetX = imagesx($gdimg) - imagesx($img_watermark) - $margin; |
|
1359
|
|
|
$originOffsetY = $margin; |
|
1360
|
|
|
break; |
|
1361
|
|
|
|
|
1362
|
|
|
case 'BR': |
|
1363
|
|
|
default: |
|
1364
|
|
|
if (!empty($originOffsetX) || !empty($originOffsetY)) { |
|
1365
|
|
|
// absolute pixel positioning |
|
1366
|
|
|
} else { |
|
1367
|
|
|
$x_offset = $text_width - (imagefontwidth($size) * strlen($line)); |
|
1368
|
|
|
$originOffsetX = imagesx($gdimg) - imagesx($img_watermark) - $margin; |
|
1369
|
|
|
$originOffsetY = imagesy($gdimg) - imagesy($img_watermark) - $margin; |
|
1370
|
|
|
} |
|
1371
|
|
|
break; |
|
1372
|
|
|
} |
|
1373
|
|
|
$this->DebugMessage('WatermarkText() calling imagestring($img_watermark, ' . $size . ', ' . $x_offset . ', ' . ($key * imagefontheight($size)) . ', ' . $line . ', $text_color_watermark)', __FILE__, __LINE__); |
|
1374
|
|
|
imagestring($img_watermark, $size, $x_offset, $key * imagefontheight($size), $line, $text_color_watermark); |
|
1375
|
|
|
if ($angle && $img_watermark_mask) { |
|
1376
|
|
|
$this->DebugMessage('WatermarkText() calling imagestring($img_watermark_mask, ' . $size . ', ' . $x_offset . ', ' . ($key * imagefontheight($size) * $lineheight) . ', ' . $text . ', $mask_color_watermark)', __FILE__, __LINE__); |
|
1377
|
|
|
imagestring($img_watermark_mask, $size, $x_offset, $key * imagefontheight($size) * $lineheight, $text, $mask_color_watermark); |
|
1378
|
|
|
} |
|
1379
|
|
|
} |
|
1380
|
|
|
if ($angle && $img_watermark_mask) { |
|
1381
|
|
|
$img_watermark = imagerotate($img_watermark, $angle, $text_color_background); |
|
1382
|
|
|
$img_watermark_mask = imagerotate($img_watermark_mask, $angle, $mask_color_background); |
|
1383
|
|
|
$this->ApplyMask($img_watermark_mask, $img_watermark); |
|
1384
|
|
|
} |
|
1385
|
|
|
//phpthumb_filters::WatermarkOverlay($gdimg, $img_watermark, $alignment, $opacity, $margin); |
|
1386
|
|
|
$this->DebugMessage('WatermarkText() calling phpthumb_filters::WatermarkOverlay($gdimg, $img_watermark, ' . ($originOffsetX . 'x' . $originOffsetY) . ', ' . $opacity . ', 0)', __FILE__, __LINE__); |
|
1387
|
|
|
$this->WatermarkOverlay($gdimg, $img_watermark, $originOffsetX . 'x' . $originOffsetY, $opacity, 0); |
|
1388
|
|
|
imagedestroy($img_watermark); |
|
1389
|
|
|
return true; |
|
1390
|
|
|
} |
|
1391
|
|
|
} |
|
1392
|
|
|
return false; |
|
1393
|
|
|
} |
|
1394
|
|
|
|
|
1395
|
|
|
public function WatermarkOverlay(&$gdimg_dest, &$img_watermark, $alignment = '*', $opacity = 50, $margin_x = 5, $margin_y = null) |
|
1396
|
|
|
{ |
|
1397
|
|
|
if ((is_resource($gdimg_dest) || (is_object($gdimg_dest) && $gdimg_dest instanceof \GdImage)) && (is_resource($img_watermark) || (is_object($img_watermark) && $img_watermark instanceof \GdImage))) { |
|
|
|
|
|
|
1398
|
|
|
$img_source_width = imagesx($gdimg_dest); |
|
1399
|
|
|
$img_source_height = imagesy($gdimg_dest); |
|
1400
|
|
|
$watermark_source_width = imagesx($img_watermark); |
|
1401
|
|
|
$watermark_source_height = imagesy($img_watermark); |
|
1402
|
|
|
$watermark_opacity_percent = max(0, min(100, $opacity)); |
|
1403
|
|
|
$margin_y = (null === $margin_y ? $margin_x : $margin_y); |
|
1404
|
|
|
$watermark_margin_x = ((($margin_x > 0) && ($margin_x < 1)) ? round((1 - $margin_x) * $img_source_width) : $margin_x); |
|
1405
|
|
|
$watermark_margin_y = ((($margin_y > 0) && ($margin_y < 1)) ? round((1 - $margin_y) * $img_source_height) : $margin_y); |
|
1406
|
|
|
$watermark_destination_x = 0; |
|
1407
|
|
|
$watermark_destination_y = 0; |
|
1408
|
|
|
if (preg_match('#^([0-9\\.\\-]*)x([0-9\\.\\-]*)$#i', $alignment, $matches)) { |
|
1409
|
|
|
$watermark_destination_x = (int)$matches[1]; |
|
1410
|
|
|
$watermark_destination_y = (int)$matches[2]; |
|
1411
|
|
|
} else { |
|
1412
|
|
|
switch ($alignment) { |
|
1413
|
|
|
case '*': |
|
1414
|
|
|
if ($gdimg_tiledwatermark = phpthumb_functions::ImageCreateFunction($img_source_width, $img_source_height)) { |
|
1415
|
|
|
imagealphablending($gdimg_tiledwatermark, false); |
|
1416
|
|
|
imagesavealpha($gdimg_tiledwatermark, true); |
|
1417
|
|
|
$text_color_transparent = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_tiledwatermark, 255, 0, 255, 127); |
|
1418
|
|
|
imagefill($gdimg_tiledwatermark, 0, 0, $text_color_transparent); |
|
1419
|
|
|
|
|
1420
|
|
|
// set the tiled image transparent color to whatever the untiled image transparency index is |
|
1421
|
|
|
// imagecolortransparent($gdimg_tiledwatermark, imagecolortransparent($img_watermark)); |
|
1422
|
|
|
|
|
1423
|
|
|
// a "cleaner" way of doing it, but can't handle the margin feature :( |
|
1424
|
|
|
// imagesettile($gdimg_tiledwatermark, $img_watermark); |
|
1425
|
|
|
// imagefill($gdimg_tiledwatermark, 0, 0, IMG_COLOR_TILED); |
|
1426
|
|
|
// break; |
|
1427
|
|
|
|
|
1428
|
|
|
// imagefill($gdimg_tiledwatermark, 0, 0, imagecolortransparent($gdimg_tiledwatermark)); |
|
1429
|
|
|
// tile the image as many times as can fit |
|
1430
|
|
|
for ($x = $watermark_margin_x; $x < ($img_source_width + $watermark_source_width); $x += ($watermark_source_width + $watermark_margin_x)) { |
|
1431
|
|
|
for ($y = $watermark_margin_y; $y < ($img_source_height + $watermark_source_height); $y += ($watermark_source_height + $watermark_margin_y)) { |
|
1432
|
|
|
imagecopy( |
|
1433
|
|
|
$gdimg_tiledwatermark, |
|
1434
|
|
|
$img_watermark, |
|
1435
|
|
|
$x, |
|
|
|
|
|
|
1436
|
|
|
$y, |
|
|
|
|
|
|
1437
|
|
|
0, |
|
1438
|
|
|
0, |
|
1439
|
|
|
min($watermark_source_width, $img_source_width - $x - $watermark_margin_x), |
|
1440
|
|
|
min($watermark_source_height, $img_source_height - $y - $watermark_margin_y) |
|
1441
|
|
|
); |
|
1442
|
|
|
} |
|
1443
|
|
|
} |
|
1444
|
|
|
|
|
1445
|
|
|
$watermark_source_width = imagesx($gdimg_tiledwatermark); |
|
1446
|
|
|
$watermark_source_height = imagesy($gdimg_tiledwatermark); |
|
1447
|
|
|
$watermark_destination_x = 0; |
|
1448
|
|
|
$watermark_destination_y = 0; |
|
1449
|
|
|
|
|
1450
|
|
|
imagedestroy($img_watermark); |
|
1451
|
|
|
$img_watermark = $gdimg_tiledwatermark; |
|
1452
|
|
|
} |
|
1453
|
|
|
break; |
|
1454
|
|
|
|
|
1455
|
|
|
case 'T': |
|
1456
|
|
|
$watermark_destination_x = round((($img_source_width / 2) - ($watermark_source_width / 2)) + $watermark_margin_x); |
|
1457
|
|
|
$watermark_destination_y = $watermark_margin_y; |
|
1458
|
|
|
break; |
|
1459
|
|
|
|
|
1460
|
|
|
case 'B': |
|
1461
|
|
|
$watermark_destination_x = round((($img_source_width / 2) - ($watermark_source_width / 2)) + $watermark_margin_x); |
|
1462
|
|
|
$watermark_destination_y = $img_source_height - $watermark_source_height - $watermark_margin_y; |
|
1463
|
|
|
break; |
|
1464
|
|
|
|
|
1465
|
|
|
case 'L': |
|
1466
|
|
|
$watermark_destination_x = $watermark_margin_x; |
|
1467
|
|
|
$watermark_destination_y = round((($img_source_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_y); |
|
1468
|
|
|
break; |
|
1469
|
|
|
|
|
1470
|
|
|
case 'R': |
|
1471
|
|
|
$watermark_destination_x = $img_source_width - $watermark_source_width - $watermark_margin_x; |
|
1472
|
|
|
$watermark_destination_y = round((($img_source_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_y); |
|
1473
|
|
|
break; |
|
1474
|
|
|
|
|
1475
|
|
|
case 'C': |
|
1476
|
|
|
$watermark_destination_x = round(($img_source_width / 2) - ($watermark_source_width / 2)); |
|
1477
|
|
|
$watermark_destination_y = round(($img_source_height / 2) - ($watermark_source_height / 2)); |
|
1478
|
|
|
break; |
|
1479
|
|
|
|
|
1480
|
|
|
case 'TL': |
|
1481
|
|
|
$watermark_destination_x = $watermark_margin_x; |
|
1482
|
|
|
$watermark_destination_y = $watermark_margin_y; |
|
1483
|
|
|
break; |
|
1484
|
|
|
|
|
1485
|
|
|
case 'TR': |
|
1486
|
|
|
$watermark_destination_x = $img_source_width - $watermark_source_width - $watermark_margin_x; |
|
1487
|
|
|
$watermark_destination_y = $watermark_margin_y; |
|
1488
|
|
|
break; |
|
1489
|
|
|
|
|
1490
|
|
|
case 'BL': |
|
1491
|
|
|
$watermark_destination_x = $watermark_margin_x; |
|
1492
|
|
|
$watermark_destination_y = $img_source_height - $watermark_source_height - $watermark_margin_y; |
|
1493
|
|
|
break; |
|
1494
|
|
|
|
|
1495
|
|
|
case 'BR': |
|
1496
|
|
|
default: |
|
1497
|
|
|
$watermark_destination_x = $img_source_width - $watermark_source_width - $watermark_margin_x; |
|
1498
|
|
|
$watermark_destination_y = $img_source_height - $watermark_source_height - $watermark_margin_y; |
|
1499
|
|
|
break; |
|
1500
|
|
|
} |
|
1501
|
|
|
} |
|
1502
|
|
|
imagealphablending($gdimg_dest, false); |
|
1503
|
|
|
imagesavealpha($gdimg_dest, true); |
|
1504
|
|
|
imagesavealpha($img_watermark, true); |
|
1505
|
|
|
phpthumb_functions::ImageCopyRespectAlpha($gdimg_dest, $img_watermark, $watermark_destination_x, $watermark_destination_y, 0, 0, $watermark_source_width, $watermark_source_height, $watermark_opacity_percent); |
|
1506
|
|
|
|
|
1507
|
|
|
return true; |
|
1508
|
|
|
} |
|
1509
|
|
|
return false; |
|
1510
|
|
|
} |
|
1511
|
|
|
} |
|
1512
|
|
|
|