<?php
/*
-Copyright(c)2008 Internet Archive. Software license AGPL version 3.
+Copyright(c) 2008-2010 Internet Archive. Software license AGPL version 3.
-This file is part of BookReader.
+This file is part of BookReader. The full source code can be found at GitHub:
+http://github.com/openlibrary/bookreader
The canonical short name of an image type is the same as in the MIME type.
For example both .jpeg and .jpg are considered to have type "jpeg" since
along with BookReader. If not, see <http://www.gnu.org/licenses/>.
*/
-$MIMES = array('gif' => 'image/gif',
- 'jp2' => 'image/jp2',
- 'jpg' => 'image/jpeg',
- 'jpeg' => 'image/jpeg',
- 'png' => 'image/png',
- 'tif' => 'image/tiff',
- 'tiff' => 'image/tiff');
-
-$EXTENSIONS = array('gif' => 'gif',
- 'jp2' => 'jp2',
- 'jpeg' => 'jpeg',
- 'jpg' => 'jpeg',
- 'png' => 'png',
- 'tif' => 'tiff',
- 'tiff' => 'tiff');
-
-$exiftool = '/petabox/sw/books/exiftool/exiftool';
-
-// Process some of the request parameters
-$zipPath = $_REQUEST['zip'];
-$file = $_REQUEST['file'];
-if (isset($_REQUEST['ext'])) {
- $ext = $_REQUEST['ext'];
-} else {
- // Default to jpg
- $ext = 'jpg';
-}
-if (isset($_REQUEST['callback'])) {
- // XXX sanitize
- $callback = $_REQUEST['callback'];
-} else {
- $callback = null;
-}
-
-/*
- * Approach:
- *
- * Get info about requested image (input)
- * Get info about requested output format
- * Determine processing parameters
- * Process image
- * Return image data
- * Clean up temporary files
- */
-
-function getUnarchiveCommand($archivePath, $file)
-{
- $lowerPath = strtolower($archivePath);
- if (preg_match('/\.([^\.]+)$/', $lowerPath, $matches)) {
- $suffix = $matches[1];
-
- if ($suffix == 'zip') {
- return 'unzip -p '
- . escapeshellarg($archivePath)
- . ' ' . escapeshellarg($file);
- } else if ($suffix == 'tar') {
- return '7z e -so '
- . escapeshellarg($archivePath)
- . ' ' . escapeshellarg($file);
- } else {
- BRfatal('Incompatible archive format');
- }
+// Include BookReaderImages class definition
+require_once('BookReaderImages.inc.php');
+// Serve request
+$bri = new BookReaderImages();
+try {
+ if (array_key_exists('page', $_REQUEST) && $_REQUEST['page']) {
+ // Need to lookup metadata
+ $bri->serveLookupRequest($_REQUEST);
} else {
- BRfatal('Bad image stack path');
- }
-
- BRfatal('Bad image stack path or archive format');
-
-}
-
-/*
- * Returns the image type associated with the file extension.
- */
-function imageExtensionToType($extension)
-{
- global $EXTENSIONS;
-
- if (array_key_exists($extension, $EXTENSIONS)) {
- return $EXTENSIONS[$extension];
- } else {
- BRfatal('Unknown image extension');
- }
-}
-
-/*
- * Get the image width, height and depth from a jp2 file in zip.
- */
-function getImageInfo($zipPath, $file)
-{
- global $exiftool;
-
- $fileExt = strtolower(pathinfo($file, PATHINFO_EXTENSION));
- $type = imageExtensionToType($fileExt);
-
- // We look for all the possible tags of interest then act on the
- // ones presumed present based on the file type
- $tagsToGet = ' -ImageWidth -ImageHeight -FileType' // all formats
- . ' -BitsPerComponent -ColorSpace' // jp2
- . ' -BitDepth' // png
- . ' -BitsPerSample'; // tiff
-
- $cmd = getUnarchiveCommand($zipPath, $file)
- . ' | '. $exiftool . ' -S -fast' . $tagsToGet . ' -';
- exec($cmd, $output);
-
- $tags = Array();
- foreach ($output as $line) {
- $keyValue = explode(": ", $line);
- $tags[$keyValue[0]] = $keyValue[1];
- }
-
- $width = intval($tags["ImageWidth"]);
- $height = intval($tags["ImageHeight"]);
- $type = strtolower($tags["FileType"]);
-
- switch ($tags["FileType"]) {
- case "JP2":
- $bits = intval($tags["BitsPerComponent"]);
- break;
- case "TIFF":
- $bits = intval($tags["BitsPerSample"]);
- break;
- case "JPEG":
- $bits = 8;
- break;
- case "PNG":
- $bits = intval($tags["BitDepth"]);
- break;
- default:
- BRfatal("Unsupported image type");
- break;
+ // Request should be fully qualified - no lookup needed
+ $bri->serveRequest($_REQUEST);
}
-
-
- $retval = Array('width' => $width, 'height' => $height,
- 'bits' => $bits, 'type' => $type);
+} catch (Exception $e) {
+ header("HTTP/1.0 404 Not Found");
+ header("Content-type: text/plain");
- return $retval;
-}
-
-/*
- * Output JSON given the imageInfo associative array
- */
-function outputJSON($imageInfo, $callback)
-{
- header('Content-type: text/plain');
- $jsonOutput = json_encode($imageInfo);
- if ($callback) {
- $jsonOutput = $callback . '(' . $jsonOutput . ');';
- }
- echo $jsonOutput;
+ print "Error serving request:\n";
+ print " " . $e->getMessage() . "\n\n";
+ print "Debugging information:\n";
+ echo $e->getTraceAsString();
}
-// Get the image size and depth
-$imageInfo = getImageInfo($zipPath, $file);
-
-// Output json if requested
-if ('json' == $ext) {
- outputJSON($imageInfo, $callback);
- exit;
-}
-
-// Unfortunately kakadu requires us to know a priori if the
-// output file should be .ppm or .pgm. By decompressing to
-// .bmp kakadu will write a file we can consistently turn into
-// .pnm. Really kakadu should support .pnm as the file output
-// extension and automatically write ppm or pgm format as
-// appropriate.
-$decompressToBmp = true;
-if ($decompressToBmp) {
- $stdoutLink = '/tmp/stdout.bmp';
-} else {
- $stdoutLink = '/tmp/stdout.ppm';
-}
-
-$fileExt = strtolower(pathinfo($file, PATHINFO_EXTENSION));
-
-// Rotate is currently only supported for jp2 since it does not add server load
-$allowedRotations = array("0", "90", "180", "270");
-$rotate = $_REQUEST['rotate'];
-if ( !in_array($rotate, $allowedRotations) ) {
- $rotate = "0";
-}
-
-// Image conversion options
-$pngOptions = '';
-$jpegOptions = '-quality 75';
-
-// The pbmreduce reduction factor produces an image with dimension 1/n
-// The kakadu reduction factor produceds an image with dimension 1/(2^n)
-
-if (isset($_REQUEST['height'])) {
- $ratio = floatval($_REQUEST['origHeight']) / floatval($_REQUEST['height']);
- if ($ratio <= 2) {
- $scale = 2;
- $powReduce = 1;
- } else if ($ratio <= 4) {
- $scale = 4;
- $powReduce = 2;
- } else {
- //$powReduce = 3; //too blurry!
- $scale = 2;
- $powReduce = 1;
- }
-
-} else {
- $scale = $_REQUEST['scale'];
- if (1 >= $scale) {
- $scale = 1;
- $powReduce = 0;
- } else if (2 == $scale) {
- $powReduce = 1;
- } else if (4 == $scale) {
- $powReduce = 2;
- } else if (8 == $scale) {
- $powReduce = 3;
- } else if (16 == $scale) {
- $powReduce = 4;
- } else if (32 == $scale) {
- $powReduce = 5;
- } else {
- // $$$ Leaving this in as default though I'm not sure why it is...
- $scale = 8;
- $powReduce = 3;
- }
-}
-
-if (!file_exists($stdoutLink))
-{
- system('ln -s /dev/stdout ' . $stdoutLink);
-}
-
-
-putenv('LD_LIBRARY_PATH=/petabox/sw/lib/kakadu');
-
-$unzipCmd = getUnarchiveCommand($zipPath, $file);
-
-if ('jp2' == $fileExt) {
- $decompressCmd =
- " | /petabox/sw/bin/kdu_expand -no_seek -quiet -reduce $powReduce -rotate $rotate -i /dev/stdin -o " . $stdoutLink;
- if ($decompressToBmp) {
- $decompressCmd .= ' | bmptopnm ';
- }
-
-} else if ('tif' == $fileExt) {
- // We need to create a temporary file for tifftopnm since it cannot
- // work on a pipe (the file must be seekable).
- // We use the BookReaderTiff prefix to give a hint in case things don't
- // get cleaned up.
- $tempFile = tempnam("/tmp", "BookReaderTiff");
-
- $pbmReduce = reduceCommand($scale);
-
- $decompressCmd =
- ' > ' . $tempFile . ' ; tifftopnm ' . $tempFile . ' 2>/dev/null' . $pbmReduce;
-
-} else if ('jpg' == $fileExt) {
- $decompressCmd = ' | jpegtopnm ' . reduceCommand($scale);
-
-} else if ('png' == $fileExt) {
- $decompressCmd = ' | pngtopnm ' . reduceCommand($scale);
-
-} else {
- BRfatal('Unknown source file extension: ' . $fileExt);
-}
-
-// Non-integer scaling is currently disabled on the cluster
-// if (isset($_REQUEST['height'])) {
-// $cmd .= " | pnmscale -height {$_REQUEST['height']} ";
-// }
-
-if ('jpg' == $ext) {
- $compressCmd = ' | pnmtojpeg ' . $jpegOptions;
-} else if ('png' == $ext) {
- $compressCmd = ' | pnmtopng ' . $pngOptions;
-}
-
-if (($ext == $fileExt) && ($scale == 1) && ($rotate === "0")) {
- // Just pass through original data if same format and size
- $cmd = $unzipCmd;
-} else {
- $cmd = $unzipCmd . $decompressCmd . $compressCmd;
-}
-
-# print $cmd;
-
-
-header('Content-type: ' . $MIMES[$ext]);
-header('Cache-Control: max-age=15552000');
-passthru ($cmd); # cmd returns image data
-
-if (isset($tempFile)) {
- unlink($tempFile);
-}
-
-function BRFatal($string) {
- echo "alert('$string');\n";
- die(-1);
-}
-
-// Returns true if using a power node
-function onPowerNode() {
- exec("lspci | fgrep -c Realtek", $output, $return);
- if ("0" != $output[0]) {
- return true;
- } else {
- exec("egrep -q AMD /proc/cpuinfo", $output, $return);
- if ($return == 0) {
- return true;
- }
- }
- return false;
-}
-
-function reduceCommand($scale) {
- if (1 != $scale) {
- if (onPowerNode()) {
- return ' | pnmscale -reduce ' . $scale;
- } else {
- return ' | pnmscale -nomix -reduce ' . $scale;
- }
- } else {
- return '';
- }
-}
-
-
-?>
-
+?>
\ No newline at end of file