. */ $MIMES = array('jpg' => 'image/jpeg', 'png' => 'image/png'); $zipPath = $_REQUEST['zip']; $file = $_REQUEST['file']; // 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'; } if (isset($_REQUEST['ext'])) { $ext = $_REQUEST['ext']; } else { // Default to jpg $ext = 'jpg'; } $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 = 'unzip -p ' . escapeshellarg($zipPath) . ' ' . escapeshellarg($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 GnuBookTiff prefix to give a hint in case things don't // get cleaned up. $tempFile = tempnam("/tmp", "GnuBookTiff"); if (1 != $scale) { if (onPowerNode()) { $pbmReduce = ' | pnmscale -reduce ' . $scale; } else { $pbmReduce = ' | pnmscale -nomix -reduce ' . $scale; } } else { $pbmReduce = ''; } $decompressCmd = ' > ' . $tempFile . ' ; tifftopnm ' . $tempFile . ' 2>/dev/null' . $pbmReduce; } else { GBfatal('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; } $cmd = $unzipCmd . $decompressCmd . $compressCmd; //print $cmd; header('Content-type: ' . $MIMES[$ext]); header('Cache-Control: max-age=15552000'); passthru ($cmd); if (isset($tempFile)) { unlink($tempFile); } function GBFatal($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; } ?>