How do I alter image field code without hacking core? I need to change the style of the title in image field to be a text area rather than a text field. I can achieve this by hacking core in the following way:

image.field.inc line 410

$element['title'] = array(
    '#type' =&gt; 'textarea',
    '#title' =&gt; t('Title'),
    '#default_value' =&gt; isset($item['title']) ? $item['title'] : '',
    '#description' =&gt; t('The title is used as a tool tip when the user hovers the mouse over the image.'),
    '#maxlength' =&gt; variable_get('image_title_length', 500),
    '#weight' =&gt; -1,
    '#access' =&gt; (bool) $item['fid'] &amp;&amp; $settings['title_field'],
  );

// Change '#type' =&gt; 'textarea'  to '#type' =&gt; 'textfield'


I don't though, want to hack core.
How can I create a preprocess function to allow me to do this via my template.php.
You won't (easily) be able to use a preprocess function to do this as the element is generated by a form. 

You could use a non-generic hook_form_alter() implementation to do this on a single form, but the best way would be to write a small custom module and implementhook_field_widget_form_alter() to override the element.

The alt and title fields (along with some others) are only added in a #process function of each image element (image_field_widget_process()), so you'll need to add your own #process function to run after that one, and alter the field type in there.

The following code is tested and seems to work well (including playing nicely with the AJAX functionality on the image field):

function MYMODULE_field_widget_form_alter(&amp;$element, &amp;$form_state, $context) {
  // If this is an image field type
  if ($context['field']['type'] == 'image') {
    // Loop through the element children (there will always be at least one).
    foreach (element_children($element) as $key =&gt; $child) {
      // Add the new process function to the element
      $element[$key]['#process'][] = 'MYMODULE_image_field_widget_process';
    }
  }
}

function MYMODULE_image_field_widget_process($element, &amp;$form_state, $form) {
  // Change the title field to a textarea
  $element['title']['#type'] = 'textarea';

  // Return the altered element
  return $element;
}


It produces results like this:



It might be worth bearing in mind that the maximum size of the title column is set in the database, so you won't be able to go any higher than 1024 characters.