Bump version number
[bookreader.git] / GnuBookIA / datanode / GnuBookImages.php
1 <?php
2
3 /*
4 Copyright(c)2008 Internet Archive. Software license AGPL version 3.
5
6 This file is part of GnuBook.
7
8     GnuBook is free software: you can redistribute it and/or modify
9     it under the terms of the GNU Affero General Public License as published by
10     the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12
13     GnuBook is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU Affero General Public License for more details.
17
18     You should have received a copy of the GNU Affero General Public License
19     along with GnuBook.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 $MIMES = array('jpg' => 'image/jpeg',
23                'png' => 'image/png');
24
25 $zipPath  = $_REQUEST['zip'];
26 $file     = $_REQUEST['file'];
27
28 // Unfortunately kakadu requires us to know a priori if the
29 // output file should be .ppm or .pgm.  By decompressing to
30 // .bmp kakadu will write a file we can consistently turn into
31 // .pnm.  Really kakadu should support .pnm as the file output
32 // extension and automatically write ppm or pgm format as
33 // appropriate.
34 $decompressToBmp = true;
35 if ($decompressToBmp) {
36   $stdoutLink = '/tmp/stdout.bmp';
37 } else {
38   $stdoutLink = '/tmp/stdout.ppm';
39 }
40
41 if (isset($_REQUEST['ext'])) {
42   $ext = $_REQUEST['ext'];
43 } else {
44   // Default to jpg
45   $ext = 'jpg';
46 }
47
48 $fileExt = strtolower(pathinfo($file, PATHINFO_EXTENSION));
49
50 // Rotate is currently only supported for jp2 since it does not add server load
51 $allowedRotations = array("0", "90", "180", "270");
52 $rotate = $_REQUEST['rotate'];
53 if ( !in_array($rotate, $allowedRotations) ) {
54     $rotate = "0";
55 }
56
57 // Image conversion options
58 $pngOptions = '';
59 $jpegOptions = '-quality 75';
60
61 // The pbmreduce reduction factor produces an image with dimension 1/n
62 // The kakadu reduction factor produceds an image with dimension 1/(2^n)
63
64 if (isset($_REQUEST['height'])) {
65     $ratio = floatval($_REQUEST['origHeight']) / floatval($_REQUEST['height']);
66     if ($ratio <= 2) {
67         $scale = 2;
68         $powReduce = 1;    
69     } else if ($ratio <= 4) {
70         $scale = 4;
71         $powReduce = 2;
72     } else {
73         //$powReduce = 3; //too blurry!
74         $scale = 2;
75         $powReduce = 1;
76     }
77
78 } else {
79     $scale = $_REQUEST['scale'];
80     if (1 >= $scale) {
81         $scale = 1;
82         $powReduce = 0;
83     } else if (2 == $scale) {
84         $powReduce = 1;
85     } else if (4 == $scale) {
86         $powReduce = 2;
87     } else if (8 == $scale) {
88         $powReduce = 3;
89     } else if (16 == $scale) {
90         $powReduce = 4;
91     } else if (32 == $scale) {
92         $powReduce = 5;
93     } else {
94         // $$$ Leaving this in as default though I'm not sure why it is...
95         $scale = 8;
96         $powReduce = 3;
97     }
98 }
99
100 if (!file_exists($stdoutLink)) 
101 {  
102   system('ln -s /dev/stdout ' . $stdoutLink);  
103 }
104
105
106 putenv('LD_LIBRARY_PATH=/petabox/sw/lib/kakadu');
107
108 $unzipCmd  = 'unzip -p ' . 
109         escapeshellarg($zipPath) .
110         ' ' . escapeshellarg($file);
111         
112 if ('jp2' == $fileExt) {
113     $decompressCmd = 
114         " | /petabox/sw/bin/kdu_expand -no_seek -quiet -reduce $powReduce -rotate $rotate -i /dev/stdin -o " . $stdoutLink;
115     if ($decompressToBmp) {
116         $decompressCmd .= ' | bmptopnm ';
117     }
118     
119 } else if ('tif' == $fileExt) {
120     // We need to create a temporary file for tifftopnm since it cannot
121     // work on a pipe (the file must be seekable).
122     // We use the GnuBookTiff prefix to give a hint in case things don't
123     // get cleaned up.
124     $tempFile = tempnam("/tmp", "GnuBookTiff");
125     
126     if (1 != $scale) {
127         if (onPowerNode()) {
128             $pbmReduce = ' | pnmscale -reduce ' . $scale;
129         } else {
130             $pbmReduce = ' | pnmscale -nomix -reduce ' . $scale;
131         }
132     } else {
133         $pbmReduce = '';
134     }
135     
136     $decompressCmd = 
137         ' > ' . $tempFile . ' ; tifftopnm ' . $tempFile . ' 2>/dev/null' . $pbmReduce;
138
139 } else {
140     GBfatal('Unknown source file extension: ' . $fileExt);
141 }
142        
143 // Non-integer scaling is currently disabled on the cluster
144 // if (isset($_REQUEST['height'])) {
145 //     $cmd .= " | pnmscale -height {$_REQUEST['height']} ";
146 // }
147
148 if ('jpg' == $ext) {
149     $compressCmd = ' | pnmtojpeg ' . $jpegOptions;
150 } else if ('png' == $ext) {
151     $compressCmd = ' | pnmtopng ' . $pngOptions;
152 }
153
154 $cmd = $unzipCmd . $decompressCmd . $compressCmd;
155
156 //print $cmd;
157
158 header('Content-type: ' . $MIMES[$ext]);
159 header('Cache-Control: max-age=15552000');
160
161 passthru ($cmd);
162
163 if (isset($tempFile)) {
164   unlink($tempFile);
165 }
166
167 function GBFatal($string) {
168     echo "alert('$string')\n";
169     die(-1);
170 }
171
172 // Returns true if using a power node
173 function onPowerNode() {
174     exec("lspci | fgrep -c Realtek", $output, $return);
175     if ("0" != $output[0]) {
176         return true;
177     } else {
178         exec("egrep -q AMD /proc/cpuinfo", $output, $return);
179         if ($return == 0) {
180             return true;
181         }
182     }
183     return false;
184 }
185
186
187 ?>
188