Posts tagged ‘PHP’

Customizing WordPress Images with a Plugin: ImageFX

My post about how to customize WordPress images with tricks like greyscale and such got me lots of feedback, so I figured I might as well turn it into a plugin.

The ImageFX plugin allows you to customize the image sizes from WordPress or custom ones for your theme, by applying filters to them.

The way it works is basically identical to my original post on the topic, only it allows the filters to be defined on a per-image-size level. It also allows the addition of a “slug” to be appended to the image filename, which is useful for cases where you want to have two images at the same size, but with different filters.

Since it was easy to do, I went ahead and created several other simple image filters that you can use for your images:

  • Greyscale (black and white)
  • Sepia tone (old-timey!)
  • Colorize with red, yellow, green, blue, or purple
  • Photonegative
  • Emboss
  • Brighten
  • Greyscale except red, green, or blue (classy!)

Here’s some examples. This a pic of me, Nacin, Rose, and Matt at WordCamp San Francisco. I ran it through the sepia, blue colorize, and grey-except-red filters.



These are some of the default filters included, but since I could, I went ahead and made it easily expandable too. All you have to do to define a filter is to create a function to do the image filtering you want, then call the imagefx_register_filter() function to add it.

To implement your own custom filter, you can do it like this:

imagefx_register_filter('custom-name','my_custom_filter');
function my_custom_filter(&$image) {
 // modify the $image here as you see fit
}

Note that the $image is passed by reference, so you don’t have to return it. This is because the $image resource takes up a lot of memory, so to save on memory usage, you are manipulating it in place, sort of thing.

You can use any of the image functions in PHP to change the image however you like. The filters I’ve implemented are mostly pretty simple. You can see them all in the filters.php file, in the plugin.

Caveats: The plugin will only filter JPG images, to avoid the overhead of recompressing PNGs and to avoid breaking animated GIF files. Also note that I haven’t tested these filters extensively. They’re only a starting point, sort of thing. I spent all of about 20 minutes writing them, so don’t expect miracles. :)

You can download version 0.1 of the plugin from the WordPress plugin directory: http://wordpress.org/extend/plugins/imagefx/

Enjoy!

Customizing WordPress images

Manipulating images in PHP isn’t all that difficult. WordPress offers some functions to make it easier, and integrating with the WordPress uploader isn’t at all difficult, really.

For example, let’s say your theme needed a black and white version of the images, sized at 100×100, and cropped to that size. This might be suitable for Next/Previous images to use for a gallery, perhaps…

When black and white bears attack...

First, we need to create the image size itself:

add_action('after_setup_theme','themename_bw_size');
function themename_bw_size() {
	add_image_size('themename-bw-image', 100, 100, true);
}

This simple function hooks into the after_setup_theme hook, which is loaded after the theme’s functions.php file is loaded. The function calls add_image_size to add a new image size for the uploader to create for each image that is uploaded into the WordPress media library. The size is specified as 100×100 with hard cropping.

Now that is easy enough, but we need to make the image black and white. To do this, we’ll hook into the wp_generate_attachment_metadata filter. This filter is called after the images have been resized and saved, but before the metadata about those resized images has been added to the attachment post. We’re not actually using this filter as a “filter”, but we need some of the meta data so this is as good a place to hook as any, as long as we remember to return the metadata again.

add_filter('wp_generate_attachment_metadata','themename_bw_filter');
function themename_bw_filter($meta) {
	$file = wp_upload_dir();
	$file = trailingslashit($file['path']).$meta['sizes']['themename-bw-image']['file'];
	list($orig_w, $orig_h, $orig_type) = @getimagesize($file);
	$image = wp_load_image($file);
	imagefilter($image, IMG_FILTER_GRAYSCALE);
	switch ($orig_type) {
		case IMAGETYPE_GIF:
			imagegif( $image, $file );
			break;
		case IMAGETYPE_PNG:
			imagepng( $image, $file );
			break;
		case IMAGETYPE_JPEG:
			imagejpeg( $image, $file );
			break;
	}
	return $meta;
}

Let’s break this down piece by piece:

$file = wp_upload_dir();
$file = trailingslashit($file['path']).$meta['sizes']['themename-bw-image']['file'];

This bit of code gets our upload directory path, makes sure it’s trailing slashed, then appends the filename of our themename-bw-image file to it. Thus, after this is run, $file contains the full local path to the image we want to make black and white.

list($orig_w, $orig_h, $orig_type) = @getimagesize($file);

This line of code simply gets the image size and type into some variables. We really only need the type for later, but this is an easy way to do it.

