View source
<?php
function imagefield_crop_menu($may_cache) {
if (!$may_cache && $_SESSION['imagefield']) {
foreach ($_SESSION['imagefield'] as $fieldname => $files) {
if (is_array($files)) {
foreach ($files as $delta => $file) {
if ($file['crop']['preview']) {
$items[] = array(
'path' => $file['crop']['preview'],
'callback' => '_imagefield_crop_cropped_preview',
'access' => TRUE,
'type' => MENU_CALLBACK,
);
}
}
}
}
}
return $items;
}
function _imagefield_crop_cropped_preview() {
foreach ($_SESSION['imagefield'] as $fieldname => $files) {
foreach ($files as $delta => $file) {
if ($file['crop']['preview'] == $_GET['q']) {
file_transfer($file['crop']['filepath'], array(
'Content-Type: ' . mime_header_encode($file['filemime']),
'Content-Length: ' . $file['filesize'],
));
exit;
}
}
}
}
function imagefield_crop_widget_info() {
return array(
'image crop' => array(
'label' => 'Image with cropping',
'field types' => array(
'image',
),
),
);
}
function imagefield_crop_widget_settings($op, $widget) {
switch ($op) {
case 'callbacks':
return array(
'default value' => CONTENT_CALLBACK_CUSTOM,
);
case 'form':
$form = array();
$form['collapsible'] = array(
'#type' => 'radios',
'#title' => t('Collapsible behavior'),
'#options' => array(
1 => t('None.'),
2 => t('Collapsible, expanded by default.'),
3 => t('Collapsible, collapsed by default.'),
),
'#default_value' => isset($widget['collapsible']) ? $widget['collapsible'] : 2,
);
$form['resolution'] = array(
'#type' => 'textfield',
'#title' => t('The resolution to crop the image onto'),
'#default_value' => isset($widget['resolution']) ? $widget['resolution'] : '200x150',
'#size' => 15,
'#maxlength' => 10,
'#description' => t('The output resolution of the cropped image, expressed as WIDTHxHEIGHT (e.g. 640x480). Set to 0 not to rescale after cropping.'),
);
$form['enforce_ratio'] = array(
'#type' => 'checkbox',
'#title' => t('Enforce box crop box ratio'),
'#default_value' => isset($widget['enforce_ratio']) ? $widget['enforce_ratio'] : 1,
'#description' => t('Check this to force the ratio of the output on the crop box. NOTE: If you leave this unchecked, final images may be distorted'),
);
$form['croparea'] = array(
'#type' => 'textfield',
'#title' => t('The resolution of the cropping area'),
'#default_value' => isset($widget['croparea']) ? $widget['croparea'] : '500x500',
'#size' => 15,
'#maxlength' => 10,
'#description' => t('The resolution of the area used for the cropping of the image. Image will be scaled down to this size before cropping. Use WIDTHxHEIGHT format'),
);
$form['always_show'] = array(
'#type' => 'checkbox',
'#title' => t('Always show the cropping area'),
'#default_value' => isset($widget['always_show']) ? $widget['always_show'] : 0,
'#description' => t('Check this to show the cropping area even before the image is uploaded'),
);
$form['use_unscaled'] = array(
'#type' => 'checkbox',
'#title' => t('Use original (unscaled) image for cropping'),
'#default_value' => isset($widget['use_unscaled']) ? $widget['use_unscaled'] : 1,
'#description' => t('For better quality, use the original image for cropping, and not the one scaled for viewing'),
);
$form['image_path'] = array(
'#type' => 'textfield',
'#title' => t('Image path'),
'#default_value' => $widget['image_path'] ? $widget['image_path'] : '',
'#description' => t('Optional subdirectory within the "%dir" directory where images will be stored. Do not include trailing slash.', array(
'%dir' => variable_get('file_directory_path', 'files'),
)),
'#after_build' => array(
'imagefield_form_check_directory',
),
);
$form['custom_alt'] = array(
'#type' => 'checkbox',
'#title' => t('Enable custom alternate text'),
'#default_value' => $widget['custom_alt'] ? $widget['custom_alt'] : 0,
'#description' => t('Enable custom alternate text for images. Filename will be used if not checked.'),
);
$form['custom_title'] = array(
'#type' => 'checkbox',
'#title' => t('Enable custom title text'),
'#default_value' => $widget['custom_title'] ? $widget['custom_title'] : 0,
'#description' => t('Enable custom title text for images. Filename will be used if not checked.'),
);
return $form;
case 'validate':
list($rw, $rh) = explode('x', $widget['resolution']);
if ($widget['enforce_ratio'] && (!is_numeric($rw) || intval($rw) != $rw || $rw <= 0 || !is_numeric($rh) || intval($rh) != $rh || $rh <= 0)) {
form_set_error('resolution', t('Target resolution must be defined as WIDTHxHEIGHT if resolution is to be enforced'));
}
list($cw, $ch) = explode('x', $widget['croparea']);
if (!is_numeric($cw) || intval($cw) != $cw || $cw <= 0 || !is_numeric($ch) || intval($ch) != $ch || $ch <= 0) {
form_set_error('croparea', t('Crop area resolution must be defined as WIDTHxHEIGHT'));
}
_imagefield_crop_verify_gd();
break;
case 'save':
return array(
'collapsible',
'resolution',
'enforce_ratio',
'croparea',
'always_show',
'use_unscaled',
'image_path',
'custom_alt',
'custom_title',
);
}
}
function imagefield_crop_widget($op, &$node, $field, &$node_field) {
switch ($op) {
case 'default value':
return array();
case 'prepare form values':
_imagefield_crop_widget_prepare_form_values($node, $field, $node_field);
break;
case 'form':
return _imagefield_crop_widget_form($node, $field, $node_field);
break;
case 'validate':
if ($field['required']) {
if (!count($node_field)) {
form_set_error($field['field_name'], $field['widget']['label'] . ' is required.');
}
}
break;
case 'submit':
foreach ($node_field as $delta => $file) {
$cropped = $file['crop']['filepath'];
if (is_file($cropped)) {
if (!file_copy($cropped, $file['filepath'], FILE_EXISTS_REPLACE)) {
form_set_error(NULL, 'Could not copy cropped file');
}
file_delete($file['crop']['filepath']);
if (module_exists('imagecache')) {
imagecache_image_flush($file['filepath']);
}
}
file_delete($file['filepath'] . '.unscaled');
}
break;
}
}
function _imagefield_crop_widget_prepare_form_values(&$node, $field, &$node_field) {
$fieldname = $field['field_name'];
if (!count($_POST)) {
imagefield_crop_clear_session();
}
$new_file_uploaded = FALSE;
if ($file = file_check_upload($fieldname . '_upload')) {
$file = (array) $file;
if (strpos($file['filemime'], 'image') !== FALSE) {
$file = _imagefield_crop_scale_image($file, $field);
if ($pos = strrpos($file['filename'], '.')) {
$name = substr($file['filename'], 0, $pos);
$ext = substr($file['filename'], $pos);
}
else {
$name = $file['filename'];
}
$filepath = file_create_filename($name . '_' . time() . $ext, file_create_path($field['widget']['image_path']));
if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PRIVATE) {
if (strpos($filepath, file_directory_path()) !== FALSE) {
$filepath = trim(substr($filepath, strlen(file_directory_path())), '\\/');
}
$filepath = 'system/files/' . $filepath;
}
$file['fid'] = 'upload';
$file['preview'] = $filepath;
if (!$field['multiple']) {
if (is_array($node_field)) {
foreach ($node_field as $delta => $session_file) {
$node_field[$delta]['flags']['delete'] = TRUE;
}
}
imagefield_crop_clear_field_session($fieldname);
}
$file_id = count($node_field) + count($_SESSION['imagefield'][$fieldname]);
$_SESSION['imagefield'][$fieldname][$file_id] = $file;
unset($_SESSION['imagefield'][$fieldname][$file_id]['crop']);
$new_file_uploaded = TRUE;
}
}
if (is_array($_SESSION['imagefield'][$fieldname]) && count($_SESSION['imagefield'][$fieldname])) {
foreach ($_SESSION['imagefield'][$fieldname] as $delta => $file) {
if (isset($_POST[$fieldname][$delta]['crop'])) {
foreach (array(
'x',
'y',
'width',
'height',
'changed',
) as $att) {
$file['crop'][$att] = $_POST[$fieldname][$delta]['crop'][$att];
}
}
if (!isset($file['filepath'])) {
$node_field[$delta]['crop'] = $file['crop'];
}
else {
$node_field[] = $file;
}
}
}
else {
if (is_array($_POST[$fieldname])) {
foreach ($_POST[$fieldname] as $delta => $file) {
$node_field[$delta]['crop'] = $file['crop'];
}
}
else {
foreach ($node_field as $delta => $file) {
$node_field[$delta] = _imagefield_crop_scale_image($file, $field);
}
}
}
foreach ($node_field as $delta => $file) {
if ($file['crop']['changed']) {
if ($delta) {
$node_field[$delta - 1]['flags']['delete'] = TRUE;
}
if (!isset($file['crop']['filepath'])) {
$node_field[$delta]['crop']['filepath'] = tempnam(file_directory_temp(), 'tmpcp_');
}
_imagefield_crop_resize($node_field[$delta]['filepath'], $file['crop'], $field['widget']['resolution'], $node_field[$delta]['crop']['filepath']);
$node_field[$delta]['crop']['preview'] = ($node_field[$delta]['fid'] == 'upload' ? $node_field[$delta]['preview'] : $node_field[$delta]['filepath']) . '-crop';
$_SESSION['imagefield'][$fieldname][$delta]['crop'] = $node_field[$delta]['crop'];
}
}
}
function imagefield_crop_clear_session() {
if (is_array($_SESSION['imagefield']) && count($_SESSION['imagefield'])) {
foreach (array_keys($_SESSION['imagefield']) as $fieldname) {
imagefield_crop_clear_field_session($fieldname);
}
unset($_SESSION['imagefield']);
}
}
function imagefield_crop_clear_field_session($fieldname) {
if (is_array($_SESSION['imagefield'][$fieldname]) && count($_SESSION['imagefield'][$fieldname])) {
foreach ($_SESSION['imagefield'][$fieldname] as $files) {
file_delete($file['filepath']);
file_delete($file['crop']['filepath']);
file_delete($file['filepath'] . '.unscaled');
}
unset($_SESSION['imagefield'][$fieldname]);
}
}
function _imagefield_crop_widget_form($node, $field, &$node_field) {
$fieldname = $field['field_name'];
drupal_add_css(drupal_get_path('module', 'imagefield') . '/imagefield.css');
$module_path = drupal_get_path('module', 'imagefield_crop');
drupal_add_css($module_path . '/imagefield_crop.css');
jquery_interface_add();
if ($field['widget']['enforce_ratio']) {
list($w, $h) = explode('x', $field['widget']['resolution']);
$ratio = $h / $w;
}
else {
$ratio = 0;
}
drupal_add_js("Drupal.imagefield_crop_{$fieldname} = { ratio: {$ratio} }", 'inline');
drupal_add_js($module_path . '/imagefield_crop.js');
$form = array();
$form[$fieldname] = array(
'#type' => 'fieldset',
'#title' => $field['widget']['label'],
'#weight' => $field['widget']['weight'],
'#collapsible' => $field['widget']['collapsible'] != 1,
'#collapsed' => $field['widget']['collapsible'] == 3,
'#tree' => TRUE,
);
$form[$fieldname][$fieldname . '_upload'] = array(
'#type' => 'file',
'#description' => $field['widget']['description'],
'#tree' => FALSE,
'#weight' => 9,
);
$form[$fieldname]['upload'] = array(
'#type' => 'button',
'#value' => t('Upload'),
'#name' => 'cck_imagefield_' . $fieldname . '_op',
'#attributes' => array(
'id' => $fieldname . '-attach-button',
),
'#tree' => FALSE,
'#weight' => 10,
);
list($w, $h) = explode('x', $field['widget']['resolution']);
if (is_array($node_field) && count($node_field)) {
$crop_attrs = array(
'x' => array(
'weight' => 5,
'default' => 0,
),
'y' => array(
'weight' => 6,
'default' => 0,
),
'width' => array(
'weight' => 7,
'default' => $w ? $w : 50,
),
'height' => array(
'weight' => 8,
'default' => $h ? $h : 50,
),
'changed' => array(
'weight' => 0,
'default' => 0,
),
);
foreach ($node_field as $delta => $file) {
if ($file['filepath'] && !$file['flags']['delete']) {
$cropid = "{$fieldname}-{$delta}";
$form[$fieldname][$delta] = array(
'#theme' => 'imagefield_crop_edit_crop_image_row',
'#croparea' => $field['widget']['croparea'],
'#cropid' => $cropid,
);
$form[$fieldname][$delta]['flags']['delete'] = array(
'#type' => 'checkbox',
'#title' => t('Delete'),
'#default_value' => 0,
);
$filename = $file['fid'] == 'upload' ? file_create_filename($file['filename'], file_create_path($field['widget']['image_path'])) : $file['filepath'];
if (is_file($file['filepath']) && (list($width, $height, $type, $image_attributes) = @getimagesize($file['filepath']))) {
if ($field['widget']['enforce_ratio']) {
list($fw, $fh) = explode('x', $field['widget']['resolution']);
$ratio = $fw / $fh;
$image_ratio = $width / $height;
if ($ratio > $image_ratio) {
$height = $width / $ratio;
}
else {
$width = $height * $ratio;
}
$crop_attrs['changed']['default'] = $ratio != $image_ratio;
}
$crop_attrs['width']['default'] = $width;
$crop_attrs['height']['default'] = $height;
}
$form[$fieldname][$delta]['preview'] = array(
'#type' => 'markup',
'#value' => theme('imagefield_crop_crop_image', $file, $file['alt'], $file['title'], NULL, TRUE, "{$fieldname}-{$delta}"),
);
$form[$fieldname][$delta]['crop'] = array();
foreach ($crop_attrs as $attr => $value) {
$form[$fieldname][$delta]['crop'][$attr] = array(
'#type' => 'hidden',
'#title' => $attr,
'#size' => 4,
'#maxlength' => 25,
'#weight' => $value['weight'],
'#attributes' => array(
'class' => 'edit-image-crop-' . $attr,
),
'#value' => $file['crop'][$attr] ? $file['crop'][$attr] : $value['default'],
);
}
$cropped = $file['crop'];
$cropped['fid'] = 'upload';
$form[$fieldname][$delta]['crop']['preview'] = array(
'#type' => 'markup',
'#value' => theme('imagefield_image', $cropped, '', '', array(
'class' => 'imagefield-crop-image-preview',
)),
);
$form[$fieldname][$delta]['description'] = array(
'#type' => 'markup',
'#value' => '<strong>' . t('Filename: ') . '</strong>' . $file['filename'],
);
$form[$fieldname][$delta]['alt'] = array(
'#type' => 'hidden',
'#value' => $file['filename'],
);
if ($field['widget']['custom_alt']) {
$form[$fieldname][$delta]['alt'] = array(
'#type' => 'textfield',
'#title' => t('Alternate text'),
'#default_value' => $file['alt'],
'#description' => t('Alternate text to be displayed if the image cannot be displayed.'),
'#maxlength' => 255,
'#size' => 10,
);
}
$form[$fieldname][$delta]['title'] = array(
'#type' => 'hidden',
'#value' => $file['filename'],
);
if ($field['widget']['custom_title']) {
$form[$fieldname][$delta]['title'] = array(
'#type' => 'textfield',
'#title' => t('Title'),
'#default_value' => $file['title'],
'#description' => t('Text to be displayed on mouse overs.'),
'#maxlength' => 255,
'#size' => 10,
);
}
if (!$field['multiple']) {
$form[$fieldname][$delta]['replace'] = array(
'#type' => 'markup',
'#value' => t('If a new image is chosen, the current image will be replaced upon submitting the form.'),
);
}
}
elseif ($file['filepath'] && $file['flags']['delete']) {
$form[$fieldname][$delta]['flags']['delete'] = array(
'#type' => 'value',
'#value' => $file['flags']['delete'],
);
$form[$fieldname][$delta]['title'] = array(
'#type' => 'value',
'#value' => $file['title'],
);
$form[$fieldname][$delta]['alt'] = array(
'#type' => 'value',
'#value' => $file['alt'],
);
}
$form[$fieldname][$delta]['filename'] = array(
'#type' => 'value',
'#value' => $file['filename'],
);
$form[$fieldname][$delta]['filepath'] = array(
'#type' => 'value',
'#value' => $file['filepath'],
);
$form[$fieldname][$delta]['filemime'] = array(
'#type' => 'value',
'#value' => $file['filemime'],
);
$form[$fieldname][$delta]['filesize'] = array(
'#type' => 'value',
'#value' => $file['filesize'],
);
$form[$fieldname][$delta]['fid'] = array(
'#type' => 'value',
'#value' => $file['fid'],
);
$form[$fieldname][$delta]['crop']['filepath'] = array(
'#type' => 'value',
'#value' => $file['crop']['filepath'],
);
}
}
else {
if ($field['widget']['always_show']) {
$cropid = "{$fieldname}-0";
$form[$fieldname][0] = array(
'#theme' => 'imagefield_crop_edit_crop_image_row',
'#croparea' => $field['widget']['croparea'],
'#cropid' => $cropid,
);
$form[$fieldname][0]['preview'] = array(
'#type' => 'markup',
'#value' => theme('imagefield_crop_crop_image', NULL, '', '', NULL, FALSE, $cropid),
);
}
}
return $form;
}
function _imagefield_crop_verify_gd() {
if (image_get_toolkit() != 'gd') {
$toolkits = image_get_available_toolkits();
drupal_set_message(t('Image cropping only works with %toolkit. Please select it at !url, or ask your system administrator to do so', array(
'%toolkit' => $toolkits['gd'],
'!url' => l('Image Toolkit selection page', 'admin/settings/image-toolkit'),
)), 'error');
return FALSE;
}
return TRUE;
}
function _imagefield_crop_resize($src, $crop = NULL, $resize = 0, $dst = NULL) {
if (!is_file($src)) {
return FALSE;
}
if (!_imagefield_crop_verify_gd()) {
return FALSE;
}
$info = image_get_info($src);
if (!$info) {
return FALSE;
}
$unscaled = $src . '.unscaled';
if (is_file($unscaled)) {
$unscaled_info = image_get_info($unscaled);
$scale = array();
$scale['width'] = $unscaled_info['width'] / $info['width'];
$scale['height'] = $unscaled_info['height'] / $info['height'];
if (!empty($crop)) {
$crop['x'] *= $scale['width'];
$crop['y'] *= $scale['height'];
$crop['width'] *= $scale['width'];
$crop['height'] *= $scale['height'];
}
$src = $unscaled;
$info = $unscaled_info;
}
list($width, $height) = array(
$info['width'],
$info['height'],
);
if ($resize) {
list($width, $height) = explode('x', $resize);
}
elseif (!empty($crop)) {
list($width, $height) = array(
$crop['width'],
$crop['height'],
);
}
$im = image_gd_open($src, $info['extension']);
$res = imageCreateTrueColor($width, $height);
$background = imageColorAllocate($res, 255, 255, 255);
imageCopyResampled($res, $im, 0, 0, $src_x = $crop['x'] ? $crop['x'] : 0, $src_y = $crop['y'] ? $crop['y'] : 0, $width, $height, $src_w = $crop['width'] ? $crop['width'] : $info['width'], $src_h = $crop['height'] ? $crop['height'] : $info['height']);
$ratio_w = $width / $src_w;
$ratio_h = $height / $src_h;
imageFilledRectangle($res, 0, $ratio_h * ($info['height'] - $src_y), $width, $height, $background);
imageFilledRectangle($res, $ratio_w * ($info['width'] - $src_x), 0, $width, $height, $background);
if ($src_y < 0) {
imageFilledRectangle($res, 0, 0, $width, $ratio_h * -1 * $src_y, $background);
}
if ($src_x < 0) {
imageFilledRectangle($res, 0, 0, $ratio_w * -1 * $src_x, $height, $background);
}
$result = image_gd_close($res, empty($dst) ? $src : $dst, $info['extension']);
imageDestroy($im);
imageDestroy($res);
return $result;
}
function _imagefield_crop_scale_image($file, $field) {
if ($field['widget']['use_unscaled'] && $file['filepath'] != NULL) {
$unscaled = $file['filepath'];
file_copy($unscaled, $file['filepath'] . '.unscaled', FILE_EXISTS_REPLACE);
}
$file = _imagefield_scale_image($file, $field['widget']['croparea']);
return $file;
}
function theme_imagefield_crop_edit_crop_image_row($element) {
list($cropw, $croph) = explode('x', $element['#croparea']);
$cropid = $element['#cropid'];
$output .= '<div class="imagefield-crop-preview" style="width:' . $cropw . 'px; height:' . $croph . 'px">';
$output .= drupal_render($element['preview']) . '</div>';
if ($element['crop']) {
$output .= '<div class="imagefield-edit-image-detail" id="imagefield-edit-image-detail-' . $cropid . '">';
$output .= '<div class="imagefield-edit-image-flags">' . drupal_render($element['flags']) . '</div>';
$output .= '<div class="imagefield-edit-image-description">' . drupal_render($element['description']);
$output .= '</div>';
$output .= drupal_render($element['crop']);
$output .= drupal_render($element['alt']);
$output .= drupal_render($element['title']);
$output .= '</div>';
}
$output = '<div class="imagefield-edit-image-row clear-block" id="imagefield-edit-image-row-' . $cropid . '">' . $output . '</div>';
if (isset($element['replace'])) {
$output .= '<div class="imagefield-edit-image-replace">' . drupal_render($element['replace']) . '</div>';
}
return $output;
}
function theme_imagefield_crop_crop_image($file = NULL, $alt = '', $title = '', $attributes = NULL, $getsize = TRUE, $cropId = '') {
$output = '<div class="imagefield-crop-wrapper">';
if (!empty($file)) {
$file = (array) $file;
if (!$getsize || is_file($file['filepath']) && (list($width, $height, $type, $image_attributes) = @getimagesize($file['filepath']))) {
$alt = empty($alt) ? $file['alt'] : $alt;
$title = empty($title) ? $file['title'] : $title;
$url = $file['fid'] == 'upload' ? url($file['preview']) : file_create_url($file['filepath']);
$output .= '
<div id="image-crop-container-' . $cropId . '" class="image-crop-container"
style="background-image: url(\'' . $url . '\'); width:' . $width . 'px; height:' . $height . 'px; margin-left:-' . $width / 2 . 'px; margin-top:-' . $height / 2 . 'px;">
</div>
<div id="resizeMe-' . $cropId . '" class="resizeMe" style="background-image: url(\'' . $url . '\')">
<div id="resizeSE-' . $cropId . '" class="resizeSE"></div>
<div id="resizeE-' . $cropId . '" class="resizeE"></div>
<div id="resizeNE-' . $cropId . '" class="resizeNE"></div>
<div id="resizeN-' . $cropId . '" class="resizeN"></div>
<div id="resizeNW-' . $cropId . '" class="resizeNW"></div>
<div id="resizeW-' . $cropId . '" class="resizeW"></div>
<div id="resizeSW-' . $cropId . '" class="resizeSW"></div>
<div id="resizeS-' . $cropId . '" class="resizeS"></div>
</div>';
}
}
$output .= '</div>';
return $output;
}