6270cdc6ae9ff0a9633c60c0e52b51761a787742
[surrogator.git] / surrogator.php
1 #!/usr/bin/env php
2 <?php
3 namespace surrogator;
4 $cfgFile = __DIR__ . '/data/surrogator.config.php';
5 if (!file_exists($cfgFile)) {
6     $cfgFile = '/etc/surrogator.config.php';
7     if (!file_exists($cfgFile)) {
8         logErr(
9             "Configuration file does not exist.\n"
10             . "Copy data/surrogator.config.php.dist to data/surrogator.config.php"
11         );
12         exit(2);
13     }
14 }
15 require $cfgFile;
16
17 array_shift($argv);
18 $files = array();
19 foreach ($argv as $arg) {
20     if ($arg == '-v' || $arg == '--verbose') {
21         ++$logLevel;
22     } else if ($arg == '-vv') {
23         $logLevel += 2;
24     } else if ($arg == '-q' || $arg == '--quiet') {
25         $logLevel = 0;
26     } else if ($arg == '-f' || $arg == '--force') {
27         $forceUpdate = true;
28     } else if ($arg == '-h' || $arg == '--help') {
29         showHelp();
30         exit(4);
31     } else if ($arg == '--version') {
32         echo "surrogator 0.0.1\n";
33         exit();
34     } else if (file_exists($arg)) {
35         $files[] = $arg;
36     } else {
37         logErr('Unknown argument: ' . $arg);
38         exit(3);
39     }
40 }
41
42 function showHelp()
43 {
44     echo <<<HLP
45 Usage: php surrogator.php [options] [filename(s)]
46
47 surrogator - a simple libravatar server
48  Put files in raw/ dir and run surrogator.php to generate different sizes
49
50 Options:
51
52  -h, --help     Show help
53  -v, --verbose  Be verbose (more log messages, also -vv)
54  -q, --quiet    Be quiet (no log messages)
55  -f, --force    Force update of all files
56      --version  Show program version
57
58 filenames       One or several files whose small images shall get generated.
59                 If none given, all will be checked
60
61 HLP;
62 }
63
64 if (!isset($rawDir)) {
65     logErr('$rawDir not set');
66     exit(1);
67 }
68 if (!isset($varDir)) {
69     logErr('$varDir not set');
70     exit(1);
71 }
72 if (!isset($sizes)) {
73     logErr('$sizes not set');
74     exit(1);
75 }
76 if (!isset($maxSize)) {
77     logErr('$maxSize not set');
78     exit(1);
79 }
80 if (!isset($logLevel)) {
81     logErr('$logLevel not set');
82     exit(1);
83 }
84
85
86 if (!is_dir($varDir . '/square')) {
87     log('creating square dir: ' . $varDir . '/square');
88     if (!mkdir($varDir . '/square', 0755, true)) {
89         logErr('cannot create square dir');
90         exit(5);
91     }
92 }
93 log('sizes: ' . implode(', ', $sizes), 2);
94 foreach ($sizes as $size) {
95     if (!is_dir($varDir . '/' . $size)) {
96         log('creating size dir: ' . $varDir . '/' . $size);
97         mkdir($varDir . '/' . $size, 0755);
98     }
99 }
100
101 if (count($files)) {
102     $fileInfos = array();
103     foreach ($files as $file) {
104         $fileInfos[] = new \SplFileInfo($file);
105     }
106 } else {
107     $fileInfos = new \RegexIterator(
108         new \DirectoryIterator($rawDir),
109         '#^.+\.(png|jpg)$#'
110     );
111 }
112 foreach ($fileInfos as $fileInfo) {
113     $origPath   = $fileInfo->getPathname();
114     $fileName   = $fileInfo->getFilename();
115     $ext        = strtolower(substr($fileName, strrpos($fileName, '.') + 1));
116     $squarePath = $varDir . '/square/'
117         . substr($fileName, 0, -strlen($ext)) . 'png';
118
119     log('processing ' . $fileName, 1);
120     if (image_uptodate($origPath, $squarePath)) {
121         log(' image up to date', 2);
122         continue;
123     }
124
125     if (!createSquare($origPath, $ext, $squarePath, $maxSize)) {
126         continue;
127     }
128
129     if ($fileName == 'default.png') {
130         $md5 = $sha256 = 'default';
131     } else {
132         list($md5, $sha256) = getHashes($fileName);
133     }
134
135     log(' creating sizes for ' . $fileName, 2);
136     log(' md5:    ' . $md5, 3);
137     log(' sha256: ' . $sha256, 3);
138     $imgSquare = imagecreatefrompng($squarePath);
139     foreach ($sizes as $size) {
140         log(' size ' . $size, 3);
141         $sizePathMd5    = $varDir . '/' . $size . '/' . $md5 . '.png';
142         $sizePathSha256 = $varDir . '/' . $size . '/' . $sha256 . '.png';
143
144         $imgSize = imagecreatetruecolor($size, $size);
145         imagealphablending($imgSize, false);
146         imagefilledrectangle(
147             $imgSize, 0, 0, $size - 1, $size - 1,
148             imagecolorallocatealpha($imgSize, 0, 0, 0, 127)
149         );
150         imagecopyresampled(
151             $imgSize, $imgSquare, 
152             0, 0, 0, 0,
153             $size, $size, $maxSize, $maxSize
154         );
155         imagesavealpha($imgSize, true);
156         imagepng($imgSize, $sizePathMd5);
157         imagepng($imgSize, $sizePathSha256);
158         imagedestroy($imgSize);
159         
160     }
161     imagedestroy($imgSquare);
162 }
163
164 function getHashes($fileName)
165 {
166     $fileNameNoExt = substr($fileName, 0, -strlen(strrpos($fileName, '.')) - 2);
167     $emailAddress  = trim(strtolower($fileNameNoExt));
168
169     return array(
170         md5($emailAddress), hash('sha256', $emailAddress)
171     );
172 }
173
174
175 function createSquare($origPath, $ext, $targetPath, $maxSize)
176 {
177     if ($ext == 'png') {
178         $imgOrig = imagecreatefrompng($origPath);
179     } else if ($ext == 'jpg' || $ext == 'jpeg') {
180         $imgOrig = imagecreatefromjpeg($origPath);
181     } else {
182         //unsupported format
183         return false;
184     }
185
186     if ($imgOrig === false) {
187         logErr('Error loading image file: ' . $origPath);
188         return false;
189     }
190
191     $imgSquare = imagecreatetruecolor($maxSize, $maxSize);
192     imagealphablending($imgSquare, false);
193     imagefilledrectangle(
194         $imgSquare, 0, 0, $maxSize - 1, $maxSize - 1,
195         imagecolorallocatealpha($imgSquare, 0, 0, 0, 127)
196     );
197     imagealphablending($imgSquare, true);
198
199     $oWidth    = imagesx($imgOrig);
200     $oHeight   = imagesy($imgOrig);
201     if ($oWidth > $oHeight) {
202         $flScale = $maxSize / $oWidth;
203     } else {
204         $flScale = $maxSize / $oHeight;
205     }
206     $nWidth  = (int)($oWidth * $flScale);
207     $nHeight = (int)($oHeight * $flScale);
208
209     imagecopyresampled(
210         $imgSquare, $imgOrig, 
211         ($maxSize - $nWidth) / 2, ($maxSize - $nHeight) / 2,
212         0, 0,
213         $nWidth, $nHeight,
214         $oWidth, $oHeight
215     );
216
217     imagesavealpha($imgSquare, true);
218     imagepng($imgSquare, $targetPath);
219
220     imagedestroy($imgSquare);
221     imagedestroy($imgOrig);
222     return true;
223 }
224
225 function image_uptodate($sourcePath, $targetPath)
226 {
227     global $forceUpdate;
228     if ($forceUpdate) {
229         return false;
230     }
231     if (!file_exists($targetPath)) {
232         return false;
233     }
234     if (filemtime($sourcePath) > filemtime($targetPath)) {
235         //source newer
236         return false;
237     }
238
239     return true;
240 }
241
242 function log($msg, $level = 1)
243 {
244     global $logLevel;
245     if ($level <= $logLevel) {
246         echo $msg . "\n";
247     }
248 }
249
250 function logErr($msg)
251 {
252     file_put_contents('php://stderr', $msg . "\n");
253 }
254
255 ?>