XOOPS 2.5.6  Final
 All Classes Namespaces Files Functions Variables Pages
phpthumb.unsharp.php
Go to the documentation of this file.
1 <?php
12 // //
13 // Reformatted by James Heinrich <info@silisoftware.com> //
14 // for use in phpThumb() on 3 February 2003. //
15 // updated to v2.1.1 on 24 April 2011 //
16 // //
17 // phpThumb() is found at http://phpthumb.sourceforge.net ///
19 
20 /*
21 New:
22 - In version 2.1 (February 26 2007) Tom Bishop has done some important speed enhancements.
23 - From version 2 (July 17 2006) the script uses the imageconvolution function in PHP
24  version >= 5.1, which improves the performance considerably.
25 
26 Unsharp masking is a traditional darkroom technique that has proven very suitable for
27 digital imaging. The principle of unsharp masking is to create a blurred copy of the image
28 and compare it to the underlying original. The difference in colour values
29 between the two images is greatest for the pixels near sharp edges. When this
30 difference is subtracted from the original image, the edges will be
31 accentuated.
32 
33 The Amount parameter simply says how much of the effect you want. 100 is 'normal'.
34 Radius is the radius of the blurring circle of the mask. 'Threshold' is the least
35 difference in colour values that is allowed between the original and the mask. In practice
36 this means that low-contrast areas of the picture are left unrendered whereas edges
37 are treated normally. This is good for pictures of e.g. skin or blue skies.
38 
39 Any suggenstions for improvement of the algorithm, expecially regarding the speed
40 and the roundoff errors in the Gaussian blur process, are welcome.
41 */
42 
44 
45  function applyUnsharpMask(&$img, $amount, $radius, $threshold) {
46 
47  // $img is an image that is already created within php using
48  // imgcreatetruecolor. No url! $img must be a truecolor image.
49 
50  // Attempt to calibrate the parameters to Photoshop:
51  $amount = min($amount, 500) * 0.016;
52  $radius = abs(round(min(50, $radius) * 2)); // Only integers make sense.
53  $threshold = min(255, $threshold);
54  if ($radius == 0) {
55  return true;
56  }
57  $w = ImageSX($img);
58  $h = ImageSY($img);
59  $imgCanvas = ImageCreateTrueColor($w, $h);
60  $imgBlur = ImageCreateTrueColor($w, $h);
61 
62  // Gaussian blur matrix:
63  //
64  // 1 2 1
65  // 2 4 2
66  // 1 2 1
67  //
69 
70  if (function_exists('imageconvolution')) { // PHP >= 5.1
71  $matrix = array(
72  array(1, 2, 1),
73  array(2, 4, 2),
74  array(1, 2, 1)
75  );
76  ImageCopy($imgBlur, $img, 0, 0, 0, 0, $w, $h);
77  ImageConvolution($imgBlur, $matrix, 16, 0);
78 
79  } else {
80 
81  // Move copies of the image around one pixel at the time and merge them with weight
82  // according to the matrix. The same matrix is simply repeated for higher radii.
83  for ($i = 0; $i < $radius; $i++) {
84  ImageCopy( $imgBlur, $img, 0, 0, 1, 0, $w - 1, $h); // left
85  ImageCopyMerge($imgBlur, $img, 1, 0, 0, 0, $w , $h, 50); // right
86  ImageCopyMerge($imgBlur, $img, 0, 0, 0, 0, $w , $h, 50); // center
87  ImageCopy( $imgCanvas, $imgBlur, 0, 0, 0, 0, $w , $h);
88  ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 1, $w , $h - 1, 33.33333); // up
89  ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 0, 0, $w , $h, 25); // down
90  }
91  }
92 
93  if ($threshold > 0){
94  // Calculate the difference between the blurred pixels and the original
95  // and set the pixels
96  for ($x = 0; $x < $w-1; $x++) { // each row
97  for ($y = 0; $y < $h; $y++) { // each pixel
98 
99  $rgbOrig = ImageColorAt($img, $x, $y);
100  $rOrig = (($rgbOrig >> 16) & 0xFF);
101  $gOrig = (($rgbOrig >> 8) & 0xFF);
102  $bOrig = ($rgbOrig & 0xFF);
103 
104  $rgbBlur = ImageColorAt($imgBlur, $x, $y);
105 
106  $rBlur = (($rgbBlur >> 16) & 0xFF);
107  $gBlur = (($rgbBlur >> 8) & 0xFF);
108  $bBlur = ($rgbBlur & 0xFF);
109 
110  // When the masked pixels differ less from the original
111  // than the threshold specifies, they are set to their original value.
112  $rNew = ((abs($rOrig - $rBlur) >= $threshold) ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig);
113  $gNew = ((abs($gOrig - $gBlur) >= $threshold) ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig);
114  $bNew = ((abs($bOrig - $bBlur) >= $threshold) ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig);
115 
116  if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) {
117  $pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew);
118  ImageSetPixel($img, $x, $y, $pixCol);
119  }
120  }
121  }
122  } else {
123  for ($x = 0; $x < $w; $x++) { // each row
124  for ($y = 0; $y < $h; $y++) { // each pixel
125  $rgbOrig = ImageColorAt($img, $x, $y);
126  $rOrig = (($rgbOrig >> 16) & 0xFF);
127  $gOrig = (($rgbOrig >> 8) & 0xFF);
128  $bOrig = ($rgbOrig & 0xFF);
129 
130  $rgbBlur = ImageColorAt($imgBlur, $x, $y);
131 
132  $rBlur = (($rgbBlur >> 16) & 0xFF);
133  $gBlur = (($rgbBlur >> 8) & 0xFF);
134  $bBlur = ($rgbBlur & 0xFF);
135 
136  $rNew = min(255, max(0, ($amount * ($rOrig - $rBlur)) + $rOrig));
137  $gNew = min(255, max(0, ($amount * ($gOrig - $gBlur)) + $gOrig));
138  $bNew = min(255, max(0, ($amount * ($bOrig - $bBlur)) + $bOrig));
139  $rgbNew = ($rNew << 16) + ($gNew <<8) + $bNew;
140  ImageSetPixel($img, $x, $y, $rgbNew);
141  }
142  }
143  }
144  ImageDestroy($imgCanvas);
145  ImageDestroy($imgBlur);
146  return true;
147  }
148 }
149 ?>