Subscribe to Developer OraclesNews FeedSubscribe to Developer OraclesComments — Translate page:        

How to save the images processed with Imagick as file

August 4, 2008 by methode  
Filed under IMagick

Scenario: You created with Imagick a cool thumbnail, and now you want to send it to a buffer other than the browser window. We already saw that it’s possible to process images on-the-fly, for example you have a 1024*768 wide image and you want to show its thumbnail version without having a thumbnail for the respective image. So what we do now is the exact opposite: we load the image in Imagick, process it, then save as a file. Probably this is the most encountered situation when processing images.

Let’s see the code, then I explain it step by step, as usual:

$im = new Imagick('/path/to/your/image.jpg');
$im->thumbnailImage( 100, null );
$fp =fopen('/path/to/the_new/thumbnail.jpg', 'w');
@fwrite($fp, $im);
@fclose($fp);

Now the explanation:

  1. st line: we loaded the image in Imagick, it’s now ready to be processed
  2. nd line: this time we create a thumbnail, store it in memory/cache: the X axis to be 100 pixels and preserve aspect ratio by setting the second parameter to ‘null’
  3. rd line: create a new file, you specify the path. The file shouldn’t exist, but all the directories Yes! W means we open the file for write
  4. th line: we write the Imagick object’s ($im) content in the open file
  5. th line: and finally, we close the file

That was all. We saved again the world.

As always, if you have questions regarding the post, drop a comment and will try to answer as soon as possible.

Filter your variables easily but like a pro!

July 13, 2008 by methode  
Filed under Development, PHP

How painful input validation is! Think about all the possible threats, combination of threats… think with the users’ mind. It’s a pain. And usually who can write scripts which filters effectively the user inputs is considered a pro, without hesitation. Just because it’s hard to do it.
Take the following scenario: you have a text-field which accepts text as user comment. You don’t want to let the user to use HTML in the comment box, and definitely not to allow the user to put javascript in the comment.
So how do you sanitize the string you get? It’s a long and hard way. You would use RegExp to exclude some entities then some php inbuilt functions to encode the remaining or even better to strip tags.
I show you an easier way:

filter_var(’<script>alert('Hello');</script>', FILTER_SANITIZE_STRING);

Done, the <script> tags will be stripped so the string will arrive in the database as alert(’Hello World’).
There are many available filters, just to mention the most interesting ones:

  • FILTER_SANITIZE_EMAIL — it sanitizes email address, strips characters which are not in conformance with the applicable RFC (link)
  • FILTER_SANITIZE_URL — whether the URL from the variable is in conformance with the applicable RFC (link)
  • FILTER_VALIDATE_IP — whether if the input is an IP address or not

I recommend using the filter_var() function and its filters for two obvious reasons: it saves you a lot of headaches and saves you time. Even though the filter_var function was introduced only in php 5.2 the function is extremely useful and gives another reason for you of why to upgrade to php5 ;)

For a complete reference please check php.net.

Additional tweaks to tighten php

July 13, 2008 by methode  
Filed under PHP, Server Management

Believe me or not, the resource limiting of PHP can also be an enormous security factor.
Take this scenario: Mr. John Hacker managed somehow to upload to your server a script, let’s say an IRC bot which eats up computing power and RAM. Your server became inaccessible due to the running script, who your regular users blame? You, of course, who else?
Php has some very neat settings you can tweak in order to limit its memory usage, to expose what version of php you are using or not, and others.
Let’s start from the beginning:
asp_tags and short_open_tags, whether to allow the use of asp-like tags like “<%” and short open tags like “<?” instead of “<?php”. I usually set these to off, for one reason: I usually know I set them to off thus I’m not trying to use them in the scripts, but others don’t know. If they manage to upload a script containing these tags it will be much likely useless for them as PHP won’t do anything with them.
expose_php if set to on, will append to the server signature the PHP version you are using. If you didn’t upgrade yet to the latest php, you should set it to off, else it’s up to you what you do. I like to set it off, let’s not allow others what version the server runs.
memory_limit, this is a nice one and you should tweak it to extreme. You can set how much memory would you like to allocate for PHP. If your scripts are not memory eaters, this should be a low value, if they are, a higher value. You can also disable the directive by setting a value of -1, but be aware that with -1, PHP can use as much memory as it wants. I learned that the golden middle is 32, try first that value and if everything is running well, leave at that value.
register_globals, the black sheep :|. Whether to register the $_ENV, $_GET, $_POST, $_SERVER and $_COOKIE variables as global variables. This is covered in too much articles already, i won’t explain why to set it OFF. If you rely on it, stop doing so, learn how to not rely on it or give up coding, period.
file_uploads and upload_max_filesize, whether to allow or not file uploads, and if you allow, what’s the maximum filesize you would like to accept via the HTTP request. The file upload is pretty useless to have it enabled if you don’t use file upload scripts, so if you are not using disable it. Why let Mr. John Hacker to put file-upload scripts on your server?

And these were all the settings I wanted to cover in this post. Consider using them, think carefully before allowing something and before setting something, always.
Here are the settings I recommend:

asp_tags = Off
short_open_tags = Off
expose_php = Off
memory_limit = 32M
register_globals = Off
file_uploads = Off
upload_max_filesize = 2M

Again, much likely others would do it in another way, that’s my way, feel free to use it or not :)

Create thumbnails on-the-fly using Imagick

July 12, 2008 by methode  
Filed under IMagick, PHP

OK, this will be simple. I said it’s simple, more simpler than anyone can expect. Let’s see the overcomplicated code:

<?php
$im = new Imagick( 'path/to/your/image.jpg' );
$im->thumbnailImage( 200, null );
header( "Content-Type: image/jpg" );
echo $im;
?>

