### Issue #1551686 by mondrake, fietserwin, adci_contributor, ankitgarg,...

`Issue #1551686 by mondrake, fietserwin, adci_contributor, ankitgarg, claudiu.cristea: Image rotate dimensions callback can calculate new dimensions for every angle.`
parent 561b42ce
 0 && \$height > 0) { \$this->width = \$width; \$this->height = \$height; \$this->boundingWidth = \$width; \$this->boundingHeight = \$height; } else { throw new \InvalidArgumentException("Invalid dimensions ({\$width}x{\$height}) specified for a Rectangle object"); } } /** * Rotates the rectangle. * * @param float \$angle * Rotation angle. * * @return \$this */ public function rotate(\$angle) { // PHP 5.5 GD bug: https://bugs.php.net/bug.php?id=65148: To prevent buggy // behavior on negative multiples of 30 degrees we convert any negative // angle to a positive one between 0 and 360 degrees. \$angle -= floor(\$angle / 360) * 360; // For some rotations that are multiple of 30 degrees, we need to correct // an imprecision between GD that uses C floats internally, and PHP that // uses C doubles. Also, for rotations that are not multiple of 90 degrees, // we need to introduce a correction factor of 0.5 to match the GD // algorithm used in PHP 5.5 (and above) to calculate the width and height // of the rotated image. if ((int) \$angle == \$angle && \$angle % 90 == 0) { \$imprecision = 0; \$correction = 0; } else { \$imprecision = -0.00001; \$correction = 0.5; } // Do the trigonometry, applying imprecision fixes where needed. \$rad = deg2rad(\$angle); \$cos = cos(\$rad); \$sin = sin(\$rad); \$a = \$this->width * \$cos; \$b = \$this->height * \$sin + \$correction; \$c = \$this->width * \$sin; \$d = \$this->height * \$cos + \$correction; if ((int) \$angle == \$angle && in_array(\$angle, [60, 150, 300])) { \$a = \$this->fixImprecision(\$a, \$imprecision); \$b = \$this->fixImprecision(\$b, \$imprecision); \$c = \$this->fixImprecision(\$c, \$imprecision); \$d = \$this->fixImprecision(\$d, \$imprecision); } // This is how GD on PHP5.5 calculates the new dimensions. \$this->boundingWidth = abs((int) \$a) + abs((int) \$b); \$this->boundingHeight = abs((int) \$c) + abs((int) \$d); return \$this; } /** * Performs an imprecision check on the input value and fixes it if needed. * * GD that uses C floats internally, whereas we at PHP level use C doubles. * In some cases, we need to compensate imprecision. * * @param float \$input * The input value. * @param float \$imprecision * The imprecision factor. * * @return float * A value, where imprecision is added to input if the delta part of the * input is lower than the absolute imprecision. */ protected function fixImprecision(\$input, \$imprecision) { if (\$this->delta(\$input) < abs(\$imprecision)) { return \$input + \$imprecision; } return \$input; } /** * Returns the fractional part of a float number, unsigned. * * @param float \$input * The input value. * * @return float * The fractional part of the input number, unsigned. */ protected function fraction(\$input) { return abs((int) \$input - \$input); } /** * Returns the difference of a fraction from the closest between 0 and 1. * * @param float \$input * The input value. * * @return float * the difference of a fraction from the closest between 0 and 1. */ protected function delta(\$input) { \$fraction = \$this->fraction(\$input); return \$fraction > 0.5 ? (1 - \$fraction) : \$fraction; } /** * Gets the bounding width of the rectangle. * * @return int * The bounding width of the rotated rectangle. */ public function getBoundingWidth() { return \$this->boundingWidth; } /** * Gets the bounding height of the rectangle. * * @return int * The bounding height of the rotated rectangle. */ public function getBoundingHeight() { return \$this->boundingHeight; } }
 ... ... @@ -8,6 +8,7 @@ namespace Drupal\image\Plugin\ImageEffect; use Drupal\Component\Utility\Color; use Drupal\Component\Utility\Rectangle; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Image\ImageInterface; use Drupal\image\ConfigurableImageEffectBase; ... ... @@ -43,14 +44,13 @@ public function applyEffect(ImageInterface \$image) { * {@inheritdoc} */ public function transformDimensions(array &\$dimensions, \$uri) { // If the rotate is not random and the angle is a multiple of 90 degrees, // If the rotate is not random and current dimensions are set, // then the new dimensions can be determined. if (!\$this->configuration['random'] && ((int) (\$this->configuration['degrees']) == \$this->configuration['degrees']) && (\$this->configuration['degrees'] % 90 == 0)) { if (\$this->configuration['degrees'] % 180 != 0) { \$temp = \$dimensions['width']; \$dimensions['width'] = \$dimensions['height']; \$dimensions['height'] = \$temp; } if (!\$this->configuration['random'] && \$dimensions['width'] && \$dimensions['height']) { \$rect = new Rectangle(\$dimensions['width'], \$dimensions['height']); \$rect = \$rect->rotate(\$this->configuration['degrees']); \$dimensions['width'] = \$rect->getBoundingWidth(); \$dimensions['height'] = \$rect->getBoundingHeight(); } else { \$dimensions['width'] = \$dimensions['height'] = NULL; ... ...
 ... ... @@ -213,11 +213,14 @@ function testImageDimensions() { \$effect_id = \$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(), 41); \$this->assertEqual(\$image_file->getHeight(), 41); \$effect_plugin = \$style->getEffect(\$effect_id); \$style->deleteImageEffect(\$effect_plugin); ... ...
 ... ... @@ -203,8 +203,8 @@ function testManipulations() { 'rotate_5' => array( 'function' => 'rotate', 'arguments' => array('degrees' => 5, 'background' => '#FF00FF'), // Fuchsia background. 'width' => 42, 'height' => 24, 'width' => 41, 'height' => 23, 'corners' => array_fill(0, 4, \$this->fuchsia), ), 'rotate_90' => array( ... ... @@ -217,8 +217,8 @@ function testManipulations() { 'rotate_transparent_5' => array( 'function' => 'rotate', 'arguments' => array('degrees' => 5), 'width' => 42, 'height' => 24, 'width' => 41, 'height' => 23, 'corners' => array_fill(0, 4, \$this->rotateTransparent), ), 'rotate_transparent_90' => array( ... ... @@ -289,20 +289,6 @@ function testManipulations() { \$correct_dimensions_real = TRUE; \$correct_dimensions_object = TRUE; // PHP 5.5 GD bug: https://bugs.php.net/bug.php?id=65148. PHP 5.5 GD // rotates differently then it did in PHP 5.4 resulting in different // dimensions then what math teaches us. For the test images, the // dimensions will be 1 pixel smaller in both dimensions (though other // tests have shown a difference of 0 to 3 pixels in both dimensions. // @todo: if and when the PHP bug gets solved, add an upper limit // version check. // @todo: in [#1551686] the dimension calculations for rotation are // reworked. That issue should also check if these tests can be made // more robust. if (version_compare(PHP_VERSION, '5.5', '>=') && \$values['function'] === 'rotate' && \$values['arguments']['degrees'] % 90 != 0) { \$values['height']--; \$values['width']--; } if (imagesy(\$toolkit->getResource()) != \$values['height'] || imagesx(\$toolkit->getResource()) != \$values['width']) { \$correct_dimensions_real = FALSE; } ... ...
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment