Issue #375062 by cs_shadow, David_Rothstein, mondrake, juampy, theunraveler, hswong3i, smk-ka, fietserwin: "imagecolorsforindex() Color index nnn out of range in GDToolkit" message sometimes appears

merge-requests/26/head
David Rothstein 2015-03-30 01:18:18 -04:00
parent be97f50fba
commit 5a1ad44dae
3 changed files with 79 additions and 14 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

View File

@ -261,6 +261,7 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
*/
function testManipulations() {
// If GD isn't available don't bother testing this.
module_load_include('inc', 'system', 'image.gd');
if (!function_exists('image_gd_check_settings') || !image_gd_check_settings()) {
$this->pass(t('Image manipulations for the GD toolkit were skipped because the GD toolkit is not available.'));
return;
@ -379,7 +380,7 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
array_fill(0, 3, 76) + array(3 => 0),
array_fill(0, 3, 149) + array(3 => 0),
array_fill(0, 3, 29) + array(3 => 0),
array_fill(0, 3, 0) + array(3 => 127)
array_fill(0, 3, 225) + array(3 => 127)
),
),
);
@ -394,11 +395,14 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
continue 2;
}
// Transparent GIFs and the imagefilter function don't work together.
// There is a todo in image.gd.inc to correct this.
// All images should be converted to truecolor when loaded.
$image_truecolor = imageistruecolor($image->resource);
$this->assertTrue($image_truecolor, format_string('Image %file after load is a truecolor image.', array('%file' => $file)));
if ($image->info['extension'] == 'gif') {
if ($op == 'desaturate') {
$values['corners'][3] = $this->white;
// Transparent GIFs and the imagefilter function don't work together.
$values['corners'][3][3] = 0;
}
}
@ -451,7 +455,8 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
$directory = file_default_scheme() . '://imagetests';
file_prepare_directory($directory, FILE_CREATE_DIRECTORY);
image_save($image, $directory . '/' . $op . '.' . $image->info['extension']);
$file_path = $directory . '/' . $op . '.' . $image->info['extension'];
image_save($image, $file_path);
$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)));
@ -460,8 +465,37 @@ class ImageToolkitGdTestCase extends DrupalWebTestCase {
$this->assertTrue($correct_colors, format_string('Image %file object after %action action has the correct color placement.', array('%file' => $file, '%action' => $op)));
}
}
}
// Check that saved image reloads without raising PHP errors.
$image_reloaded = image_load($file_path);
}
}
/**
* Tests loading an image whose transparent color index is out of range.
*/
function testTransparentColorOutOfRange() {
// This image was generated by taking an initial image with a palette size
// of 6 colors, and setting the transparent color index to 6 (one higher
// than the largest allowed index), as follows:
// @code
// $image = imagecreatefromgif('modules/simpletest/files/image-test.gif');
// imagecolortransparent($image, 6);
// imagegif($image, 'modules/simpletest/files/image-test-transparent-out-of-range.gif');
// @endcode
// This allows us to test that an image with an out-of-range color index
// can be loaded correctly.
$file = 'image-test-transparent-out-of-range.gif';
$image = image_load(drupal_get_path('module', 'simpletest') . '/files/' . $file);
if (!$image) {
$this->fail(format_string('Could not load image %file.', array('%file' => $file)));
}
else {
// All images should be converted to truecolor when loaded.
$image_truecolor = imageistruecolor($image->resource);
$this->assertTrue($image_truecolor, format_string('Image %file after load is a truecolor image.', array('%file' => $file)));
}
}
}

View File

@ -229,7 +229,24 @@ function image_gd_desaturate(stdClass $image) {
function image_gd_load(stdClass $image) {
$extension = str_replace('jpg', 'jpeg', $image->info['extension']);
$function = 'imagecreatefrom' . $extension;
return (function_exists($function) && $image->resource = $function($image->source));
if (function_exists($function) && $image->resource = $function($image->source)) {
if (imageistruecolor($image->resource)) {
return TRUE;
}
else {
// Convert indexed images to truecolor, copying the image to a new
// truecolor resource, so that filters work correctly and don't result
// in unnecessary dither.
$resource = image_gd_create_tmp($image, $image->info['width'], $image->info['height']);
if ($resource) {
imagecopy($resource, $image->resource, 0, 0, 0, 0, imagesx($resource), imagesy($resource));
imagedestroy($image->resource);
$image->resource = $resource;
}
}
return (bool) $image->resource;
}
return FALSE;
}
/**
@ -297,17 +314,31 @@ function image_gd_create_tmp(stdClass $image, $width, $height) {
$res = imagecreatetruecolor($width, $height);
if ($image->info['extension'] == 'gif') {
// Grab transparent color index from image resource.
// Find out if a transparent color is set, will return -1 if no
// transparent color has been defined in the image.
$transparent = imagecolortransparent($image->resource);
if ($transparent >= 0) {
// The original must have a transparent color, allocate to the new image.
$transparent_color = imagecolorsforindex($image->resource, $transparent);
$transparent = imagecolorallocate($res, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
// Find out the number of colors in the image palette. It will be 0 for
// truecolor images.
$palette_size = imagecolorstotal($image->resource);
if ($palette_size == 0 || $transparent < $palette_size) {
// Set the transparent color in the new resource, either if it is a
// truecolor image or if the transparent color is part of the palette.
// Since the index of the transparency color is a property of the
// image rather than of the palette, it is possible that an image
// could be created with this index set outside the palette size (see
// http://stackoverflow.com/a/3898007).
$transparent_color = imagecolorsforindex($image->resource, $transparent);
$transparent = imagecolorallocate($res, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
// Flood with our new transparent color.
imagefill($res, 0, 0, $transparent);
imagecolortransparent($res, $transparent);
// Flood with our new transparent color.
imagefill($res, 0, 0, $transparent);
imagecolortransparent($res, $transparent);
}
else {
imagefill($res, 0, 0, imagecolorallocate($res, 255, 255, 255));
}
}
}
elseif ($image->info['extension'] == 'png') {