Skip to content

Instantly share code, notes, and snippets.

@DrewAPicture
Forked from NateWr/imager-for-wp.php
Created March 12, 2014 23:06
Show Gist options
  • Save DrewAPicture/9518468 to your computer and use it in GitHub Desktop.
Save DrewAPicture/9518468 to your computer and use it in GitHub Desktop.
<?php
/**
* Integrate Imager.js with WordPress
*
* Imager.js is BBC's solution for serving responsive and retina images, without
* the double payload issues that affect other solutions. For more information:
*
* https://github.com/BBC-News/Imager.js/
*
* This collection of functions modifies the output of WordPress's
* the_post_thumbnail() function, as well as the default gallery, to comply
* with Imager.js's formatting. But it is not a complete solution. You'd need
* to set up the proper image sizes in the $retina_image_sizes array below,
* integrate the Imager.js library, and initialize it on the .imager-placeholder
* class.
*
* This code has not been banged around much. I'm posting it up early in the
* hope that someone can help me figure out how to integrate Imager.js with
* inline images as well as the attachment pages. I have searched through the
* code as best I can, but inline images represent a pretty complex problem,
* because the output is saved directly in the editor. I don't really want to
* filter the_content() with a big preg_match either, because that seems pretty
* taxing for the server.
*
* Version: 0.0.1
* Author: Nate Wright
* Author URI: https://github.com/NateWr
* License: GNU General Public License v2.0 or later
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
*/
/**
* Your theme needs to define a set of image sizes that should be "retina'd".
* This array needs to be accessible from imager_rename_retina_images().
*
$retina_image_sizes = array(
'sample-sml' => array( 140, 140 ),
'sample-med' => array( 340, 340 ),
'sample-lrg' => array( 600, 600 )
);
*
* Then loop over each image size and register a 2x version...
*
foreach ( $retina_image_sizes as $id => $size ) {
add_image_size( $id, $size[0], $size[1], true );
add_image_size( $id . '-2x', ( $size[0] * 2 ), ( $size[1] * 2 ), true );
}
*
* ...then let the magic work.
*/
/**
* Rename the 2x image size filenames so they are compatible with imager.js
*
* @h/t http://wordpress.stackexchange.com/questions/123240/rename-image-uploads-replacing-width-and-height-in-filename-with-medium
* @since 0.0.1
*/
if ( !function_exists( 'imager_rename_retina_images' ) ) {
function imager_rename_retina_images( $image ) {
// Split the $image path into directory/extension/name
$info = pathinfo($image);
$dir = $info['dirname'] . '/';
$ext = '.' . $info['extension'];
$name = wp_basename( $image, $ext );
// Get image information
$img = wp_get_image_editor( $image );
$img_size = $img->get_size();
// Pull in the array of retina images somehow
global $retina_image_sizes;
// Modify filenames for retina image sizes
foreach ( $retina_image_sizes as $id => $size ) {
if ( $img_size['width'] == ( $size[0] * 2 ) && $img_size['height'] == ( $size[1] * 2 ) ) {
$name = str_replace(
array( $img_size['width'], $img_size['height'] ),
array( $size[0], $size[1] ),
$name
);
$name .= '-2x';
}
}
// Rename our new image
$new_name = $dir . $name . $ext;
$did_it = rename( $image, $new_name );
if( $did_it ) {
return $new_name;
}
return $image;
}
} // endif;
add_filter( 'image_make_intermediate_size', 'imager_rename_retina_images' );
/**
* Redefine an image's attributes to output a placeholder div compatible with
* imager.js responsive and retina image replacement.
*
* @since 0.0.1
*/
if ( !function_exists( 'imager_image_attributes' ) ) {
function imager_image_attributes( $attr, $attachment ) {
// This prevents it from firing without the full image src
if ( strpos( $attr['class'], 'attachment-full' ) !== false ) {
$attr['data-src'] = get_imager_src( $attr['src'] );
$attr['data-alt'] = $attr['alt'];
$attr['data-class'] = $attr['class'];
$attr['class'] = 'imager-placeholder';
// Encode a 1x1 transparence pixel for the src attribute, in order to
// prevent the browser making another request to the server. Note that this
// incures a small performance hit on mobile devices, which must decode the
// image. I don't know enough about CPU issues to know whether this is
// significant.
$attr['src'] = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D';
unset( $attr['alt'] );
}
return $attr;
}
} // endif;
add_filter( 'wp_get_attachment_image_attributes', 'imager_image_attributes', 100, 2 );
/**
* Set the post thumbnail size to "full", so that we retrieve the image path
* with no image dimensions. That way we can easily tack on the imager.js
* attributes as needed.
*
* @since 0.0.1
*/
if ( !function_exists( 'imager_post_thumbnail_size' ) ) {
function imager_post_thumbnail_size( $size ) {
return 'full';
}
} // endif;
add_filter( 'post_thumbnail_size', 'imager_post_thumbnail_size' );
/**
* Filter gallery shortcode so that it retrieves the filename for the full
* image, which we need to output a proper imager.js data-src attribute.
*
* @since 0.0.1
*/
if ( !function_exists( 'imager_gallery_atts' ) ) {
function imager_gallery_atts( $out, $pairs, $atts ) {
$out['size'] = 'full';
return $out;
}
add_filter( 'shortcode_atts_gallery', 'imager_gallery_atts', 10, 3 );
}
/**
* Generate a data-src attribute for an image placeholder with imager.js
*
* @since 0.0.1
*/
if ( !function_exists( 'get_imager_src' ) ) {
function get_imager_src( $url ) {
$parts = pathinfo( $url );
return trailingslashit( $parts['dirname'] ) . $parts['filename'] . '-{width}{pixel_ratio}.' . $parts['extension'];
}
} // endif;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment