Entity view (Content)

Speeding up manual image cropping

By kmoll
Dec. 1, 2014

Images are an important part of any website and for some media companies they are the most important part. Sites need to take big images and display them in different sizes throughout the site. There may need to be a small thumbnail sized image for a listing, or a bigger sized image for a main article photo. Thankfully Drupal provides image styles to assist in this. All you need to do is create an image style that defines a width and height and Drupal will automatically create an image with those dimensions. You can even specify if you wan it to scale the image down, so it’s the entire image, just smaller, or crop the image, which would just a section of the image. Very convenient. The problem is that the crop that Drupal will select might not be what you want. If you have an image of some friends, it could crop their faces right out of the image. Not exactly ideal.

There are many modules that have been created to solve this problem. Many of them allow you to select the crop for each image style. Many of these are great modules and I’ve used a few of them before. But the one thing they all lack is a UI that allows users to quickly and easily select a crop by removing steps in the workflow. For most of these modules, you have to select and image style, select a crop, click save which will bring you back to the edit form and repeat. For companies trying to shorten and editor’s workflow, this process can be a bit daunting.

While working on a project at Time Inc., the main goal was to shorten the process and make it easy for editors to select the crops quickly and easily. Thankfully, one of Time Inc. brands, Sports Illustrated was already working on the problem. They came up with a UI that listed the image styles on the left and the full sized image on the right. We inserted JCrop, a javascript library to select a section of the page, and allowed users to select the part of the image they wanted use as the crop. All that was needed was to work this into Drupal’s image style system so that Drupal would create and render an image with that particular crop when requested by a page.

Let's take a look at whats was needed to do that.

First, we wanted to create our own image effect. This will allow us to only target image styles we to allow manual cropping on, and allow other to function as they would without manual cropping. To do this, we implement

hook_image_effect_info ()

You can read the docs to get a detailed explanation of the variables involved, but basically you define a set of call backs to for the settings form, and what function to call to crop the image. Once we have our effect, all we need to do is create an image style and apply our effect to it and give it a height and a width.

Now that we have our image effect and image styles, we need a page to display it. We can create a menu call back which will add our page to the list of items in the menu on the node form.

/** * Implements hook_menu(). */ function mymodule_menu() { $items = array(); $items['node/%node/crop'] = array( 'title' => 'Crop Image', 'description' => 'Edit and crop a image.', 'page callback' => 'mymodule_crop, 'page arguments' => array(1), 'access callback' => TRUE, // should set to a permission to allow certain users to crop. 'type' => MENU_LOCAL_TASK, 'weight' => 50, ); $items['admin/config/mymodule/save'] = array( 'title' => 'Temp Image Crop Validate URL', 'description' => 'Save cropped photos.', 'page callback' => 'mymodule_save', 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); return $items; }

Our callback for this menu will grab all the image styles we applied our effect to and the dimensions of those effects. We’ll use this info to create links or buttons on the left side for each style. This way we can allow the user to stay on the same page and allow them to set the crops for all the image styles without having to got back to the origin page (the node edit form) every time they save a crop. Well use the second item in our hook_menu() to save the information we pass from our UI with an AJAX call.

That section of our template would look like this:

$style) : ?> $effect) : ?>  

Selecting a different button will update the dimensions of the cropped area. Users can quickly go through and select a crop for each image style while staying on the same page.

Jcrop is a wonderful tool for selecting sections of an image. I won’t get into the details as the jcrop site provides a simple tutorial on how to use their library. All we do is implement that same process and add a “Save” button. We attach an ajax call to that button to send the data about the crop to our, along with the node and image style to our callback we defined in hook_menu(). We need to store that information in a database table for use in our callbacks we defined in our hook_image_effect_info().

Now when there is a request for our image, we grab the data about the crop, the height, width, x and y coordinates, and pass it to image_crop_effect(). This will create an image with the dimensions and area of the selected crop to be used in the page. Note that with image styles, the image is only created once and stored (cached) so that subsequent requests just pulls the image already created.

Post Tags: