thumbnail.php ➔ drawText()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 6
nop 5
dl 0
loc 48
rs 9.1344
c 0
b 0
f 0
1
<?php
2
3
//@WARNING: requires Imagick!
4
5
//@FIXME:	This is a *very* basic example! Check and validations still need to be done.
6
7
if(!is_dir($_SERVER['DOCUMENT_ROOT'])) {
8
    $_SERVER['DOCUMENT_ROOT'] = dirname(dirname($_SERVER['SCRIPT_FILENAME']));
9
}
10
11
$sRootDirectory = $_SERVER['DOCUMENT_ROOT'];
12
13
if (isset($_SERVER['THUMBNAIL_DIRECTORY'])) {
14
    $sThumbDirectory = $_SERVER['THUMBNAIL_DIRECTORY'];
15
} else {
16
    $sThumbDirectory =  sys_get_temp_dir() . '/.thumbs/';
17
}
18
19
if (is_dir($sThumbDirectory) === false) {
20
    mkdir($sThumbDirectory);
21
}
22
23
if(isset($_GET['DEBUG']) || isset($_GET['debug']) ) {
24
    define('DEBUG', true);
25
} else {
26
    define('DEBUG', false);
27
}
28
29
if(isset($_GET['file'])) {
30
    $sFilePath = $sRootDirectory . $_GET['file'];
31
}
32
else {
33
    $sFilePath = $sThumbDirectory . 'empty.png';
34
}
35
36
try {
37
    if(strlen($sFilePath) - strrpos($sFilePath, '.svg') === 4) {
38
        // Display SVG directly
39
        header('Content-Type: image/svg+xml');
40
        readfile($sFilePath);
41
    } else {
42
        outputThumbnail($sFilePath, $sThumbDirectory, 200);
43
    }
44
} catch(Exception $eAny) {
45
    buildExceptionImage($eAny);
46
}
47
48
function outputThumbnail($p_sFilePath, $p_sThumbDirectory, $p_iImageWidth, $p_sOutputType = 'png') {
49
50
    $bIOnlyKnowHowToWorkImagickByUsingTheCommandline = true;
51
52
    if(!is_dir($p_sThumbDirectory)) {
53
        throw new Exception('The directory to store the Thumbnails in does not exist at "'.$p_sThumbDirectory.'"');
54
    }
55
    elseif(!is_writable($p_sThumbDirectory)) {
56
        throw new Exception('The directory to store the Thumbnails is not writable "'.$p_sThumbDirectory.'"');
57
    }
58
59
    //@TODO: check if file is on of following: '.gif', '.jpg', '.png', '.svg', '.tiff', '.ps', '.pdf', '.bmp', '.eps', '.psd',
60
    /* for .swf support look at http://www.swftools.org/ ?
61
     * for html preview, it is already possible to do to pdf... http://code.google.com/p/wkhtmltopdf/
62
     * although it's a bit of a hack that might work.
63
     */
64
65
    $sSaveFileName = sanitize($p_sFilePath) . '.' . $p_sOutputType;
66
    $sSaveFilePath = $p_sThumbDirectory . $sSaveFileName;
67
68
    if(class_exists('Imagick')) {
69
        $bRefresh=false;
70
        if($bRefresh === true && is_file($sSaveFilePath)) {
71
            unlink($sSaveFilePath);
72
        }#if
73
74
        if(!is_file($sSaveFilePath)) {
75
            $aSize = getimagesize($p_sFilePath);
76
            // Create thumb for file
77
            if($bIOnlyKnowHowToWorkImagickByUsingTheCommandline === true) {
78
                // Save Locally
79
                $iImageWidth = $p_iImageWidth;
80
                if(isset($aSize[0]) && $aSize[0] <= $p_iImageWidth) {
81
                    $iImageWidth = $aSize[0];
82
                }#if
83
84
                $sCommand =
85
                    'convert \'' . urldecode($p_sFilePath) . '[0]\''
86
                        . ' -colorspace RGB'
87
                        . ' -geometry ' . $iImageWidth
88
                        . ' \'' . $sSaveFilePath . '\''
89
                ;
90
91
                $aResult = executeCommand($sCommand);
92
93
                if($aResult['return'] !== 0) {
94
                    throw new Exception('Error executing '.$aResult['stderr'] . '(full command : "'. $aResult['stdin'] .'")');
95
                }#if
96
            }
97
            else {
98
                // This probably still needs some fixing before it'll actually work :-S
99
                $oImagick = new imagick( $p_sFilePath.'[0]');      // Read First Page of PDF
100
101
                $oImagick->setResolution($p_iImageWidth, 0);  // If 0 is provided as a width or height parameter, aspect ratio is maintained
102
103
                $oImagick->setImageFormat( "png" );         // Convert to png
104
                header('Content-Type: image/png');          // Send out
105
106
                echo $oImagick;
107
            }#if
108
        }#if
109
        $oImagick = new imagick($sSaveFilePath);      // Read First Page
110
        header('Content-Type: image/png');          // Send out
111
        echo $oImagick;
112
    } /** @noinspection SpellCheckingInspection */
113
    elseif(function_exists('imagettfbbox') === true) {
114
        throw new Exception('Currently only Imagick is supported');
115
    }else {
116
        throw new Exception('Either Imagick or the GD2 library need to installed on the server');
117
    }#if
118
}
119
120
//@TODO: This needs to be placed somewhere more suitable
121
/*
122
 * Because exec/sytem/etc. Are a bit lame in giving error feedback a workaround
123
 * is required. Instead of executing commands directly, we open a stream, write
124
 * the command to the stream and read whatever comes back out of the pipes.
125
 *
126
 * For general info on Standard input (stdin), Standard output (stdout) and
127
 * Standard error (stderr) please visit:
128
 *      http://en.wikipedia.org/wiki/Standard_streams
129
 */
