Cropping and Resizing Animated Gifs with Gifsicle 您所在的位置:网站首页 newimage/wfish4.gif Cropping and Resizing Animated Gifs with Gifsicle

Cropping and Resizing Animated Gifs with Gifsicle

2022-03-26 12:02| 来源: 网络整理| 查看: 265

I recently had an interesting request on a client project: how can we resize animated gifs without losing the animation in the thumbnails? WordPress lets you upload animated gifs, but as soon as it resizes them the thumbnails are decidedly less animated.

Generating a thumbnail could take your gif from this:

Ron Burgundy and the Channel 4 News Team jumping for joy

You can feel the joy!

…to this:

A still frame from the Anchorman "Yay" gif.

Why does that one statue kind of look like Paul Rudd?

As a purveyor of fine, animated gifs, I can tell you that an animated gif with no animation is no gif worth having!

Fortunately, there’s a free, open-source library called Gifsicle designed to manipulate animated gifs. The fun part is using Gifsicle to resize your gifs for you, automatically.

Note: since the work that I do for clients is technically work-for-hire, I can’t just wholesale include the plugin I wrote. I’m hoping to get them to release it publicly in the future, but until then I’ll instead have to teach you how to work with Gifsicle; “teach a man to fish,” and all that.Give a man a fish and feed him for a day. Don't teach a man to fish...and feed yourself. He's a grown man. And fishing's not that hard. Determining image sizes

The hardest part of resizing any image, animated or not, is determining its target dimensions and cropping. In WordPress, we can make the platform do the heavy lifting, using image_resize_dimensions():

PHP 12345678910 $source = getimagesize( $file ); // $width and $height represent the target dimensions.$dimensions = image_resize_dimensions(  $source[0],   $source[1],   $width,   $height,   true );

Luckily, the return value of image_resize_dimensions() is an array that closely matches the arguments of PHP’s imagecopyresampled() function; if you’re not using WordPress pretty much any resizing tutorial that has you preparing values for imagecopyresampled() should give you the values you need:

$dst_x x-coordinate of destination point. $dst_y y-coordinate of destination point. $src_x x-coordinate of source point. $src_y y-coordinate of source point. $dst_w Destination width. $dst_h Destination height. $src_w Source width. $src_h Source height. Resizing the images with Gifsicle

There are libraries available for interacting with Gifsicle from PHP, but those who have seen my Building for the PHP Command Line Interface talk know that we can actually execute system commands from within PHP, using functions like passthru(). Once Gifsicle is installed on your server, using it from within PHP will look something like this:

PHP 12345678910111213 try {  if ( ! exec( 'which gifsicle' ) ) {    throw new Exception( 'Unable to find Gifsicle!' );  }   $command = 'gifsicle {some args}';   // Execute the command.  passthru( $command ); } catch ( Exception $e ) {  error_log( 'Unable to resize gif: ' . $e->getMessage() );}

This lets us execute Gifsicle the same as we would via the command line (because – technically – we are)!

Building the arguments

Now comes the fun part: assembling the right arguments. Since the majority of you reading this page are more likely just looking for the answer, I’ll lead with that, then break it down:

PHP 12345678910111213 $command = sprintf(  'gifsicle --crop %s --resize %s %s > %s',  escapeshellarg( sprintf(    '%d,%d-%d,%d',    $src_x,    $src_y,    $src_w - $src_x,    $src_h - $src_y  ) ),  escapeshellarg( sprintf( '%dx%d', $dst_w, $dst_h ) ),  escapeshellarg( $file ),  escapeshellarg( $destination ) );

Well, that was easy, wasn’t it? In case you’re not well-versed in juggling arguments and using PHP to assemble CLI commands, we’ll apply some real numbers: let’s say we have this gif of America’s Sweetheart, Nick Offerman:

Nick Offerman breakdancing

The original dimensions of this image are 500×281, approximately a 16:9 aspect ratio. Now, let’s say we want a square version of that same image, at 150×150. In order to achieve this, we need to perform two operations: resizing the image to fit as much of it as possible into a 150×150 box, then crop off anything outside that area.

Fortunately, resizing the image is easy: Gifsicle has a --resize option, and the math that led us to our getimagesize()-compatible calculations up above would tell us that to fit a 500×281 image in a 150×150 box, our target dimensions would be 267×150.

Confused? Just remember that we have a 16:9 aspect ratio, meaning the height is the smaller dimension and thus cannot end up smaller than 150px or we risk our 150×150 frame not being filled. Given the height, we can calculate the width thusly: $src_width / $src_height * $dst_height, or 500 / 281 * 150, which gives us a width of 267px.

With these numbers at hand, we can ask Gifsicle to resize our image to 267×150:

1 $ gifsicle --resize 267x150 original.gif > resized.gif

Of course, that’s just going to give us a Gif that’s 150px tall, but not a 150×150 square. To do this, we’ll need to add the --crop option:

12 gifsicle --crop 0,0-281x281 --resize 150x150 \  original.gif > resized-cropped.gif

Did you catch that “0,0” at the beginning of the --crop option? By default, Gifsicle will want to draw the crop from the top-left corner, giving us something like this (I’ve masked the cropped area rather than directly cropping the image):

Offerman's still dancing, but the entire right side of the image is missing.

That’s not bad, but Jimmy Fallon’s reaction to Offerman’s breakdancing helps sell the gif. If we can calculate the starting point along the horizontal axis to get the center, we can get a much more appealing image.

It’s worth mentioning that, according to the Gifsicle documentation, “[cropping] takes place before any rotation, flipping, resizing, or positioning.” This means that our calculations around the center of the image will need to be based on the source image’s coordinates, not the target size. In the case of our Offerman gif, that means drawing a 281×281 square smack-dab in the center:

Nick Offerman breakdancing with portions of the image outside of our crop zone masked out.

Whoa, that’s a much more interesting image, isn’t it?

Calculating the starting point is just a matter of doing some simple math: ($src_width - $dest_width) / 2, or (500 - 281) / 2, which gives us 109. With that value, we can tell Gifsicle to start the cropping at coordinates (109, 0):

12 gifsicle --crop 109,0+281x281 --resize 150x150 original.gif \  > resized-cropped-centered.gif

Now that we have the hard-coded version, we’ll break this up into placeholders (using proper escaping for shell arguments, of course) and we’ll find ourselves with the full, variable-filled version we had before!

Gotchas

You may have noticed there’s a bit of math involved with resizing images; it’s nothing that requires an advanced degree, but it’s still not how I’d like to spend my afternoon. Even if you’re not using WordPress, I’d encourage you to look at the image_resize_dimensions() function and how it’s implemented; this is a geometry problem that’s been solved before, so there’s no need to reinvent the wheel.

You may also notice that there was some rounding going on, even in my examples. In my testing, I’ve found that gifs with even dimensions (e.g. 500×280 instead of 500×281) tend to resize much cleaner and with less distortion. The smaller you go, the harder Gifsicle has to work to round everything out; in fact, you may find that gifs with smaller dimensions sometimes carry a larger filesize.

Finally, I’ll remind you that while gifs can be a lot of fun, they’re not always the best way to convey a message. A page full of gifs can make even a beefy computer or device strain itself, so just because you can bombard your users with animations doesn’t mean that you should (at least, if you care about user experience). Also, as with any media meant to convey meaning on the web, please make sure you’re including relevant alternative text.

Now, go forth and gif!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有