1: <?php
2: /**
3: ##DOC-SIGNATURE##
4:
5: This file is part of WideImage.
6:
7: WideImage is free software; you can redistribute it and/or modify
8: it under the terms of the GNU Lesser General Public License as published by
9: the Free Software Foundation; either version 2.1 of the License, or
10: (at your option) any later version.
11:
12: WideImage is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU Lesser General Public License for more details.
16:
17: You should have received a copy of the GNU Lesser General Public License
18: along with WideImage; if not, write to the Free Software
19: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20:
21: * @package Internal/Operations
22: **/
23:
24: namespace WideImage\Operation;
25:
26: /**
27: * Unsharp filter
28: *
29: * This filter was taken from http://vikjavev.no/computing/ump.php,
30: * the original author Torstein Hønsi. Adapted to fit better within
31: * the Wideimage package.
32: *
33: * @package Internal/Operations
34: */
35: class Unsharp
36: {
37: /**
38: * Returns sharpened image
39: *
40: * @param \WideImage\Image $image
41: * @param float $amount
42: * @param int $radius
43: * @param float $threshold
44: * @return \WideImage\Image
45: */
46: public function execute($image, $amount, $radius, $threshold)
47: {
48: // Attempt to calibrate the parameters to Photoshop:
49: if ($amount > 500) {
50: $amount = 500;
51: }
52:
53: $amount = $amount * 0.016;
54:
55: if ($radius > 50) {
56: $radius = 50;
57: }
58:
59: $radius = $radius * 2;
60:
61: if ($threshold > 255) {
62: $threshold = 255;
63: }
64:
65: $radius = abs(round($radius)); // Only integers make sense.
66:
67: if ($radius == 0) {
68: return $image;
69: }
70:
71: // Gaussian blur matrix
72: $matrix = array(
73: array(1, 2, 1),
74: array(2, 4, 2),
75: array(1, 2, 1)
76: );
77:
78: $blurred = $image->applyConvolution($matrix, 16, 0);
79:
80: if ($threshold > 0) {
81: // Calculate the difference between the blurred pixels and the original
82: // and set the pixels
83: for ($x = 0; $x < $image->getWidth(); $x++) {
84: for ($y = 0; $y < $image->getHeight(); $y++) {
85: $rgbOrig = $image->getRGBAt($x, $y);
86: $rOrig = $rgbOrig["red"];
87: $gOrig = $rgbOrig["green"];
88: $bOrig = $rgbOrig["blue"];
89:
90: $rgbBlur = $blurred->getRGBAt($x, $y);
91: $rBlur = $rgbBlur["red"];
92: $gBlur = $rgbBlur["green"];
93: $bBlur = $rgbBlur["blue"];
94:
95: // When the masked pixels differ less from the original
96: // than the threshold specifies, they are set to their original value.
97: $rNew = (abs($rOrig - $rBlur) >= $threshold)
98: ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig))
99: : $rOrig;
100: $gNew = (abs($gOrig - $gBlur) >= $threshold)
101: ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig))
102: : $gOrig;
103: $bNew = (abs($bOrig - $bBlur) >= $threshold)
104: ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig))
105: : $bOrig;
106: $rgbNew = array("red" => $rNew, "green" => $gNew, "blue" => $bNew, "alpha" => 0);
107:
108: if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) {
109: $image->setRGBAt($x, $y, $rgbNew);
110: }
111: }
112: }
113: } else {
114: $w = $image->getWidth();
115: $h = $image->getHeight();
116:
117: for ($x = 0; $x < $w; $x++) {
118: for ($y = 0; $y < $h; $y++) {
119: $rgbOrig = $image->getRGBAt($x, $y);
120: $rOrig = $rgbOrig["red"];
121: $gOrig = $rgbOrig["green"];
122: $bOrig = $rgbOrig["blue"];
123:
124: $rgbBlur = $blurred->getRGBAt($x, $y);
125: $rBlur = $rgbBlur["red"];
126: $gBlur = $rgbBlur["green"];
127: $bBlur = $rgbBlur["blue"];
128:
129: $rNew = static::bit(($amount * ($rOrig - $rBlur)) + $rOrig);
130: $gNew = static::bit(($amount * ($gOrig - $gBlur)) + $gOrig);
131: $bNew = static::bit(($amount * ($bOrig - $bBlur)) + $bOrig);
132: $rgbNew = array("red" => $rNew, "green" => $gNew, "blue" => $bNew, "alpha" => 0);
133:
134: $image->setRGBAt($x, $y, $rgbNew);
135: }
136: }
137: }
138:
139: return $image;
140: }
141:
142: protected static function bit($val)
143: {
144: if ($val > 255) {
145: return 255;
146: }
147:
148: if ($val < 0) {
149: return 0;
150: }
151:
152: return $val;
153: }
154: }
155: