Commit f15394b0 authored by webchick's avatar webchick

Issue #1129642 by jbrown: Fixed Populate HTML image tags with dimension...

Issue #1129642 by jbrown: Fixed Populate HTML image tags with dimension attributes (like D6 imagefield) without re-introducing I/O.
parent 8a60e68f
......@@ -160,7 +160,7 @@ function image_get_info($filepath, $toolkit = FALSE) {
* The target height, in pixels.
*
* @return
* TRUE or FALSE, based on success.
* TRUE on success, FALSE on failure.
*
* @see image_load()
* @see image_resize()
......@@ -178,12 +178,13 @@ function image_scale_and_crop(stdClass $image, $width, $height) {
}
/**
* Scales an image to the given width and height while maintaining aspect ratio.
* Scales image dimensions while maintaining aspect ratio.
*
* The resulting image can be smaller for one or both target dimensions.
* The resulting dimensions can be smaller for one or both target dimensions.
*
* @param $image
* An image object returned by image_load().
* @param $dimensions
* Dimensions to be modified - an array with components width and height, in
* pixels.
* @param $width
* The target width, in pixels. This value is omitted then the scaling will
* based only on the height value.
......@@ -195,13 +196,12 @@ function image_scale_and_crop(stdClass $image, $width, $height) {
* up. This generally results in a low quality image.
*
* @return
* TRUE or FALSE, based on success.
* TRUE if $dimensions was modified, FALSE otherwise.
*
* @see image_load()
* @see image_scale_and_crop()
* @see image_scale()
*/
function image_scale(stdClass $image, $width = NULL, $height = NULL, $upscale = FALSE) {
$aspect = $image->info['height'] / $image->info['width'];
function image_dimensions_scale(array &$dimensions, $width = NULL, $height = NULL, $upscale = FALSE) {
$aspect = $dimensions['height'] / $dimensions['width'];
if ($upscale) {
// Set width/height according to aspect ratio if either is empty.
......@@ -214,19 +214,56 @@ function image_scale(stdClass $image, $width = NULL, $height = NULL, $upscale =
$height = !empty($height) ? $height : 9999999;
// Don't scale up.
if (round($width) >= $image->info['width'] && round($height) >= $image->info['height']) {
return TRUE;
if (round($width) >= $dimensions['width'] && round($height) >= $dimensions['height']) {
return FALSE;
}
}
if ($aspect < $height / $width) {
$height = $width * $aspect;
$dimensions['width'] = $width;
$dimensions['height'] = (int) round($width * $aspect);
}
else {
$width = $height / $aspect;
$dimensions['width'] = (int) round($height / $aspect);
$dimensions['height'] = $height;
}
return TRUE;
}
/**
* Scales an image while maintaining aspect ratio.
*
* The resulting image can be smaller for one or both target dimensions.
*
* @param $image
* An image object returned by image_load().
* @param $width
* The target width, in pixels. This value is omitted then the scaling will
* based only on the height value.
* @param $height
* 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 scaled
* up. This generally results in a low quality image.
*
* @return
* TRUE on success, FALSE on failure.
*
* @see image_dimensions_scale()
* @see image_load()
* @see image_scale_and_crop()
*/
function image_scale(stdClass $image, $width = NULL, $height = NULL, $upscale = FALSE) {
$dimensions = $image->info;
// Scale the dimensions - if they don't change then just return success.
if (!image_dimensions_scale($dimensions, $width, $height, $upscale)) {
return TRUE;
}
return image_resize($image, $width, $height);
return image_resize($image, $dimensions['width'], $dimensions['height']);
}
/**
......@@ -240,7 +277,7 @@ function image_scale(stdClass $image, $width = NULL, $height = NULL, $upscale =
* The target height, in pixels.
*
* @return
* TRUE or FALSE, based on success.
* TRUE on success, FALSE on failure.
*
* @see image_load()
* @see image_gd_resize()
......@@ -267,7 +304,7 @@ function image_resize(stdClass $image, $width, $height) {
* be white.
*
* @return
* TRUE or FALSE, based on success.
* TRUE on success, FALSE on failure.
*
* @see image_load()
* @see image_gd_rotate()
......@@ -291,7 +328,7 @@ function image_rotate(stdClass $image, $degrees, $background = NULL) {
* The target height, in pixels.
*
* @return
* TRUE or FALSE, based on success.
* TRUE on success, FALSE on failure.
*
* @see image_load()
* @see image_scale_and_crop()
......@@ -315,7 +352,7 @@ function image_crop(stdClass $image, $x, $y, $width, $height) {
* An image object returned by image_load().
*
* @return
* TRUE or FALSE, based on success.
* TRUE on success, FALSE on failure.
*
* @see image_load()
* @see image_gd_desaturate()
......@@ -379,7 +416,7 @@ function image_load($file, $toolkit = FALSE) {
* original image file will be overwritten.
*
* @return
* TRUE or FALSE, based on success.
* TRUE on success, FALSE on failure.
*
* @see image_load()
* @see image_gd_save()
......
......@@ -22,6 +22,10 @@
* following items:
* - "label": The human-readable name of the effect.
* - "effect callback": The function to call to perform this image effect.
* - "dimensions passthrough": (optional) Set this item if the effect doesn't
* change the dimensions of the image.
* - "dimensions callback": (optional) The function to call to transform
* dimensions for this effect.
* - "help": (optional) A brief description of the effect that will be shown
* when adding or configuring this image effect.
* - "form callback": (optional) The name of a function that will return a
......@@ -37,7 +41,8 @@ function hook_image_effect_info() {
$effects['mymodule_resize'] = array(
'label' => t('Resize'),
'help' => t('Resize an image to an exact set of dimensions, ignoring aspect ratio.'),
'effect callback' => 'mymodule_resize_image',
'effect callback' => 'mymodule_resize_effect',
'dimensions callback' => 'mymodule_resize_dimensions',
'form callback' => 'mymodule_resize_form',
'summary theme' => 'mymodule_resize_summary',
);
......@@ -56,6 +61,7 @@ function hook_image_effect_info() {
function hook_image_effect_info_alter(&$effects) {
// Override the Image module's crop effect with more options.
$effects['image_crop']['effect callback'] = 'mymodule_crop_effect';
$effects['image_crop']['dimensions callback'] = 'mymodule_crop_dimensions';
$effects['image_crop']['form callback'] = 'mymodule_crop_form';
}
......
......@@ -14,6 +14,7 @@ function image_image_effect_info() {
'label' => t('Resize'),
'help' => t('Resizing will make images an exact set of dimensions. This may cause images to be stretched or shrunk disproportionately.'),
'effect callback' => 'image_resize_effect',
'dimensions callback' => 'image_resize_dimensions',
'form callback' => 'image_resize_form',
'summary theme' => 'image_resize_summary',
),
......@@ -21,6 +22,7 @@ function image_image_effect_info() {
'label' => t('Scale'),
'help' => t('Scaling will maintain the aspect-ratio of the original image. If only a single dimension is specified, the other dimension will be calculated.'),
'effect callback' => 'image_scale_effect',
'dimensions callback' => 'image_scale_dimensions',
'form callback' => 'image_scale_form',
'summary theme' => 'image_scale_summary',
),
......@@ -28,6 +30,7 @@ function image_image_effect_info() {
'label' => t('Scale and crop'),
'help' => t('Scale and crop will maintain the aspect-ratio of the original image, then crop the larger dimension. This is most useful for creating perfectly square thumbnails without stretching the image.'),
'effect callback' => 'image_scale_and_crop_effect',
'dimensions callback' => 'image_resize_dimensions',
'form callback' => 'image_resize_form',
'summary theme' => 'image_resize_summary',
),
......@@ -35,6 +38,7 @@ function image_image_effect_info() {
'label' => t('Crop'),
'help' => t('Cropping will remove portions of an image to make it the specified dimensions.'),
'effect callback' => 'image_crop_effect',
'dimensions callback' => 'image_resize_dimensions',
'form callback' => 'image_crop_form',
'summary theme' => 'image_crop_summary',
),
......@@ -42,11 +46,13 @@ function image_image_effect_info() {
'label' => t('Desaturate'),
'help' => t('Desaturate converts an image to grayscale.'),
'effect callback' => 'image_desaturate_effect',
'dimensions passthrough' => TRUE,
),
'image_rotate' => array(
'label' => t('Rotate'),
'help' => t('Rotating an image may cause the dimensions of an image to increase to fit the diagonal.'),
'effect callback' => 'image_rotate_effect',
'dimensions callback' => 'image_rotate_dimensions',
'form callback' => 'image_rotate_form',
'summary theme' => 'image_rotate_summary',
),
......@@ -79,6 +85,24 @@ function image_resize_effect(&$image, $data) {
return TRUE;
}
/**
* Image dimensions callback; Resize.
*
* @param $dimensions
* Dimensions to be modified - an array with components width and height, in
* pixels.
* @param $data
* An array of attributes to use when performing the resize effect with the
* following items:
* - "width": An integer representing the desired width in pixels.
* - "height": An integer representing the desired height in pixels.
*/
function image_resize_dimensions(array &$dimensions, array $data) {
// The new image will have the exact dimensions defined for the effect.
$dimensions['width'] = $data['width'];
$dimensions['height'] = $data['height'];
}
/**
* Image effect callback; Scale an image resource.
*
......@@ -89,8 +113,8 @@ function image_resize_effect(&$image, $data) {
* following items:
* - "width": An integer representing the desired width in pixels.
* - "height": An integer representing the desired height in pixels.
* - "upscale": A Boolean indicating that the image should be upscalled if
* the dimensions are larger than the original image.
* - "upscale": A boolean indicating that the image should be upscaled if the
* dimensions are larger than the original image.
*
* @return
* TRUE on success. FALSE on failure to scale image.
......@@ -114,6 +138,26 @@ function image_scale_effect(&$image, $data) {
return TRUE;
}
/**
* Image dimensions callback; Scale.
*
* @param $dimensions
* Dimensions to be modified - an array with components width and height, in
* pixels.
* @param $data
* An array of attributes to use when performing the scale effect with the
* following items:
* - "width": An integer representing the desired width in pixels.
* - "height": An integer representing the desired height in pixels.
* - "upscale": A boolean indicating that the image should be upscaled if the
* dimensions are larger than the original image.
*/
function image_scale_dimensions(array &$dimensions, array $data) {
if ($dimensions['width'] && $dimensions['height']) {
image_dimensions_scale($dimensions, $data['width'], $data['height'], $data['upscale']);
}
}
/**
* Image effect callback; Crop an image resource.
*
......@@ -198,7 +242,7 @@ function image_desaturate_effect(&$image, $data) {
* An array of attributes to use when performing the rotate effect containing
* the following items:
* - "degrees": The number of (clockwise) degrees to rotate the image.
* - "random": A Boolean indicating that a random rotation angle should be
* - "random": A boolean indicating that a random rotation angle should be
* used for this image. The angle specified in "degrees" is used as a
* positive and negative maximum.
* - "bgcolor": The background color to use for exposed areas of the image.
......@@ -241,3 +285,32 @@ function image_rotate_effect(&$image, $data) {
}
return TRUE;
}
/**
* Image dimensions callback; Rotate.
*
* @param $dimensions
* Dimensions to be modified - an array with components width and height, in
* pixels.
* @param $data
* An array of attributes to use when performing the rotate effect containing
* the following items:
* - "degrees": The number of (clockwise) degrees to rotate the image.
* - "random": A boolean indicating that a random rotation angle should be
* used for this image. The angle specified in "degrees" is used as a
* positive and negative maximum.
*/
function image_rotate_dimensions(array &$dimensions, array $data) {
// If the rotate is not random and the angle is a multiple of 90 degrees,
// then the new dimensions can be determined.
if (!$data['random'] && ((int) ($data['degrees']) == $data['degrees']) && ($data['degrees'] % 90 == 0)) {
if ($data['degrees'] % 180 != 0) {
$temp = $dimensions['width'];
$dimensions['width'] = $dimensions['height'];
$dimensions['height'] = $temp;
}
}
else {
$dimensions['width'] = $dimensions['height'] = NULL;
}
}
......@@ -208,6 +208,18 @@ function image_field_prepare_view($entity_type, $entities, $field, $instances, $
*/
function image_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
file_field_presave($entity_type, $entity, $field, $instance, $langcode, $items);
// Determine the dimensions if necessary.
foreach ($items as &$item) {
if (!isset($item['width']) || !isset($item['height'])) {
$info = image_get_info(file_load($item['fid'])->uri);
if (is_array($info)) {
$item['width'] = $info['width'];
$item['height'] = $info['height'];
}
}
}
}
/**
......@@ -346,9 +358,42 @@ function image_field_widget_process($element, &$form_state, $form) {
// Add the image preview.
if ($element['#file'] && $widget_settings['preview_image_style']) {
$variables = array(
'style_name' => $widget_settings['preview_image_style'],
'path' => $element['#file']->uri,
);
// Determine image dimensions.
if (isset($element['#value']['width']) && isset($element['#value']['height'])) {
$variables['width'] = $element['#value']['width'];
$variables['height'] = $element['#value']['height'];
}
else {
$info = image_get_info($element['#file']->uri);
if (is_array($info)) {
$variables['width'] = $info['width'];
$variables['height'] = $info['height'];
}
else {
$variables['width'] = $variables['height'] = NULL;
}
}
$element['preview'] = array(
'#type' => 'markup',
'#markup' => theme('image_style', array('style_name' => $widget_settings['preview_image_style'], 'path' => $element['#file']->uri)),
'#markup' => theme('image_style', $variables),
);
// Store the dimensions in the form so the file doesn't have to be accessed
// again. This is important for remote files.
$element['width'] = array(
'#type' => 'hidden',
'#value' => $variables['width'],
);
$element['height'] = array(
'#type' => 'hidden',
'#value' => $variables['height'],
);
}
......@@ -534,6 +579,12 @@ function theme_image_formatter($variables) {
'path' => $item['uri'],
'alt' => $item['alt'],
);
if (isset($item['width']) && isset($item['height'])) {
$image['width'] = $item['width'];
$image['height'] = $item['height'];
}
// Do not output an empty 'title' attribute.
if (drupal_strlen($item['title']) > 0) {
$image['title'] = $item['title'];
......
......@@ -127,6 +127,16 @@ function image_field_schema($field) {
'length' => 128,
'not null' => FALSE,
),
'width' => array(
'description' => 'The width of the image in pixels.',
'type' => 'int',
'unsigned' => TRUE,
),
'height' => array(
'description' => 'The height of the image in pixels.',
'type' => 'int',
'unsigned' => TRUE,
),
),
'indexes' => array(
'fid' => array('fid'),
......
......@@ -185,6 +185,8 @@ function image_theme() {
'variables' => array(
'style_name' => NULL,
'path' => NULL,
'width' => NULL,
'height' => NULL,
'alt' => '',
'title' => NULL,
'attributes' => array(),
......@@ -804,6 +806,39 @@ function image_style_create_derivative($style, $source, $destination) {
return TRUE;
}
/**
* Determines the dimensions of the styled image.
*
* Applies all of an image style's effects to $dimensions.
*
* @param $style_name
* The name of the style to be applied.
* @param $dimensions
* Dimensions to be modified - an array with components width and height, in
* pixels.
*/
function image_style_transform_dimensions($style_name, array &$dimensions) {
module_load_include('inc', 'image', 'image.effects');
$style = image_style_load($style_name);
if (!is_array($style)) {
return;
}
foreach ($style['effects'] as $effect) {
if (isset($effect['dimensions passthrough'])) {
continue;
}
if (isset($effect['dimensions callback'])) {
$effect['dimensions callback']($dimensions, $effect['data']);
}
else {
$dimensions['width'] = $dimensions['height'] = NULL;
}
}
}
/**
* Flush cached media for a style.
*
......@@ -1130,6 +1165,8 @@ function image_effect_apply($image, $effect) {
* - path: The path of the image file relative to the Drupal files directory.
* This function does not work with images outside the files directory nor
* with remotely hosted images.
* - width: The width of the source image (if known).
* - height: The height of the source image (if known).
* - alt: The alternative text for text-based browsers.
* - title: The title text is displayed when the image is hovered in some
* popular browsers.
......@@ -1138,6 +1175,18 @@ function image_effect_apply($image, $effect) {
* @ingroup themeable
*/
function theme_image_style($variables) {
// Determine the dimensions of the styled image.
$dimensions = array(
'width' => $variables['width'],
'height' => $variables['height'],
);
image_style_transform_dimensions($variables['style_name'], $dimensions);
$variables['width'] = $dimensions['width'];
$variables['height'] = $dimensions['height'];
// Determine the url for the styled image.
$variables['path'] = image_style_url($variables['style_name'], $variables['path']);
return theme('image', $variables);
}
......
This diff is collapsed.
......@@ -11,3 +11,31 @@ function image_module_test_file_download($uri) {
}
return -1;
}
/**
* Implements hook_image_effect_info().
*/
function image_module_test_image_effect_info() {
$effects = array(
'image_module_test_null' => array(
'effect callback' => 'image_module_test_null_effect',
),
);
return $effects;
}
/**
* Image effect callback; Null.
*
* @param $image
* An image object returned by image_load().
* @param $data
* An array with no attributes.
*
* @return
* TRUE
*/
function image_module_test_null_effect(array &$image, array $data) {
return TRUE;
}
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