130
function executeCommand($p_sCommand, $p_sInput='') {
131
132
    $rProcess = proc_open(
133
        $p_sCommand
134
        , array(
135
              0 => array('pipe', 'r')
136
            , 1 => array('pipe', 'w')
137
            , 2 => array('pipe', 'w'))
138
        , $aPipes
139
    );
140
    fwrite($aPipes[0], $p_sInput);
141
    fclose($aPipes[0]);
142
143
144
    $sStandardOutput = stream_get_contents($aPipes[1]);
145
    fclose($aPipes[1]);
146
147
    $sStandardError = stream_get_contents($aPipes[2]);
148
    fclose($aPipes[2]);
149
150
    $iReturn=proc_close($rProcess);
151
152
    return array(
153
          'stdin'  => $p_sCommand
154
        , 'stdout' => $sStandardOutput
155
        , 'stderr' => $sStandardError
156
        , 'return' => $iReturn
157
    );
158
}
159
160
161
function buildExceptionImage(\Exception $ex) {
162
    $aMessage = array();
163
    if (DEBUG === true) {
164
        $aMessage[] = 'Uncaught ' . get_class($ex);
165
        $aMessage[] = ' in ' . basename($ex->getFile()) . ':' . $ex->getLine();
166
        $aMessage[] = "\n";
167
    }
168
    $aMessage[] = ' Error: ' . $ex->getMessage() . ' ';
169
170
    $message = implode("\n", $aMessage);
171
172
    $rImage = drawText($message, 10, '255.0.0.0');
173
174
    imagerectangle($rImage, 0, 0, \imagesx($rImage) - 1, \imagesy($rImage) - 1, imagecolorallocatealpha($rImage, 255, 0, 0, 0));
175
176
    header('Content-Type: image/png');
177
    imagepng($rImage);
178
    imagedestroy($rImage);
179
}
180
181
function drawText($p_sText, $p_dSize, $p_sRgba, $p_iAngle=0, $p_sFontFile=null) {
182
    $text  = (string) $p_sText;
183
    $size  = (float)  $p_dSize;
184
    $angle = (int)    $p_iAngle;
185
186
    if($p_sFontFile === null) {
187
        $sFontFile = __DIR__ . '/DroidSans.ttf';
188
    }
189
    else {
190
        $sFontFile = $p_sFontFile;
191
    }
192
193
    if(!is_file($sFontFile)) {
194
        echo 'Could not find font ' . $sFontFile;
195
        die;
196
    }
197
198
    if (1 !== preg_match('~^([\d]+?)\.([\d]+?)\.([\d]+?)\.([\d]+?)$~', $p_sRgba)) {
199
        $sRgba = '0.0.0.0';
200
    }
201
    else {
202
        $sRgba = $p_sRgba;
203
    }
204
    list($r, $g, $b, $a) = explode('.', $sRgba);
205
206
    $size = max(8, min(127, intval($size)));
207
    $r = max(0, min(255, intval($r)));
208
    $g = max(0, min(255, intval($g)));
209
    $b = max(0, min(255, intval($b)));
210
    $a = max(0, min(127, intval($a)));
211
212
    $box = imagettfbbox($size, $angle, $sFontFile, $text);
213
    $width  = abs($box[4]) + abs($box[0]);// - $box[6];
214
    $height = abs($box[3]) + abs($box[7]);// - $box[1];
215
    $x = 0; // $width;
216
    $y = $height - $box[1]; // $height;
217
    $image = imagecreatetruecolor($width, $height);
218
    imagesavealpha($image, true);
219
    imagealphablending($image, true);
220
221
    $transp = imagecolorallocatealpha($image, 255, 0, 0, 127);
222
    imagefill($image, 0, 0, $transp);
223
224
    $black = imagecolorallocatealpha($image, $r, $g, $b, $a);
225
    imagettftext($image, $size, $angle, $x, $y, $black, $sFontFile, $text);
226
227
    return $image;
228
}
229
230
function sanitize($p_sName){
231
    return preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', '__'), $p_sName);
232
}
233
234
#EOF
235