$image = wp_load_image($file);

The wp_load_image function is a handy one. It reads in the image and returns a PHP image resource for us to work with.

imagefilter($image, IMG_FILTER_GRAYSCALE);

This simply applies the grayscale filter to the image resource, making it black and white.

switch ($orig_type) {
	case IMAGETYPE_GIF:
		imagegif( $image, $file );
		break;
	case IMAGETYPE_PNG:
		imagepng( $image, $file );
		break;
	case IMAGETYPE_JPEG:
		imagejpeg( $image, $file );
		break;
}

Finally, we save the image back to the same file, overwriting the color one with the black and white one.

return $meta;

Since we used a filter, it’s important that we don’t leave out the final return to return the original information we were passed in, so that the metadata gets properly stored in the attachment post. We didn’t actually modify the metadata here, though we could.

Pretty simple to manipulate images in this way. You could apply one of the many other types of filters available, or change all the images into pictures of bears, or whatever you like, really.

A Good Use For Base 64 Encoding: Data URIs

First, WordPress plugin authors: Please don’t do this.

if ( isset($_GET['resource']) && !empty($_GET['resource']) ) {
	$resources = array(
		'icon1.png' => '... base 64 encoded code ...',
		'icon2.png' => '... base 64 encoded code ...',
		);

	if ( array_key_exists($_GET['resource'], $resources) ) {
		$content = base64_decode($resources[ $_GET['resource'] ]);
                header('Content-Length: '.strlen($content));
                header('Content-Type: image/png');
            	echo $content;
		exit;
	}
}

I’ve seen a few different versions of this, and while the idea is nice, this is really the wrong way to go about it.

The idea is to include small icons or images in the plugin file itself, instead of as separate files. This sort of code then lets you reference them by calling a URL of ?resource=icon1.png or whatever. When that resource variable is detected, the plugin kicks in and serves up the image instead of the site.

Advantages to this sort of thing:

  • No need for extra icon files

Disadvantages to this sort of thing:

  • Now every http request to get an icon file on your admin page results in loading up the WordPress code, causing extra CPU usage.

Here’s a better way. It’s called the Data URI.

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />

Here’s that code in action, right here: Red dot

Why this is better:

  • Same benefits as before, no need for extra icon files
  • No extra CPU load from loading WordPress to get that icon file
  • No extra HTTP requests at all, in fact, since the data for the tiny icon is contained right there in the code

Disadvantage:

  • Doesn’t work in IE7. You can work around this by detecting IE7 and serving up the image separately, if you really want. Or you can just ignore it like most people do. Seriously. IE7 is insecure (link, link) and nobody should be using it, anywhere. WordPress itself will probably drop IE7 support in the admin in the next couple of versions.

So use Data URIs for small images (under 32KB in size). They’re fast and easy. They’re an idea whose time has come.

Google Translation Tip

While looking at my backlinks today, I noticed a site in French had linked to my post about making photo galleries. He mentioned that the Google Translate wasn’t great. I took a look, and while I don’t know how good the text translation was, I did notice that Google strangely tried to translate the code as well, thus screwing it all up.

A quick search revealed that all one had to do was to add the “notranslate” class to any wrapping object to prevent its contents from being translated.

Now, I use the Syntax Highligher Evolved plugin to display code on my site (although I use an older version because I like the look and functionality of it better than the latest version). So I edited the plugin and found where it inserts the PRE tag, and added the notranslate class to it. And voila, now my code doesn’t get translated anymore.

Just a helpful tip for anybody who posts code on their sites.

WP Quickie: Adding Chrome Voice Search

Saw this post about Chrome voice searching in HTML forms on Google’s blog today. Very cool, so I had to give it a try. If you check the “Search” box in the upper right corner of the page, you’ll see a little icon (if you’re using a dev version of Chrome). Click it to do a search-by-voice.

What I didn’t expect was how totally easy it is to implement. Seriously, it’s less than a line of code.

Example. Say your search box (possibly in your theme’s searchform.php file) looks like this:

<form id="searchform" action="<?php bloginfo('home'); ?>/" method="get">
<input id="s" name="s" size="20" type="text" value="<?php _e('Search') ?>..." />
</form>

All you have to do is to add some bits to the input element box. Specifically, you add x-webkit-speech speech onwebkitspeechchange=”this.form.submit();”. That’s it. Seriously:

<form id="searchform" action="<?php bloginfo('home'); ?>/" method="get">
<input id="s" name="s" size="20" type="text" value="<?php _e('Search') ?>..." x-webkit-speech speech onwebkitspeechchange="this.form.submit();" />
</form>

