EXIF Again

Earlier this year, I talked about how I’d persuaded WordPress to automagically fill in some fields for me when I upload pictures. I was moderately pleased with the results, but the formatting of EXIF data was a bit restricted by the way it was being inserted as part of the image caption. I’d probably have let it go, but the recently released WordPress 3.5 has a shiny new form for uploading images, and in the finest tradition of shiny new things, it broke my bit of borrowed and tweaked code.

In particular, it had stopped filling in the Alternative text field in the form. I tried a few basic tweaks, which helpfully inserted a new field in the form with the data, which wasn’t quite what I wanted at all. So I did some reading, and found where the text was being stored[1], and how to change it. Woo, hoo, etc.

And since I was doing some tweaking anyway, I wondered if I could put the EXIF data in that Description box and leave the Caption to be, well, the caption. I soon found that I could, and ended up with a new function (which you will note is simpler than the mess of code I had previously):

add_action( 'add_attachment', 'lcb_populate_image_fields' );
function lcb_populate_image_fields($id) {
$attachment = & get_post( $id, ARRAY_A );
if ( !empty( $attachment ) ) {
$attachment['post_excerpt'] = $attachment['post_title'];
$attachment['post_content'] = '[exif id="' . $id .'"
    show="camera,aperture,iso,shutter,focus,location,time"]';
update_post_meta($id,'_wp_attachment_image_alt', $attachment['post_title']);
wp_update_post($attachment);
}
}

Which will fill in the boxes based on the title of your image, or the filename if it doesn’t have an actual EXIF Title:

Attachment

Attachment

The next question was how to actually insert that Description into my posts. Once again, a bit of reading turned up some examples, which looked reasonable enough, but didn’t actually work as expected. The way to do it is to replace the standard Caption shortcode function with your own, which is the kind of thing WordPress makes nice and simple. The trouble was that the examples I’d seen were based on an older version of WordPress, and were therefore breaking. It was a reasonably simple matter to copy the standard function, which lives in media.php in the wp-includes folder, and add in the extra code to insert the description. Like the other code, I put this in my own Functionality Plugin rather than in any theme’s functions.php – this means the code will always work even if I change themes for any reason. So here’s that modified shortcode function:

add_shortcode('wp_caption', 'custom_img_caption_shortcode');
add_shortcode('caption', 'custom_img_caption_shortcode');

function custom_img_caption_shortcode($attr, $content = null) {
	if ( ! isset( $attr['caption'] ) ) {
        	if ( preg_match( '#((?:<a [^>]+>\s*)?<img [^>]+>(?:\s*</a>)?)(.*)#is', $content, $matches ) ) {
			$content = $matches[1];
			$attr['caption'] = trim( $matches[2] );
		}
	}

	// Allow plugins/themes to override the default caption template.
	$output = apply_filters('img_caption_shortcode', '', $attr, $content);
	if ( $output != '' )
		return $output;

	extract(shortcode_atts(array(
		'id'	=> '',
		'align'	=> 'alignnone',
		'width'	=> '',
		'caption' => ''
	), $attr));

	if ( 1 > (int) $width || empty($caption) )
		return $content;

// Grab ID to query post_content [description] field for image
	preg_match('/([\d]+)/', $id, $matches);

	$description = '';
	if ($matches[0]) {

		global $wpdb;
		$custom_description = $wpdb->get_row("SELECT post_content FROM $wpdb->posts WHERE ID = {$matches[0]};");

		if ($custom_description->post_content) {

			$description = '<div class="wp-custom-description">'. $custom_description->post_content . '</div>';

		}
	}

	if ( $id ) $id = 'id="' . esc_attr($id) . '" ';

	return '<div ' . $id . 'class="wp-caption ' . esc_attr($align) . '" style="width: ' . (10 + (int) $width) . 'px">'
	. do_shortcode( $content ) . '<p class="wp-caption-text">' . $caption . '</p></div>' . $description;
}

Then it was just a matter of fiddling with some custom CSS to make it look nice. I decided to slightly adapt some existing CSS that I’ll mention in another post. I fiddled around a bit until I got something that looks reasonable. I put this in the Custom CSS section of the Jetpack plugin rather than in the theme’s style.css for reasons I’ll explain later:

.exif {
	display: block;
	margin: 0 auto 5px;
	border-radius: 4px;
	-moz-border-radius: 4px;
	-webkit-border-radius: 4px;
	padding: 5px 10px;
	background: #eee;
	width: 400px;
	font-size: 80%;
	color: #333;
}

p.wp-caption-text {
	margin-bottom: 5px;
}

So there it is. Any images I upload have their EXIF data inserted in a nice block below the caption. Now I just have to tidy up older posts to make them consistent. I’ve only got about 200 of those to do…

[1] All the other bits – Title, Caption and the optional Description are stored as part of the record for the image attachment, which is a special kind of post. But the Alt text is stored as metadata in a separate table. There’s probably a Good Reason for that, but I don’t know what it is offhand.

2 thoughts on “EXIF Again

  1. Pingback: Yes, it’s another new look | Losing it

  2. Pingback: They took my title away! | Losing it

Comments are closed.