2005-02-01 16:27:43 +00:00
< ? php
// $Id$
2007-08-08 07:46:09 +00:00
/**
* @ file
* API for manipulating images .
*/
/**
* @ defgroup image Image toolkits
* @ {
* Drupal ' s image toolkits provide an abstraction layer for common image file
* manipulations like scaling , cropping , and rotating . The abstraction frees
* module authors from the need to support multiple image libraries , and it
* allows site administrators to choose the library that ' s best for them .
*
* PHP includes the GD library by default so a GD toolkit is installed with
* Drupal . Other toolkits like ImageMagic are available from contrib modules .
* GD works well for small images , but using it with larger files may cause PHP
* to run out of memory . In contrast the ImageMagick library does not suffer
* from this problem , but it requires the ISP to have installed additional
* software .
*
2008-07-08 01:08:15 +00:00
* Image toolkits are discovered based on the associated module ' s
* hook_image_toolkits . Additionally the image toolkit include file
2008-12-20 18:24:41 +00:00
* must be identified in the files array in the module . info file . The
2008-07-08 01:08:15 +00:00
* toolkit must then be enabled using the admin / settings / image - toolkit
* form .
2007-08-08 07:46:09 +00:00
*
2008-07-08 01:08:15 +00:00
* Only one toolkit may be selected at a time . If a module author wishes to call
2007-08-08 07:46:09 +00:00
* a specific toolkit they can check that it is installed by calling
* image_get_available_toolkits (), and then calling its functions directly .
*/
2005-02-01 16:27:43 +00:00
/**
* Return a list of available toolkits .
*
2007-08-02 20:19:02 +00:00
* @ return
2009-03-09 11:44:54 +00:00
* An array with the toolkit names as keys and the descriptions as values .
2005-02-01 16:27:43 +00:00
*/
function image_get_available_toolkits () {
2008-07-08 01:08:15 +00:00
// hook_image_toolkits returns an array of toolkit names.
$toolkits = module_invoke_all ( 'image_toolkits' );
2005-02-01 16:27:43 +00:00
$output = array ();
2009-03-09 11:44:54 +00:00
foreach ( $toolkits as $name => $info ) {
// Only allow modules that aren't marked as unavailable.
if ( $info [ 'available' ]) {
$output [ $name ] = $info [ 'title' ];
2005-02-01 16:27:43 +00:00
}
}
2009-03-09 11:44:54 +00:00
2005-02-01 16:27:43 +00:00
return $output ;
}
/**
* Retrieve the name of the currently used toolkit .
*
2007-08-02 20:19:02 +00:00
* @ return
* String containing the name of the selected toolkit , or FALSE on error .
2005-02-01 16:27:43 +00:00
*/
function image_get_toolkit () {
static $toolkit ;
2007-08-02 20:19:02 +00:00
2009-03-09 11:44:54 +00:00
if ( ! isset ( $toolkit )) {
$toolkits = image_get_available_toolkits ();
2005-03-29 00:01:23 +00:00
$toolkit = variable_get ( 'image_toolkit' , 'gd' );
2009-03-09 11:44:54 +00:00
if ( ! isset ( $toolkits [ $toolkit ]) || ! drupal_function_exists ( 'image_' . $toolkit . '_load' )) {
// The selected toolkit isn't available so return the first one found. If
// none are available this will return FALSE.
$toolkit = reset ( $toolkits );
2005-02-01 16:27:43 +00:00
}
}
return $toolkit ;
}
/**
* Invokes the given method using the currently selected toolkit .
*
2007-08-02 20:19:02 +00:00
* @ param $method
* A string containing the method to invoke .
2009-03-09 11:44:54 +00:00
* @ param $image
* An image object returned by image_load () .
2007-08-02 20:19:02 +00:00
* @ param $params
* An optional array of parameters to pass to the toolkit method .
* @ return
2007-08-08 07:46:09 +00:00
* Mixed values ( typically Boolean indicating successful operation ) .
2005-02-01 16:27:43 +00:00
*/
2009-03-09 11:44:54 +00:00
function image_toolkit_invoke ( $method , stdClass $image , array $params = array ()) {
$function = 'image_' . $image -> toolkit . '_' . $method ;
if ( drupal_function_exists ( $function )) {
array_unshift ( $params , $image );
return call_user_func_array ( $function , $params );
2005-03-23 20:26:21 +00:00
}
2009-03-09 11:44:54 +00:00
watchdog ( 'image' , 'The selected image handling toolkit %toolkit can not correctly process %function.' , array ( '%toolkit' => $image -> toolkit , '%function' => $function ), WATCHDOG_ERROR );
return FALSE ;
2005-02-01 16:27:43 +00:00
}
/**
* Get details about an image .
*
2007-08-02 20:19:02 +00:00
* Drupal only supports GIF , JPG and PNG file formats .
*
* @ return
* FALSE , if the file could not be found or is not an image . Otherwise , a
* keyed array containing information about the image :
2009-03-09 11:44:54 +00:00
* 'width' - Width , in pixels .
* 'height' - Height , in pixels .
2007-08-02 20:19:02 +00:00
* 'extension' - Commonly used file extension for the image .
* 'mime_type' - MIME type ( 'image/jpeg' , 'image/gif' , 'image/png' ) .
* 'file_size' - File size in bytes .
2005-02-01 16:27:43 +00:00
*/
function image_get_info ( $file ) {
2005-06-19 08:59:06 +00:00
if ( ! is_file ( $file )) {
2006-07-05 11:45:51 +00:00
return FALSE ;
2005-02-01 16:27:43 +00:00
}
2006-07-05 11:45:51 +00:00
$details = FALSE ;
2005-02-01 16:27:43 +00:00
$data = @ getimagesize ( $file );
2005-07-31 09:57:27 +00:00
$file_size = @ filesize ( $file );
2005-02-01 16:27:43 +00:00
2005-12-14 20:10:45 +00:00
if ( isset ( $data ) && is_array ( $data )) {
2005-02-01 16:27:43 +00:00
$extensions = array ( '1' => 'gif' , '2' => 'jpg' , '3' => 'png' );
$extension = array_key_exists ( $data [ 2 ], $extensions ) ? $extensions [ $data [ 2 ]] : '' ;
$details = array ( 'width' => $data [ 0 ],
2005-03-29 00:01:23 +00:00
'height' => $data [ 1 ],
'extension' => $extension ,
2005-07-31 09:57:27 +00:00
'file_size' => $file_size ,
2005-03-29 00:01:23 +00:00
'mime_type' => $data [ 'mime' ]);
2005-02-01 16:27:43 +00:00
}
return $details ;
}
2007-05-11 11:45:11 +00:00
/**
2009-03-09 11:44:54 +00:00
* Scales an image to the exact width and height given .
*
* This function achieves the target aspect ratio by cropping the original image
* equally on both sides , or equally on the top and bottom . This function is
* useful to create uniform sized avatars from larger images .
2007-05-11 11:45:11 +00:00
*
* The resulting image always has the exact target dimensions .
*
2009-03-09 11:44:54 +00:00
* @ param $image
* An image object returned by image_load () .
2007-08-02 20:19:02 +00:00
* @ param $width
* The target width , in pixels .
* @ param $height
* The target height , in pixels .
* @ return
* TRUE or FALSE , based on success .
2009-03-09 11:44:54 +00:00
*
* @ see image_load ()
* @ see image_resize ()
* @ see image_crop ()
2007-05-11 11:45:11 +00:00
*/
2009-03-09 11:44:54 +00:00
function image_scale_and_crop ( stdClass $image , $width , $height ) {
$scale = max ( $width / $image -> info [ 'width' ], $height / $image -> info [ 'height' ]);
$x = ( $image -> info [ 'width' ] * $scale - $width ) / 2 ;
$y = ( $image -> info [ 'height' ] * $scale - $height ) / 2 ;
2007-05-11 11:45:11 +00:00
2009-03-09 11:44:54 +00:00
if ( image_resize ( $image , $image -> info [ 'width' ] * $scale , $image -> info [ 'height' ] * $scale )) {
return image_crop ( $image , $x , $y , $width , $height );
2007-05-11 11:45:11 +00:00
}
return FALSE ;
}
2005-02-01 16:27:43 +00:00
/**
2009-03-09 11:44:54 +00:00
* Scales an image to the given width and height while maintaining aspect ratio .
2005-02-01 16:27:43 +00:00
*
2007-05-11 11:45:11 +00:00
* The resulting image can be smaller for one or both target dimensions .
*
2009-03-09 11:44:54 +00:00
* @ param $image
* An image object returned by image_load () .
2007-08-02 20:19:02 +00:00
* @ param $width
2009-03-09 11:44:54 +00:00
* The target width , in pixels . This value is omitted then the scaling will
* based only on the height value .
2007-08-02 20:19:02 +00:00
* @ param $height
2009-03-09 11:44:54 +00:00
* The target height , in pixels . This value is omitted then the scaling will
* based only on the width value .
* @ param $upscale
* Boolean indicating that files smaller than the dimensions will be scalled
* up . This generally results in a low quality image .
2007-08-02 20:19:02 +00:00
* @ return
* TRUE or FALSE , based on success .
2009-03-09 11:44:54 +00:00
*
* @ see image_load ()
* @ see image_scale_and_crop ()
2005-02-01 16:27:43 +00:00
*/
2009-03-09 11:44:54 +00:00
function image_scale ( stdClass $image , $width = NULL , $height = NULL , $upscale = FALSE ) {
$aspect = $image -> info [ 'height' ] / $image -> info [ 'width' ];
2005-02-01 16:27:43 +00:00
2009-03-09 11:44:54 +00:00
if ( $upscale ) {
// Set width/height according to aspect ratio if either is empty.
$width = ! empty ( $width ) ? $width : $height / $aspect ;
$height = ! empty ( $height ) ? $height : $width / $aspect ;
}
else {
// Set impossibly large values if the width and height aren't set.
$width = ! empty ( $width ) ? $width : 9999999 ;
$height = ! empty ( $height ) ? $height : 9999999 ;
// Don't scale up.
if ( round ( $width ) >= $image -> info [ 'width' ] && round ( $height ) >= $image -> info [ 'height' ]) {
return TRUE ;
}
2005-02-01 16:27:43 +00:00
}
if ( $aspect < $height / $width ) {
2009-03-09 11:44:54 +00:00
$height = $width * $aspect ;
2005-10-22 15:14:46 +00:00
}
else {
2009-03-09 11:44:54 +00:00
$width = $height / $aspect ;
2005-02-01 16:27:43 +00:00
}
2009-03-09 11:44:54 +00:00
return image_resize ( $image , $width , $height );
2005-02-01 16:27:43 +00:00
}
/**
* Resize an image to the given dimensions ( ignoring aspect ratio ) .
*
2009-03-09 11:44:54 +00:00
* @ param $image
* An image object returned by image_load () .
2007-08-02 20:19:02 +00:00
* @ param $width
* The target width , in pixels .
* @ param $height
* The target height , in pixels .
* @ return
* TRUE or FALSE , based on success .
2009-03-09 11:44:54 +00:00
*
* @ see image_load ()
2009-03-10 09:43:01 +00:00
* @ see image_gd_resize ()
2005-02-01 16:27:43 +00:00
*/
2009-03-09 11:44:54 +00:00
function image_resize ( stdClass $image , $width , $height ) {
$width = ( int ) round ( $width );
$height = ( int ) round ( $height );
return image_toolkit_invoke ( 'resize' , $image , array ( $width , $height ));
2005-02-01 16:27:43 +00:00
}
2009-03-10 09:43:01 +00:00
/**
* Rotate an image by the given number of degrees .
*
* @ param $image
* An image object returned by image_load () .
* @ param $degrees
* The number of ( clockwise ) degrees to rotate the image .
* @ param $background
* An hexadecimal integer specifying the background color to use for the
* uncovered area of the image after the rotation . E . g . 0x000000 for black ,
* 0xff00ff for magenta , and 0xffffff for white . For images that support
* transparency , this will default to transparent . Otherwise it will
* be white .
* @ return
* TRUE or FALSE , based on success .
*
* @ see image_load ()
* @ see image_gd_rotate ()
*/
function image_rotate ( stdClass $image , $degrees , $background = NULL ) {
return image_toolkit_invoke ( 'rotate' , $image , array ( $degrees , $background ));
}
2005-02-01 16:27:43 +00:00
/**
* Crop an image to the rectangle specified by the given rectangle .
*
2009-03-09 11:44:54 +00:00
* @ param $image
* An image object returned by image_load () .
2007-08-02 20:19:02 +00:00
* @ param $x
2009-03-09 11:44:54 +00:00
* The top left coordinate , in pixels , of the crop area ( x axis value ) .
2007-08-02 20:19:02 +00:00
* @ param $y
2009-03-09 11:44:54 +00:00
* The top left coordinate , in pixels , of the crop area ( y axis value ) .
2007-08-02 20:19:02 +00:00
* @ param $width
* The target width , in pixels .
* @ param $height
* The target height , in pixels .
* @ return
* TRUE or FALSE , based on success .
2009-03-09 11:44:54 +00:00
*
* @ see image_load ()
* @ see image_scale_and_crop ()
2009-03-10 09:43:01 +00:00
* @ see image_gd_crop ()
2009-03-09 11:44:54 +00:00
*/
function image_crop ( stdClass $image , $x , $y , $width , $height ) {
$aspect = $image -> info [ 'height' ] / $image -> info [ 'width' ];
if ( empty ( $height )) $height = $width / $aspect ;
if ( empty ( $width )) $width = $height * $aspect ;
$width = ( int ) round ( $width );
$height = ( int ) round ( $height );
return image_toolkit_invoke ( 'crop' , $image , array ( $x , $y , $width , $height ));
}
/**
* Convert an image to grayscale .
*
* @ param $image
* An image object returned by image_load () .
* @ return
* TRUE or FALSE , based on success .
*
* @ see image_load ()
2009-03-10 09:43:01 +00:00
* @ see image_gd_desaturate ()
2009-03-09 11:44:54 +00:00
*/
function image_desaturate ( stdClass $image ) {
return image_toolkit_invoke ( 'desaturate' , $image );
}
/**
* Load an image file and return an image object .
*
* Any changes to the file are not saved until image_save () is called .
*
* @ param $file
* Path to an image file .
* @ param $toolkit
* An optional , image toolkit name to override the default .
* @ return
* An image object or FALSE if there was a problem loading the file . The
* image object has the following properties :
* - 'source' - The original file path .
* - 'info' - The array of information returned by image_get_info ()
* - 'toolkit' - The name of the image toolkit requested when the image was
* loaded .
* Image tookits may add additional properties . The caller is advised not to
* monkey about with them .
*
* @ see image_save ()
* @ see image_get_info ()
* @ see image_get_available_toolkits ()
2009-03-10 09:43:01 +00:00
* @ see image_gd_load ()
2005-02-01 16:27:43 +00:00
*/
2009-03-09 11:44:54 +00:00
function image_load ( $file , $toolkit = FALSE ) {
if ( ! $toolkit ) {
$toolkit = image_get_toolkit ();
}
if ( $toolkit ) {
$image = new stdClass ();
$image -> source = $file ;
$image -> info = image_get_info ( $file );
$image -> toolkit = $toolkit ;
if ( image_toolkit_invoke ( 'load' , $image )) {
return $image ;
}
}
return FALSE ;
}
/**
* Close the image and save the changes to a file .
*
* @ param $image
* An image object returned by image_load () . The object 's ' info ' property
* will be updated if the file is saved successfully .
* @ param $destination
* Destination path where the image should be saved . If it is empty the
* original image file will be overwritten .
* @ return
* TRUE or FALSE , based on success .
*
* @ see image_load ()
2009-03-10 09:43:01 +00:00
* @ see image_gd_save ()
2009-03-09 11:44:54 +00:00
*/
function image_save ( stdClass $image , $destination = NULL ) {
if ( empty ( $destination )) {
$destination = $image -> source ;
}
if ( $return = image_toolkit_invoke ( 'save' , $image , array ( $destination ))) {
// Clear the cached file size and refresh the image information.
clearstatcache ();
$image -> info = image_get_info ( $destination );
if ( @ chmod ( $destination , 0664 )) {
return $return ;
}
watchdog ( 'image' , 'Could not set permissions on destination file: %file' , array ( '%file' => $destination ));
}
return FALSE ;
2005-02-01 16:27:43 +00:00
}
/**
2007-08-02 20:19:02 +00:00
* @ } End of " defgroup image " .
2005-02-01 16:27:43 +00:00
*/