1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Thermal\Graphics\Filter; |
4
|
|
|
|
5
|
|
|
use Thermal\Graphics\Filter; |
6
|
|
|
|
7
|
|
|
class FloydSteinberg implements Filter |
8
|
|
|
{ |
9
|
|
|
/** |
10
|
|
|
* Convert an image resource to black and white aplying dither. |
11
|
|
|
* The original image resource will not be changed, a new image resource will be created. |
12
|
|
|
* |
13
|
|
|
* @param ImageResource $image The source image resource |
14
|
|
|
* @return ImageResource The black and white image resource |
15
|
|
|
*/ |
16
|
3 |
|
public function process($image) |
|
|
|
|
17
|
|
|
{ |
18
|
3 |
|
$width = imagesx($image); |
19
|
3 |
|
$height = imagesy($image); |
20
|
3 |
|
$new_image = imagecreatetruecolor($width, $height); |
21
|
|
|
// sets background to black |
22
|
3 |
|
$black = imagecolorallocate($new_image, 0, 0, 0); |
23
|
3 |
|
$white = imagecolorallocate($new_image, 255, 255, 255); |
24
|
3 |
|
$pixel = []; |
25
|
3 |
|
for ($y = 0; $y < $height; $y++) { |
26
|
3 |
|
for ($x = 0; $x < $width; $x++) { |
27
|
3 |
|
$color = imagecolorat($image, $x, $y); |
28
|
3 |
|
$red = ($color >> 16) & 0xFF; |
29
|
3 |
|
$green = ($color >> 8) & 0xFF; |
30
|
3 |
|
$blue = $color & 0xFF; |
31
|
3 |
|
$gray = (int)($red * 0.3 + $green * 0.59 + $blue * 0.11); |
32
|
|
|
// Add errors to color if there are |
33
|
3 |
|
if (isset($pixel[$x][$y])) { |
34
|
3 |
|
$gray += $pixel[$x][$y]; |
35
|
|
|
} |
36
|
3 |
|
$new_color = $black; |
37
|
3 |
|
if ($gray > 127) { |
38
|
3 |
|
$new_color = $white; |
39
|
|
|
} |
40
|
3 |
|
imagesetpixel($new_image, $x, $y, $new_color); |
41
|
3 |
|
$error = $gray - ($new_color & 0xFF); |
42
|
3 |
|
if ($x + 1 < $width) { |
43
|
3 |
|
$pixel[$x + 1][$y] = (isset($pixel[$x + 1][$y]) ? $pixel[$x + 1][$y] : 0) + ($error * 7 >> 4); |
44
|
|
|
} |
45
|
|
|
// if we are in the last line |
46
|
3 |
|
if ($y == $height - 1) { |
47
|
3 |
|
continue; |
48
|
|
|
} |
49
|
3 |
|
if ($x > 0) { |
50
|
3 |
|
$prev = isset($pixel[$x - 1][$y + 1]) ? $pixel[$x - 1][$y + 1] : 0; |
51
|
3 |
|
$pixel[$x - 1][$y + 1] = $prev + ($error * 3 >> 4); |
52
|
|
|
} |
53
|
3 |
|
$pixel[$x][$y + 1] = (isset($pixel[$x][$y + 1]) ? $pixel[$x][$y + 1] : 0) + ($error * 5 >> 4); |
54
|
3 |
|
if ($x < $width - 1) { |
55
|
3 |
|
$prev = isset($pixel[$x + 1][$y + 1]) ? $pixel[$x + 1][$y + 1] : 0; |
56
|
3 |
|
$pixel[$x + 1][$y + 1] = $prev + ($error * 1 >> 4); |
57
|
|
|
} |
58
|
|
|
} |
59
|
|
|
} |
60
|
3 |
|
return $new_image; |
|
|
|
|
61
|
|
|
} |
62
|
|
|
} |
63
|
|
|
|
A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.
You can also find more information in the “Code” section of your repository.