Commit b2bd3e0d authored by Fabianx's avatar Fabianx

Issue #2215369 by fietserwin, Lowell, mondrake, mr.baileys, David_Rothstein,...

Issue #2215369 by fietserwin, Lowell, mondrake, mr.baileys, David_Rothstein, kristofferwiklund, TwoD, bradjones1, svanou, kristiaanvandeneynde, Fabianx: Various bugs with PHP 5.5 imagerotate(), including when incorrect color indices are passed in
parent d833cb7c
......@@ -19,7 +19,7 @@ Drupal 7.50, xxxx-xx-xx (development version)
regressions with certain contributed modules.
- Fixed the locale safety check that is used to ensure that translations are
safe to allow for tokens in the href/src attributes of translated strings.
- Implemented various fixes for automated test failures on PHP 5.4+.
- Implemented various fixes for automated test failures on PHP 5.4+ and PHP 7.
- Improved performance of queries on authmap table.
- Numerous small bugfixes.
- Numerous API documentation improvements.
......@@ -35,9 +35,9 @@ Drupal 7.50, xxxx-xx-xx (development version)
- Fixed robots.txt to allow search engines to access CSS, JavaScript and image
files.
- Fixed handling of missing files and functions inside the registry.
- Fixed various PHP 5.4 test failures.
- Fixed various PHP 7 test failures.
- Fixed various PHP 7 problems.
- Fixed various bugs with PHP 5.5 imagerotate(), including when incorrect color
indices are passed in.
Drupal 7.44, 2016-06-15
-----------------------
......
......@@ -207,9 +207,11 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
protected $green = array(0, 255, 0, 0);
protected $blue = array(0, 0, 255, 0);
protected $yellow = array(255, 255, 0, 0);
protected $fuchsia = array(255, 0, 255, 0); // Used as background colors.
protected $transparent = array(0, 0, 0, 127);
protected $white = array(255, 255, 255, 0);
protected $transparent = array(0, 0, 0, 127);
// Used as rotate background colors.
protected $fuchsia = array(255, 0, 255, 0);
protected $rotate_transparent = array(255, 255, 255, 127);
protected $width = 40;
protected $height = 20;
......@@ -275,6 +277,7 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
$files = array(
'image-test.png',
'image-test.gif',
'image-test-no-transparency.gif',
'image-test.jpg',
);
......@@ -334,13 +337,6 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
// Systems using non-bundled GD2 don't have imagerotate. Test if available.
if (function_exists('imagerotate')) {
$operations += array(
'rotate_5' => array(
'function' => 'rotate',
'arguments' => array(5, 0xFF00FF), // Fuchsia background.
'width' => 42,
'height' => 24,
'corners' => array_fill(0, 4, $this->fuchsia),
),
'rotate_90' => array(
'function' => 'rotate',
'arguments' => array(90, 0xFF00FF), // Fuchsia background.
......@@ -348,13 +344,6 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
'height' => 40,
'corners' => array($this->fuchsia, $this->red, $this->green, $this->blue),
),
'rotate_transparent_5' => array(
'function' => 'rotate',
'arguments' => array(5),
'width' => 42,
'height' => 24,
'corners' => array_fill(0, 4, $this->transparent),
),
'rotate_transparent_90' => array(
'function' => 'rotate',
'arguments' => array(90),
......@@ -363,6 +352,49 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
'corners' => array($this->transparent, $this->red, $this->green, $this->blue),
),
);
// As of PHP version 5.5, GD uses a different algorithm to rotate images
// than version 5.4 and below, resulting in different dimensions.
// See https://bugs.php.net/bug.php?id=65148.
// For the 40x20 test images, the dimensions resulting from rotation will
// be 1 pixel smaller in both width and height in PHP 5.5 and above.
// @todo: If and when the PHP bug gets solved, add an upper limit
// version check.
if (version_compare(PHP_VERSION, '5.5', '>=')) {
$operations += array(
'rotate_5' => array(
'function' => 'rotate',
'arguments' => array(5, 0xFF00FF), // Fuchsia background.
'width' => 41,
'height' => 23,
'corners' => array_fill(0, 4, $this->fuchsia),
),
'rotate_transparent_5' => array(
'function' => 'rotate',
'arguments' => array(5),
'width' => 41,
'height' => 23,
'corners' => array_fill(0, 4, $this->rotate_transparent),
),
);
}
else {
$operations += array(
'rotate_5' => array(
'function' => 'rotate',
'arguments' => array(5, 0xFF00FF), // Fuchsia background.
'width' => 42,
'height' => 24,
'corners' => array_fill(0, 4, $this->fuchsia),
),
'rotate_transparent_5' => array(
'function' => 'rotate',
'arguments' => array(5),
'width' => 42,
'height' => 24,
'corners' => array_fill(0, 4, $this->rotate_transparent),
),
);
}
}
// Systems using non-bundled GD2 don't have imagefilter. Test if available.
......@@ -430,6 +462,11 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
}
// Now check each of the corners to ensure color correctness.
foreach ($values['corners'] as $key => $corner) {
// The test gif that does not have transparency has yellow where the
// others have transparent.
if ($file === 'image-test-no-transparency.gif' && $corner === $this->transparent) {
$corner = $this->yellow;
}
// Get the location of the corner.
switch ($key) {
case 0:
......
......@@ -116,38 +116,62 @@ function image_gd_rotate(stdClass $image, $degrees, $background = NULL) {
return FALSE;
}
$width = $image->info['width'];
$height = $image->info['height'];
// PHP 5.5 GD bug: https://bugs.php.net/bug.php?id=65148: To prevent buggy
// behavior on negative multiples of 90 degrees we convert any negative
// angle to a positive one between 0 and 360 degrees.
$degrees -= floor($degrees / 360) * 360;
// Convert the hexadecimal background value to a color index value.
// Convert the hexadecimal background value to a RGBA array.
if (isset($background)) {
$rgb = array();
for ($i = 16; $i >= 0; $i -= 8) {
$rgb[] = (($background >> $i) & 0xFF);
}
$background = imagecolorallocatealpha($image->resource, $rgb[0], $rgb[1], $rgb[2], 0);
$background = array(
'red' => $background >> 16 & 0xFF,
'green' => $background >> 8 & 0xFF,
'blue' => $background & 0xFF,
'alpha' => 0,
);
}
// Set the background color as transparent if $background is NULL.
else {
// Get the current transparent color.
$background = imagecolortransparent($image->resource);
// If no transparent colors, use white.
if ($background == 0) {
$background = imagecolorallocatealpha($image->resource, 255, 255, 255, 0);
}
// Background color is not specified: use transparent white as background.
$background = array(
'red' => 255,
'green' => 255,
'blue' => 255,
'alpha' => 127
);
}
// Store the color index for the background as that is what GD uses.
$background_idx = imagecolorallocatealpha($image->resource, $background['red'], $background['green'], $background['blue'], $background['alpha']);
// 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 ($transparent_index != 0) {
$transparent_gif_color = imagecolorsforindex($image->resource, $transparent_index);
// GIF does not work with a transparency channel, but can define 1 color
// in its palette to act as transparent.
// Get the current transparent color, if any.
$gif_transparent_id = imagecolortransparent($image->resource);
if ($gif_transparent_id !== -1) {
// The gif already has a transparent color set: remember it to set it on
// the rotated image as well.
$transparent_gif_color = imagecolorsforindex($image->resource, $gif_transparent_id);
if ($background['alpha'] >= 127) {
// We want a transparent background: use the color already set to act
// as transparent, as background.
$background_idx = $gif_transparent_id;
}
}
else {
// The gif does not currently have a transparent color set.
if ($background['alpha'] >= 127) {
// But as the background is transparent, it should get one.
$transparent_gif_color = $background;
}
}
}
$image->resource = imagerotate($image->resource, 360 - $degrees, $background);
$image->resource = imagerotate($image->resource, 360 - $degrees, $background_idx);
// GIFs need to reassign the transparent color after performing the rotate.
if (isset($transparent_gif_color)) {
......
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