That was all. Yup.
OK, now step by step:

  1. We instruct Imagick to work with the file from the parameter.
  2. Ask nicely Imagick to create a thumbnail: width should be 200px and no fixed height. That’s good, cos Imagick will automatically preserve the aspect ratio, so, bye-bye ugly thumbnails
  3. Set the correct Content-type header
  4. echo() the Imagick object which contains the image data, namely $im

That’s all. We saved the world again…

If something is not clear, the comments are open, just ask and will try to answer as soon as possible.

Watermarking images using Imagick

July 12, 2008 by methode  
Filed under IMagick, PHP

This is a perfect day to show all how easy is to use php’s imagick library to watermark an image.
What you need is to have imagick installed and working correctly, a font you will use to write your website’s name on the image and of course an image you will put the text on.

I will explain each step but for those who don’t want to read, here’s the script:

<?php
$img	= 'path/to/your/image.jpg';
$text	= 'devoracles.com';
$font	= 'path/to/your/yourfont.ttf'
$font_size	= '20';
$watermark	= array();
$image = new Imagick($img);
$image->setImageFormat("jpg");
$draw = new ImagickDraw();
$draw->setGravity(Imagick::GRAVITY_CENTER);
$draw->setFont($font);
$draw->setFontSize($font_size);
$textColor = new ImagickPixel("black");
$draw->setFillColor($textColor);
$im = new imagick();
$properties = $im->queryFontMetrics($draw,$text);
$watermark['w'] = intval($properties["textWidth"] + 5);
$watermark['h'] = intval($properties["textHeight"] + 5);
$im->newImage($watermark['w'],$watermark['h'],new ImagickPixel("transparent"));
$im->setImageFormat("jpg");
$im->annotateImage($draw, 0, 0, 0, $text);
$watermark = $im->clone();
$watermark->setImageBackgroundColor($textColor);
$watermark->shadowImage(80, 2, 2, 2);
$watermark->compositeImage($im, Imagick::COMPOSITE_OVER, 0, 0);
$image->compositeImage($watermark, Imagick::COMPOSITE_OVER, 0, 0);
header("Content-Type: image/jpg");
echo $image;
?>

And the result is:

Watermark with Imagick

Watermark with Imagick


That was all, now a bit of explanation for almost all the lines. The first steps, as you see was to set up some variables which will be used in the script, I think the variable names talk for themselves so I don’t have to explain them. Do I?
Next, I instructed imagick to read the image which will be worked with and specified the type of the image, in the above case a “jpg”.

$image = new Imagick($img);
$image->setImageFormat("jpg");

By the way, if you want to write a script you will pass through all your images, thus all the images are watermarked, first assure that the image you work with is from your server, read, no one can use your script to watermark images on another server. The second thing, you can get the image’s extension using mime_content_type(’path/to/your/image.jpg’). Not the best method I admit, but it’s simple and effective.
Let’s proceed further. I fired up a new class, ImagickDraw(), this will let Imagick know what font to use and also the text’s properties like font size, font color, etc. “Imagick::GRAVITY_CENTER” basically means to center the text on it’s, say, layer. You can play with it and try to set other parameters too, like “Imagick::GRAVITY_SOUTH” which means to place the text on the bottom of the layer, “Imagick::GRAVITY_WEST” to put it on the left side, you get the point.

$draw = new ImagickDraw();
$draw->setGravity(Imagick::GRAVITY_CENTER);
$draw->setFont($font);
$draw->setFontSize($f_size);
$textColor = new ImagickPixel("black");
$draw->setFillColor($textColor);

We get then the parameters of the text we want to put on the image and we add an additional 5 pixels to it, both horizontal and vertical axis. The 5 pixels will be needed later to have place for the drop-down shadow of the text. Then we simply create the canvas and with annotateImage() we put the text on the image.

$im = new imagick();
$properties = $im->queryFontMetrics($draw,$text);
$watermark['w'] = intval($properties["textWidth"] + 5);
$watermark['h'] = intval($properties["textHeight"] + 5);
$im->newImage($watermark['w'],$watermark['h'],new ImagickPixel(”transparent”));
$im->setImageFormat(”jpg”);
$im->annotateImage($draw, 0, 0, 0, $text);

OK, now let’s play a bit with the shadow. First we clone the $im object, which is basically the text we’ll put on the image. The color of the image will be the same as the text’s. And now the interesting stuff: shadowImage(). This will create the drop-down shadow and the parameters tells Imagick how to create that shadow. The usage is:

shadowImage ( float $opacity , float $sigma , int $x , int $y )

So the first parameter sets how opaque the shadow has to be, the last two sets where to drop that shadow. Don’t ask me the second what does, i have no idea :D
OK, lastly let’s put our shadow on the image with compositeImage().

$watermark = $im->clone();
$watermark->setImageBackgroundColor($textColor);
$watermark->shadowImage(80, 2, 2, 2);
$watermark->compositeImage($im, Imagick::COMPOSITE_OVER, 0, 0);

The last steps are to put the watermark on the image, set the correct content-type header image/jpg in our case and echo the data. Why do we have to set the content-type header? Well, if I’m not mistaken, this is a php script and the browsers, if not overridden expects text/html, which in our case is not good at all.

$image->compositeImage($watermark, Imagick::COMPOSITE_OVER, 0, 0);
header("Content-Type: image/jpg");
echo $image;

That’s all. It was a bit complicated, but I’d rate its difficulty as ‘medium’ but it’s extremely useful in many cases. This is not JavaScript, so the watermark will be in place whatever the user does. If you are at least a bit familiar with object oriented PHP, I say give it a go and try it.

If something is not clear, the comments are open, just ask and will try to answer as soon as possible.

« Previous PageNext Page »