Image field: mark an image as a "cover photo" with a radio button
One approach would be to use file entity and add a field to the image file entity, but that would require re-working your current solution quite a bit.

Another approach would be to use the

Field Attach API

e.g:


field_attach_form
field_attach_submit


to attach the additional field to the image. The field would then need to be checked during output to show/hide that image as the cover image.

Update:

Here's an example to add a checkbox to an image field. I had some settings on the instance form to show/hide the extra fields, removed for conciseness here. You may be able to use hook_field_attach_form though I used a element process hook instead.

/**
 * Implements hook_element_info().
 */
function MODULE_element_info() {
  $extra = array(
    '#process' =&gt; array('MODULE_element_process'),
  );

  $elements = array();
  // Add our process function to all managed_file elements
  $elements['managed_file'] = $extra;

  return $elements;
}

/**
 * An additional preprocess callback to append the form.
 */
function MODULE_element_process($element, $form_state, $complete_form) {

  if (!isset($element['#entity_type']) || !isset($element['#field_name'])) {
    return $element;
  }

  // You can get the field data, settings etc.. like this
  $item = $element['#value'];
  $field = field_info_field($element['#field_name']);
  $instance = field_info_instance($element['#entity_type'], $element['#field_name'], $element['#bundle']);
  $settings = $instance['settings'];
  $widget_type = $instance['widget']['type'];

  // Add element, only if file id available
  if ($element['fid']['#value']) {
    // Note default value selects from cache / db table TABLE_file_data
    $element['cover'] = array(
     '#type' =&gt; 'checkbox',
     '#title' =&gt; t('Cover'),
     '#default_value' =&gt; MODULE_file_data_value($element['fid']['#value'], 'cover', '')
    );
  }

  return $element;

}

/**
 * Implements hook_field_attach_presave
 *
 * Saves a files additional field data.
 */
function MODULE_field_attach_presave($entity_type, $entity) {
  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
  $supported_widgets = array('image_image', 'imagefield_crop_widget');
  $instances = field_info_instances($entity_type, $bundle);
  foreach ($instances as $field_name =&gt; $instance) {
    if (in_array($instance['widget']['type'], $supported_widgets)) {

      $settings = $instance['settings'];
      // I have some settings I check as well, if enabled on field instance..
      //if (empty($settings['display_cover'])){
      //  continue;
      //}
      // Find all of the field items.
      $items = field_get_items($entity_type, $entity, $instance['field_name']);

      if (is_array($items)) {
        // Loop over and save extended field values
        foreach ($items as $delta =&gt; $item) {
          $fields = array();
          if (!empty($item['fid'])) {
            if(isset($item['cover'])){
              $fields['cover'] = $item['cover'];
            }
            $fields['changed'] = REQUEST_TIME;
            db_merge('TABLE_file_data')
              -&gt;key(array('fid' =&gt; $item['fid']))
              -&gt;fields($fields)-&gt;execute();
            // Need to clear entity cache for this file
            // as update was not with api but direct query
            cache_clear_all($item['fid'], 'cache_entity_file');
          }
        }
      }
    }
  }
}