Drupal PHP Cross Reference Content Management Systems

Source: /modules/system/image.gd.inc - 367 lines - 11840 bytes - Summary - Text - Print

   1  <?php
   2  
   3  /**
   4   * @file
   5   * GD2 toolkit for image manipulation within Drupal.
   6   */
   7  
   8  /**
   9   * @addtogroup image
  10   * @{
  11   */
  12  
  13  /**
  14   * Retrieve settings for the GD2 toolkit.
  15   */
  16  function image_gd_settings() {
  17    if (image_gd_check_settings()) {
  18      $form['status'] = array(
  19        '#markup' => t('The GD toolkit is installed and working properly.')
  20      );
  21  
  22      $form['image_jpeg_quality'] = array(
  23        '#type' => 'textfield',
  24        '#title' => t('JPEG quality'),
  25        '#description' => t('Define the image quality for JPEG manipulations. Ranges from 0 to 100. Higher values mean better image quality but bigger files.'),
  26        '#size' => 10,
  27        '#maxlength' => 3,
  28        '#default_value' => variable_get('image_jpeg_quality', 75),
  29        '#field_suffix' => t('%'),
  30      );
  31      $form['#element_validate'] = array('image_gd_settings_validate');
  32  
  33      return $form;
  34    }
  35    else {
  36      form_set_error('image_toolkit', t('The GD image toolkit requires that the GD module for PHP be installed and configured properly. For more information see <a href="@url">PHP\'s image documentation</a>.', array('@url' => 'http://php.net/image')));
  37      return FALSE;
  38    }
  39  }
  40  
  41  /**
  42   * Validate the submitted GD settings.
  43   */
  44  function image_gd_settings_validate($form, &$form_state) {
  45    // Validate image quality range.
  46    $value = $form_state['values']['image_jpeg_quality'];
  47    if (!is_numeric($value) || $value < 0 || $value > 100) {
  48      form_set_error('image_jpeg_quality', t('JPEG quality must be a number between 0 and 100.'));
  49    }
  50  }
  51  
  52  /**
  53   * Verify GD2 settings (that the right version is actually installed).
  54   *
  55   * @return
  56   *   A boolean indicating if the GD toolkit is available on this machine.
  57   */
  58  function image_gd_check_settings() {
  59    if ($check = get_extension_funcs('gd')) {
  60      if (in_array('imagegd2', $check)) {
  61        // GD2 support is available.
  62        return TRUE;
  63      }
  64    }
  65    return FALSE;
  66  }
  67  
  68  /**
  69   * Scale an image to the specified size using GD.
  70   *
  71   * @param $image
  72   *   An image object. The $image->resource, $image->info['width'], and
  73   *   $image->info['height'] values will be modified by this call.
  74   * @param $width
  75   *   The new width of the resized image, in pixels.
  76   * @param $height
  77   *   The new height of the resized image, in pixels.
  78   * @return
  79   *   TRUE or FALSE, based on success.
  80   *
  81   * @see image_resize()
  82   */
  83  function image_gd_resize(stdClass $image, $width, $height) {
  84    $res = image_gd_create_tmp($image, $width, $height);
  85  
  86    if (!imagecopyresampled($res, $image->resource, 0, 0, 0, 0, $width, $height, $image->info['width'], $image->info['height'])) {
  87      return FALSE;
  88    }
  89  
  90    imagedestroy($image->resource);
  91    // Update image object.
  92    $image->resource = $res;
  93    $image->info['width'] = $width;
  94    $image->info['height'] = $height;
  95    return TRUE;
  96  }
  97  
  98  /**
  99   * Rotate an image the given number of degrees.
 100   *
 101   * @param $image
 102   *   An image object. The $image->resource, $image->info['width'], and
 103   *   $image->info['height'] values will be modified by this call.
 104   * @param $degrees
 105   *   The number of (clockwise) degrees to rotate the image.
 106   * @param $background
 107   *   An hexadecimal integer specifying the background color to use for the
 108   *   uncovered area of the image after the rotation. E.g. 0x000000 for black,
 109   *   0xff00ff for magenta, and 0xffffff for white. For images that support
 110   *   transparency, this will default to transparent. Otherwise it will
 111   *   be white.
 112   * @return
 113   *   TRUE or FALSE, based on success.
 114   *
 115   * @see image_rotate()
 116   */
 117  function image_gd_rotate(stdClass $image, $degrees, $background = NULL) {
 118    // PHP installations using non-bundled GD do not have imagerotate.
 119    if (!function_exists('imagerotate')) {
 120      watchdog('image', 'The image %file could not be rotated because the imagerotate() function is not available in this PHP installation.', array('%file' => $image->source));
 121      return FALSE;
 122    }
 123  
 124    $width = $image->info['width'];
 125    $height = $image->info['height'];
 126  
 127    // Convert the hexadecimal background value to a color index value.
 128    if (isset($background)) {
 129      $rgb = array();
 130      for ($i = 16; $i >= 0; $i -= 8) {
 131        $rgb[] = (($background >> $i) & 0xFF);
 132      }
 133      $background = imagecolorallocatealpha($image->resource, $rgb[0], $rgb[1], $rgb[2], 0);
 134    }
 135    // Set the background color as transparent if $background is NULL.
 136    else {
 137      // Get the current transparent color.
 138      $background = imagecolortransparent($image->resource);
 139  
 140      // If no transparent colors, use white.
 141      if ($background == 0) {
 142        $background = imagecolorallocatealpha($image->resource, 255, 255, 255, 0);
 143      }
 144    }
 145  
 146    // Images are assigned a new color palette when rotating, removing any
 147    // transparency flags. For GIF images, keep a record of the transparent color.
 148    if ($image->info['extension'] == 'gif') {
 149      $transparent_index = imagecolortransparent($image->resource);
 150      if ($transparent_index != 0) {
 151        $transparent_gif_color = imagecolorsforindex($image->resource, $transparent_index);
 152      }
 153    }
 154  
 155    $image->resource = imagerotate($image->resource, 360 - $degrees, $background);
 156  
 157    // GIFs need to reassign the transparent color after performing the rotate.
 158    if (isset($transparent_gif_color)) {
 159      $background = imagecolorexactalpha($image->resource, $transparent_gif_color['red'], $transparent_gif_color['green'], $transparent_gif_color['blue'], $transparent_gif_color['alpha']);
 160      imagecolortransparent($image->resource, $background);
 161    }
 162  
 163    $image->info['width'] = imagesx($image->resource);
 164    $image->info['height'] = imagesy($image->resource);
 165    return TRUE;
 166  }
 167  
 168  /**
 169   * Crop an image using the GD toolkit.
 170   *
 171   * @param $image
 172   *   An image object. The $image->resource, $image->info['width'], and
 173   *   $image->info['height'] values will be modified by this call.
 174   * @param $x
 175   *   The starting x offset at which to start the crop, in pixels.
 176   * @param $y
 177   *   The starting y offset at which to start the crop, in pixels.
 178   * @param $width
 179   *   The width of the cropped area, in pixels.
 180   * @param $height
 181   *   The height of the cropped area, in pixels.
 182   * @return
 183   *   TRUE or FALSE, based on success.
 184   *
 185   * @see image_crop()
 186   */
 187  function image_gd_crop(stdClass $image, $x, $y, $width, $height) {
 188    $res = image_gd_create_tmp($image, $width, $height);
 189  
 190    if (!imagecopyresampled($res, $image->resource, 0, 0, $x, $y, $width, $height, $width, $height)) {
 191      return FALSE;
 192    }
 193  
 194    // Destroy the original image and return the modified image.
 195    imagedestroy($image->resource);
 196    $image->resource = $res;
 197    $image->info['width'] = $width;
 198    $image->info['height'] = $height;
 199    return TRUE;
 200  }
 201  
 202  /**
 203   * Convert an image resource to grayscale.
 204   *
 205   * Note that transparent GIFs loose transparency when desaturated.
 206   *
 207   * @param $image
 208   *   An image object. The $image->resource value will be modified by this call.
 209   * @return
 210   *   TRUE or FALSE, based on success.
 211   *
 212   * @see image_desaturate()
 213   */
 214  function image_gd_desaturate(stdClass $image) {
 215    // PHP installations using non-bundled GD do not have imagefilter.
 216    if (!function_exists('imagefilter')) {
 217      watchdog('image', 'The image %file could not be desaturated because the imagefilter() function is not available in this PHP installation.', array('%file' => $image->source));
 218      return FALSE;
 219    }
 220  
 221    return imagefilter($image->resource, IMG_FILTER_GRAYSCALE);
 222  }
 223  
 224  /**
 225   * GD helper function to create an image resource from a file.
 226   *
 227   * @param $image
 228   *   An image object. The $image->resource value will populated by this call.
 229   * @return
 230   *   TRUE or FALSE, based on success.
 231   *
 232   * @see image_load()
 233   */
 234  function image_gd_load(stdClass $image) {
 235    $extension = str_replace('jpg', 'jpeg', $image->info['extension']);
 236    $function = 'imagecreatefrom' . $extension;
 237    return (function_exists($function) && $image->resource = $function($image->source));
 238  }
 239  
 240  /**
 241   * GD helper to write an image resource to a destination file.
 242   *
 243   * @param $image
 244   *   An image object.
 245   * @param $destination
 246   *   A string file URI or path where the image should be saved.
 247   * @return
 248   *   TRUE or FALSE, based on success.
 249   *
 250   * @see image_save()
 251   */
 252  function image_gd_save(stdClass $image, $destination) {
 253    $scheme = file_uri_scheme($destination);
 254    // Work around lack of stream wrapper support in imagejpeg() and imagepng().
 255    if ($scheme && file_stream_wrapper_valid_scheme($scheme)) {
 256      // If destination is not local, save image to temporary local file.
 257      $local_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_LOCAL);
 258      if (!isset($local_wrappers[$scheme])) {
 259        $permanent_destination = $destination;
 260        $destination = drupal_tempnam('temporary://', 'gd_');
 261      }
 262      // Convert stream wrapper URI to normal path.
 263      $destination = drupal_realpath($destination);
 264    }
 265  
 266    $extension = str_replace('jpg', 'jpeg', $image->info['extension']);
 267    $function = 'image' . $extension;
 268    if (!function_exists($function)) {
 269      return FALSE;
 270    }
 271    if ($extension == 'jpeg') {
 272      $success = $function($image->resource, $destination, variable_get('image_jpeg_quality', 75));
 273    }
 274    else {
 275      // Always save PNG images with full transparency.
 276      if ($extension == 'png') {
 277        imagealphablending($image->resource, FALSE);
 278        imagesavealpha($image->resource, TRUE);
 279      }
 280      $success = $function($image->resource, $destination);
 281    }
 282    // Move temporary local file to remote destination.
 283    if (isset($permanent_destination) && $success) {
 284      return (bool) file_unmanaged_move($destination, $permanent_destination, FILE_EXISTS_REPLACE);
 285    }
 286    return $success;
 287  }
 288  
 289  /**
 290   * Create a truecolor image preserving transparency from a provided image.
 291   *
 292   * @param $image
 293   *   An image object.
 294   * @param $width
 295   *   The new width of the new image, in pixels.
 296   * @param $height
 297   *   The new height of the new image, in pixels.
 298   * @return
 299   *   A GD image handle.
 300   */
 301  function image_gd_create_tmp(stdClass $image, $width, $height) {
 302    $res = imagecreatetruecolor($width, $height);
 303  
 304    if ($image->info['extension'] == 'gif') {
 305      // Grab transparent color index from image resource.
 306      $transparent = imagecolortransparent($image->resource);
 307  
 308      if ($transparent >= 0) {
 309        // The original must have a transparent color, allocate to the new image.
 310        $transparent_color = imagecolorsforindex($image->resource, $transparent);
 311        $transparent = imagecolorallocate($res, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
 312  
 313        // Flood with our new transparent color.
 314        imagefill($res, 0, 0, $transparent);
 315        imagecolortransparent($res, $transparent);
 316      }
 317    }
 318    elseif ($image->info['extension'] == 'png') {
 319      imagealphablending($res, FALSE);
 320      $transparency = imagecolorallocatealpha($res, 0, 0, 0, 127);
 321      imagefill($res, 0, 0, $transparency);
 322      imagealphablending($res, TRUE);
 323      imagesavealpha($res, TRUE);
 324    }
 325    else {
 326      imagefill($res, 0, 0, imagecolorallocate($res, 255, 255, 255));
 327    }
 328  
 329    return $res;
 330  }
 331  
 332  /**
 333   * Get details about an image.
 334   *
 335   * @param $image
 336   *   An image object.
 337   * @return
 338   *   FALSE, if the file could not be found or is not an image. Otherwise, a
 339   *   keyed array containing information about the image:
 340   *   - "width": Width, in pixels.
 341   *   - "height": Height, in pixels.
 342   *   - "extension": Commonly used file extension for the image.
 343   *   - "mime_type": MIME type ('image/jpeg', 'image/gif', 'image/png').
 344   *
 345   * @see image_get_info()
 346   */
 347  function image_gd_get_info(stdClass $image) {
 348    $details = FALSE;
 349    $data = getimagesize($image->source);
 350  
 351    if (isset($data) && is_array($data)) {
 352      $extensions = array('1' => 'gif', '2' => 'jpg', '3' => 'png');
 353      $extension = isset($extensions[$data[2]]) ?  $extensions[$data[2]] : '';
 354      $details = array(
 355        'width'     => $data[0],
 356        'height'    => $data[1],
 357        'extension' => $extension,
 358        'mime_type' => $data['mime'],
 359      );
 360    }
 361  
 362    return $details;
 363  }
 364  
 365  /**
 366   * @} End of "addtogroup image".
 367   */

title

Description

title

Description

title

Description

title

title

Body