/** * Retrieves what you really want to know about an image file, PDFs included, * before making calls such as the above based on good information. * Returns as follows: * array('format' => 'file extension: gif, jpg, png or pdf', 'width' => width in pixels, 'height' => height in pixels); * $format is the recommended file extension based on the actual file type, not the user's (possibly totally false or absent) * claimed file extension. * If the file does not have a valid header identifying it as one of these types, false is returned. * If the 'format-only' option is true, only the format field is returned. This is much faster if the * file is a PDF. * @param mixed $file * @param mixed $options * @return mixed */ public static function getInfo($file, $options = array()) { $formatOnly = isset($options['format-only']) && $options['format-only']; $result = array(); $in = fopen($file, "rb"); $data = fread($in, 4); fclose($in); if ($data === '%PDF') { // format-only if ($formatOnly || !aImageConverter::supportsInput('pdf')) { // All we can do is confirm the format and allow // download of the original (which, for PDF, is // usually fine) return array('format' => 'pdf'); } $result['format'] = 'pdf'; $path = sfConfig::get("app_aimageconverter_path", ""); if (strlen($path)) { if (!preg_match("/\\/\$/", $path)) { $path .= "/"; } } // Bounding box goes to stderr, not stdout! Charming // 5 second timeout for reading dimensions. Keeps us from getting stuck on // PDFs that just barely work in Adobe but are noncompliant and hang ghostscript. // Read the output one line at a time so we can catch the happy // bounding box message without hanging // Problem: this doesn't work. We regain control but the process won't die for some reason. It helps // with import but for now go with the simpler standard invocation and hope they fix gs // $cmd = "(PATH=$path:\$PATH; export PATH; gs -sDEVICE=bbox -dNOPAUSE -dFirstPage=1 -dLastPage=1 -r100 -q " . escapeshellarg($file) . " -c quit ) 2>&1"; $cmd = "( PATH={$path}:\$PATH; export PATH; gs -sDEVICE=bbox -dNOPAUSE -dFirstPage=1 -dLastPage=1 -r100 -q " . escapeshellarg($file) . " -c quit & GS=\$!; ( sleep 5; kill \$GS ) & TIMEOUT=\$!; wait \$GS; kill \$TIMEOUT ) 2>&1"; // For some reason system() does not get the same result when killing subshells as I get when executing // $cmd directly. I don't know why this is this the case but it's easily reproduced $script = aFiles::getTemporaryFilename() . '.sh'; file_put_contents($script, $cmd); $cmd = "/bin/sh " . escapeshellarg($script); $in = popen($cmd, "r"); $data = stream_get_contents($in); pclose($in); // Actual nonfatal errors in the bbox output mean it's not safe to just // read this naively with fscanf, look for the good part if (preg_match("/%%BoundingBox: \\d+ \\d+ (\\d+) (\\d+)/", $data, $matches)) { $result['width'] = $matches[1]; $result['height'] = $matches[2]; } if (!isset($result['width'])) { // Bad PDF return false; } return $result; } else { $formats = array(IMAGETYPE_JPEG => "jpg", IMAGETYPE_PNG => "png", IMAGETYPE_GIF => "gif"); $data = getimagesize($file); if (count($data) < 3) { return false; } if (!isset($formats[$data[2]])) { return false; } $format = $formats[$data[2]]; $result['format'] = $format; if ($formatOnly) { return $result; } $result['width'] = $data[0]; $result['height'] = $data[1]; if ($format === 'jpg') { // Some EXIF orientations swap width and height switch (aImageConverter::getRotation($file, $data)) { case 5: // vertical flip + 90 rotate right // vertical flip + 90 rotate right case 6: // 90 rotate right // 90 rotate right case 7: // horizontal flip + 90 rotate right // horizontal flip + 90 rotate right case 8: // 90 rotate left $result['width'] = $data[1]; $result['height'] = $data[0]; break; } } return $result; } }
public static function getInfo($file) { $result = array(); $in = fopen($file, "rb"); $data = fread($in, 4); fclose($in); if ($data === '%PDF') { if (!aImageConverter::supportsInput('pdf')) { // All we can do is confirm the format and allow // download of the original (which, for PDF, is // usually fine) return array('format' => 'pdf'); } $result['format'] = 'pdf'; $path = sfConfig::get("app_aimageconverter_path", ""); if (strlen($path)) { if (!preg_match("/\\/\$/", $path)) { $path .= "/"; } } // Bounding box goes to stderr, not stdout! Charming $cmd = "(PATH={$path}:\$PATH; export PATH; gs -sDEVICE=bbox -dNOPAUSE -dFirstPage=1 -dLastPage=1 -r100 -q " . escapeshellarg($file) . " -c quit) 2>&1"; // sfContext::getInstance()->getLogger()->info("PDFINFO: $cmd"); $in = popen($cmd, "r"); $data = stream_get_contents($in); pclose($in); // Actual nonfatal errors in the bbox output mean it's not safe to just // read this naively with fscanf, look for the good part if (preg_match("/%%BoundingBox: \\d+ \\d+ (\\d+) (\\d+)/", $data, $matches)) { $result['width'] = $matches[1]; $result['height'] = $matches[2]; } else { // Bad PDF return false; } return $result; } else { $formats = array(IMAGETYPE_JPEG => "jpg", IMAGETYPE_PNG => "png", IMAGETYPE_GIF => "gif"); $data = getimagesize($file); if (count($data) < 3) { return false; } if (!isset($formats[$data[2]])) { return false; } $format = $formats[$data[2]]; $result['width'] = $data[0]; $result['height'] = $data[1]; $result['format'] = $format; return $result; } }