Index: modules/image/image.css
===================================================================
RCS file: modules/image/image.css
diff -N modules/image/image.css
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/image/image.css	1 Sep 2009 12:16:27 -0000
@@ -0,0 +1,15 @@
+/* $Id$ */
+
+/**
+ * Image widget.
+ */
+div.image-preview {
+  float: left;
+  padding: 0 10px 10px 0;
+}
+div.image-widget-data {
+  float: left;
+}
+div.image-widget-data input.text-field {
+  width: auto;
+}
Index: modules/image/image.field.inc
===================================================================
RCS file: modules/image/image.field.inc
diff -N modules/image/image.field.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/image/image.field.inc	1 Sep 2009 12:16:27 -0000
@@ -0,0 +1,323 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Field hooks to provide an "image" widget for file fields.
+ */
+
+/**
+ * Implement hook_field_widget_settings_form().
+ */
+function image_field_widget_settings_form($field, $instance) {
+  $widget = $instance['widget'];
+  $defaults = field_info_widget_settings($widget['type']);
+  $settings = array_merge($defaults, $widget['settings']);
+
+  // Use the file widget settings form as a basis.
+  $form = file_field_widget_settings_form($field, $instance);
+
+  // Add maximum and minimum resolution settings.
+  $max_resolution = explode('x', $settings['max_resolution']) + array('', '');
+  $form['max_resolution'] = array(
+    '#title' => t('Maximum image resolution'),
+    '#element_validate' => array('_image_field_resolution_validate'),
+    '#theme_wrappers' => array('form_element'),
+    '#weight' => 3.1,
+    '#description' => t('The maximum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Leave blank for no restriction. If a larger image is uploaded, it will be resized to reflect the given width and height. Resizing images on upload will cause the loss of <a href="http://en.wikipedia.org/wiki/Exchangeable_image_file_format">EXIF data</a> in the image.'),
+  );
+  $form['max_resolution']['x'] = array(
+    '#type' => 'textfield',
+    '#default_value' => $max_resolution[0],
+    '#size' => 5,
+    '#maxlength' => 5,
+    '#field_suffix' => ' x ',
+  );
+  $form['max_resolution']['y'] = array(
+    '#type' => 'textfield',
+    '#default_value' => $max_resolution[1],
+    '#size' => 5,
+    '#maxlength' => 5,
+    '#field_suffix' => ' ' . t('pixels'),
+  );
+
+  $min_resolution = explode('x', $settings['min_resolution']) + array('', '');
+  $form['min_resolution'] = array(
+    '#title' => t('Minimum image resolution'),
+    '#element_validate' => array('_image_field_resolution_validate'),
+    '#theme_wrappers' => array('form_element'),
+    '#weight' => 3.2,
+    '#description' => t('The minimum allowed image size expressed as WIDTHxHEIGHT (e.g. 640x480). Leave blank for no restriction. If a smaller image is uploaded, it will be rejected.'),
+  );
+  $form['min_resolution']['x'] = array(
+    '#type' => 'textfield',
+    '#default_value' => $min_resolution[0],
+    '#size' => 5,
+    '#maxlength' => 5,
+    '#field_suffix' => ' x ',
+  );
+  $form['min_resolution']['y'] = array(
+    '#type' => 'textfield',
+    '#default_value' => $min_resolution[1],
+    '#size' => 5,
+    '#maxlength' => 5,
+    '#field_suffix' => ' ' . t('pixels'),
+  );
+
+  // Add settings for preview image style.
+  $form['preview_image_style'] = array(
+    '#title' => t('Preview image style'),
+    '#type' => 'select',
+    '#options' => array('' => '<' . t('no preview') . '>') + image_style_options(FALSE),
+    '#default_value' => $settings['preview_image_style'],
+    '#description' => t('The preview image will be shown while editing the content.'),
+  );
+
+  // Add title and alt configuration options.
+  $form['additional']['alt_field'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Enable <em>Alt</em> field'),
+    '#default_value' => $settings['alt_field'],
+    '#description' => t('The alt attribute may be used by search engines, screen readers, and when the image cannot be loaded.'),
+    '#parents' => array('instance', 'widget', 'settings', 'alt_field'),
+    '#weight' => -2,
+  );
+  $form['additional']['title_field'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Enable <em>Title</em> field'),
+    '#default_value' => $settings['title_field'],
+    '#description' => t('The title attribute is used as a tooltip when the mouse hovers over the image.'),
+    '#parents' => array('instance', 'widget', 'settings', 'title_field'),
+    '#weight' => -1,
+  );
+
+  return $form;
+}
+
+/**
+ * Element validate function for resolution fields.
+ */
+function _image_field_resolution_validate($element, &$form_state) {
+  if (!empty($element['x']['#value']) || !empty($element['y']['#value'])) {
+    foreach (array('x', 'y') as $dimension) {
+      $value = $element[$dimension]['#value'];
+      if (!is_numeric($value)) {
+        form_error($element[$dimension], t('Height and width values must be numeric.'));
+        return;
+      }
+      if (intval($value) == 0) {
+        form_error($element[$dimension], t('Both a height and width value must be specified in the !name field.', array('!name' => $element['#title'])));
+        return;
+      }
+    }
+    form_set_value($element, intval($element['x']['#value']) . 'x' . intval($element['y']['#value']), $form_state);
+  }
+  else {
+    form_set_value($element, '', $form_state);
+  }
+}
+
+/**
+ * Implement hook_field_widget_info().
+ */
+function image_field_widget_info() {
+  return array(
+    'file_image' => array(
+      'label' => t('Image'),
+      'field types' => array('file'),
+      'settings' => array(
+        'progress_indicator' => 'throbber',
+        'alt_field' => 0,
+        'title_field' => 0,
+        'description_field' => 0,
+        'max_resolution' => '',
+        'min_resolution' => '',
+        'preview_image_style' => 'thumbnail',
+        'default_file_extensions' => 'png gif jpg jpeg',
+      ),
+      'behaviors' => array(
+        'multiple values' => FIELD_BEHAVIOR_CUSTOM,
+        'default value' => FIELD_BEHAVIOR_NONE,
+      ),
+    ),
+  );
+}
+
+/**
+ * Implementation of hook_field_widget().
+ */
+function image_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) {
+  $elements = file_field_widget($form, $form_state, $field, $instance, $items, $delta);
+
+  $settings = $instance['widget']['settings'];
+  
+  foreach (element_children($elements) as $delta) {
+    // Add upload resolution validation.
+    if ($settings['max_resolution'] || $settings['min_resolution']) {
+      $elements[$delta]['#upload_validators']['file_validate_image_resolution'] = array($settings['max_resolution'], $settings['min_resolution']);
+    }
+
+    // If not using custom extension validation, ensure this is an image.
+    $supported_extensions = array('png', 'gif', 'jpg', 'jpeg');
+    $extensions = isset($elements[$delta]['#upload_validators']['file_validate_extensions'][0]) ? $elements[$delta]['#upload_validators']['file_validate_extensions'][0] : implode(' ', $supported_extensions);
+    $extensions = array_intersect(explode(' ', $extensions), $supported_extensions);
+    $elements[$delta]['#upload_validators']['file_validate_extensions'][0] = implode(' ', $extensions);
+
+    // Add all extra functionality provided by the image widget.
+    $elements[$delta]['#process'][] = 'image_field_widget_process';
+  }
+
+  if ($field['cardinality'] == 1) {
+    // If there's only one field, return it as delta 0.
+    if (empty($elements[0]['#default_value']['fid'])) {
+      $elements[0]['#description'] = theme('file_upload_help', $instance['description'], $elements[0]['#upload_validators']);
+    }
+  }
+  else {
+    $elements['#file_upload_description'] = theme('file_upload_help', '', $elements[0]['#upload_validators']);
+  }
+
+  return $elements;
+}
+
+/**
+ * An element #process callback for the file_image field type.
+ *
+ * Expands the file_image type to include the alt, title, and caption fields.
+ */
+function image_field_widget_process($element, &$form_state, $form) {
+  $item = $element['#value'];
+  $item['fid'] = $element['fid']['#value'];
+
+  $field = field_info_field($element['#field_name']);
+  $instance = field_info_instance($element['#field_name'], $element['#bundle']);
+  $settings = $instance['widget']['settings'];
+
+  $element['#theme'] = 'image_widget';
+  $element['#attached_css'][] = drupal_get_path('module', 'image') . '/image.css';
+
+  // Add the image preview.
+  if ($element['#file'] && $settings['preview_image_style']) {
+    $element['preview'] = array(
+      '#type' => 'markup',
+      '#markup' => theme('image_style', $settings['preview_image_style'], $element['#file']->uri, NULL, NULL, array(), FALSE),
+    );
+  }
+
+  // Add the additional alt and title fields.
+  $element['data']['alt'] = array(
+    '#title' => t('Alternate Text'),
+    '#type' => 'textfield',
+    '#default_value' => isset($item['data']['alt']) ? $item['data']['alt'] : '',
+    '#description' => t('This text will be used by screen readers, search engines, or when the image cannot be loaded.'),
+    '#maxlength' => variable_get('image_alt_length', 80), // See http://www.gawds.org/show.php?contentid=28.
+    '#weight' => -2,
+  );
+  $element['data']['title'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Title'),
+    '#default_value' => isset($item['data']['title']) ? $item['data']['title'] : '',
+    '#description' => t('The title is used as a tool tip when the user hovers the mouse over the image.'),
+    '#maxlength' => variable_get('image_title_length', 500),
+    '#weight' => -1,
+  );
+
+  // If fields are disabled, convert the type to "value" to save existing data.
+  if (!$settings['alt_field']) {
+    $element['data']['alt']['#type'] = 'value';
+    $element['data']['alt']['#value'] = $element['data']['alt']['#default_value'];
+  }
+  if (!$settings['title_field']) {
+    $element['data']['title']['#type'] = 'value';
+    $element['data']['title']['#value'] = $element['data']['title']['#default_value'];
+  }
+
+  return $element;
+}
+
+/**
+ * Implement hook_field_create_instance().
+ */
+function image_field_create_instance($instance) {
+  // If creating a new image widget, set some matching formatters.
+  if (isset($instance['widget']['type']) && $instance['widget']['type'] == 'file_image') {
+    if (!isset($instance['display'])) {
+      $instance['display']['full']['type'] = 'image';
+      $instance['display']['teaser']['type'] = 'image';
+    }
+    if (!isset($instance['settings']['file_extensions'])) {
+      $instance['settings']['file_extensions'] = 'png jpg gif';
+    }
+    field_update_instance($instance);
+  }
+}
+
+/**
+ * Theme the display of the image field widget.
+ */
+function theme_image_widget($element) {
+  $output = '';
+  $output .= '<div class="image-widget form-managed-file clearfix">';
+
+  if (isset($element['preview'])) {
+    $output .= '<div class="image-preview">';
+    $output .= drupal_render($element['preview']);
+    $output .= '</div>';
+  }
+
+  $output .= '<div class="image-widget-data">';
+  if ($element['fid']['#value'] != 0) {
+    $element['filename']['#markup'] .= ' <span class="file-size">(' . format_size($element['#file']->filesize) . ')</span> ';
+  }
+  $output .= drupal_render_children($element);
+  $output .= '</div>';
+  $output .= '</div>';
+
+  return $output;
+}
+
+/**
+ * Implement hook_field_formatter_info().
+ */
+function image_field_formatter_info() {
+  $formatters = array(
+    'image' => array(
+      'label' => t('Image'),
+      'field types' => array('file'),
+    ),
+    'image_link_content' => array(
+      'label' => t('Image linked to content'),
+      'field types' => array('file'),
+    ),
+    'image_link_file' => array(
+      'label' => t('Image linked to file'),
+      'field types' => array('file'),
+    ),
+  );
+
+  // TODO: Add image style formatters.
+
+  return $formatters;
+}
+
+/**
+ * Theme function for 'image' file field formatter.
+ */
+function theme_field_formatter_image($element) {
+  return theme('image', $element['#item']['uri'], $element['#item']['data']['alt'], $element['#item']['data']['title']);
+}
+
+/**
+ * Theme function for 'image_link_content' file field formatter.
+ */
+function theme_field_formatter_image_link_content($element) {
+  list($id, $vid, $bundle) = field_attach_extract_ids($element['#object_type'], $element['#object']);
+  return l(theme('field_formatter_image', $element), $element['#object_type'] . '/' . $id, array('html' => TRUE));
+}
+
+/**
+ * Theme function for 'image_link_file' file field formatter.
+ */
+function theme_field_formatter_image_link_file($element) {
+  return l(theme('field_formatter_image', $element), file_create_url($element['#item']['uri']), array('html' => TRUE));
+}
Index: modules/image/image.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/image/image.info,v
retrieving revision 1.2
diff -u -p -r1.2 image.info
--- modules/image/image.info	21 Jul 2009 07:09:46 -0000	1.2
+++ modules/image/image.info	1 Sep 2009 12:16:27 -0000
@@ -7,5 +7,6 @@ core = 7.x
 files[] = image.module
 files[] = image.admin.inc
 files[] = image.effects.inc
+files[] = image.field.inc
 files[] = image.install
 files[] = image.test
Index: modules/image/image.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/image/image.module,v
retrieving revision 1.16
diff -u -p -r1.16 image.module
--- modules/image/image.module	26 Aug 2009 03:20:39 -0000	1.16
+++ modules/image/image.module	1 Sep 2009 12:16:28 -0000
@@ -6,6 +6,9 @@
  * Exposes global functionality for creating image styles.
  */
 
+// Load all Field module hooks for Image.
+require_once DRUPAL_ROOT . '/modules/image/image.field.inc';
+
 /**
  * Implement of hook_help().
  */
@@ -126,6 +129,7 @@ function image_menu() {
  */
 function image_theme() {
   return array(
+    // Theme functions in image.module.
     'image_style' => array(
       'arguments' => array(
         'style' => NULL,
@@ -136,6 +140,8 @@ function image_theme() {
         'getsize' => TRUE,
       ),
     ),
+
+    // Theme functions in image.admin.inc.
     'image_style_list' => array(
       'arguments' => array('styles' => NULL),
     ),
@@ -160,6 +166,20 @@ function image_theme() {
     'image_rotate_summary' => array(
       'arguments' => array('data' => NULL),
     ),
+
+    // Theme functions in image.field.inc.
+    'image_widget' => array(
+      'arguments' => array('element' => NULL),
+    ),
+    'field_formatter_image' => array(
+      'arguments' => array('element' => NULL),
+    ),
+    'field_formatter_image_link_content' => array(
+      'arguments' => array('element' => NULL),
+    ),
+    'field_formatter_image_link_file' => array(
+      'arguments' => array('element' => NULL),
+    ),
   );
 }
 
@@ -464,7 +484,7 @@ function image_style_generate() {
   // acquiring the lock.
   $success = file_exists($destination) || image_style_create_derivative($style, $path, $destination);
 
-  if ($lock_acquired) {
+  if (!empty($lock_acquired)) {
     lock_release($lock_name);
   }
 
@@ -773,6 +793,7 @@ function image_effect_delete($effect) {
  *   TRUE on success. FALSE if unable to perform the image effect on the image.
  */
 function image_effect_apply($image, $effect) {
+  module_load_include('inc', 'image', 'image.effects');
   if (function_exists($effect['effect callback'])) {
     return call_user_func($effect['effect callback'], $image, $effect['data']);
   }
@@ -810,7 +831,7 @@ function theme_image_style($style_name, 
   if (!file_exists($style_path)) {
     $style_path = image_style_url($style_name, $path);
   }
-  return theme('image', file_create_url($style_path), $alt, $title, $attributes, $getsize);
+  return theme('image', $style_path, $alt, $title, $attributes, $getsize);
 }
 
 /**
