Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.95% covered (success)
95.95%
71 / 74
85.71% covered (success)
85.71%
6 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
Vizhash16x16
95.95% covered (success)
95.95%
71 / 74
85.71% covered (success)
85.71%
6 / 7
23
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 generate
90.91% covered (success)
90.91%
30 / 33
0.00% covered (danger)
0.00%
0 / 1
8.05
 getInt
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getX
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getY
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 degrade
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
4
 drawshape
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
7
1<?php declare(strict_types=1);
2/**
3 * VizHash_GD
4 *
5 * Visual Hash implementation in php4+GD,
6 * stripped down from version 0.0.5 beta, modified for PrivateBin
7 *
8 * @link      https://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd
9 * @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
10 * @license   https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
11 */
12
13namespace PrivateBin;
14
15/**
16 * Vizhash16x16
17 *
18 * Example:
19 * $vz = new Vizhash16x16();
20 * $data = $vz->generate(sha512('hello'));
21 * header('Content-type: image/png');
22 * echo $data;
23 * exit;
24 */
25class Vizhash16x16
26{
27    /**
28     * hash values
29     *
30     * @access private
31     * @var    array
32     */
33    private $VALUES;
34
35    /**
36     * index of current value
37     *
38     * @access private
39     * @var    int
40     */
41    private $VALUES_INDEX;
42
43    /**
44     * image width
45     *
46     * @access private
47     * @var    int
48     */
49    private $width;
50
51    /**
52     * image height
53     *
54     * @access private
55     * @var    int
56     */
57    private $height;
58
59    /**
60     * constructor
61     *
62     * @access public
63     */
64    public function __construct()
65    {
66        $this->width = 16;
67        $this->height = 16;
68    }
69
70    /**
71     * Generate a 16x16 png corresponding to $text.
72     *
73     * The given text should to be 128 to 150 characters long
74     *
75     * @access public
76     * @param  string $text
77     * @return string PNG data. Or empty string if GD is not available.
78     */
79    public function generate($text)
80    {
81        if (!function_exists('gd_info')) {
82            return '';
83        }
84
85        $textlen = strlen($text);
86
87        // We convert the hash into an array of integers.
88        $this->VALUES = [];
89        for ($i = 0; $i < $textlen; $i = $i + 2) {
90            array_push($this->VALUES, hexdec(substr($text, $i, 2)));
91        }
92        $this->VALUES_INDEX = 0; // to walk the array.
93
94        // Then use these integers to drive the creation of an image.
95        $image = imagecreatetruecolor($this->width, $this->height);
96        if ($image === false) {
97            return '';
98        }
99
100        $r = $r0 = $this->getInt();
101        $g = $g0 = $this->getInt();
102        $b = $b0 = $this->getInt();
103
104        // First, create an image with a specific gradient background.
105        $op = 'v';
106        if (($this->getInt() % 2) === 0) {
107            $op = 'h';
108        }
109        $image = $this->degrade($image, $op, [$r0, $g0, $b0], [0, 0, 0]);
110
111        for ($i = 0; $i < 7; ++$i) {
112            $action = $this->getInt();
113            $color = imagecolorallocate($image, $r, $g, $b);
114            $r = $r0 = (int) ($r0 + $this->getInt() / 25) % 256;
115            $g = $g0 = (int) ($g0 + $this->getInt() / 25) % 256;
116            $b = $b0 = (int) ($b0 + $this->getInt() / 25) % 256;
117            $this->drawshape($image, $action, $color);
118        }
119
120        $color = imagecolorallocate($image, $this->getInt(), $this->getInt(), $this->getInt());
121        $this->drawshape($image, $this->getInt(), $color);
122        ob_start();
123        imagepng($image);
124        $imagedata = ob_get_contents();
125        ob_end_clean();
126        if (version_compare(PHP_VERSION, '8.5', '<') && defined('imagedestroy')) {
127            imagedestroy($image);
128        }
129
130        return $imagedata;
131    }
132
133    /**
134     * Returns a single integer from the $VALUES array (0...255)
135     *
136     * @access private
137     * @return int
138     */
139    private function getInt()
140    {
141        $v = $this->VALUES[$this->VALUES_INDEX];
142        ++$this->VALUES_INDEX;
143        $this->VALUES_INDEX %= count($this->VALUES); // Wrap around the array
144        return $v;
145    }
146
147    /**
148     * Returns a single integer from the array (roughly mapped to image width)
149     *
150     * @access private
151     * @return int
152     */
153    private function getX()
154    {
155        return (int) ($this->width * $this->getInt() / 256);
156    }
157
158    /**
159     * Returns a single integer from the array (roughly mapped to image height)
160     *
161     * @access private
162     * @return int
163     */
164    private function getY()
165    {
166        return (int) ($this->height * $this->getInt() / 256);
167    }
168
169    /**
170     * Gradient function
171     *
172     * taken from:
173     * @link   https://www.supportduweb.com/scripts_tutoriaux-code-source-41-gd-faire-un-degrade-en-php-gd-fonction-degrade-imagerie.html
174     *
175     * @access private
176     * @param  resource|\GdImage $img
177     * @param  string $direction
178     * @param  array $color1
179     * @param  array $color2
180     * @return resource|\GdImage
181     */
182    private function degrade($img, $direction, $color1, $color2)
183    {
184        if ($direction === 'h') {
185            $size = imagesx($img);
186            $sizeinv = imagesy($img);
187        } else {
188            $size = imagesy($img);
189            $sizeinv = imagesx($img);
190        }
191        $diffs = [
192            ($color2[0] - $color1[0]) / $size,
193            ($color2[1] - $color1[1]) / $size,
194            ($color2[2] - $color1[2]) / $size,
195        ];
196        for ($i = 0; $i < $size; ++$i) {
197            $r = $color1[0] + ((int) $diffs[0] * $i);
198            $g = $color1[1] + ((int) $diffs[1] * $i);
199            $b = $color1[2] + ((int) $diffs[2] * $i);
200            if ($direction === 'h') {
201                imageline($img, $i, 0, $i, $sizeinv, imagecolorallocate($img, $r, $g, $b));
202            } else {
203                imageline($img, 0, $i, $sizeinv, $i, imagecolorallocate($img, $r, $g, $b));
204            }
205        }
206        return $img;
207    }
208
209    /**
210     * Draw a shape
211     *
212     * @access private
213     * @param  resource|\GdImage $image
214     * @param  int $action
215     * @param  int $color
216     */
217    private function drawshape($image, $action, $color)
218    {
219        switch ($action % 7) {
220            case 0:
221                imagefilledrectangle($image, $this->getX(), $this->getY(), $this->getX(), $this->getY(), $color);
222                break;
223            case 1:
224            case 2:
225                imagefilledellipse($image, $this->getX(), $this->getY(), $this->getX(), $this->getY(), $color);
226                break;
227            case 3:
228                $points = [$this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY()];
229                version_compare(PHP_VERSION, '8.1', '<') ? imagefilledpolygon($image, $points, 4, $color) : imagefilledpolygon($image, $points, $color);
230                break;
231            default:
232                $start = (int) ($this->getInt() * 360 / 256);
233                $end = (int) ($start + $this->getInt() * 180 / 256);
234                imagefilledarc($image, $this->getX(), $this->getY(), $this->getX(), $this->getY(), $start, $end, $color, IMG_ARC_PIE);
235        }
236    }
237}