diff --git a/core/modules/image/src/Plugin/ImageEffect/RotateImageEffect.php b/core/modules/image/src/Plugin/ImageEffect/RotateImageEffect.php index 3b79e43..c516dfe 100644 --- a/core/modules/image/src/Plugin/ImageEffect/RotateImageEffect.php +++ b/core/modules/image/src/Plugin/ImageEffect/RotateImageEffect.php @@ -28,12 +28,9 @@ class RotateImageEffect extends ConfigurableImageEffectBase { * {@inheritdoc} */ public function applyEffect(ImageInterface $image) { - if (!empty($this->configuration['random'])) { - $degrees = abs((float) $this->configuration['degrees']); - $this->configuration['degrees'] = rand(-$degrees, $degrees); - } + $degrees = $this->configuration['random'] ? $this->getRotationFromUri($image->getSource(), $this->configuration['degrees']) : $this->configuration['degrees']; - if (!$image->rotate($this->configuration['degrees'], $this->configuration['bgcolor'])) { + if (!$image->rotate($degrees, $this->configuration['bgcolor'])) { $this->logger->error('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())); return FALSE; } @@ -44,11 +41,12 @@ public function applyEffect(ImageInterface $image) { * {@inheritdoc} */ public function transformDimensions(array &$dimensions, $uri) { - // If the rotate is not random and current dimensions are set, - // then the new dimensions can be determined. - if (!$this->configuration['random'] && $dimensions['width'] && $dimensions['height']) { + // If the current dimensions are set, then the new dimensions can be + // determined. + if ($dimensions['width'] && $dimensions['height']) { + $degrees = $this->configuration['random'] ? $this->getRotationFromUri($uri, $this->configuration['degrees']) : $this->configuration['degrees']; $rect = new Rectangle($dimensions['width'], $dimensions['height']); - $rect = $rect->rotate($this->configuration['degrees']); + $rect = $rect->rotate($degrees); $dimensions['width'] = $rect->getBoundingWidth(); $dimensions['height'] = $rect->getBoundingHeight(); } @@ -58,6 +56,27 @@ public function transformDimensions(array &$dimensions, $uri) { } /** + * Returns a pseudo-random angle for rotation. + * + * Uses a CRC32B hash of the URI to calculate the pseudo-random angle. + * + * @param string $uri + * The URI of the original file. + * @param int $max_degrees + * The maximum rotation angle. + * + * @return int + * An integer angle in the range 0-360. + */ + protected function getRotationFromUri($uri, $max_degrees) { + if (!$max_degrees || $max_degrees === 0) { + return 0; + } + $max_degrees = abs((int) $max_degrees); + return (((int) hash('crc32b', $uri)) % ($max_degrees * 2)) - $max_degrees; + } + + /** * {@inheritdoc} */ public function getSummary() { diff --git a/core/modules/image/src/Tests/ImageDimensionsTest.php b/core/modules/image/src/Tests/ImageDimensionsTest.php index 6d2fa7d..f7f53b8 100644 --- a/core/modules/image/src/Tests/ImageDimensionsTest.php +++ b/core/modules/image/src/Tests/ImageDimensionsTest.php @@ -164,7 +164,7 @@ function testImageDimensions() { $effect = array( 'id' => 'image_rotate', 'data' => array( - 'degrees' => 180, + 'degrees' => -37, 'random' => TRUE, ), 'weight' => 5, @@ -172,11 +172,14 @@ function testImageDimensions() { $style->addImageEffect($effect); $style->save(); - $this->assertEqual($this->getImageTag($variables), ''); + $this->assertEqual($this->getImageTag($variables), ''); $this->assertFalse(file_exists($generated_uri), 'Generated file does not exist.'); $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_file = $image_factory->get($generated_uri); + $this->assertEqual($image_file->getWidth(), 80); + $this->assertEqual($image_file->getHeight(), 100); // Add a crop effect.