Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
85.42% covered (warning)
85.42%
41 / 48
0.00% covered (danger)
0.00%
0 / 1
CRAP
0.00% covered (danger)
0.00%
0 / 1
Thresholding
85.42% covered (warning)
85.42%
41 / 48
0.00% covered (danger)
0.00%
0 / 1
20.12
0.00% covered (danger)
0.00%
0 / 1
 integralThresholding
85.42% covered (warning)
85.42%
41 / 48
0.00% covered (danger)
0.00%
0 / 1
20.12
1<?php
2/**
3 * Jingga
4 *
5 * PHP Version 8.1
6 *
7 * @package   phpOMS\Image
8 * @copyright Dennis Eichhorn
9 * @license   OMS License 2.0
10 * @version   1.0.0
11 * @link      https://jingga.app
12 */
13declare(strict_types=1);
14
15namespace phpOMS\Image;
16
17use phpOMS\Utils\ImageUtils;
18
19/**
20 * Image thresholding
21 *
22 * @package phpOMS\Image
23 * @license OMS License 2.0
24 * @link    https://jingga.app
25 * @since   1.0.0
26 */
27final class Thresholding
28{
29    /**
30     * Perform integral thresholding
31     *
32     * @param string $inPath  Image path to process
33     * @param string $outPath Output path to store the processed image
34     *
35     * @return void
36     *
37     * @see https://people.scs.carleton.ca/~roth/iit-publications-iti/docs/gerh-50002.pdf
38     * @see http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.817.6856&rep=rep1&type=pdf
39     *
40     * @since 1.0.0
41     */
42    public static function integralThresholding(string $inPath, string $outPath) : void
43    {
44        $im = null;
45        if (\strripos($inPath, 'png') !== false) {
46            $im = \imagecreatefrompng($inPath);
47        } elseif (\strripos($inPath, 'jpg') !== false || \strripos($inPath, 'jpeg') !== false) {
48            $im = \imagecreatefromjpeg($inPath);
49        } else {
50            $im = \imagecreatefromgif($inPath);
51        }
52
53        if ($im === false) {
54            return;
55        }
56
57        $dim = [\imagesx($im), \imagesy($im)];
58        $out = \imagecreate($dim[0], $dim[1]);
59        if ($out == false) {
60            return;
61        }
62
63        $intImg = [[]];
64        for ($i = 0; $i < $dim[0]; ++$i) {
65            $sum = 0.0;
66
67            for ($j = 0; $j < $dim[1]; ++$j) {
68                $rgb = \imagecolorat($im, $i, $j);
69                if ($rgb === false) {
70                    $rgb = 0;
71                }
72
73                $sum += ImageUtils::lightness($rgb);
74
75                $intImg[$i][$j] = $i === 0 ? $sum : $intImg[$i - 1][$j] + $sum;
76            }
77        }
78
79        $s = (int) ($dim[0] / 96.0); // can be changed 8
80        $t = 30; // can be changed 15
81
82        $black = \imagecolorallocate($out, 0, 0, 0);
83        $white = \imagecolorallocate($out, 255, 255, 255);
84
85        if ($black === false || $white === false) {
86            return;
87        }
88
89        for ($i = 0; $i < $dim[0]; ++$i) {
90            for ($j = 0; $j < $dim[1]; ++$j) {
91                $x1 = \max(1, (int) ($i - $s / 2.0));
92                $x2 = \min((int) ($i + $s / 2.0), $dim[0] - 1);
93
94                $y1 = \max(1, (int) ($j - $s / 2.0));
95                $y2 = \min((int) ($j + $s / 2.0), $dim[1] - 1);
96
97                $count = ($x2 - $x1) * ($y2 - $y1);
98                $sum   = $intImg[$x2][$y2] - $intImg[$x2][$y1 - 1] - $intImg[$x1 - 1][$y2] + $intImg[$x1 - 1][$y1 - 1];
99
100                $rgb = \imagecolorat($im, $i, $j);
101                if ($rgb === false) {
102                    $rgb = 0;
103                }
104
105                $brightness = ImageUtils::lightness($rgb);
106
107                $color = $brightness * $count <= ($sum * (100.0 - $t) / 100.0) ? $black : $white;
108
109                \imagesetpixel($out, $i, $j, $color);
110            }
111        }
112
113        if (\strripos($outPath, 'png') !== false) {
114            \imagepng($out, $outPath);
115        } elseif (\strripos($outPath, 'jpg') !== false || \strripos($outPath, 'jpeg') !== false) {
116            \imagejpeg($out, $outPath);
117        } else {
118            \imagegif($out, $outPath);
119        }
120
121        \imagedestroy($im);
122        \imagedestroy($out);
123    }
124}