Note that this won’t validate, if you care about that sort of thing. Works fine though.

You can do a whole lot more with Javascript and events and translations and multiple choices and such, if you’re thinking of developing something cool with it. I’m just shocked and amazed that this is already in my browser and I had no idea it was there. Very cool.

Passing parameters from PHP to Javascripts in plugins

A while back, I wrote a post detailing why it was a bad idea to generate Javascripts using PHP in WordPress plugins. In that post, I mentioned a couple of better ways to do it.

At the time, I didn’t know about the third, and best way, to accomplish this. Mike’s comment over there reminded me of it. WordPress has it built in.

If you already know about wp_localize_script, you can stop reading now.

The wp_localize_script function was made in order to allow for WordPress translations to be able to also translate some of the JS files inside WordPress. Thus the name “localize”. The way it works is to load up the translated versions of text from the translation files and then include them into the resulting HTML output as a Javascript object. The scripts then use that object to produce any text output they need to produce.

Turns out that’s really similar to our goal of sending arbitrary parameters from WordPress to be used by Javascript code.

How to do it:

1. Make your script static (instead of generated) and enqueue your script as per normal. Example:

wp_enqueue_script('my-script','/path/to/whatever.js',…);

No real changes there. You’ll have to come back and modify your script to use these parameters it’s getting passed, but we’ll get to that in a minute.

2. Build an array of your parameters that you want to send to the script.

$params = array(
  'foo' => 'bar',
  'setting' => 123,
);

Note that my parameters are simple examples, but this is PHP code. You can get your parameters however you like. Such as get_option to pull them from the database, perhaps.

3. Call wp_localize_script and give your parameters a unique name.

wp_localize_script( 'my-script', 'MyScriptParams', $params );

What this will do is make WordPress output an inline script with your parameters (properly encoded) just before the enqueue outputs the script tag that loads your script in the first place. So then those parameters will be available to your script as an instance of an object with “MyScriptParams” (from my example).

This means that Javascript code can now reference them as attributes of the name you gave.

So, step 4. Modify your script to use those parameters. In my example, I used “MyScriptParams” and the parameter names are “foo” and “setting”. In my Javascript code I can use them as “MyScriptParams.foo” and “MyScriptParams.setting”.

Much cleaner. One static and unchanging JS file to cache. Parameters get put into your HTML itself as a one-liner. You can deal with the parameters using a normal PHP array before passing them over. No need to screw around with generating Javascript from PHP or looking for wp-load or even messing with tricky actions.

Perfect.

Don’t include wp-load, please.

Originally published here: http://ottodestruct.com/blog/2010/dont-include-wp-load-please/

Note: There is a followup post to this one, which details an even better way than the two given below: http://ottopress.com/2010/passing-parameters-from-php-to-javascripts-in-plugins/

Time for Otto’s general griping: WordPress plugin programming edition.

Here’s a practice I see in plugins far too often:

  1. Plugin.php file adds something like this to the wp_head:
    <script src='http://example.com/wp-content/plugins/my-plugin/script.js.php'>
  2. Script.js.php has code like the following:
    <?php
    include "../../../wp-load.php";
    ?>
    ... javascript code ...
    

The reason for this sort of thing is that there’s some option or code or something that the javascript needs from the database or from WordPress or whatever. This PHP file is, basically, generating the javascript on the fly.

Usually, the case for this turns out to be something minor. The code needs the value from an option, or some flag to turn it on or off. Or whatever.

Problem is that finding wp-load.php can be a bit of a chore. I’ve seen extreme efforts to find and load that file in plugins before, including searching for it, examining the directory structure to make decent guesses, etc. This sort of thing has existed even before wp-load.php came around, with people trying to load wp-config.php themselves and such.

But the real problem is simpler: This is always the wrong way to do it.
Continue reading ‘Don’t include wp-load, please.’ »

WordPress Settings API Tutorial

Originally posted here: http://ottodestruct.com/blog/2009/wordpress-settings-api-tutorial/

When writing the Simple Facebook Connect plugin, I investigated how the Settings API worked. It’s relatively new to WordPress (introduced in version 2.7), and many things I read said that it was much easier to use.

It is much easier to use in that it makes things nice and secure almost automatically for you. No confusion about nonces or anything along those lines. However, it’s slightly more difficult to use in that there’s very little good documentation for it. Especially for the most common case: Making your own settings page.

So, here is my little documentation attempt.

Continue reading ‘WordPress Settings API Tutorial’ »