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
|
|
|
|