[Gist] Regular expression for ImageMagick “Geometry”

Some time ago, I created ImageMagickPHP, a PHP library that allows you to create ImageMagick commands similar to what we can do in command line with convert or mogrify for example.

This lib is still a “Work in progress” because I don’t have much time to work on it, but it stores all command instructions, you’re able to prepend/append informations depending on the instruction type, etc., and when you run the command you get a CommandResponse object that you can use to check whether the command failed or not.

But, the hardest part of this library was that when processing images, for example if you want to resize it, you need to pass a Geometry argument, which represents the “way you want to resize” your image.

For example you can use this:

This will resize to 250×350 but will keep proportions and ratio, so if your image is a square of 1500×1500 pixels, it will be resized to the lowest value of the ratio, so your image will be 250×250 in fine.

There are plenty of other things you can do with Geometry arguments.

For example, you can crop an image.

Let’s get an example:

We want to crop this image:

Orbitale logo

We’ll crop it to get just a portion of the center of the image.

As a reminder, it’s 322×322 px wide.

Here’s the result:

output

 

The Geometry argument was the following: 160×160+80+80.

Images are analyzed as bitmaps, so if I say “coordinates 0,0” it is interpreted as the top left of the picture. The first value is the offset “to the bottom”, and the second is the offset “to the right”.

So with the above command, we want a picture that is 160×160 pixels wide and that starts 80px to the bottom and 80px to the right.

What was cropped actually was this:

final

The problem is that Geometry arguments are veeeeeery complex to parse.

If you read the docs of the Geometry argument, you may have noticed that it’s extremely flexible but some parts are very restrictive. For example, you can use 200×250200 (only 200 with), ×250 (only height), but not 200× because it’s an error.

There are more tricks and I’m not going to tell about all of them, but I had to think very hard when I wanted to validate the Geometry option in the ImageMagick PHP command.

As you can see in the GeometryTest class, I tested all different geometry combinations and asked ImageMagick whether it works or not. Some fails were surprising, some not.

But the validator was made from this tests, actually. I developed the regexp at first, but it did not suit effectively my needs, so I developed all tests and then adapted my regexp to what ImageMagick answered me (success or failure).

First, I had to check that numbers were valid. In fact, numbers are restricted to a single pattern in ImageMagick commands, so I used it in all other portions of the regexp.

Then, we need to check width and height, which can be both present or not, and which can be calculated in percentage OR in pixels.

Then, the aspect ratio flag, which can be present only if width and/or height are present.

After that, the offset, which can be present even if there are no width nor height.

Thanks to the great PCRE regexp I could add identifiers to each part of the regexp so a preg_match would allow using the  $matches argument to retrieve all Geometry informations if one need them.

Here is the final result of the regexp, and don’t cry:

Leave a Reply