function ToolkitGdTest::testManipulations

Since PHP can't visually check that our images have been manipulated properly, build a list of expected color values for each of the corners and the expected height and widths for the final images.

File

drupal/core/modules/system/lib/Drupal/system/Tests/Image/ToolkitGdTest.php, line 98
Definition of Drupal\system\Tests\Image\ToolkitGdTest.

Class

ToolkitGdTest
Test the core GD image manipulation functions.

Namespace

Drupal\system\Tests\Image

Code

function testManipulations() {

  // Typically the corner colors will be unchanged. These colors are in the
  // order of top-left, top-right, bottom-right, bottom-left.
  $default_corners = array(
    $this->red,
    $this->green,
    $this->blue,
    $this->transparent,
  );

  // A list of files that will be tested.
  $files = array(
    'image-test.png',
    'image-test.gif',
    'image-test.jpg',
  );

  // Setup a list of tests to perform on each type.
  $operations = array(
    'resize' => array(
      'function' => 'resize',
      'arguments' => array(
        20,
        10,
      ),
      'width' => 20,
      'height' => 10,
      'corners' => $default_corners,
    ),
    'scale_x' => array(
      'function' => 'scale',
      'arguments' => array(
        20,
        NULL,
      ),
      'width' => 20,
      'height' => 10,
      'corners' => $default_corners,
    ),
    'scale_y' => array(
      'function' => 'scale',
      'arguments' => array(
        NULL,
        10,
      ),
      'width' => 20,
      'height' => 10,
      'corners' => $default_corners,
    ),
    'upscale_x' => array(
      'function' => 'scale',
      'arguments' => array(
        80,
        NULL,
        TRUE,
      ),
      'width' => 80,
      'height' => 40,
      'corners' => $default_corners,
    ),
    'upscale_y' => array(
      'function' => 'scale',
      'arguments' => array(
        NULL,
        40,
        TRUE,
      ),
      'width' => 80,
      'height' => 40,
      'corners' => $default_corners,
    ),
    'crop' => array(
      'function' => 'crop',
      'arguments' => array(
        12,
        4,
        16,
        12,
      ),
      'width' => 16,
      'height' => 12,
      'corners' => array_fill(0, 4, $this->white),
    ),
    'scale_and_crop' => array(
      'function' => 'scale_and_crop',
      'arguments' => array(
        10,
        8,
      ),
      'width' => 10,
      'height' => 8,
      'corners' => array_fill(0, 4, $this->black),
    ),
  );

  // 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.
        'width' => 20,
        'height' => 40,
        'corners' => array(
          $this->transparent,
          $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,
        ),
        'width' => 20,
        'height' => 40,
        'corners' => array(
          $this->transparent,
          $this->red,
          $this->green,
          $this->blue,
        ),
      ),
    );
  }

  // Systems using non-bundled GD2 don't have imagefilter. Test if available.
  if (function_exists('imagefilter')) {
    $operations += array(
      'desaturate' => array(
        'function' => 'desaturate',
        'arguments' => array(),
        'height' => 20,
        'width' => 40,
        // Grayscale corners are a bit funky. Each of the corners are a shade of
        // gray. The values of these were determined simply by looking at the
        // final image to see what desaturated colors end up being.
        'corners' => array(
          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, 225) + array(
            3 => 127,
          ),
        ),
      ),
    );
  }
  $manager = new ImageToolkitManager($this->container
    ->get('container.namespaces'));
  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'));
      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);
      $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') {

          // Transparent GIFs and the imagefilter function don't work together.
          $values['corners'][3][3] = 0;
        }
      }

      // Perform our operation.
      $function = 'image_' . $values['function'];
      $arguments = array();
      $arguments[] =& $image;
      $arguments = array_merge($arguments, $values['arguments']);
      call_user_func_array($function, $arguments);

      // To keep from flooding the test with assert values, make a general
      // value for whether each group of values fail.
      $correct_dimensions_real = TRUE;
      $correct_dimensions_object = TRUE;
      $correct_colors = TRUE;

      // Check the real dimensions of the image first.
      if (imagesy($image->resource) != $values['height'] || imagesx($image->resource) != $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']) {
        $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']);
      $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') {

        // Now check each of the corners to ensure color correctness.
        foreach ($values['corners'] as $key => $corner) {

          // Get the location of the corner.
          switch ($key) {
            case 0:
              $x = 0;
              $y = 0;
              break;
            case 1:
              $x = $values['width'] - 1;
              $y = 0;
              break;
            case 2:
              $x = $values['width'] - 1;
              $y = $values['height'] - 1;
              break;
            case 3:
              $x = 0;
              $y = $values['height'] - 1;
              break;
          }
          $color = $this
            ->getPixelColor($image, $x, $y);
          $correct_colors = $this
            ->colorsAreEqual($color, $corner);
          $this
            ->assertTrue($correct_colors, format_string('Image %file object after %action action has the correct color placement at corner %corner.', array(
            '%file' => $file,
            '%action' => $op,
            '%corner' => $key,
          )));
        }
      }
    }
  }
}