Last active
May 18, 2018 11:19
-
-
Save Daniel-KM/7559570 to your computer and use it in GitHub Desktop.
Allow to use Omeka when server forbids to use ImageMagick via command line (See http://omeka.org/forums/topic/imagemagick-as-php-module). Simply replace application/libraries/Omeka/File/Derivative/Image/Creator.php with this file. Some work needs to be done in order to be able to select it via the admin UI.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Omeka | |
* | |
* @copyright Copyright 2007-2012 Roy Rosenzweig Center for History and New Media | |
* @copyright Copyright 2013 Daniel Berthereau for Mines ParisTech | |
* @license http://www.gnu.org/licenses/gpl-3.0.txt GNU GPLv3 | |
*/ | |
/** | |
* Create derivative images for a file in Omeka via the php Imagick extension. | |
* | |
* @package Omeka\File\Derivative | |
*/ | |
class Omeka_File_Derivative_Image_Creator | |
{ | |
/** | |
* Determine whether or not the Php Imagick extension is installed. | |
* | |
* @todo To be renamed. | |
* | |
* @return boolean | |
*/ | |
public static function isValidImageMagickPath($dirToIm) | |
{ | |
return class_exists('Imagick'); | |
} | |
/** | |
* Create all the derivatives requested with addDerivative(). | |
* | |
* @param string $fromFilePath | |
* @param string $derivFilename | |
* @param string $mimeType | |
* @return boolean | |
*/ | |
public function create($fromFilePath, $derivFilename, $mimeType) | |
{ | |
if (empty($derivFilename) || !is_string($derivFilename)) { | |
throw new InvalidArgumentException("Invalid derivative filename."); | |
} | |
if (!is_readable($fromFilePath)) { | |
throw new RuntimeException("File at '$fromFilePath' is not readable."); | |
} | |
if (!$this->_isDerivable($fromFilePath)) { | |
return false; | |
} | |
// If we have no derivative images to generate, signal nothing was done. | |
if (empty($this->_derivatives)) { | |
return false; | |
} | |
$workingDir = dirname($fromFilePath); | |
if (empty($workingDir) || !is_string($workingDir)) { | |
throw new InvalidArgumentException("Invalid derivative working path."); | |
} | |
if (!(is_dir($workingDir) && is_writable($workingDir))) { | |
throw new RuntimeException("Derivative working directory '$workingDir' is not writable."); | |
} | |
foreach ($this->_derivatives as $storageType => $cmdArgs) { | |
$newFilePath = rtrim($workingDir, DIRECTORY_SEPARATOR ) | |
. DIRECTORY_SEPARATOR . $storageType . '_' . $derivFilename; | |
$this->_createImage($fromFilePath, $newFilePath, $cmdArgs); | |
} | |
return true; | |
} | |
/** | |
* Add a derivative image to be created. | |
* | |
* @param string $storageType | |
* @param integer|string $size If an integer, it is the size constraint for | |
* the image, meaning it will have that maximum width or height, depending | |
* on whether the image is landscape or portrait. Otherwise, it is a string | |
* of comma separated process to be passed to ImageMagick. Each process | |
* should be a method name followed by its arguments, for example: | |
* flattenImages, cropImage 300 300 0 0 | |
* @param boolean $square Whether the derivative to add should be made square. | |
*/ | |
public function addDerivative($storageType, $sizeOrProcess, $square = false) | |
{ | |
if (!preg_match('/^\w+$/', $storageType)) { | |
throw new InvalidArgumentException("Invalid derivative type given: '$storageType' " | |
. "must be alphanumeric string."); | |
} | |
if (empty($sizeOrProcess)) { | |
throw new InvalidArgumentException("Invalid derivative storage size given."); | |
} | |
if (is_numeric($sizeOrProcess)) { | |
$this->_derivatives[$storageType] = $this->_getResizeCmdArgs($sizeOrProcess, $square); | |
} elseif (is_string($sizeOrProcess)) { | |
$this->_derivatives[$storageType] = $this->_getProcessArgs($sizeOrProcess); | |
} else { | |
throw new InvalidArgumentException("Invalid derivative storage size given."); | |
} | |
} | |
/** | |
* Generate a derivative image from an existing file stored in Omeka. | |
* | |
* This image will be generated based on a constraint given in pixels. For | |
* example, if the constraint is 500, the resulting image file will be scaled | |
* so that the largest side is 500px. If the image is less than 500px on both | |
* sides, the image will not be resized. | |
* | |
* Derivative images will only be generated for files with mime types | |
* that can be identified with ImageMagick's 'identify' command | |
* | |
* @throws Omeka_File_Derivative_Exception | |
* @param string $origPath Path to original file. | |
* @param string $newPath Path to newly generated derivative file. | |
* @param array $convertArgs List of methods and arguments to pass to | |
* ImageMagick. | |
*/ | |
private function _createImage($origPath, $newPath, $convertArgs) | |
{ | |
try { | |
$image = new Imagick(); | |
$image->readImage($origPath); | |
// Automatic use of first image of multi-pages images, because we | |
// convert to thumbnail. | |
foreach ($convertArgs as $method => $args) { | |
if (is_null($args)) { | |
$image->$method(); | |
} | |
elseif (!is_array($args)) { | |
$image->$method($args); | |
} | |
else { | |
// ImageMagick don't have more than eight arguments. | |
switch (count($args)) { | |
case 0: | |
$image->$method(); | |
break; | |
case 1: | |
$image->$method($args[0]); | |
break; | |
case 2: | |
$image->$method($args[0], $args[1]); | |
break; | |
case 3: | |
$image->$method($args[0], $args[1], $args[2]); | |
break; | |
case 4: | |
$image->$method($args[0], $args[1], $args[2], $args[3]); | |
break; | |
case 5: | |
$image->$method($args[0], $args[1], $args[2], $args[3], $args[4]); | |
break; | |
case 6: | |
$image->$method($args[0], $args[1], $args[2], $args[3], $args[4], $args[5]); | |
break; | |
case 7: | |
$image->$method($args[0], $args[1], $args[2], $args[3], $args[4], $args[5], $args[6]); | |
break; | |
case 8: | |
default: | |
$image->$method($args[0], $args[1], $args[2], $args[3], $args[4], $args[5], $args[6], $args[7]); | |
} | |
} | |
} | |
$image->writeImage($newPath); | |
$image->destroy(); | |
} catch (ImagickException $e) { | |
throw new Omeka_File_Derivative_Exception("ImageMagick failed."); | |
} | |
} | |
/** | |
* Get the ImageMagick process for resizing to the given constraints. | |
* | |
* @param integer $constraint Maximum side length in pixels. | |
* @param boolean $square Whether the derivative should be squared off. | |
* @return array | |
*/ | |
private function _getResizeCmdArgs($constraint, $square) | |
{ | |
$process = array(); | |
if (!$square) { | |
$process['setImageBackgroundColor'] = new ImagickPixel('#ffffff'); | |
$process['flattenImages'] = null; | |
// Tthumbnailing isn't used in order to get better quality images. | |
// Generally, the time used to import images in Omeka is not a | |
// problem. | |
$process['resizeImage'] = array($constraint, $constraint, Imagick::FILTER_LANCZOS, 1, true); | |
// Remove the canvas. | |
$process['setImagePage'] = array(0, 0, 0, 0); | |
} | |
else { | |
$process['setImageBackgroundColor'] = new ImagickPixel('#ffffff'); | |
$process['flattenImages'] = null; | |
$process['cropThumbnailImage'] = array($constraint, $constraint); | |
// Remove the canvas. | |
$process['setImagePage'] = array(0, 0, 0, 0); | |
} | |
return $process; | |
} | |
/** | |
* Get the ImageMagick process selected by the user. | |
* | |
* @param string $process A comma-separated string to convert to a process. | |
* Example: | |
* flattenImages, cropImage 300 300 0 0 | |
* @return array | |
*/ | |
private function _getProcessArgs($process) | |
{ | |
$list = array(); | |
foreach (explode(',', $process) as $value) { | |
$value = trim($value); | |
if (strpos($value, ' ') === false) { | |
$list[$value] = array(); | |
} | |
else { | |
$values = explode(' ', $value); | |
$key = trim($values[0]); | |
unset($values[0]); | |
$list[$key] = $values; | |
} | |
} | |
return $list; | |
} | |
/** | |
* Returns true only if ImageMagick is able to make derivative images of that file based | |
* upon whether or not it can be identified by ImageMagick's 'identify' binary. Otherwise returns false. | |
* | |
* @param string $filePath | |
* @return boolean | |
*/ | |
private function _isDerivable($filePath) | |
{ | |
// Next we'll check that it is identifiable by ImageMagick, and isn't on a blacklist | |
return (file_exists($filePath) | |
&& is_readable($filePath) | |
&& $this->_isIdentifiable($filePath)); | |
} | |
/** | |
* Returns true only if the file can be identified by ImageMagick. | |
* | |
* @param string $filePath | |
* @return boolean | |
*/ | |
private function _isIdentifiable($filePath) | |
{ | |
try { | |
$image = new Imagick(); | |
$image->readImage($filePath); | |
$isImage = $image->identifyImage(); | |
$isImage = (boolean) $isImage; | |
$image->destroy(); | |
} catch (ImagickException $e) { | |
$isImage = false; | |
} | |
return $isImage; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment