diff --git a/core/includes/common.inc b/core/includes/common.inc index a4805c0..5726d32 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -3083,7 +3083,6 @@ function _drupal_bootstrap_code() { require_once __DIR__ . '/tablesort.inc'; require_once __DIR__ . '/file.inc'; require_once __DIR__ . '/unicode.inc'; - require_once __DIR__ . '/image.inc'; require_once __DIR__ . '/form.inc'; require_once __DIR__ . '/mail.inc'; require_once __DIR__ . '/ajax.inc'; diff --git a/core/includes/image.inc b/core/includes/image.inc deleted file mode 100644 index 9e2d06f..0000000 --- a/core/includes/image.inc +++ /dev/null @@ -1,332 +0,0 @@ -source = $filepath; - $image->toolkit = $toolkit; - $details = $toolkit->getInfo($image); - if (isset($details) && is_array($details)) { - $details['file_size'] = filesize($filepath); - } - } - - return $details; -} - -/** - * Scales an image to the exact width and height given. - * - * This function achieves the target aspect ratio by cropping the original image - * equally on both sides, or equally on the top and bottom. This function is - * useful to create uniform sized avatars from larger images. - * - * The resulting image always has the exact target dimensions. - * - * @param object $image - * An image object returned by image_load(). - * @param int $width - * The target width, in pixels. - * @param int $height - * The target height, in pixels. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see image_load() - * @see image_resize() - * @see image_crop() - */ -function image_scale_and_crop($image, $width, $height) { - $scale = max($width / $image->info['width'], $height / $image->info['height']); - $x = ($image->info['width'] * $scale - $width) / 2; - $y = ($image->info['height'] * $scale - $height) / 2; - - if (image_resize($image, $image->info['width'] * $scale, $image->info['height'] * $scale)) { - return image_crop($image, $x, $y, $width, $height); - } - return FALSE; -} - -/** - * Scales image dimensions while maintaining aspect ratio. - * - * @deprecated as of Drupal 8.0. Use - * \Drupal\Component\Image\Image::scaleDimensions() directly instead. - * - * @see image_scale() - */ -function image_dimensions_scale(array &$dimensions, $width = NULL, $height = NULL, $upscale = FALSE) { - return Image::scaleDimensions($dimensions, $width, $height, $upscale); -} - -/** - * Scales an image while maintaining aspect ratio. - * - * The resulting image can be smaller for one or both target dimensions. - * - * @param object $image - * An image object returned by image_load(). - * @param int $width - * (optional) The target width, in pixels. This value is omitted then the - * scaling will based only on the height value. - * @param int $height - * (optional) The target height, in pixels. This value is omitted then the - * scaling will based only on the width value. - * @param bool $upscale - * (optional) Boolean indicating that files smaller than the dimensions will - * be scaled up. This generally results in a low quality image. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see image_dimensions_scale() - * @see image_load() - * @see image_scale_and_crop() - */ -function image_scale($image, $width = NULL, $height = NULL, $upscale = FALSE) { - $dimensions = $image->info; - - // Scale the dimensions - if they don't change then just return success. - if (!image_dimensions_scale($dimensions, $width, $height, $upscale)) { - return TRUE; - } - - return image_resize($image, $dimensions['width'], $dimensions['height']); -} - -/** - * Resizes an image to the given dimensions (ignoring aspect ratio). - * - * @param object $image - * An image object returned by image_load(). - * @param int $width - * The target width, in pixels. - * @param int $height - * The target height, in pixels. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see image_load() - * @see \Drupal\system\Plugin\ImageToolkitInterface::resize() - */ -function image_resize($image, $width, $height) { - $width = (int) round($width); - $height = (int) round($height); - - return $image->toolkit->resize($image, $width, $height); -} - -/** - * Rotates an image by the given number of degrees. - * - * @param $image - * An image object returned by image_load(). - * @param int $degrees - * The number of (clockwise) degrees to rotate the image. - * @param string $background - * (optional) An hexadecimal integer specifying the background color to use - * for the uncovered area of the image after the rotation. E.g. 0x000000 for - * black, 0xff00ff for magenta, and 0xffffff for white. For images that - * support transparency, this will default to transparent. Otherwise it will - * be white. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see image_load() - * @see \Drupal\system\Plugin\ImageToolkitInterface::rotate() - */ -function image_rotate($image, $degrees, $background = NULL) { - return $image->toolkit->rotate($image, $degrees, $background); -} - -/** - * Crops an image to a rectangle specified by the given dimensions. - * - * @param $image - * An image object returned by image_load(). - * @param int $x - * The top left coordinate, in pixels, of the crop area (x axis value). - * @param int $y - * The top left coordinate, in pixels, of the crop area (y axis value). - * @param int $width - * The target width, in pixels. - * @param int $height - * The target height, in pixels. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see image_load() - * @see image_scale_and_crop() - * @see \Drupal\system\Plugin\ImageToolkitInterface::crop() - */ -function image_crop($image, $x, $y, $width, $height) { - $aspect = $image->info['height'] / $image->info['width']; - if (empty($height)) $height = $width / $aspect; - if (empty($width)) $width = $height * $aspect; - - $width = (int) round($width); - $height = (int) round($height); - - return $image->toolkit->crop($image, $x, $y, $width, $height); -} - -/** - * Converts an image to grayscale. - * - * @param $image - * An image object returned by image_load(). - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see image_load() - * @see \Drupal\system\Plugin\ImageToolkitInterface::desaturate() - */ -function image_desaturate($image) { - return $image->toolkit->desaturate($image); -} - -/** - * Loads an image file and returns an image object. - * - * Any changes to the file are not saved until image_save() is called. - * - * @param string $file - * Path to an image file. - * @param \Drupal\system\Plugin\ImageToolkitInterface $toolkit - * (optional) Image toolkit object to override the default. - * - * @return object - * An image object or FALSE if there was a problem loading the file. The - * image object has the following properties: - * - 'source' - The original file path. - * - 'info' - The array of information returned by image_get_info() - * - 'toolkit' - The name of the image toolkit requested when the image was - * loaded. - * Image toolkits may add additional properties. The caller is advised not to - * monkey about with them. - * - * @see image_save() - * @see image_get_info() - */ -function image_load($file, ImageToolkitInterface $toolkit = NULL) { - if ($toolkit === NULL) { - $toolkit = Drupal::service('image.toolkit'); - } - if ($toolkit) { - $image = new stdClass(); - $image->source = $file; - $image->info = image_get_info($file, $toolkit); - if (isset($image->info) && is_array($image->info)) { - $image->toolkit = $toolkit; - if ($toolkit->load($image)) { - return $image; - } - } - } - return FALSE; -} - -/** - * Closes the image and saves the changes to a file. - * - * @param object $image - * An image object returned by image_load(). The object's 'info' property - * will be updated if the file is saved successfully. - * @param $destination - * (optional) Destination path where the image should be saved. If it is empty - * the original image file will be overwritten. - * - * @return bool - * TRUE on success, FALSE on failure. - * - * @see image_load() - * @see \Drupal\system\Plugin\ImageToolkitInterface::save() - */ -function image_save($image, $destination = NULL) { - if (empty($destination)) { - $destination = $image->source; - } - if ($return = $image->toolkit->save($image, $destination)) { - // Clear the cached file size and refresh the image information. - clearstatcache(TRUE, $destination); - $image->info = image_get_info($destination, $image->toolkit); - - if (drupal_chmod($destination)) { - return $return; - } - } - return FALSE; -} - -/** - * @} End of "defgroup image". - */ diff --git a/core/lib/Drupal/Core/Image/ImageFile.php b/core/lib/Drupal/Core/Image/ImageFile.php new file mode 100644 index 0000000..6ae5393 --- /dev/null +++ b/core/lib/Drupal/Core/Image/ImageFile.php @@ -0,0 +1,481 @@ +source = $source; + } + + /** + * Returns the extension of the image file. + * + * @return string + * The extension of the file, or an empty string if the file is invalid. + */ + public function getExtension() { + $this->processInfo(); + return $this->extension; + } + + /** + * Returns the height of the image file. + * + * @return int + * The height of the file, or 0 if the file is invalid. + */ + public function getHeight() { + $this->processInfo(); + return $this->height; + } + + /** + * Sets the height of the image file. + * + * @param int $height + * + * @return self + * Returns this image file. + */ + public function setHeight($height) { + $this->height = $height; + return $this; + } + + /** + * Returns the width of the image file. + * + * @return int + * The width of the file, or 0 if the file is invalid. + */ + public function getWidth() { + $this->processInfo(); + return $this->width; + } + + /** + * Sets the width of the image file. + * + * @param int $width + * + * @return self + * Returns this image file. + */ + public function setWidth($width) { + $this->width = $width; + return $this; + } + + /** + * Returns the size of the image file. + * + * @return int + * The size of the file in bytes, or 0 if the file is invalid. + */ + public function getFileSize() { + $this->processInfo(); + return $this->fileSize; + } + + /** + * Returns the MIME type of the image file. + * + * @return string + * The MIME type of the file, or an empty string if the file is invalid. + */ + public function getMimeType() { + $this->processInfo(); + return $this->mimeType; + } + + /** + * Sets the image file resource. + * + * @param resource $resource + * The image file handle. + * + * @return self + * Returns this image file. + */ + public function setResource($resource) { + $this->resource = $resource; + return $this; + } + + /** + * Determines if this image file has a resource set. + * + * @return bool + * TRUE if this image file has a resource set, FALSE otherwise. + */ + public function hasResource() { + return (bool) $this->resource; + } + + /** + * Retrieves the image file resource. + * + * @return resource + * The image file handle. + */ + public function getResource() { + if (!$this->hasResource()) { + $this->processInfo(); + $this->getToolkit()->load($this); + } + return $this->resource; + } + + /** + * Sets the source path of the image file. + * + * @param string $source + * A string specifying the path of the image file. + * + * @return self + * Returns this image file. + */ + public function setSource($source) { + $this->source = $source; + return $this; + } + + /** + * Retrieves the source path of the image file. + * + * @return string + * The source path of the image file. + */ + public function getSource() { + return $this->source; + } + + /** + * Sets a custom image toolkit. + * + * @param \Drupal\system\Plugin\ImageToolkitInterface $toolkit + * The image toolkit to use for this image file. + * + * @return self + * Returns this image file. + */ + public function setToolkit(ImageToolkitInterface $toolkit) { + $this->toolkit = $toolkit; + return $this; + } + + /** + * Returns the image toolkit being used for this image file. + * + * If a custom toolkit was not specified, this will fallback to the default. + * + * @return \Drupal\system\Plugin\ImageToolkitInterface + * The image toolkit used for this image file. + */ + protected function getToolkit() { + if (!$this->toolkit) { + $this->toolkit = \Drupal::service('image.toolkit'); + } + return $this->toolkit; + } + + /** + * Returns the ID of the image toolkit used for this image file. + * + * @return string + * The ID of the image toolkit. + */ + public function getToolkitId() { + return $this->getToolkit()->getPluginId(); + } + + /** + * Closes the image and saves the changes to a file. + * + * @param string|null $destination + * (optional) Destination path where the image should be saved. If it is empty + * the original image file will be overwritten. + * + * @return bool + * TRUE on success, FALSE on failure. + * + * @see \Drupal\system\Plugin\ImageToolkitInterface::save() + */ + public function save($destination = NULL) { + if (empty($destination)) { + $destination = $this->getSource(); + } + if ($return = $this->getToolkit()->save($this, $destination)) { + // Clear the cached file size and refresh the image information. + clearstatcache(TRUE, $destination); + $this->setSource($destination); + $this->processInfo(); + + if (drupal_chmod($destination)) { + return $return; + } + } + return FALSE; + } + + /** + * Prepares the image information. + * + * Drupal supports GIF, JPG and PNG file formats when used with the GD + * toolkit, and may support others, depending on which toolkits are + * installed. + * + * @return bool + * FALSE, if the file could not be found or is not an image. Otherwise, the + * image information is populated. + */ + protected function processInfo() { + if ($this->processed) { + return TRUE; + } + + $destination = $this->getSource(); + if (!is_file($destination) && !is_uploaded_file($destination)) { + return FALSE; + } + + if ($details = $this->getToolkit()->getInfo($this)) { + $this->height = $details['height']; + $this->width = $details['width']; + $this->extension = $details['extension']; + $this->mimeType = $details['mime_type']; + $this->fileSize = filesize($destination); + $this->processed = TRUE; + } + return TRUE; + } + + /** + * Scales an image while maintaining aspect ratio. + * + * The resulting image can be smaller for one or both target dimensions. + * + * @param int $width + * (optional) The target width, in pixels. This value is omitted then the + * scaling will based only on the height value. + * @param int $height + * (optional) The target height, in pixels. This value is omitted then the + * scaling will based only on the width value. + * @param bool $upscale + * (optional) Boolean indicating that files smaller than the dimensions will + * be scaled up. This generally results in a low quality image. + * + * @return bool + * TRUE on success, FALSE on failure. + */ + public function scale($width = NULL, $height = NULL, $upscale = FALSE) { + $dimensions = array( + 'width' => $this->getWidth(), + 'height' => $this->getHeight(), + ); + + // Scale the dimensions - if they don't change then just return success. + if (!Image::scaleDimensions($dimensions, $width, $height, $upscale)) { + return TRUE; + } + + return $this->resize($dimensions['width'], $dimensions['height']); + + } + + /** + * Scales an image to the exact width and height given. + * + * This function achieves the target aspect ratio by cropping the original image + * equally on both sides, or equally on the top and bottom. This function is + * useful to create uniform sized avatars from larger images. + * + * The resulting image always has the exact target dimensions. + * + * @param int $width + * The target width, in pixels. + * @param int $height + * The target height, in pixels. + * + * @return bool + * TRUE on success, FALSE on failure. + */ + public function scaleAndCrop($width, $height) { + $scale = max($width / $this->getWidth(), $height / $this->getHeight()); + $x = ($this->getWidth() * $scale - $width) / 2; + $y = ($this->getHeight() * $scale - $height) / 2; + + if ($this->resize($this->getWidth() * $scale, $this->getHeight() * $scale)) { + return $this->crop($x, $y, $width, $height); + } + return FALSE; + } + + /** + * Crops an image to a rectangle specified by the given dimensions. + * + * @param int $x + * The top left coordinate, in pixels, of the crop area (x axis value). + * @param int $y + * The top left coordinate, in pixels, of the crop area (y axis value). + * @param int $width + * The target width, in pixels. + * @param int $height + * The target height, in pixels. + * + * @return bool + * TRUE on success, FALSE on failure. + * + * @see \Drupal\system\Plugin\ImageToolkitInterface::crop() + */ + function crop($x, $y, $width, $height) { + $aspect = $this->getHeight() / $this->getWidth(); + if (empty($height)) $height = $width / $aspect; + if (empty($width)) $width = $height * $aspect; + + $width = (int) round($width); + $height = (int) round($height); + + return $this->getToolkit()->crop($this, $x, $y, $width, $height); + } + + /** + * Resizes an image to the given dimensions (ignoring aspect ratio). + * + * @param int $width + * The target width, in pixels. + * @param int $height + * The target height, in pixels. + * + * @return bool + * TRUE on success, FALSE on failure. + * + * @see \Drupal\system\Plugin\ImageToolkitInterface::resize() + */ + public function resize($width, $height) { + $width = (int) round($width); + $height = (int) round($height); + + return $this->getToolkit()->resize($this, $width, $height); + } + + /** + * Converts an image to grayscale. + * + * @return bool + * TRUE on success, FALSE on failure. + * + * @see \Drupal\system\Plugin\ImageToolkitInterface::desaturate() + */ + public function desaturate() { + return $this->getToolkit()->desaturate($this); + } + + /** + * Rotates an image by the given number of degrees. + * + * @param int $degrees + * The number of (clockwise) degrees to rotate the image. + * @param string $background + * (optional) An hexadecimal integer specifying the background color to use + * for the uncovered area of the image after the rotation. E.g. 0x000000 for + * black, 0xff00ff for magenta, and 0xffffff for white. For images that + * support transparency, this will default to transparent. Otherwise it will + * be white. + * + * @return bool + * TRUE on success, FALSE on failure. + * + * @see \Drupal\system\Plugin\ImageToolkitInterface::rotate() + */ + public function rotate($degrees, $background = NULL) { + return $this->getToolkit()->rotate($this, $degrees, $background); + } + +} diff --git a/core/modules/file/file.module b/core/modules/file/file.module index 70dfdb4..ae2f2f7 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -5,11 +5,11 @@ * Defines a "managed_file" Form API field and a "file" field for Field module. */ +use Drupal\Core\Image\ImageFile; use Drupal\file\Plugin\Core\Entity\File; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Template\Attribute; use Symfony\Component\HttpFoundation\JsonResponse; -use Drupal\file\FileUsage\DatabaseFileUsageBackend; use Drupal\file\FileUsage\FileUsageInterface; use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\ReplaceCommand; @@ -408,7 +408,7 @@ function file_validate_size(File $file, $file_limit = 0, $user_limit = 0) { } /** - * Checks that the file is recognized by image_get_info() as an image. + * Checks that the file is recognized by ImageFile::getInfo() as an image. * * @param Drupal\file\File $file * A file entity. @@ -421,8 +421,8 @@ function file_validate_size(File $file, $file_limit = 0, $user_limit = 0) { function file_validate_is_image(File $file) { $errors = array(); - $info = image_get_info($file->getFileUri()); - if (!$info || empty($info['extension'])) { + $image = new ImageFile($file->getFileUri()); + if (!$image->getExtension()) { $errors[] = t('Only JPEG, PNG and GIF images are allowed.'); } @@ -456,16 +456,18 @@ function file_validate_image_resolution(File $file, $maximum_dimensions = 0, $mi $errors = array(); // Check first that the file is an image. - if ($info = image_get_info($file->getFileUri())) { + $image = new ImageFile($file->getFileUri()); + if ($image->getExtension()) { if ($maximum_dimensions) { // Check that it is smaller than the given dimensions. list($width, $height) = explode('x', $maximum_dimensions); - if ($info['width'] > $width || $info['height'] > $height) { + if ($image->getWidth() > $width || $image->getHeight() > $height) { // Try to resize the image to fit the dimensions. - if ($image = image_load($file->getFileUri())) { - image_scale($image, $width, $height); - image_save($image); - $file->filesize = $image->info['file_size']; + $image = new ImageFile($file->getFileUri()); + if ($image->getResource()) { + $image->scale($width, $height); + $image->save(); + $file->filesize = $image->getFileSize(); drupal_set_message(t('The image was resized to fit within the maximum allowed dimensions of %dimensions pixels.', array('%dimensions' => $maximum_dimensions))); } else { @@ -477,7 +479,7 @@ function file_validate_image_resolution(File $file, $maximum_dimensions = 0, $mi if ($minimum_dimensions) { // Check that it is larger than the given dimensions. list($width, $height) = explode('x', $minimum_dimensions); - if ($info['width'] < $width || $info['height'] < $height) { + if ($image->getWidth() < $width || $image->getHeight() < $height) { $errors[] = t('The image is too small; the minimum dimensions are %dimensions pixels.', array('%dimensions' => $minimum_dimensions)); } } diff --git a/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php b/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php index 8012c4d..a4be16b 100644 --- a/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php +++ b/core/modules/file/lib/Drupal/file/Tests/ValidatorTest.php @@ -7,6 +7,8 @@ namespace Drupal\file\Tests; +use Drupal\Core\Image\ImageFile; + /** * This will run tests against the file validation functions (file_validate_*). */ @@ -87,9 +89,9 @@ function testFileValidateImageResolution() { $errors = file_validate_image_resolution($this->image, '10x5'); $this->assertEqual(count($errors), 0, 'No errors should be reported when an oversized image can be scaled down.', 'File'); - $info = image_get_info($this->image->getFileUri()); - $this->assertTrue($info['width'] <= 10, 'Image scaled to correct width.', 'File'); - $this->assertTrue($info['height'] <= 5, 'Image scaled to correct height.', 'File'); + $image = new ImageFile($this->image->getFileUri()); + $this->assertTrue($image->getWidth() <= 10, 'Image scaled to correct width.', 'File'); + $this->assertTrue($image->getHeight() <= 5, 'Image scaled to correct height.', 'File'); drupal_unlink('temporary://druplicon.png'); } diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc index 1e2646f..fa34ecd 100644 --- a/core/modules/image/image.admin.inc +++ b/core/modules/image/image.admin.inc @@ -6,9 +6,9 @@ */ use Drupal\Component\Utility\String; +use Drupal\Core\Image\ImageFile; use Drupal\image\ConfigurableImageEffectInterface; use Drupal\image\ImageStyleInterface; -use Symfony\Component\HttpFoundation\RedirectResponse; /** * Menu callback; Listing of all current image styles. @@ -380,7 +380,11 @@ function theme_image_style_preview($variables) { // Set up original file information. $original_path = $sample_image; - $original_image = image_get_info($original_path); + $original_image = new ImageFile($original_path); + $original_image = array( + 'width' => $original_image->getWidth(), + 'height' => $original_image->getHeight(), + ); if ($original_image['width'] > $original_image['height']) { $original_width = min($original_image['width'], $sample_width); $original_height = round($original_width / $original_image['width'] * $original_image['height']); @@ -389,15 +393,18 @@ function theme_image_style_preview($variables) { $original_height = min($original_image['height'], $sample_height); $original_width = round($original_height / $original_image['height'] * $original_image['width']); } - $original_attributes = array_intersect_key($original_image, array('width' => '', 'height' => '')); - $original_attributes['style'] = 'width: ' . $original_width . 'px; height: ' . $original_height . 'px;'; + $original_image['style'] = 'width: ' . $original_width . 'px; height: ' . $original_height . 'px;'; // Set up preview file information. $preview_file = $style->buildUri($original_path); if (!file_exists($preview_file)) { $style->createDerivative($original_path, $preview_file); } - $preview_image = image_get_info($preview_file); + $preview_image = new ImageFile($preview_file); + $preview_image = array( + 'width' => $preview_image->getWidth(), + 'height' => $preview_image->getHeight(), + ); if ($preview_image['width'] > $preview_image['height']) { $preview_width = min($preview_image['width'], $sample_width); $preview_height = round($preview_width / $preview_image['width'] * $preview_image['height']); @@ -406,8 +413,7 @@ function theme_image_style_preview($variables) { $preview_height = min($preview_image['height'], $sample_height); $preview_width = round($preview_height / $preview_image['height'] * $preview_image['width']); } - $preview_attributes = array_intersect_key($preview_image, array('width' => '', 'height' => '')); - $preview_attributes['style'] = 'width: ' . $preview_width . 'px; height: ' . $preview_height . 'px;'; + $preview_image['style'] = 'width: ' . $preview_width . 'px; height: ' . $preview_height . 'px;'; // In the previews, timestamps are added to prevent caching of images. $output = '
'; @@ -416,8 +422,8 @@ function theme_image_style_preview($variables) { $original_url = file_create_url($original_path); $output .= '
'; $output .= t('original') . ' (' . l(t('view actual size'), $original_url) . ')'; - $output .= '
'; - $output .= '' . theme('image', array('uri' => $original_path, 'alt' => t('Sample original image'), 'title' => '', 'attributes' => $original_attributes)) . ''; + $output .= '
'; + $output .= '' . theme('image', array('uri' => $original_path, 'alt' => t('Sample original image'), 'title' => '', 'attributes' => $original_image)) . ''; $output .= '
' . $original_image['height'] . 'px
'; $output .= '
' . $original_image['width'] . 'px
'; $output .= '
'; // End preview-image. @@ -427,8 +433,8 @@ function theme_image_style_preview($variables) { $preview_url = file_create_url($preview_file) . '?cache_bypass=' . REQUEST_TIME; $output .= '
'; $output .= check_plain($style->label()) . ' (' . l(t('view actual size'), file_create_url($preview_file) . '?' . time()) . ')'; - $output .= '
'; - $output .= '' . theme('image', array('uri' => $preview_url, 'alt' => t('Sample modified image'), 'title' => '', 'attributes' => $preview_attributes)) . ''; + $output .= '
'; + $output .= '' . theme('image', array('uri' => $preview_url, 'alt' => t('Sample modified image'), 'title' => '', 'attributes' => $preview_image)) . ''; $output .= '
' . $preview_image['height'] . 'px
'; $output .= '
' . $preview_image['width'] . 'px
'; $output .= '
'; // End preview-image. diff --git a/core/modules/image/image.field.inc b/core/modules/image/image.field.inc index 824f14c..b1c5331 100644 --- a/core/modules/image/image.field.inc +++ b/core/modules/image/image.field.inc @@ -7,6 +7,7 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Image\ImageFile; /** * Implements hook_field_info(). @@ -226,15 +227,13 @@ function _image_field_resolution_validate($element, &$form_state) { * Implements hook_field_presave(). */ function image_field_presave(EntityInterface $entity, $field, $instance, $langcode, &$items) { - // Determine the dimensions if necessary. foreach ($items as &$item) { if (!isset($item['width']) || !isset($item['height'])) { - $info = image_get_info(file_load($item['target_id'])->getFileUri()); - - if (is_array($info)) { - $item['width'] = $info['width']; - $item['height'] = $info['height']; + $image = new ImageFile(file_load($item['target_id'])->getFileUri()); + if ($image->getExtension()) { + $item['width'] = $image->getWidth(); + $item['height'] = $image->getHeight(); } } } @@ -301,11 +300,10 @@ function image_field_widget_process($element, &$form_state, $form) { $variables['height'] = $element['#value']['height']; } else { - $info = image_get_info($file->getFileUri()); - - if (is_array($info)) { - $variables['width'] = $info['width']; - $variables['height'] = $info['height']; + $image = new ImageFile($file->getFileUri()); + if ($image->getExtension()) { + $variables['width'] = $image->getWidth(); + $variables['height'] = $image->getHeight(); } else { $variables['width'] = $variables['height'] = NULL; diff --git a/core/modules/image/image.install b/core/modules/image/image.install index 1617e8c..58cf110 100644 --- a/core/modules/image/image.install +++ b/core/modules/image/image.install @@ -6,7 +6,6 @@ */ use Drupal\Component\Uuid\Uuid; -use Drupal\field\Plugin\Core\Entity\Field; /** * Implements hook_install(). diff --git a/core/modules/image/image.module b/core/modules/image/image.module index fefbf00..9c75bd4 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -6,6 +6,7 @@ */ use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Image\ImageFile; use Drupal\field\Plugin\Core\Entity\Field; use Drupal\field\Plugin\Core\Entity\FieldInstance; use Drupal\file\Plugin\Core\Entity\File; @@ -276,15 +277,16 @@ function image_file_download($uri) { $original_uri = file_uri_scheme($uri) . '://' . implode('/', $args); // Check that the file exists and is an image. - if ($info = image_get_info($uri)) { + $image = new ImageFile($uri); + if ($image->getExtension()) { // Check the permissions of the original to grant access to this image. $headers = module_invoke_all('file_download', $original_uri); // Confirm there's at least one module granting access and none denying access. if (!empty($headers) && !in_array(-1, $headers)) { return array( // Send headers describing the image's size, and MIME-type... - 'Content-Type' => $info['mime_type'], - 'Content-Length' => $info['file_size'], + 'Content-Type' => $image->getMimeType(), + 'Content-Length' => $image->getFileSize(), // By not explicitly setting them here, this uses normal Drupal // Expires, Cache-Control and ETag headers to prevent proxy or // browser caching of private images. diff --git a/core/modules/image/lib/Drupal/image/Controller/ImageStyleDownloadController.php b/core/modules/image/lib/Drupal/image/Controller/ImageStyleDownloadController.php index 34146c2..d06bffa 100644 --- a/core/modules/image/lib/Drupal/image/Controller/ImageStyleDownloadController.php +++ b/core/modules/image/lib/Drupal/image/Controller/ImageStyleDownloadController.php @@ -11,6 +11,7 @@ use Drupal\Core\Config\ConfigFactory; use Drupal\Core\Controller\ControllerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Image\ImageFile; use Drupal\Core\Lock\LockBackendInterface; use Drupal\Core\StringTranslation\Translator\TranslatorInterface; use Drupal\image\ImageStyleInterface; @@ -159,11 +160,11 @@ public function deliver(Request $request, $scheme, ImageStyleInterface $image_st } if ($success) { - $image = image_load($derivative_uri); - $uri = $image->source; + $image = new ImageFile($derivative_uri); + $uri = $image->getSource(); $headers += array( - 'Content-Type' => $image->info['mime_type'], - 'Content-Length' => $image->info['file_size'], + 'Content-Type' => $image->getMimeType(), + 'Content-Length' => $image->getFileSize(), ); return new BinaryFileResponse($uri, 200, $headers); } diff --git a/core/modules/image/lib/Drupal/image/ImageEffectInterface.php b/core/modules/image/lib/Drupal/image/ImageEffectInterface.php index 05d5efd..2d4a5af 100644 --- a/core/modules/image/lib/Drupal/image/ImageEffectInterface.php +++ b/core/modules/image/lib/Drupal/image/ImageEffectInterface.php @@ -8,6 +8,7 @@ namespace Drupal\image; use Drupal\Component\Plugin\PluginInspectionInterface; +use Drupal\Core\Image\ImageFile; /** * Defines the interface for image effects. @@ -17,13 +18,13 @@ /** * Applies an image effect to the image object. * - * @param \stdClass $image - * An image object returned by image_load(). + * @param \Drupal\Core\Image\ImageFile $image + * An image file object. * * @return bool * TRUE on success. FALSE if unable to perform the image effect on the image. */ - public function applyEffect($image); + public function applyEffect(ImageFile $image); /** * Determines the dimensions of the styled image. diff --git a/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php b/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php index ed17dee..a07f060 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php +++ b/core/modules/image/lib/Drupal/image/Plugin/Core/Entity/ImageStyle.php @@ -11,6 +11,7 @@ use Drupal\Core\Entity\Annotation\EntityType; use Drupal\Core\Annotation\Translation; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Image\ImageFile; use Drupal\image\ImageEffectBag; use Drupal\image\ImageEffectInterface; use Drupal\image\ImageStyleInterface; @@ -277,7 +278,8 @@ public function createDerivative($original_uri, $derivative_uri) { return FALSE; } - if (!$image = image_load($original_uri)) { + $image = new ImageFile($original_uri); + if (!$image->getResource()) { return FALSE; } @@ -285,7 +287,7 @@ public function createDerivative($original_uri, $derivative_uri) { $effect->applyEffect($image); } - if (!image_save($image, $derivative_uri)) { + if (!$image->save($derivative_uri)) { if (file_exists($derivative_uri)) { watchdog('image', 'Cached image file %destination already exists. There may be an issue with your rewrite configuration.', array('%destination' => $derivative_uri), WATCHDOG_ERROR); } diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php index 11f228e..35f4afa 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/CropImageEffect.php @@ -8,6 +8,7 @@ namespace Drupal\image\Plugin\ImageEffect; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Image\ImageFile; use Drupal\image\Annotation\ImageEffect; /** @@ -24,17 +25,17 @@ class CropImageEffect extends ResizeImageEffect { /** * {@inheritdoc} */ - public function applyEffect($image) { + public function applyEffect(ImageFile $image) { // Set sane default values. $this->configuration += array( 'anchor' => 'center-center', ); list($x, $y) = explode('-', $this->configuration['anchor']); - $x = image_filter_keyword($x, $image->info['width'], $this->configuration['width']); - $y = image_filter_keyword($y, $image->info['height'], $this->configuration['height']); - if (!image_crop($image, $x, $y, $this->configuration['width'], $this->configuration['height'])) { - watchdog('image', 'Image crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); + $x = image_filter_keyword($x, $image->getWidth(), $this->configuration['width']); + $y = image_filter_keyword($y, $image->getHeight(), $this->configuration['height']); + if (!$image->crop($x, $y, $this->configuration['width'], $this->configuration['height'])) { + watchdog('image', 'Image crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()), WATCHDOG_ERROR); return FALSE; } return TRUE; diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php index 816ed3e..c75606a 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/DesaturateImageEffect.php @@ -8,6 +8,7 @@ namespace Drupal\image\Plugin\ImageEffect; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Image\ImageFile; use Drupal\image\Annotation\ImageEffect; use Drupal\image\ImageEffectBase; @@ -31,9 +32,9 @@ public function transformDimensions(array &$dimensions) { /** * {@inheritdoc} */ - public function applyEffect($image) { - if (!image_desaturate($image)) { - watchdog('image', 'Image desaturate failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); + public function applyEffect(ImageFile $image) { + if (!$image->desaturate()) { + watchdog('image', 'Image desaturate failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()), WATCHDOG_ERROR); return FALSE; } return TRUE; diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php index 484e6a0..7e92a28 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ResizeImageEffect.php @@ -8,6 +8,7 @@ namespace Drupal\image\Plugin\ImageEffect; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Image\ImageFile; use Drupal\image\Annotation\ImageEffect; use Drupal\image\ConfigurableImageEffectInterface; use Drupal\image\ImageEffectBase; @@ -26,9 +27,9 @@ class ResizeImageEffect extends ImageEffectBase implements ConfigurableImageEffe /** * {@inheritdoc} */ - public function applyEffect($image) { - if (!image_resize($image, $this->configuration['width'], $this->configuration['height'])) { - watchdog('image', 'Image resize failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); + public function applyEffect(ImageFile $image) { + if (!$image->resize($this->configuration['width'], $this->configuration['height'])) { + watchdog('image', 'Image resize failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()), WATCHDOG_ERROR); return FALSE; } return TRUE; diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php index dee537e..8169ed9 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/RotateImageEffect.php @@ -8,6 +8,7 @@ namespace Drupal\image\Plugin\ImageEffect; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Image\ImageFile; use Drupal\image\Annotation\ImageEffect; use Drupal\image\ConfigurableImageEffectInterface; use Drupal\image\ImageEffectBase; @@ -26,7 +27,7 @@ class RotateImageEffect extends ImageEffectBase implements ConfigurableImageEffe /** * {@inheritdoc} */ - public function applyEffect($image) { + public function applyEffect(ImageFile $image) { // Set sane default values. $this->configuration += array( 'degrees' => 0, @@ -53,8 +54,8 @@ public function applyEffect($image) { $this->configuration['degrees'] = rand(-1 * $degrees, $degrees); } - if (!image_rotate($image, $this->configuration['degrees'], $this->configuration['bgcolor'])) { - watchdog('image', 'Image rotate failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); + if (!$image->rotate($this->configuration['degrees'], $this->configuration['bgcolor'])) { + watchdog('image', 'Image rotate failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()), WATCHDOG_ERROR); return FALSE; } return TRUE; diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleAndCropImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleAndCropImageEffect.php index dfa5955..8dab4b8 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleAndCropImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleAndCropImageEffect.php @@ -8,6 +8,7 @@ namespace Drupal\image\Plugin\ImageEffect; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Image\ImageFile; use Drupal\image\Annotation\ImageEffect; /** @@ -24,9 +25,9 @@ class ScaleAndCropImageEffect extends ResizeImageEffect { /** * {@inheritdoc} */ - public function applyEffect($image) { - if (!image_scale_and_crop($image, $this->configuration['width'], $this->configuration['height'])) { - watchdog('image', 'Image scale and crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); + public function applyEffect(ImageFile $image) { + if (!$image->scaleAndCrop($this->configuration['width'], $this->configuration['height'])) { + watchdog('image', 'Image scale and crop failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()), WATCHDOG_ERROR); return FALSE; } return TRUE; diff --git a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php index 47ada5a..452df8d 100644 --- a/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php +++ b/core/modules/image/lib/Drupal/image/Plugin/ImageEffect/ScaleImageEffect.php @@ -9,6 +9,7 @@ use Drupal\Component\Image\Image; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Image\ImageFile; use Drupal\image\Annotation\ImageEffect; /** @@ -25,7 +26,7 @@ class ScaleImageEffect extends ResizeImageEffect { /** * {@inheritdoc} */ - public function applyEffect($image) { + public function applyEffect(ImageFile $image) { // Set sane default values. $this->configuration += array( 'width' => NULL, @@ -33,8 +34,8 @@ public function applyEffect($image) { 'upscale' => FALSE, ); - if (!image_scale($image, $this->configuration['width'], $this->configuration['height'], $this->configuration['upscale'])) { - watchdog('image', 'Image scale failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->toolkit->getPluginId(), '%path' => $image->source, '%mimetype' => $image->info['mime_type'], '%dimensions' => $image->info['width'] . 'x' . $image->info['height']), WATCHDOG_ERROR); + if (!$image->scale($this->configuration['width'], $this->configuration['height'], $this->configuration['upscale'])) { + watchdog('image', 'Image scale failed using the %toolkit toolkit on %path (%mimetype, %dimensions)', array('%toolkit' => $image->getToolkitId(), '%path' => $image->getSource(), '%mimetype' => $image->getMimeType(), '%dimensions' => $image->getWidth() . 'x' . $image->getHeight()), WATCHDOG_ERROR); return FALSE; } return TRUE; diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php index 0ff6738..d661552 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php @@ -7,6 +7,7 @@ namespace Drupal\image\Tests; +use Drupal\Core\Image\ImageFile; use Drupal\simpletest\WebTestBase; /** @@ -53,9 +54,9 @@ function testImageDimensions() { 'height' => 20, ); // Verify that the original image matches the hard-coded values. - $image_info = image_get_info($original_uri); - $this->assertEqual($image_info['width'], $variables['width']); - $this->assertEqual($image_info['height'], $variables['height']); + $image_file = new ImageFile($original_uri); + $this->assertEqual($image_file->getWidth(), $variables['width']); + $this->assertEqual($image_file->getHeight(), $variables['height']); // Scale an image that is wider than it is high. $effect = array( @@ -75,9 +76,9 @@ function testImageDimensions() { $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_info = image_get_info($generated_uri); - $this->assertEqual($image_info['width'], 120); - $this->assertEqual($image_info['height'], 60); + $image_file = new ImageFile($generated_uri); + $this->assertEqual($image_file->getWidth(), 120); + $this->assertEqual($image_file->getHeight(), 60); // Rotate 90 degrees anticlockwise. $effect = array( @@ -96,9 +97,9 @@ function testImageDimensions() { $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_info = image_get_info($generated_uri); - $this->assertEqual($image_info['width'], 60); - $this->assertEqual($image_info['height'], 120); + $image_file = new ImageFile($generated_uri); + $this->assertEqual($image_file->getWidth(), 60); + $this->assertEqual($image_file->getHeight(), 120); // Scale an image that is higher than it is wide (rotated by previous effect). $effect = array( @@ -118,9 +119,9 @@ function testImageDimensions() { $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_info = image_get_info($generated_uri); - $this->assertEqual($image_info['width'], 45); - $this->assertEqual($image_info['height'], 90); + $image_file = new ImageFile($generated_uri); + $this->assertEqual($image_file->getWidth(), 45); + $this->assertEqual($image_file->getHeight(), 90); // Test upscale disabled. $effect = array( @@ -140,9 +141,9 @@ function testImageDimensions() { $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_info = image_get_info($generated_uri); - $this->assertEqual($image_info['width'], 45); - $this->assertEqual($image_info['height'], 90); + $image_file = new ImageFile($generated_uri); + $this->assertEqual($image_file->getWidth(), 45); + $this->assertEqual($image_file->getHeight(), 90); // Add a desaturate effect. $effect = array( @@ -158,9 +159,9 @@ function testImageDimensions() { $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_info = image_get_info($generated_uri); - $this->assertEqual($image_info['width'], 45); - $this->assertEqual($image_info['height'], 90); + $image_file = new ImageFile($generated_uri); + $this->assertEqual($image_file->getWidth(), 45); + $this->assertEqual($image_file->getHeight(), 90); // Add a random rotate effect. $effect = array( @@ -199,9 +200,9 @@ function testImageDimensions() { $this->drupalGet($url); $this->assertResponse(200, 'Image was generated at the URL.'); $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); - $image_info = image_get_info($generated_uri); - $this->assertEqual($image_info['width'], 30); - $this->assertEqual($image_info['height'], 30); + $image_file = new ImageFile($generated_uri); + $this->assertEqual($image_file->getWidth(), 30); + $this->assertEqual($image_file->getHeight(), 30); // Rotate to a non-multiple of 90 degrees. $effect = array( diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldValidateTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldValidateTest.php index 1cd0ce9..c3f14f9 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldValidateTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldValidateTest.php @@ -7,6 +7,8 @@ namespace Drupal\image\Tests; +use Drupal\Core\Image\ImageFile; + /** * Test class to check for various validations. */ @@ -37,11 +39,11 @@ function testResolution() { $image_that_is_too_big = FALSE; $image_that_is_too_small = FALSE; foreach ($this->drupalGetTestFiles('image') as $image) { - $info = image_get_info($image->uri); - if ($info['width'] > $max_resolution) { + $image_file = new ImageFile($image->uri); + if ($image_file->getWidth() > $max_resolution) { $image_that_is_too_big = $image; } - if ($info['width'] < $min_resolution) { + if ($image_file->getWidth() < $min_resolution) { $image_that_is_too_small = $image; } if ($image_that_is_too_small && $image_that_is_too_big) { diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageItemTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageItemTest.php index 5e7472f..9574a28 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageItemTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageItemTest.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\Field\FieldInterface; use Drupal\Core\Entity\Field\FieldItemInterface; +use Drupal\Core\Image\ImageFile; use Drupal\field\Tests\FieldUnitTestBase; /** @@ -78,9 +79,9 @@ public function testImageItem() { $this->assertEqual($entity->image_test->target_id, $this->image->id()); $this->assertEqual($entity->image_test->alt, $alt); $this->assertEqual($entity->image_test->title, $title); - $info = image_get_info('public://example.jpg'); - $this->assertEqual($entity->image_test->width, $info['width']); - $this->assertEqual($entity->image_test->height, $info['height']); + $image = new ImageFile('public://example.jpg'); + $this->assertEqual($entity->image_test->width, $image->getWidth()); + $this->assertEqual($entity->image_test->height, $image->getHeight()); $this->assertEqual($entity->image_test->entity->id(), $this->image->id()); $this->assertEqual($entity->image_test->entity->uuid(), $this->image->uuid()); @@ -98,9 +99,9 @@ public function testImageItem() { $entity->save(); $this->assertEqual($entity->image_test->entity->id(), $image2->id()); $this->assertEqual($entity->image_test->entity->getFileUri(), $image2->getFileUri()); - $info = image_get_info('public://example-2.jpg'); - $this->assertEqual($entity->image_test->width, $info['width']); - $this->assertEqual($entity->image_test->height, $info['height']); + $image = new ImageFile('public://example-2.jpg'); + $this->assertEqual($entity->image_test->width, $image->getWidth()); + $this->assertEqual($entity->image_test->height, $image->getHeight()); $this->assertEqual($entity->image_test->alt, $new_alt); // Check that the image item can be set to the referenced file directly. diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageStylesPathAndUrlTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageStylesPathAndUrlTest.php index cae45d7..11c6cbf 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageStylesPathAndUrlTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageStylesPathAndUrlTest.php @@ -7,6 +7,7 @@ namespace Drupal\image\Tests; +use Drupal\Core\Image\ImageFile; use Drupal\simpletest\WebTestBase; use Symfony\Component\HttpFoundation\Request; @@ -153,9 +154,9 @@ function doImageStyleUrlAndPathTests($scheme, $clean_url = TRUE, $extra_slash = $this->assertResponse(200, 'Image was generated at the URL.'); $this->assertTrue(file_exists($generated_uri), 'Generated file does exist after we accessed it.'); $this->assertRaw(file_get_contents($generated_uri), 'URL returns expected file.'); - $generated_image_info = image_get_info($generated_uri); - $this->assertEqual($this->drupalGetHeader('Content-Type'), $generated_image_info['mime_type'], 'Expected Content-Type was reported.'); - $this->assertEqual($this->drupalGetHeader('Content-Length'), $generated_image_info['file_size'], 'Expected Content-Length was reported.'); + $image = new ImageFile($generated_uri); + $this->assertEqual($this->drupalGetHeader('Content-Type'), $image->getMimeType(), 'Expected Content-Type was reported.'); + $this->assertEqual($this->drupalGetHeader('Content-Length'), $image->getFileSize(), 'Expected Content-Length was reported.'); if ($scheme == 'private') { $this->assertEqual($this->drupalGetHeader('Expires'), 'Sun, 19 Nov 1978 05:00:00 GMT', 'Expires header was sent.'); $this->assertNotEqual(strpos($this->drupalGetHeader('Cache-Control'), 'no-cache'), FALSE, 'Cache-Control header contains \'no-cache\' to prevent caching.'); diff --git a/core/modules/image/tests/modules/image_module_test/lib/Drupal/image_module_test/Plugin/ImageEffect/NullTestImageEffect.php b/core/modules/image/tests/modules/image_module_test/lib/Drupal/image_module_test/Plugin/ImageEffect/NullTestImageEffect.php index 23b1931..f847361 100644 --- a/core/modules/image/tests/modules/image_module_test/lib/Drupal/image_module_test/Plugin/ImageEffect/NullTestImageEffect.php +++ b/core/modules/image/tests/modules/image_module_test/lib/Drupal/image_module_test/Plugin/ImageEffect/NullTestImageEffect.php @@ -8,6 +8,7 @@ namespace Drupal\image_module_test\Plugin\ImageEffect; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Image\ImageFile; use Drupal\image\Annotation\ImageEffect; use Drupal\image\ImageEffectBase; @@ -24,7 +25,7 @@ class NullTestImageEffect extends ImageEffectBase { /** * {@inheritdoc} */ - public function applyEffect($image) { + public function applyEffect(ImageFile $image) { return TRUE; } diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/GDToolkit.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/GDToolkit.php index 06cb4a6..e6f197d 100644 --- a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/GDToolkit.php +++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkit/GDToolkit.php @@ -10,6 +10,7 @@ use Drupal\Component\Plugin\PluginBase; use Drupal\Component\Annotation\Plugin; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Image\ImageFile; use Drupal\system\Plugin\ImageToolkitInterface; /** @@ -50,33 +51,34 @@ public function settingsFormSubmit($form, &$form_state) { /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::resize(). */ - public function resize($image, $width, $height) { + public function resize(ImageFile $image, $width, $height) { $res = $this->createTmp($image, $width, $height); - if (!imagecopyresampled($res, $image->resource, 0, 0, 0, 0, $width, $height, $image->info['width'], $image->info['height'])) { + if (!imagecopyresampled($res, $image->getResource(), 0, 0, 0, 0, $width, $height, $image->getWidth(), $image->getHeight())) { return FALSE; } - imagedestroy($image->resource); + imagedestroy($image->getResource()); // Update image object. - $image->resource = $res; - $image->info['width'] = $width; - $image->info['height'] = $height; + $image + ->setResource($res) + ->setWidth($width) + ->setHeight($height); return TRUE; } /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::rotate(). */ - public function rotate($image, $degrees, $background = NULL) { + public function rotate(ImageFile $image, $degrees, $background = NULL) { // PHP installations using non-bundled GD do not have imagerotate. if (!function_exists('imagerotate')) { - watchdog('image', 'The image %file could not be rotated because the imagerotate() function is not available in this PHP installation.', array('%file' => $image->source)); + watchdog('image', 'The image %file could not be rotated because the imagerotate() function is not available in this PHP installation.', array('%file' => $image->getSource())); return FALSE; } - $width = $image->info['width']; - $height = $image->info['height']; + $width = $image->getWidth(); + $height = $image->getHeight(); // Convert the hexadecimal background value to a color index value. if (isset($background)) { @@ -84,88 +86,91 @@ public function rotate($image, $degrees, $background = NULL) { for ($i = 16; $i >= 0; $i -= 8) { $rgb[] = (($background >> $i) & 0xFF); } - $background = imagecolorallocatealpha($image->resource, $rgb[0], $rgb[1], $rgb[2], 0); + $background = imagecolorallocatealpha($image->getResource(), $rgb[0], $rgb[1], $rgb[2], 0); } // Set the background color as transparent if $background is NULL. else { // Get the current transparent color. - $background = imagecolortransparent($image->resource); + $background = imagecolortransparent($image->getResource()); // If no transparent colors, use white. if ($background == 0) { - $background = imagecolorallocatealpha($image->resource, 255, 255, 255, 0); + $background = imagecolorallocatealpha($image->getResource(), 255, 255, 255, 0); } } // Images are assigned a new color palette when rotating, removing any // transparency flags. For GIF images, keep a record of the transparent color. - if ($image->info['extension'] == 'gif') { - $transparent_index = imagecolortransparent($image->resource); + if ($image->getExtension() == 'gif') { + $transparent_index = imagecolortransparent($image->getResource()); if ($transparent_index != 0) { - $transparent_gif_color = imagecolorsforindex($image->resource, $transparent_index); + $transparent_gif_color = imagecolorsforindex($image->getResource(), $transparent_index); } } - $image->resource = imagerotate($image->resource, 360 - $degrees, $background); + $image->setResource(imagerotate($image->getResource(), 360 - $degrees, $background)); // GIFs need to reassign the transparent color after performing the rotate. if (isset($transparent_gif_color)) { - $background = imagecolorexactalpha($image->resource, $transparent_gif_color['red'], $transparent_gif_color['green'], $transparent_gif_color['blue'], $transparent_gif_color['alpha']); - imagecolortransparent($image->resource, $background); + $background = imagecolorexactalpha($image->getResource(), $transparent_gif_color['red'], $transparent_gif_color['green'], $transparent_gif_color['blue'], $transparent_gif_color['alpha']); + imagecolortransparent($image->getResource(), $background); } - $image->info['width'] = imagesx($image->resource); - $image->info['height'] = imagesy($image->resource); + $image + ->setWidth(imagesx($image->getResource())) + ->setHeight(imagesy($image->getResource())); return TRUE; } /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::crop(). */ - public function crop($image, $x, $y, $width, $height) { + public function crop(ImageFile $image, $x, $y, $width, $height) { $res = $this->createTmp($image, $width, $height); - if (!imagecopyresampled($res, $image->resource, 0, 0, $x, $y, $width, $height, $width, $height)) { + if (!imagecopyresampled($res, $image->getResource(), 0, 0, $x, $y, $width, $height, $width, $height)) { return FALSE; } // Destroy the original image and return the modified image. - imagedestroy($image->resource); - $image->resource = $res; - $image->info['width'] = $width; - $image->info['height'] = $height; + imagedestroy($image->getResource()); + $image + ->setResource($res) + ->setWidth($width) + ->setHeight($height); return TRUE; } /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::desaturate(). */ - public function desaturate($image) { + public function desaturate(ImageFile $image) { // PHP installations using non-bundled GD do not have imagefilter. if (!function_exists('imagefilter')) { - watchdog('image', 'The image %file could not be desaturated because the imagefilter() function is not available in this PHP installation.', array('%file' => $image->source)); + watchdog('image', 'The image %file could not be desaturated because the imagefilter() function is not available in this PHP installation.', array('%file' => $image->getSource())); return FALSE; } - return imagefilter($image->resource, IMG_FILTER_GRAYSCALE); + return imagefilter($image->getResource(), IMG_FILTER_GRAYSCALE); } /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::load(). */ - public function load($image) { - $extension = str_replace('jpg', 'jpeg', $image->info['extension']); + public function load(ImageFile $image) { + $extension = str_replace('jpg', 'jpeg', $image->getExtension()); $function = 'imagecreatefrom' . $extension; - if (function_exists($function) && $image->resource = $function($image->source)) { - if (!imageistruecolor($image->resource)) { + if (function_exists($function) && $resource = $function($image->getSource())) { + $image->setResource($resource); + if (!imageistruecolor($resource)) { // Convert indexed images to true color, so that filters work // correctly and don't result in unnecessary dither. - $new_image = $this->createTmp($image, $image->info['width'], $image->info['height']); - imagecopy($new_image, $image->resource, 0, 0, 0, 0, $image->info['width'], $image->info['height']); - imagedestroy($image->resource); - $image->resource = $new_image; + $new_image = $this->createTmp($image, $image->getWidth(), $image->getHeight()); + imagecopy($new_image, $resource, 0, 0, 0, 0, $image->getWidth(), $image->getHeight()); + imagedestroy($resource); + $image->setResource($new_image); } - return (bool) $image->resource; + return (bool) $image->getResource(); } return FALSE; @@ -174,7 +179,7 @@ public function load($image) { /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::save(). */ - public function save($image, $destination) { + public function save(ImageFile $image, $destination) { $scheme = file_uri_scheme($destination); // Work around lack of stream wrapper support in imagejpeg() and imagepng(). if ($scheme && file_stream_wrapper_valid_scheme($scheme)) { @@ -188,21 +193,21 @@ public function save($image, $destination) { $destination = drupal_realpath($destination); } - $extension = str_replace('jpg', 'jpeg', $image->info['extension']); + $extension = str_replace('jpg', 'jpeg', $image->getExtension()); $function = 'image' . $extension; if (!function_exists($function)) { return FALSE; } if ($extension == 'jpeg') { - $success = $function($image->resource, $destination, config('system.image.gd')->get('jpeg_quality')); + $success = $function($image->getResource(), $destination, config('system.image.gd')->get('jpeg_quality')); } else { // Always save PNG images with full transparency. if ($extension == 'png') { - imagealphablending($image->resource, FALSE); - imagesavealpha($image->resource, TRUE); + imagealphablending($image->getResource(), FALSE); + imagesavealpha($image->getResource(), TRUE); } - $success = $function($image->resource, $destination); + $success = $function($image->getResource(), $destination); } // Move temporary local file to remote destination. if (isset($permanent_destination) && $success) { @@ -214,9 +219,9 @@ public function save($image, $destination) { /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::getInfo(). */ - public function getInfo($image) { + public function getInfo(ImageFile $image) { $details = FALSE; - $data = getimagesize($image->source); + $data = getimagesize($image->getSource()); if (isset($data) && is_array($data)) { $extensions = array('1' => 'gif', '2' => 'jpg', '3' => 'png'); @@ -235,7 +240,7 @@ public function getInfo($image) { /** * Creates a truecolor image preserving transparency from a provided image. * - * @param object $image + * @param \Drupal\Core\Image\ImageFile $image * An image object. * @param int $width * The new width of the new image, in pixels. @@ -245,16 +250,16 @@ public function getInfo($image) { * @return resource * A GD image handle. */ - public function createTmp($image, $width, $height) { + public function createTmp(ImageFile $image, $width, $height) { $res = imagecreatetruecolor($width, $height); - if ($image->info['extension'] == 'gif') { + if ($image->getExtension() == 'gif') { // Grab transparent color index from image resource. - $transparent = imagecolortransparent($image->resource); + $transparent = imagecolortransparent($image->getResource()); if ($transparent >= 0) { // The original must have a transparent color, allocate to the new image. - $transparent_color = imagecolorsforindex($image->resource, $transparent); + $transparent_color = imagecolorsforindex($image->getResource(), $transparent); $transparent = imagecolorallocate($res, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']); // Flood with our new transparent color. @@ -262,7 +267,7 @@ public function createTmp($image, $width, $height) { imagecolortransparent($res, $transparent); } } - elseif ($image->info['extension'] == 'png') { + elseif ($image->getExtension() == 'png') { imagealphablending($res, FALSE); $transparency = imagecolorallocatealpha($res, 0, 0, 0, 127); imagefill($res, 0, 0, $transparency); diff --git a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkitInterface.php b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkitInterface.php index 0b22f3c..f0a497b 100644 --- a/core/modules/system/lib/Drupal/system/Plugin/ImageToolkitInterface.php +++ b/core/modules/system/lib/Drupal/system/Plugin/ImageToolkitInterface.php @@ -7,13 +7,43 @@ namespace Drupal\system\Plugin; +use Drupal\Component\Plugin\PluginInspectionInterface; +use Drupal\Core\Image\ImageFile; + +/** + * @defgroup image Image toolkits + * @{ + * Functions for image file manipulations. + * + * Drupal's image toolkits provide an abstraction layer for common image file + * manipulations like scaling, cropping, and rotating. The abstraction frees + * module authors from the need to support multiple image libraries, and it + * allows site administrators to choose the library that's best for them. + * + * PHP includes the GD library by default so a GD toolkit is installed with + * Drupal. Other toolkits like ImageMagick are available from contrib modules. + * GD works well for small images, but using it with larger files may cause PHP + * to run out of memory. In contrast the ImageMagick library does not suffer + * from this problem, but it requires the ISP to have installed additional + * software. + * + * Image toolkits are discovered using the Plugin system using + * \Drupal\system\Plugin\ImageToolkitManager. The toolkit must then be enabled + * using the admin/config/media/image-toolkit form. + * + * Only one toolkit may be selected at a time. If a module author wishes to call + * a specific toolkit they can check that it is installed by calling + * \Drupal\system\Plugin\ImageToolkitManager::getAvailableToolkits(), and then + * calling its functions directly. + */ + /** * Defines an interface for image toolkits. * * An image toolkit provides common image file manipulations like scaling, * cropping, and rotating. */ -interface ImageToolkitInterface { +interface ImageToolkitInterface extends PluginInspectionInterface { /** * Retrieves toolkit's settings form. @@ -32,7 +62,7 @@ function settingsFormSubmit($form, &$form_state); /** * Scales an image to the specified size. * - * @param object $image + * @param \Drupal\Core\Image\ImageFile $image * An image object. The $image->resource, $image->info['width'], and * $image->info['height'] values will be modified by this call. * @param int $width @@ -42,15 +72,13 @@ function settingsFormSubmit($form, &$form_state); * * @return bool * TRUE or FALSE, based on success. - * - * @see image_resize() */ - function resize($image, $width, $height); + function resize(ImageFile $image, $width, $height); /** * Rotates an image the given number of degrees. * - * @param object $image + * @param \Drupal\Core\Image\ImageFile $image * An image object. The $image->resource, $image->info['width'], and * $image->info['height'] values will be modified by this call. * @param int $degrees @@ -64,15 +92,13 @@ function resize($image, $width, $height); * * @return bool * TRUE or FALSE, based on success. - * - * @see image_rotate() */ - function rotate($image, $degrees, $background = NULL); + function rotate(ImageFile $image, $degrees, $background = NULL); /** * Crops an image. * - * @param object $image + * @param \Drupal\Core\Image\ImageFile $image * An image object. The $image->resource, $image->info['width'], and * $image->info['height'] values will be modified by this call. * @param int $x @@ -89,56 +115,50 @@ function rotate($image, $degrees, $background = NULL); * * @see image_crop() */ - function crop($image, $x, $y, $width, $height); + function crop(ImageFile $image, $x, $y, $width, $height); /** * Converts an image resource to grayscale. * * Note that transparent GIFs loose transparency when desaturated. * - * @param object $image + * @param \Drupal\Core\Image\ImageFile $image * An image object. The $image->resource value will be modified by this * call. * * @return bool * TRUE or FALSE, based on success. - * - * @see image_desaturate() */ - function desaturate($image); + function desaturate(ImageFile $image); /** * Creates an image resource from a file. * - * @param object $image + * @param \Drupal\Core\Image\ImageFile $image * An image object. The $image->resource value will populated by this call. * * @return bool * TRUE or FALSE, based on success. - * - * @see image_load() */ - function load($image); + function load(ImageFile $image); /** * Writes an image resource to a destination file. * - * @param object $image + * @param \Drupal\Core\Image\ImageFile $image * An image object. * @param string $destination * A string file URI or path where the image should be saved. * * @return bool * TRUE or FALSE, based on success. - * - * @see image_save() */ - function save($image, $destination); + function save(ImageFile $image, $destination); /** * Gets details about an image. * - * @param object $image + * @param \Drupal\Core\Image\ImageFile $image * An image object. * * @return array @@ -149,9 +169,9 @@ function save($image, $destination); * - "extension": Commonly used file extension for the image. * - "mime_type": MIME type ('image/jpeg', 'image/gif', 'image/png'). * - * @see image_get_info() + * @see \Drupal\Core\Image\ImageFile::processInfo() */ - function getInfo($image); + function getInfo(ImageFile $image); /** * Verifies Image Toolkit is set up correctly. diff --git a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitGdTest.php b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitGdTest.php index 624dc79..3304656 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitGdTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitGdTest.php @@ -7,6 +7,7 @@ namespace Drupal\system\Tests\Image; +use Drupal\Core\Image\ImageFile; use Drupal\simpletest\DrupalUnitTestBase; use Drupal\system\Plugin\ImageToolkitManager; @@ -79,15 +80,15 @@ function colorsAreEqual($color_a, $color_b) { /** * Function for finding a pixel's RGBa values. */ - function getPixelColor($image, $x, $y) { - $color_index = imagecolorat($image->resource, $x, $y); + function getPixelColor(ImageFile $image, $x, $y) { + $color_index = imagecolorat($image->getResource(), $x, $y); - $transparent_index = imagecolortransparent($image->resource); + $transparent_index = imagecolortransparent($image->getResource()); if ($color_index == $transparent_index) { return array(0, 0, 0, 127); } - return array_values(imagecolorsforindex($image->resource, $color_index)); + return array_values(imagecolorsforindex($image->getResource(), $color_index)); } /** @@ -152,7 +153,7 @@ function testManipulations() { 'corners' => array_fill(0, 4, $this->white), ), 'scale_and_crop' => array( - 'function' => 'scale_and_crop', + 'function' => 'scaleAndCrop', 'arguments' => array(10, 8), 'width' => 10, 'height' => 8, @@ -219,17 +220,17 @@ function testManipulations() { foreach ($files as $file) { foreach ($operations as $op => $values) { // Load up a fresh image. - $image = image_load(drupal_get_path('module', 'simpletest') . '/files/' . $file, $manager->createInstance('gd')); + $image = new ImageFile(drupal_get_path('module', 'simpletest') . '/files/' . $file, $manager->createInstance('gd')); if (!$image) { $this->fail(t('Could not load image %file.', array('%file' => $file))); continue 2; } // All images should be converted to truecolor when loaded. - $image_truecolor = imageistruecolor($image->resource); + $image_truecolor = imageistruecolor($image->getResource()); $this->assertTrue($image_truecolor, format_string('Image %file after load is a truecolor image.', array('%file' => $file))); - if ($image->info['extension'] == 'gif') { + if ($image->getExtension() == 'gif') { if ($op == 'desaturate') { // Transparent GIFs and the imagefilter function don't work together. $values['corners'][3][3] = 0; @@ -237,11 +238,7 @@ function testManipulations() { } // Perform our operation. - $function = 'image_' . $values['function']; - $arguments = array(); - $arguments[] = &$image; - $arguments = array_merge($arguments, $values['arguments']); - call_user_func_array($function, $arguments); + call_user_func_array(array($image, $values['function']), $values['arguments']); // To keep from flooding the test with assert values, make a general // value for whether each group of values fail. @@ -250,24 +247,24 @@ function testManipulations() { $correct_colors = TRUE; // Check the real dimensions of the image first. - if (imagesy($image->resource) != $values['height'] || imagesx($image->resource) != $values['width']) { + if (imagesy($image->getResource()) != $values['height'] || imagesx($image->getResource()) != $values['width']) { $correct_dimensions_real = FALSE; } // Check that the image object has an accurate record of the dimensions. - if ($image->info['width'] != $values['width'] || $image->info['height'] != $values['height']) { + if ($image->getWidth() != $values['width'] || $image->getHeight() != $values['height']) { $correct_dimensions_object = FALSE; } $directory = $this->public_files_directory .'/imagetest'; file_prepare_directory($directory, FILE_CREATE_DIRECTORY); - image_save($image, $directory . '/' . $op . '.' . $image->info['extension']); + $image->save($directory . '/' . $op . '.' . $image->getExtension()); $this->assertTrue($correct_dimensions_real, format_string('Image %file after %action action has proper dimensions.', array('%file' => $file, '%action' => $op))); $this->assertTrue($correct_dimensions_object, format_string('Image %file object after %action action is reporting the proper height and width values.', array('%file' => $file, '%action' => $op))); // JPEG colors will always be messed up due to compression. - if ($image->info['extension'] != 'jpg') { + if ($image->getExtension() != 'jpg') { // Now check each of the corners to ensure color correctness. foreach ($values['corners'] as $key => $corner) { // Get the location of the corner. diff --git a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTest.php b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTest.php index 14a84e9..daad04c 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTest.php @@ -7,10 +7,11 @@ namespace Drupal\system\Tests\Image; +use Drupal\Core\Image\ImageFile; use Drupal\system\Plugin\ImageToolkitManager; /** - * Test that the functions in image.inc correctly pass data to the toolkit. + * Tests that the methods in ImageFile correctly pass data to the toolkit. */ class ToolkitTest extends ToolkitTestBase { public static function getInfo() { @@ -34,12 +35,13 @@ function testGetAvailableToolkits() { } /** - * Test the image_load() function. + * Tests ImageFile's methods. */ function testLoad() { - $image = image_load($this->file, $this->toolkit); + $image = new ImageFile($this->file); + $image->setToolkit($this->toolkit)->getResource(); $this->assertTrue(is_object($image), 'Returned an object.'); - $this->assertEqual($this->toolkit, $image->toolkit, 'Image had toolkit set.'); + $this->assertEqual($this->toolkit->getPluginId(), $image->getToolkitId(), 'Image had toolkit set.'); $this->assertToolkitOperationsCalled(array('load', 'get_info')); } @@ -47,7 +49,7 @@ function testLoad() { * Test the image_save() function. */ function testSave() { - $this->assertFalse(image_save($this->image), 'Function returned the expected value.'); + $this->assertFalse($this->image->save(), 'Function returned the expected value.'); $this->assertToolkitOperationsCalled(array('save')); } @@ -55,7 +57,7 @@ function testSave() { * Test the image_resize() function. */ function testResize() { - $this->assertTrue(image_resize($this->image, 1, 2), 'Function returned the expected value.'); + $this->assertTrue($this->image->resize(1, 2), 'Function returned the expected value.'); $this->assertToolkitOperationsCalled(array('resize')); // Check the parameters. @@ -69,7 +71,7 @@ function testResize() { */ function testScale() { // TODO: need to test upscaling - $this->assertTrue(image_scale($this->image, 10, 10), 'Function returned the expected value.'); + $this->assertTrue($this->image->scale(10, 10), 'Function returned the expected value.'); $this->assertToolkitOperationsCalled(array('resize')); // Check the parameters. @@ -82,7 +84,7 @@ function testScale() { * Test the image_scale_and_crop() function. */ function testScaleAndCrop() { - $this->assertTrue(image_scale_and_crop($this->image, 5, 10), 'Function returned the expected value.'); + $this->assertTrue($this->image->scaleAndCrop(5, 10), 'Function returned the expected value.'); $this->assertToolkitOperationsCalled(array('resize', 'crop')); // Check the parameters. @@ -98,7 +100,7 @@ function testScaleAndCrop() { * Test the image_rotate() function. */ function testRotate() { - $this->assertTrue(image_rotate($this->image, 90, 1), 'Function returned the expected value.'); + $this->assertTrue($this->image->rotate(90, 1), 'Function returned the expected value.'); $this->assertToolkitOperationsCalled(array('rotate')); // Check the parameters. @@ -111,7 +113,7 @@ function testRotate() { * Test the image_crop() function. */ function testCrop() { - $this->assertTrue(image_crop($this->image, 1, 2, 3, 4), 'Function returned the expected value.'); + $this->assertTrue($this->image->crop(1, 2, 3, 4), 'Function returned the expected value.'); $this->assertToolkitOperationsCalled(array('crop')); // Check the parameters. @@ -126,7 +128,7 @@ function testCrop() { * Test the image_desaturate() function. */ function testDesaturate() { - $this->assertTrue(image_desaturate($this->image), 'Function returned the expected value.'); + $this->assertTrue($this->image->desaturate(), 'Function returned the expected value.'); $this->assertToolkitOperationsCalled(array('desaturate')); // Check the parameters. diff --git a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTestBase.php index 80b1588..9918553 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTestBase.php @@ -7,6 +7,7 @@ namespace Drupal\system\Tests\Image; +use Drupal\Core\Image\ImageFile; use Drupal\simpletest\WebTestBase; use Drupal\system\Plugin\ImageToolkitManager; use stdClass; @@ -23,8 +24,19 @@ */ public static $modules = array('image_test'); + /** + * @var \Drupal\system\Plugin\ImageToolkitInterface + */ protected $toolkit; + + /** + * @var string + */ protected $file; + + /** + * @var \Drupal\Core\Image\ImageFile + */ protected $image; function setUp() { @@ -38,12 +50,12 @@ function setUp() { $file = current($this->drupalGetTestFiles('image')); $this->file = $file->uri; - // Setup a dummy image to work with, this replicate image_load() so we - // can avoid calling it. - $this->image = new stdClass(); - $this->image->source = $this->file; - $this->image->info = image_get_info($this->file); - $this->image->toolkit = $this->toolkit; + // Setup a dummy image to work with. + $this->image = new ImageFile($this->file); + // Trigger processing with the default toolkit before setting a custom one. + $this->image->getExtension(); + // Set the custom toolkit. + $this->image->setToolkit($this->toolkit); // Clear out any hook calls. $this->imageTestReset(); diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php index d395462..6d2b310 100644 --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -2149,8 +2149,8 @@ function hook_file_download($uri) { return -1; } else { - $info = image_get_info($uri); - return array('Content-Type' => $info['mime_type']); + $image = new \Drupal\Core\Image\ImageFile($uri); + return array('Content-Type' => $image->getMimeType()); } } } diff --git a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/TestToolkit.php b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/TestToolkit.php index 12ebae7..8203b18 100644 --- a/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/TestToolkit.php +++ b/core/modules/system/tests/modules/image_test/lib/Drupal/image_test/Plugin/ImageToolkit/TestToolkit.php @@ -10,6 +10,7 @@ use Drupal\Component\Plugin\PluginBase; use Drupal\Component\Annotation\Plugin; use Drupal\Core\Annotation\Translation; +use Drupal\Core\Image\ImageFile; use Drupal\system\Plugin\ImageToolkitInterface; /** @@ -38,7 +39,7 @@ public function settingsFormSubmit($form, &$form_state) {} /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::getInfo(). */ - public function getInfo($image) { + public function getInfo(ImageFile $image) { $this->logCall('get_info', array($image)); return array(); } @@ -46,7 +47,7 @@ public function getInfo($image) { /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::load(). */ - public function load($image) { + public function load(ImageFile $image) { $this->logCall('load', array($image)); return $image; } @@ -54,7 +55,7 @@ public function load($image) { /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::save(). */ - public function save($image, $destination) { + public function save(ImageFile $image, $destination) { $this->logCall('save', array($image, $destination)); // Return false so that image_save() doesn't try to chmod the destination // file that we didn't bother to create. @@ -64,7 +65,7 @@ public function save($image, $destination) { /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::crop(). */ - public function crop($image, $x, $y, $width, $height) { + public function crop(ImageFile $image, $x, $y, $width, $height) { $this->logCall('crop', array($image, $x, $y, $width, $height)); return TRUE; } @@ -72,7 +73,7 @@ public function crop($image, $x, $y, $width, $height) { /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::resize(). */ - public function resize($image, $width, $height) { + public function resize(ImageFile $image, $width, $height) { $this->logCall('resize', array($image, $width, $height)); return TRUE; } @@ -80,7 +81,7 @@ public function resize($image, $width, $height) { /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::rotate(). */ - public function rotate($image, $degrees, $background = NULL) { + public function rotate(ImageFile $image, $degrees, $background = NULL) { $this->logCall('rotate', array($image, $degrees, $background)); return TRUE; } @@ -88,7 +89,7 @@ public function rotate($image, $degrees, $background = NULL) { /** * Implements \Drupal\system\Plugin\ImageToolkitInterface::desaturate(). */ - public function desaturate($image) { + public function desaturate(ImageFile $image) { $this->logCall('desaturate', array($image)); return TRUE; }