Image   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 184
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 1

Importance

Changes 0
Metric Value
wmc 23
lcom 0
cbo 1
dl 0
loc 184
rs 10
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
F __construct() 0 178 23
1
<?php
2
3
/**
4
 * Pixeler
5
 *
6
 * UTF-8 Dot matrix renderer.
7
 *
8
 * @package pixeler
9
 * @author [email protected]
10
 * @version 1.0
11
 * @copyright Stefano Azzolini - 2014 - http://dreamnoctis.com
12
 */
13
14
namespace Pixeler;
15
16
class Image extends Matrix {
17
  const DITHER_NONE = 0,
18
        DITHER_ERROR = 1;
19
20
  public function __construct($img, $resize=1.0, $invert=false, $weight = 0.5, $dither=self::DITHER_ERROR){
21
    $ext = strtolower(pathinfo($img, PATHINFO_EXTENSION));
22
    if ($ext == 'jpg') $ext = 'jpeg';
23
    $imagecreator = 'imagecreatefrom' . $ext;
24
25
    if (!function_exists($imagecreator)) 
26
      throw new \Exception('Image format not supported.', 1);
27
28
    $im = $imagecreator($img);
29
    $w  = imagesx($im);
30
    $h  = imagesy($im);
31
32
    // Resize image
33
    $nw       = ceil($resize * $w);
34
    $nh       = ceil($resize * $h * 0.75);
35
    $new_img  = imagecreatetruecolor($nw, $nh);
36
    imagesavealpha     ($new_img, true);
37
    imagealphablending ($new_img, false);
38
    imagefill          ($new_img, 0, 0, imagecolorallocate($new_img, 255, 255, 255));
39
    imagecopyresized   ($new_img, $im, 0, 0, 0, 0, $nw, $nh, $w, $h);
40
    imagedestroy       ($im);
41
    $im = $new_img;
42
    $w = $nw; $h = $nh;
43
44
    // Init Dot Matrix
45
    parent::__construct($w, $h);
46
47
    // Create the color matrix
48
    $color_img_w = ceil($w/2);
49
    $color_img_h = ceil($h/4);
50
51
    // Lower precision -> faster palette lookup -> uglier colors.
52
    $min_color_precision = 20;
53
54
    $color_img = imagecreatetruecolor($color_img_w, $color_img_h);
55
    imagesavealpha      ($color_img, true);
56
    imagealphablending  ($color_img, false);
57
    imagefill           ($color_img, 0, 0, imagecolorallocate($color_img, 255, 255, 255));
58
    imagecopyresized    ($color_img, $im, 0, 0, 0, 0, $color_img_w, $color_img_h, $w, $h);
59
60
    // ANSI 8bit Palette
61
    $ansi256palette = [
62
      0x000000,0x800000,0x008000,0x808000,0x000080,0x800080,0x008080,0xc0c0c0,
63
      0x808080,0xff0000,0x00ff00,0xffff00,0x0000ff,0xff00ff,0x00ffff,0xffffff,
64
      0x000000,0x00005f,0x000087,0x0000af,0x0000d7,0x0000ff,0x005f00,0x005f5f,
65
      0x005f87,0x005faf,0x005fd7,0x005fff,0x008700,0x00875f,0x008787,0x0087af,
66
      0x0087d7,0x0087ff,0x00af00,0x00af5f,0x00af87,0x00afaf,0x00afd7,0x00afff,
67
      0x00d700,0x00d75f,0x00d787,0x00d7af,0x00d7d7,0x00d7ff,0x00ff00,0x00ff5f,
68
      0x00ff87,0x00ffaf,0x00ffd7,0x00ffff,0x5f0000,0x5f005f,0x5f0087,0x5f00af,
69
      0x5f00d7,0x5f00ff,0x5f5f00,0x5f5f5f,0x5f5f87,0x5f5faf,0x5f5fd7,0x5f5fff,
70
      0x5f8700,0x5f875f,0x5f8787,0x5f87af,0x5f87d7,0x5f87ff,0x5faf00,0x5faf5f,
71
      0x5faf87,0x5fafaf,0x5fafd7,0x5fafff,0x5fd700,0x5fd75f,0x5fd787,0x5fd7af,
72
      0x5fd7d7,0x5fd7ff,0x5fff00,0x5fff5f,0x5fff87,0x5fffaf,0x5fffd7,0x5fffff,
73
      0x870000,0x87005f,0x870087,0x8700af,0x8700d7,0x8700ff,0x875f00,0x875f5f,
74
      0x875f87,0x875faf,0x875fd7,0x875fff,0x878700,0x87875f,0x878787,0x8787af,
75
      0x8787d7,0x8787ff,0x87af00,0x87af5f,0x87af87,0x87afaf,0x87afd7,0x87afff,
76
      0x87d700,0x87d75f,0x87d787,0x87d7af,0x87d7d7,0x87d7ff,0x87ff00,0x87ff5f,
77
      0x87ff87,0x87ffaf,0x87ffd7,0x87ffff,0xaf0000,0xaf005f,0xaf0087,0xaf00af,
78
      0xaf00d7,0xaf00ff,0xaf5f00,0xaf5f5f,0xaf5f87,0xaf5faf,0xaf5fd7,0xaf5fff,
79
      0xaf8700,0xaf875f,0xaf8787,0xaf87af,0xaf87d7,0xaf87ff,0xafaf00,0xafaf5f,
80
      0xafaf87,0xafafaf,0xafafd7,0xafafff,0xafd700,0xafd75f,0xafd787,0xafd7af,
81
      0xafd7d7,0xafd7ff,0xafff00,0xafff5f,0xafff87,0xafffaf,0xafffd7,0xafffff,
82
      0xd70000,0xd7005f,0xd70087,0xd700af,0xd700d7,0xd700ff,0xd75f00,0xd75f5f,
83
      0xd75f87,0xd75faf,0xd75fd7,0xd75fff,0xd78700,0xd7875f,0xd78787,0xd787af,
84
      0xd787d7,0xd787ff,0xd7af00,0xd7af5f,0xd7af87,0xd7afaf,0xd7afd7,0xd7afff,
85
      0xd7d700,0xd7d75f,0xd7d787,0xd7d7af,0xd7d7d7,0xd7d7ff,0xd7ff00,0xd7ff5f,
86
      0xd7ff87,0xd7ffaf,0xd7ffd7,0xd7ffff,0xff0000,0xff005f,0xff0087,0xff00af,
87
      0xff00d7,0xff00ff,0xff5f00,0xff5f5f,0xff5f87,0xff5faf,0xff5fd7,0xff5fff,
88
      0xff8700,0xff875f,0xff8787,0xff87af,0xff87d7,0xff87ff,0xffaf00,0xffaf5f,
89
      0xffaf87,0xffafaf,0xffafd7,0xffafff,0xffd700,0xffd75f,0xffd787,0xffd7af,
90
      0xffd7d7,0xffd7ff,0xffff00,0xffff5f,0xffff87,0xffffaf,0xffffd7,0xffffff,
91
      0x080808,0x121212,0x1c1c1c,0x262626,0x303030,0x3a3a3a,0x444444,0x4e4e4e,
92
      0x585858,0x606060,0x666666,0x767676,0x808080,0x8a8a8a,0x949494,0x9e9e9e,
93
      0xa8a8a8,0xb2b2b2,0xbcbcbc,0xc6c6c6,0xd0d0d0,0xdadada,0xe4e4e4,0xeeeeee
94
    ];
95
96
    $colormap = [];
97
    foreach ($ansi256palette as $rgb) $colormap[] = [
98
      ($rgb >> 16) & 0xFF,
99
      ($rgb >> 8)  & 0xFF,
100
      ($rgb)       & 0xFF
101
    ];
102
    $ansi256palette = $colormap;
103
    $colormap = [];
0 ignored issues
show
Unused Code introduced by
$colormap is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
104
105
    // Find nearest match of passed RGB with ANSI palette 
106
    $nearest = function($rgb) use ($ansi256palette, $min_color_precision){
107
      $best = 0; $dist = 10000;
108
      foreach ($ansi256palette as $idx => $a) {
109
        $d = sqrt(
110
          pow($rgb['red']-$a[0],2) + pow($rgb['green']-$a[1],2) + pow($rgb['blue']-$a[2],2)
111
        );
112
        if($d < $dist) {
113
          $dist = $d;
114
          $best = $idx;
115
          if($d <= $min_color_precision) break;
116
        }
117
      }
118
      return $best;
119
    };
120
121
    // Read colors
122
    $c = $this->colors;
123
    for($y = $color_img_h; $y--;){
124
      $y0 = $y * $color_img_w;
125
      for($x = $color_img_w; $x-- ;){
126
        $c[ $y0 + $x ] = $nearest(imagecolorsforindex($color_img,imagecolorat($color_img, $x, $y)));
127
      }
128
    }
129
    $this->colors = $c;
130
    imagedestroy($color_img);
131
132
    // Invert image for dark backgrounds
133
    if ($invert) imagefilter($im, IMG_FILTER_NEGATE);
134
135
136
    $pixels = new \SplFixedArray($w * $h);
137
    for($y = $h ; $y-- ;){
138
      for($x = $w, $y0 = $y * $w ; $x-- ;){
139
            $pixels[$x + $y0] = imagecolorat($im, $x, $y);
140
        }
141
    }
142
    imagedestroy($im);
143
144
    $m = $this->matrix;
145
    switch($dither){
146
147
      // Threshold 1-bit quantization
148
      case self::DITHER_NONE:
149
      default:
150
        $tresh = (0xffffff * $weight) & 0xffffff;
151
        $b = $invert?1:0;
152
        for ($y=0; $y < $h; $y++){
153
            $y0 = $y * $w; $y1 = $y0 + $w; $y2 = $y1 + $w;
0 ignored issues
show
Unused Code introduced by
$y2 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
154
            for ($x=0; $x < $w; $x++) {
155
                $idx = $x + $y0;
156
                $m[$idx] = $pixels[$idx]<=$tresh?$pixels[$idx]:$b;
157
              }
158
        }
159
      break;
160
161
      // Dither image with 1-bit Atkinson Dithering
162
      // Adapted from : https://gist.github.com/lordastley/1342627
163
      case self::DITHER_ERROR:
0 ignored issues
show
Unused Code introduced by
case self::DITHER_ERROR:... } } break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
164
        $tresh = (0xffffff * $weight) & 0xffffff;
165
        for ($y=0; $y < $h; $y++){
166
            $y0 = $y * $w; $y1 = $y0 + $w; $y2 = $y1 + $w;
167
            for ($x=0; $x < $w; $x++) {
168
                $idx = $x + $y0;
169
                $old = $pixels[$idx];
170
                
171
                if ($old > $tresh){
172
                    $error_diffusion = ($old - 0xffffff) >> 3;
173
                } else {
174
                    $error_diffusion = $old >> 3;
175
                    $m[$idx] = $old;
176
                }
177
178
179
                $x1 = $x + 1; $x2 = $x + 2; $x_1 = $x - 1;
180
181
                foreach([
182
                    $x1  + $y0,
183
                    $x2  + $y0,
184
                    $x_1 + $y1,
185
                    $x   + $y1,
186
                    $x1  + $y1,
187
                    $x   + $y2,
188
                ] as $ofs) {
189
                  if (isset($pixels[$ofs])) $pixels[$ofs] += $error_diffusion;
190
                }
191
            }
192
        }
193
194
      break;
195
    }
196
197
  }
198
199
}