PIR is no longer under active development. PIR will continue to be available here and I will continue to answer email, but the project as a whole is in purely bugfix mode. I highly recommend using CSS's @font-face{} rule, as it is supported across every browser now, including IE6 and IE7. Also, check out Google's WebFont Directory, a free collection of a bunch of high-quality fonts in various styles. They even provide the CSS for you.
This page has been translated into Spanish language by Maria Ramos from Webhostinghub.com.
PHP Image Replacement
Simple, Tiny, Fast
Latest Update: 9 Apr, 2009
In the past, when one of my designs called for a heading in a fancy font that I couldn't count on people having installed, I had to manually produce an image with the desired text. This was unacceptable, so I borrowed a PHP script from A List Apart and (GREATLY) modified it to better conform to my needs. Well, that solved one issue (manually generating an image with fancy fonts), but I was still left with manually inserting images into my markup, and now they had ugly-as-sin URLs. In addition, if I wanted to make a change to the layout, such as altering the color or the size of the text, I had to go into the image and alter the URL, rather than controlling this properly through CSS.
There had to be a better way, and jQuery brought it to life. I produced this small plugin to allow me to just *write* my pages without worrying about replaced text, and then dynamically replace pieces of it with dynamically generated images. Dynamically.
As far as I can tell, this is by far the simplest iteration of this concept on the web. Many of the others don't rely on jquery, instead (badly) duplicating the selector code. The few that do use jQuery (jitr and jQIR were all I could find) don't seem to be nearly as 'smart' as mine, and are much larger over the wire.
By default it draws all relevant information (size, color, background-color, etc) automatically from the document, based on the CSS applied to the element being targetted. All you need to do is tell it what font to use. All of these options can be manually overridden, of course, if for some reason you decide you need to do so.
(And, of course, throughout all this accessibility is maintained. In the absence of javascript, you have ordinary text, styled to match with your document. In the absence of images, you *also* have ordinary text styled to match with your document, as the replaced text is inserted as the image's @alt text. In the absence of CSS, you still have a fancy-font heading, just in the browser's default size and colors for that element.)
And before you ask, yes, this is chainable. It wouldn't be a very good jQuery plugin if it wasn't.
Download the code.
Examples
This page is all the example necessary. The fancy-font headers here were all done with PIR. The code used is:
$(function() {
$.pir.options.php="pir.php";
$("h1").pir({font: "porytt.ttf", wrap: true});
$("h2").pir({font: "Forte.ttf"});
});
No extra additional markup was used on the page - those are plain-jane <h1> and <h2> tags, with their size and color specified in CSS as normal. PIR automatically grabbed all the relevant information for them.
Options
The following options can be supplied to the pir function (or set directly on the $.pir.options object if you want it to apply to *all* invocations of pir() on a page):
size:
The font size of the generated text. Defaults to the value of the font-size property on the element.
color:
The color of the text. Defaults to the value of the color property on the element.
casing:
The casing of the text. Accepts "uppercase", "lowercase", "capitalize" (the first letter of each word is capitalized), and "sentence" (the first letter of the text is capitalized - watch out when specifying this together with wrap:true, as it will act like "capitalize"). Defaults to the value of the text-transform property on the element. (text-transform doesn't have a "sentence" value, but it can be specified manually in the pir() call.)
text:
The actual text to be generated in the picture. Defaults to the textual content of the element.
php:
The path to your image-creating script (the pir.php file). Defaults to "/pir.php", that is, it expects the script to be in the root folder of your website.
font:
The font to be used for the image. This should be the actual name of the font file, which is often different from the fontname. If you are on a Unix or Linux-based system, remember that capitalization is important! Defaults to "denmark.ttf" because I sort of like that font, but this will generally *always* be overridden by you.
wrap:
Boolean determing whether pir should try to allow word-wrap. Default to false, but if set to true will split the replaced text along spaces and generate one image per word, so that you don't have to worry about a large heading going off the edge of the screen on small resolutions. Because this produces extra server requests (one per word, rather than one per element), avoid using it except when necessary.
prettyPrint:
Boolean determining whether to replace the generated images with their original text when printing, as images which appear clear on screen often appear blurry when printed. Defaults to false (do nothing special), but if set to true causes the actual text to print rather than the images.
Setup
Using PIR is simplicity itself. Obviously, jQuery itself is required. As well, your server must have support for PHP and have the GD image creation library installed (Since PHP 4.3 this is true by default.), so that it can run the pir.php script.
You will also need to have a folder for your fonts. These fonts do not need to be specially prepared in any way; you can just grab them from your computer's Fonts folder and throw them on your webserver.
Modify pir.php so that the "$fonts_folder" variable (found on line 19) points to the folder you are storing your fonts, then upload pir.php as well.
Finally, you may wish to modify jquery.pir.js (and jquery.pir.min.js) to point to your pir.php file. By default, it assumes it to sit in the root directory of your website. You can also simply modify this within a page by directly modifying the $.pir.options.php variable before calling the pir() function (which is what I did in the example code), or by passing a "php" option with a url value when calling the pir() function.
Note: Some older versions of the GD Image Creation library do not handle unicode properly, and will render non-ASCII letters as boxes. From discussion with users and my own experience, it appears that 'bundled' versions of the library (check phpinfo() - you'll see a version number something like "bundled (2.0.34 compatible)") are bad, while a version of "2.0 or higher" is good.
Browser Compat
PIR is verified compatible with IE7, IE8, FF3, Opera 9, Chrome, and Safari 3 (Win and Mac). I see no reason why it wouldn't work in FF2.
PIR uses 32-bit PNGs, and thus is not out-of-the-box compatible with IE6. It does, however, degrade gracefully - IE6 users will instead get the alt-text for the images, giving them a presentation identical to if PIR wasn't used at all. If you need IE6 to have identical presentation, there are a number of jQuery plugins that will patch IE6's transparency handling. You may be using one of them already, which is why I didn't include any such functionality in PIR.
Future Expansion
- Ability to test for image support before even trying to replace the text, to cut down on useless http requests and javascript engine activity.
- Support for rtl languages, and languages with heavy letter composition. The GD image library seems to render each letter one by one, in source order, which makes it impossible to use for languages like Urdu. I'll probably need to swap for an entirely different image creation library, unfortunately.
Change Log
- 19 Feb, 2009
- ENHANCEMENT: Added word-wrap functionality.
- ENHANCEMENT: Made pir hide the targetted elements immediately, do its work, and then show them again. This somewhat helps prevents the flicker of unstyled content. Users browsing without images are not affected, as they still get the alt text from the images.
- ENHANCEMENT: Added 'prettyprint' option for reverting to plain text when printing (as images which are clear on screen often show up blurry in printing).
- 25 Feb, 2009
- BUGFIX: Safari reported transparent colors in an unfamiliar format. Color acceptor now recognizes this.
- BUGFIX: Opera reported normal colors in a format that required url escaping. I just url-escape everything now.
- BUGFIX: Fencepost error in image width calculation, resulting in rightmost pixel column being shaved off (visible only occasionally). Added 1 to the width calculation.
- ENHANCEMENT: Upgraded to true 32-bit PNGs, for full transparency support. Feel free to use PIR headings over complex image backgrounds now. In any browser which supports rgba (Firefox 3, current versions of Safari), feel free to use transparent text colors as well! (Don't forget to specify a non-transparent color before the rgba() declaration, so that browsers which don't understand rgba still get approximately the color you want.)
- ENHANCEMENT: Code cleanup/shrinkage. Minimal in such a small plugin, but every byte counts.
- 28 Feb, 2009
- BUGFIX: String with single quotes are now escaped correctly (neither encodeURI nor encodeURIComponent escape single quotes, which somehow causes a problem when jQuery inserts text back into a DOM attribute).
- BUGFIX: Runs of multiple contiguous spaces are ignored (previously, they would send an empty string as the 'text' to the server, causing it to report an error)
- 6 Mar, 2009
- BUGFIX: A single dirty, stinking extra comma led me on a three-hour wild-goose chase trying to figure out why it didn't work in IE7, but did work everywhere else. It appears that all the other browsers (IE8 included) silently swallow a comma trailing the last entry in an object literal, but IE7 takes it as an opportunity to die with a cryptic error that doesn't even reference the correct file, let alone line number. Grr.
- ENHANCEMENT: PIR now supports the full list of SVG color names, because IE will report those as the value of color if you specify it as such. That is, if you say "color:#00f", it returns a "#00f", but if you say "color:blue", it returns "blue", even though the two colors are equivalent.
- 23 Mar, 2009
- BUGFIX: All generated images now get vertical-align:bottom applied automatically. This should make PIR actually usable on inline text (in small quantities, mind you!).
- 31 Mar, 2009
- BUGFIX: Finally fixed the issues with many symbols staying encoded in the alt text, so text now shows correctly when images are disabled.
- BUGFIX: Fixed a lingering issue due to an uninitialized variable that broke PIR if you had strict error reporting turned on in PHP.
- BUGFIX: Explicitly removed support for background-color. This was only used previously for edge-blending because I used GIF-style transparency. With true 32-bit tranparent PNGs it did nothing except waste a few cycles in the PHP script and a few bytes in the JS script.
- 9 Mar, 2009
- ENHANCEMENT: Made PIR aware of text-transform property. Hilarious coincidence: this morning I got an email from a user asking for this capability. This afternoon I received an email from an unrelated user saying they'd just *added* this capability to their own copy of PIR, and had attached the patched version for me to merge in! Sensing an opportunity to get acclaim while doing no work, I copied the code over.
Contact Me
My contact email is jackalmage@gmail.com. Please put "[PIR]" in the subject line of the email, or I may ignore it.