Dynamic Text Replacement

by Stewart Rosenberger

280 Reader Comments

Back to the Article
  1. i am not a javascript guru, etc., but here is an idea:

    extend the php/GD/etc. script to create multiple images with different appearances, give them names that can be referenced within javascripts or css code that perform rollover and style-switching in the manner described in several other ALA articles??

    i imagine this would require standardizing the image filenames created by the php/GD/etc. script so the javascript knows what to do…

    seems also possible that the php code could also dynamically create the actual javascript code or know which javascript filename to write into the code…

    this would make a good part 2 / part 3 follow-up to this excellent article.

    thank you for reading this…

    :) tom

    Copy & paste the code below to embed this comment.
  2. Wow! This quite the trick.

    Im excited (mabet a little to excited!) by how much impact this will add to my sites using content management systems and how easily it will be to plug-in.

    Copy & paste the code below to embed this comment.
  3. I was not aware when I wrote this article, but Shaun Inman (http://www.shauninman.com) developed an similar technique in April of this year. His technique uses Flash exclusively, rather than PHP images, but the principle is virtually identical.

    While I believe that both of our methods have benefits over one another, Shaun very clearly came up with this idea first. Had I done better research beforehand, I would have either credited Shaun with the development or decided against writing the article entirely.

    Anyone who’s interested should check out Shaun’s fantastic replacement technique at http://www.shauninman.com/mentary/past/ifr_revisited_and_revised.php

    Copy & paste the code below to embed this comment.
  4. I just wanted to add my $0.02 about accessibility issues with this technique.
    1. “if images are requested then the user can use them”. This is false. Most people with visual impairments or blindness surf with IE win and images on. You can’t tell whether the user will be able to see the images in any way from the server end. Very few special needs users use text-only browsers.
    2. Images cannot be recoloured on the fly or resized unless the user has special software such as the screen magnifier SuperNova and knows how to use it. There are many serious accessibility issues caused by these limitations. These issues can be minimised by ensuring that there is high contrast between the foreground and background colours, that a sans-serif font is used, that the text size used is large enough to compare with IE’s large setting for body copy, that the design does not use commonly confusable colours such as red on black, red on brown etc etc, that the images are not placed over a background image.
    3. The bottom line is that yes, you are compromising accessibility using any of the image replacement techniques; In real world web design we need techniques like these, but the question is whether you apply some common sense to minimise the additional problems you are causing.

    Copy & paste the code below to embed this comment.
  5. No-one has yet pointed out the issue of copyright. I assume it would be illegal to upload your favourite fonts to the server. Can freeware fonts be copied in this way? Or does it not matter since the fonts are turned into images? (I can see the law defining uploading the font as “copying” it, and even distributing it as the server contents are mirrored, that’s all.)

    Copy & paste the code below to embed this comment.
  6. I have been playing around with this script (i.e. these scripts) for a while. Great idea. And some great hints in this discussion either. However, I was wondering about special characters that you might need in foreign languages.

    Is there any way to have a ö character? It is said that this should cause no trouble to the script, but in fact it does not work.

    Any ideas?
    Ansgar

    Copy & paste the code below to embed this comment.
  7. Shaun shared his IFR technique with us as a potential ALA article before publishing it on his site after we decided to pass on it.

    We thought Shaun’s technique was marvelous and innovative, but we had some problems with it, and declined it.

    With the present article, no such problems presented themselves, so we approved and published Dynamic Text Replacement.

    The two techniques are different and were evolved independently. Both have their strong pluses. For us, the accessibility benefits of DTR made this article an easy buy.

    Copy & paste the code below to embed this comment.
  8. >>No-one has yet pointed out the issue of copyright. I assume it would be illegal to upload your favourite fonts to the server.

    I’m no expert on intellectual copyright law, but I don’t see why you make that assumption.

    This method does not embed copyrighted fonts on the page. This method simply creates GIF images of text. It’s no different than opening Photoshop and manually creating type GIF images, except that the process is automated.

    Is your concern that someone might hack their way into the system and download the font without paying for it? If that is your concern, I must say it seems unlikely to me that a dedicated hacker would expend energy trying to steal a font from myclient.com. For one thing, said hacker would have to KNOW that the type GIFs on the page are being dynamically generated via a font stored on the server. And how would he or she know that?

    Besides, why rob a lemonade stand when you can rob a bank? It seems to me that any dedicated hacker determined to download fonts without paying for them would spend his or her time trying to attack Adobe.com or Veer.com — not my clients’ sites.

    Copy & paste the code below to embed this comment.
  9. You normally pay for the use of a typeface on a X x CPU licence basis.

    In effect you pay to use on an agreed number of computers (normally 1x, unless its a bulk licenses) – uploading it to a server (as you need to do in this example) is an additional CPU.

    Copy & paste the code below to embed this comment.
  10. WOW. Using PHP to dynamically create an image (or 3-4 or however many) on every page hit CERTAINLY won’t be a resource drain on a server… right? Doh! Even with image caching this still seems unreasonably wasteful.

    Shouldn’t we be designing in a more typeface independent manner in the first place?

    Copy & paste the code below to embed this comment.
  11. Sending cached images to a browser incurs almost no overhead. The processor requirements for loading a PHP file and checking whether the file exists is virtually nothing. Compared to something like database access, sending a static file is practically a day off for the server.

    There is something to be said for designing in a “typeface independent” manner. Let’s be pragmatic, though: current web design only provides maybe seven universally accessible fonts to choose from: That’s not a lot of choice, and this method is simply another option for designers who have tighter requirements.

    Having just visited your website, I can see that you’re not in total disagreement: Well over half of the words on your home page are represented as images.

    Copy & paste the code below to embed this comment.
  12. Argh! I salute you, that was a masterful retort.

    Copy & paste the code below to embed this comment.
  13. This is a really great article, and something that I’ll find very helpful on my next project.

    I also had trouble with no spaces appearing between the words.  I added this line to function javascript_to_html($text)

    $text = $text.’ ‘; 

    which seemed to do the trick… although I’m guessing there’s probably an easier / cleaner way to fix the problem.

    Copy & paste the code below to embed this comment.
  14. Cool article, but…

    Ever since I viewed the demo, my fonts have been screwed up.  If I view some emails in Outlook or view some websites, the font that was used will show up.  It’s quite annoying.

    Copy & paste the code below to embed this comment.
  15. This is a great example of a technique, which is a plus for sales, for getting bigger profit from your CMS. This technique will please customers. It will generate more cash.

    I love it :)

    Copy & paste the code below to embed this comment.
  16. >You normally pay for the use of a typeface on a X x CPU licence basis. In effect you pay to use on an agreed number of computers (normally 1x, unless its a bulk licenses) – uploading it to a server (as you need to do in this example) is an additional CPU.

    Aha. Now I’m with you. Yup, you might have to pay a licensing fee for storing an additional copy of a font on a server, depending on the font house and its licensing fee structures.

    Copy & paste the code below to embed this comment.
  17. Another legal issue I’d be concerned with is people downloading the font — either someone with FTP access or someone who just figured out the URL. I’m probably just being paranoid, but I can see it happening.

    Copy & paste the code below to embed this comment.
  18. If you were concerned about someone downloading the font by figuring out the URL, couldn’t you just rename the font file X3CR3L.TFF or something similar?

    Copy & paste the code below to embed this comment.
  19. Some sanity checking should probably be added to limit the total number of cached images as this could be used as a DoS on the servers’ available disk space.

    Otherwise, someone could just run through the dictionary and start creating boatloads of images of worss.

    Just a thought.

    Copy & paste the code below to embed this comment.
  20. >Shouldn’t we be designing in a more typeface independent manner in the first place?

    If by “designing” you imply “communicating in a visual medium”, I’d have to say no. Designing without typography is akin to writing without verbs. You may get understood, but it’s crude, as is the typographically poor web of today. Good typography is the result a few thousand years of development; it should not be dismissed because current technology isn’t (yet) able to fully exploit it.

    Copy & paste the code below to embed this comment.
  21. Does this system re-renerate the images every time the page is loaded, or once a session, or are the images saved to a temp dir or to the websites webspace.

    The reason I ask is because image generation can be a pretty taxing thing for an application server, particularly for highly traffiked websites.

    Any thoughts?

    Copy & paste the code below to embed this comment.
  22. OK, I do everything with standards now, but I am coding a freelance 300page website that needs to work all the way back to the dreaded Netscape 4.77 and IE 5.0, for education. We figure for an education site, schools could very well be using old browsers + computers.

    So my question, does this PHP script work with legacy browsers like N4.77? if it does, awesome! I really don’t want to wind up producing hundreds of image headers

    Copy & paste the code below to embed this comment.
  23. I found adding:

    image.border = 0;

    to replacement.js at line 96 to be helpful.

    Copy & paste the code below to embed this comment.
  24. Great article, just one question though, when comparing the dynamic headings with those I created in Photoshop, the dynamic ones are far inferior in quality – to the extent I couldn’t bring myself to switch over.

    I’m using the same font size, background & foreground colour, etc, and have played around with the settings in the scripts but to no avail. As an example, here’s one of my PS headers – http://pacepro.cameronyule.com/images/welcome.gif and here’s a dynamic one http://pacepro.cameronyule.com/heading.php?text=Welcome to Pace

    Any ideas? Or is it back to manual graphics for me :mad:

    Copy & paste the code below to embed this comment.
  25. Pardon me but I’m not much of a PHP coder. I’ve been trying to implement dynamic text replacement but somehow the text graphics are not showing up on my page.

    I know my webserver has PHP version 4.3.5 with gd enabled. I have my font and files in the right places. The php code is being executed without any error messages but no images appear, I get the icon for broken image links instead. What am I doing wrong, or are there server-side issues I have to troubleshoot first? Thanks.

    Copy & paste the code below to embed this comment.
  26. Has anyone had problems with IE caching images sizes with this technique?

    When I change fonts or sizes, IE still uses the image sizes of previous fonts, so the text look really ugly.

    Mozilla and Opera (obviously) don’t have this problem.

    Copy & paste the code below to embed this comment.
  27. by adding a boolean called clearcache in de javascript file, and by adding this to line 90 of that file:


    if(clearcache) url  ”?date=”  (new Date()).getTime(); 

    you force IE to clear its image size cache.

    Copy & paste the code below to embed this comment.
  28. I noticed that IE bug as well. Your fix works, but by addding a unique string to the end of the image’s URL, you’re preventing any caching, which may not be ideal.

    I’ve found it better to slightly change the URL of my PHP file whenever I alter the font-settings. That way, my visitors can cache the images without worrying about this stupid IE bug making the headings pixilated.

    Copy & paste the code below to embed this comment.
  29. The php itself could cache the images so that they are only generated once per heading change, otherwise the php redirects to the cached image saving server load of GDI.  Not a huge deal on low traffic websites but every processor cycle helps on larger ones.

    Copy & paste the code below to embed this comment.
  30. Didn’t get enough sleep!

    Copy & paste the code below to embed this comment.
  31. if you have a CRLF and/or TAB after the opening tag, but before the characters, Mozilla will pass PHP the escaped CRLF and TAB characters to render in the images.

    Copy & paste the code below to embed this comment.
  32. I’m having a problem with one TT font file in particular.  I have no problems with any other font that I try.  For this problem font, the image shows up as a series of “boxes” instead of the text.  The font looks fine in any other vehicle that I use to view it. 

    Of course, this problem font is the font that I really want to use :-)

    Anybody have any ideas?

    Copy & paste the code below to embed this comment.
  33. A very very good point!  On a static site you could get around this by generating (by whatever method) a list of all the words in the headings on the site whenever a new revision is uploaded and only letting the php script return those, but on a dynamic site you may find that your headings are dynamic (is the case for me) so that’s not a viable option…

    Copy & paste the code below to embed this comment.
  34. PHP is a server-side language, that means it’s operation is completely unaffected by the browsing medium.  This is as opposed to Javascript which is a client=side language.

    With Netscape 4.7 you may have troubles running the JS file, though I’m sure someone here could make it work – but that person isn’t me, I shamelessly turn a blind eye to anything prior to Netscape 7 ;)

    Copy & paste the code below to embed this comment.
  35. As mentioned in the article, it is possible to use this technique to replace tags with dynamic Flash movie.

    A simple test page exists with downlaods available for additional/altered files at http://www.famfamfam.com/flash/dtr

    These do not have the overhead of running PHP scripts to create image content, although they do have problems as you can most likely see; Flashes of unstyled/unsized content, and differing appearance on various browsers are among the current bugs. Most, if not all of the bugs with this are fixable for anyone who has the time. I hope someone is interested enough to finish off this alternative method for a great technique.

    Copy & paste the code below to embed this comment.
  36. Isn’t there any possibility to use this script in a server that has only php 4.1?
    I asked the admin, and he said he can’t upgrade php. I could change the server, but this is from a friend and is free to me.
    Is there any modification i can do to make this technique works in php4.1?
    the gd is installed in the server.
    The technique is great, i’d like to use it.
    Thanks.

    Copy & paste the code below to embed this comment.
  37. In IE for Windows, if you go to Internet Options -> Security -> Internet and set it to High, then this does not get run at all. If it’s set to Medium it runs, but not on High.

    Copy & paste the code below to embed this comment.
  38. Bruno: PHP 4.1 did not come with the GD library support by default, but if it is installed on the server, and the module is included in PHP, then this technique will work fine.

    Brian: IE with “high security” disables all ActiveScripting support, which includes Javascript. So, naturally, that would disable this technique entirely. However, if the Javascript does not execute, the standard headers will still remain, and they can still be styled using standard CSS techniques as a fallback.

    Copy & paste the code below to embed this comment.
  39. I’ve implemented a similar technique on a new site, but the prospect of a little unobtrusive automation intrigued me.  The problem is that I have several headings that need replacement, all with different styles and colors.  My solution moves most of the configuration into the page calling the scripts. 

    The javascript in the main document is like this:
    [removed]
    function imageHeader(selector,phpfile,wordwrap){
    this.selector = selector;
    this.phpfile = phpfile;
    this.wordwrap = wordwrap;
     
    }
    var imageHeaders = [
    new imageHeader(“h5”,“heading.php?font_size=14&font_color=00ABE4&background_color=FFFFFF”,true),
    new imageHeader(“h2”,“heading.php?font_size=22&font_color=FFFFFF&background_color=CCC592”,true)
    ]
    [removed]

    In replacement.js , I’ve replaced this code
    replaceSelector(“h2”,“heading.php”,true);

    with this code

    for (var i = 0; i < imageHeaders.length; i++) {
    replaceSelector(imageHeaders.selector,imageHeaders.phpfile,imageHeaders.wordwrap);
    }

    Also in replacement.js , replace this code:
    var url = items.url + “?text=”escape(tokens[k]’ ‘)+”&selector;=”+escape(items.selector);
     
    with this code:
    var url = items.url + “&text;=”escape(tokens[k]’ ‘)+”&selector;=”+escape(items.selector);
     
    Finally, in heading.php , set up the PHP script to accept those variables from the query string

    if($_GET[‘font_size’]){ $f }
    if($_GET[‘font_size’]){ $background_color = $_GET[‘background_color’]; }
    if($_GET[‘font_size’]){ $f }

    It would be so nice if the javascript could parse the CSS color: , background-color:, white-space: and font-size: properties to populate that query string for the PHP script.  This way, we’d only have to include the javascript in the head and ALL the styles would remain in the stylesheet where they belong.

    Copy & paste the code below to embed this comment.
  40. Ok, but the server where i host my site has PHP 4.1 with GD support and it doesn’t work there. I get lots of “The server could not create this heading image” errors.
    Is there anything i can do to solve this?
    Besides having GD support, my php must have any other functionality? May it be necessary any modification in the script?
    I hope so…
    Thank you..

    Copy & paste the code below to embed this comment.
  41. Likewise, in heading.php you could add this at line 25, just below $cache_folder…

    $selector = $_GET[‘selector’] ;

    if($selector == “h2”) {
    $font_file = ‘supercoolfont.ttf’ ;
    $font_size = 12 ;
    $font_color = ‘#ff6600’ ;
    $background_color = ‘#ffffff’ ;
    $transparent_background = true ;
    $cache_images = false ;
    $cache_folder = ‘/whatever’ ;
    }

    I’m publishing this site over the weekend (save for a few Flash bugs), and found it works quite easily. I don’t feel comfortable in Javascript yet, but a simple if() statement in PHP doesn’t frighten me off.

    Still have to thank Perry for a kick in the right direction though.

    Copy & paste the code below to embed this comment.
  42. (Perhaps suggested before, but…) Why not use a class as the replacement selector, gets round the linking issue? Even cleverer would be to use a CSS parser as with the whatever:hover fix for IE to read the font info from the stylesheet rather than hard coded in the PHP (or do this parsing on the server).

    In fact having a more generic javascript CSS parser alongside getElementBySelector would be a great toolkit for CSS techniques.

    <h1><a class=“replace”>Title</a></h1>
    <h2 class=“replace”>Text</h2>

    <style>

    h1.replace, h1 a.replace {
    font-size: 16px;
    font-family: font1, serif; 
    }

    h2.replace, h2 a.replace {
    font-size: 12px;
    font-family: font2, serif;
    }

    </style>

    But ideally I’d do the replacement when the content is created and embed the names of the cached images in element id’s.

    <h1><a id=“cache_1” class=“replace”>Title</a></h1>
    <h2 id=“cache_2” class=“replace”>Text</h2>

    Copy & paste the code below to embed this comment.
  43. has anyone thought how many images you will be adding to the download time of your pages?

    A new image must be downloaded EVERY time the same words come up because it’s dynamically created.

    Why not just have images for every letter of the alphabet and replace each letter on your page with a single-character image? Users then only need download about 30 images per font size (including CAPS), and then each letter would be retrieved from the cache!
    (Not recommended for body text – but then again images aren’t recommended for ANY text!)

    Copy & paste the code below to embed this comment.
  44. For normal use, each of these headings will be between 1k and 3k. Placing even three or four of these on a site is not a large addition to the download time of a site. Many things in web development are a trade-off.

    Using individual characters would not work, because 1) the kerning of characters would be destroyed and 2) the ALT attributes of each image would be rendered entirely useless, making this technique unaccessible.

    I don’t think anyone is recommending this technique for body text. It’s simply one more option for headings.

    Copy & paste the code below to embed this comment.
  45. “I don’t think anyone is recommending this technique for body text.”

    Ah good!

    oh yes the alt text would become meaningless!

    As a header-image-generator this is an excellent tool!

    But to me it just feels wrong some how :/

    Copy & paste the code below to embed this comment.
  46. First of all, I love the idea and the creativity behind it.

    Quote from a previous post:

    “Now, if there was a way to define the color, font, textsize, etc in the css and use that data to create the images I could see this as a more usefull solution.”

    First of all, I think it’s a choice, whether or not to use CSS. When using replacing images, you obviously don’t think CSS is good enough to serve your needs.

    And if you do want to control your images trhough CSS, it might not require that much JS, I guess. Just from the top of my head(haven’t had the time to test this yet):

    var newEl = document.createElement(‘span’);
    newEl.className = ‘imgStyle’;
    var color = newEl.style.color;

    Or am I being silly here?

    Copy & paste the code below to embed this comment.
  47. I’m hoping I don’t get flamed w/ a bunch of RTFMs here but here goes…

    I have downloaded the replacement.js, layout.css and the .php file provided in the article, but how do I implement it?

    Obviously the .js and .css gets included in the head but what do I do with the .php file? Include is just like a js file with the script src tag?

    I have php 4.3.6 installed and running, but I am a CF programmer and know pretty much NOTHING about php. Can I include the php file with cfinclude?

    Also…how do I know if I have the GD graphics library? And if I don’t have it, where do I get it?

    Please forgive my “newbieness”.

    Copy & paste the code below to embed this comment.
  48. Allow me to thwart the RTFMs before they begin.

    It works! It took some work to get the php_gd2.dll as it is not installed by default like its said to be.

    But it’s working great. Thanks Stewart for the great article and ALA for providing such great info!

    Copy & paste the code below to embed this comment.
  49. It’s so amazing to observe the evolution of the idea in a creative environment. This is why I love ALA discussions.
    There is, I believe, an infinite number of ways for driving a nail into a board – starting from a hammer and working your way up to a microscope – and most of them get the work done. What to use – is entirely up to us.
    This article introduce yet another way – great. Even better, it works! Anyone wants to port it to .NET or any other platform – go right ahead, and don’t forget to share.
    Waste of bandwidth? Hard to fathom without testing under real load; I would say, it might cause some issues in some cases, but this is not the point. The point is – the more ways of skinning the cat we discuss, the larger the world population of the skinned felines will grow.
    Ewe.
    I meant it in a positive way, actually. Hmm.
    Anyway, great work, great concept, and great discussion.
    Keep it up.

    Sidetrack:
    [LazyJim] …Why not just have images for every letter of the alphabet and replace each letter on your page with a single-character image?…
    This is yet another way. And, you don’t even need PHP or any other server-side technology to implement it, you can get away with simple [removed] take a string of text, split it between characters, loop through the resulting array and write to the page whatever structure you wish to insert “YourArray.gif” image for each letter. Assuming that you have all the images pre-made and uploaded to the server.
    Here is the sample:
    http://javascript.internet.com/messages/print-line.html
    I wasn’t entirely happy with this solution, because each line of text would require numerous server trips on the first load (not only that, there was an issue with illegal characters in a file name, like ” .gif”, “?.gif”, “..gif”, etc.), so later I revised the script, using single image as a shifting background for the series of floating DIV’s and a set of CSS rules to position the background:
    http://www.gerasimenko.com
    The next iteration of the script does, in fact, dynamically replace the H1, H2, etc. tags it finds on page onload. I was going to submit a tutorial on this matter to ALA for a while, and finally did earlier this week, inspired by the article we are discussing now (I wonder if this post will be considered a “previous publication” and ALA will dismiss my submission because of that).
    Yet another way.

    [Stewart] …Using individual characters would not work, because 1) the kerning of characters would be destroyed and 2) the ALT attributes of each image would be rendered entirely useless, making this technique inaccessible…
    The kerning will be affected, yes, but not destroyed, it’s just a matter of dynamic positioning of each letter. Kerning in Photoshop is not bulletproof either, and highly typeface-dependable. The ALT attributes will make sense no more, true, but there is also TITLE you may be able to apply to the parent node element to make it up.

    [Nevel] …When using replacing images, you obviously don’t think CSS is good enough to serve your needs…
    True. It isn’t. At least not yet. This is why Stewart developed this technique in a first place.

    Copy & paste the code below to embed this comment.
  50. I set the font_size parameter to 14 (rather than the default 50), but the resulting images are still the same size and the type is all fuzzy. Is there another parameter I need to set somewhere?

    Copy & paste the code below to embed this comment.
  51. Dave: you’re running into an IE cache bug, which I have yet to solve. Even if you clear IE’s cache entirely, it still thinks the image is the original dimensions. To clear this, you’ll have to change the URL of the PHP file (i.e. rename the PHP file, and re-point the Javascript to it).

    iG.STUDiO: To my knowledge, the “title” attribute of a parent element is not an adequate substiture for the “alt” attribute of an <img> tag. Although the “title” attribute might fix the tooltips, it won’t help with screen-readers, which is where the accessibility problem comes into play. I could be mistaken, though.

    Copy & paste the code below to embed this comment.
  52. Is there a way to control kerning in the php file?

    Copy & paste the code below to embed this comment.
  53. This is an awesome technique in many ways.  But, I would think hard before placing it on a client’s site. 

    I think some clients might be unhappy with the implications of hosting a generator for images containing arbitrary text.  It’s an easy way to become the butt of jokes – “hey, look, here’s a link to the Company X website that gives you an image with ‘Company X sucks!’”. 

    A technically oriented person might laugh this off as clearly being speech not endorsed by Company X; after all, the text in the image is right there in the GET parameters of the URI! But imagine a client’s COO calling you up to say, “one of my staff showed me how to load a page from our website that displays an ethnic slur in a funny font.  Explain yourself.”

    Unlikely, maybe, but it still makes me nervous.  I’m a web-app programmer for a university, so I don’t have ‘clients’ in the sense of companies who hire me to work with their sites.  But I imagine most companies would look down on any potential source of embarrasment, no matter how minor.

    Copy & paste the code below to embed this comment.
  54. We have been using the PHP technique at Virgin Radio for the past few years (though we’re about to change it for a slightly better technique that will enable text readers to cope too – more of which later).

    It’s fairly wasteful to get your PHP parser to make all these images every single time, and will – we found – make your webserver more stressed, especially if you’re a popular site.

    Ideally, your PHP script should make the graphics once, and then cache those graphics on the server – simply pulling those files up for display once they’ve been built once. It’s not too difficult to do, and highly recommended.

    Copy & paste the code below to embed this comment.
  55. what is this, a gimic to get your mark on the web

    its nothing but a IFR FIR rip off..

    i hope ALA gets a good few hundred reads from this shit

    Copy & paste the code below to embed this comment.
  56. And it’s called Inman Flash Replacement. Uses Flash (note, Flash) and doesn’t use server-side scripting, or PNGs, etc. This can solve different problems than IFR, and may be more flexible for some. It’s just another way to solve the same problem. The web is full of those. Pay more attention before screaming “rip-off!”

    Copy & paste the code below to embed this comment.
  57. I can’t seem to get this working on my host (PHP 4.3.4, GD 2.0.15)…

    GD is set up correctly (http://www.hamsterscantfly.co.uk/headertest/barcode.htm)

    The PHP script is set up not much different from the original (http://www.hamsterscantfly.co.uk/headertest/heading.php.txt – the real one is in the same directory witha normal php extension, I’m just using Arial as a test, the ttf file is in the same directory as all the files, I’ve also tried it with different fonts)

    The Javascript file is exactly the same as the original.

    But when I go to my test page… http://www.hamsterscantfly.co.uk/headertest/font.htm the images don’t show up properly…

    Anyone got any ideas what’s wrong?
    Thanks a lot,
    Tom

    Copy & paste the code below to embed this comment.
  58. I am you know! Things could get very silly! Weeee. Many years ago I was considering Macromedia Generator to do exactly this and now we can do it for free! Superb. :)

    Copy & paste the code below to embed this comment.
  59. Could you leave the text there and set the color to transparent so that if people copy & paste the text of your entry, the text will still appear?

    Copy & paste the code below to embed this comment.
  60. Derek: As far as I know, there’s no way to set text to be transparent without setting its display to “invisible”, which then makes it un-selectable.

    IFR allows text to be selectable. If that’s something you absolutely require, and accessibility isn’t your utmost concern, you might look into Shaun’s excellent method.

    Copy & paste the code below to embed this comment.
  61. An other solution for resizing the images:

    Give them a height or width in em, relative to the font size in the body.

    Like this they will be rescaled as well when the user enlarges the font.

    Copy & paste the code below to embed this comment.
  62. I see no reason why this shouldn’t work as far back as about PHP3.1 or so, as long as a recent GD lib is supported.

    Copy & paste the code below to embed this comment.
  63. Our Sybase EAServer webserver doesn’t know about PHP, apparently.  Would it be feasible and reasonable to convert this PHP script to JSP code?

    Marvin

    Copy & paste the code below to embed this comment.
  64. I also think it is grat idea,but the script does not work at my server. I have the PHP 4.3.2 and GD version is 2.0.12. I don’t know I just copied the whole script, changed the font and size and it do not want to replace the text. It also do not want to generate pictures with the font. i like the idea and I want to use it but I can’t. Please help me What I have to do?

    Copy & paste the code below to embed this comment.
  65. This method could be implemented in JSP; possibly even easier than in PHP.

    I just threw together a quick proof-of-concept, and it wasn’t terribly difficult. The one problem is Sun’s lack of support for font kerning. Without the ability to correctly space character-pairs, font spacing looks funny. Your mileage may vary.

    I’m currently working on a repository for different versions of this technique (e.g. PHP, Java, ASP, Perl) at http://www.stewartspeak.com/dtr/—any help in the different languages would be appreciated.

    Copy & paste the code below to embed this comment.
  66. If you right-click on the image, copy the URL, paste in the URL bar to only load the image, then do a shift-reload of the image it will force IE to re-calculate the dimensions.  The bug is that IE caches the image dimensions separately from the browser cache (in the icon cache).

    Copy & paste the code below to embed this comment.
  67. i realize that another (Javan) person was asking about this – but i believe the solution suggested to him won’t help me.

    right now, i’ve got posts written by two different people, and the headings are colored differently based on the author (h3 class=daniel) or (h3 class=martha). when i apply the image replacement, it just replaces all the h3’s w/ one color… i’d like to be able to replace based on class.

    Copy & paste the code below to embed this comment.
  68. Daniel: The solution is pretty simple, actually. You’ll need to create two separate versions of the PHP script, for each style/color/font you wish to replace elements with. And then you’ll need to create a separate call to “replaceSelector” in your Javascript code for each of those H3 classes. For example:

    replaceSelector(“h3.martha”,“martha.php”,true);
    replaceSelector(“h3.daniel”,“daniel.php”,true);

    If you only target “h3” instead of specifying the class, it will mindlessly replace all of the H3s, using the same style.

    Copy & paste the code below to embed this comment.
  69. Didn’t break any new ground for me, but it’s nice to have the idea and the code explained and provided in such a way.  Classic ALA article, as far as I’m concerned.

    And on an unrelated note:  Stewart, I love your site’s design.  Very clever and elegantly done.

    Copy & paste the code below to embed this comment.
  70. success!

    thanks, oh great one. your advice worked like a charm.

    Copy & paste the code below to embed this comment.
  71. THis script is a revolutionary script which could save web developers many hours.  It’s great.

    I have one question.  My server seems not to create the images and I get the response “Error: The server could not create this heading image.”  What exacly does this mean?

    Copy & paste the code below to embed this comment.
  72. I’ve got it too…
    Don’t understand…
    Please help us !
    Thanks.

    Copy & paste the code below to embed this comment.
  73. I also have this problem on my server. on my local apache all works fine. seems like the ImageTTFBBox-function does not work on the server. but why? it has php 4.3.6 and gd 2.

    please help.
    thanks

    Copy & paste the code below to embed this comment.
  74. The limited number of typefaces available in web design are more than just a “dull headache.” It’s a serious enough problem almost to undermine the very notion of designing for the web. Typefaces are what ultimately distinguish printed periodicals from one another (contrast the New Yorker with Rolling Stone) and display content in a way that transcends the look of MS Word default settings. Aside from browser compatibility, I see this as one of the most important, fundamental problems web design must overcome. Fixing headlines is a start, but it’s less than a baby step.

    Copy & paste the code below to embed this comment.
  75. i found a solution for my problem:

    change $font_file =“font.ttf” to
    $font_file=$DOCUMENT_ROOT.“font.ttf”

    now the ImageTTFBBox-function works.

     

    Copy & paste the code below to embed this comment.
  76. I have the extensions path loaded correctly in php.ini, and I have the php_gd2.dll in there, but when I try to load the test page I get a popup on my server (running win 2k server and IIS) that says: “Unknown(): Unable to load dynamic library ‘C:\PHP\extensions\php_gd2.dll’ – The specified module could not be found”

    I know it’s there, and I know the path is right, so what could be causing this?

    Copy & paste the code below to embed this comment.
  77. Line 89: var url = items.url + “?text=”escape(tokens[k]’ ‘)+”&selector;=”+escape(items.selector);

    Should probably be changed to:

    Line 89: var url = items.url + “?text=”escape(tokens[k]’ ‘)+”&selector;=”+encodeURIComponent(items.selector);


    This allows for better handling of other charsets (like UTF-8, in my case). According to the O’Reilly book, escape() has been deprecated in later versions of the spec and replaced with encodeURI(). From my testing, I found that escape encoded special characters inconsistently from browser to browser, while encodeURI worked correctly in all environments.

    Also, I added some code for retrieving the color/size/font attributes from the CSS. The reason you’d want to do this is a) in the event that a user can’t see the replacement technique, they still see appropriately styled plaintext, and b) so that you only end up specifying the headline style in one place. I think that CSS is the most appropriate place for the specification, assuming you’re already using CSS for other style information. I can post code if anyone wants to see.

    The big problem with the technique is Safari, which doesn’t support window.getComputedStyle() or element.currentStyle,*. It’s a known bug (or so I read) and will probably be fixed eventually. But in the meantime, I had to hardcode style info into the javascript for safari. If anyone can suggest another way round this problem, I’d appreciate it.

     

    Copy & paste the code below to embed this comment.
  78. Sorry. Correcting above post:

    Line 89: var url = items.url + “?text=”escape(tokens[k]’ ‘)+”&selector;=”+escape(items.selector);

    Should probably be changed to:

    Line 89: var url = items.url + “?text=”encodeURIComponent(tokens[k]’ ‘)+”&selector;=”+encodeURIComponent(items.selector);

    Copy & paste the code below to embed this comment.
  79. Does this cache the images on the server then, i.e. once one person visits the page it generates all the images, then when more people visit it sends them the existing graphics? Or is the server creating the graphics for each user?

    Copy & paste the code below to embed this comment.
  80. Thanks for pointing out that “escape()” is deprecated. I will update my code to use “encodeURIComponent()” instead.

    Although others have also posted the suggestion that this method should pull style information from CSS—and I myself originally considered it—I decided against it for several reasons.

    CSS is a client-side technology but this technique is primarily server-based. Although, superficially, they seem similar (both working with fonts, colors, etc), the potential for a much wider difference exists. Look at the headings on http://www.stewartspeak.com/ for an example of what I mean.

    If I pulled the font and color information from CSS, what would I gain except a little headache from the added layer of complexity? Would it be easier to maintain? Probably not: I still have to update a file every time I want to change my settings. In fact, whether I update the CSS or not, I always have to update the PHP for my more abstract settings, so now I’ve simply doubled the number of places I need to edit my styles.

    And by specifying style in CSS, I would need to build a translation table to convert the different possible font-families and styles into specific font filenames that PHP (or Java, Perl, etc) would understand.

    I understand the argument for keeping “style” in a style sheet and on the surface it makes good sense. But when you break it down, it’s merely an argument based on principle and it falls apart quickly when you consider real-world applications. There’s very little benefit for the added complexity, and so I would advocate against this method.

    Copy & paste the code below to embed this comment.
  81. Is there a bug in this or is there a configuration I have not seen – when I adjust the $font_size = 50 ; in the heading.php script down to say $font_size = 20 ;  even if I delete the cache the png’s generated remain the same size but the become pixelated

    Copy & paste the code below to embed this comment.
  82. I’ve tested it with file types such as *.suit or *.ffil – yet didn’t work w/o avail. Is this only geared towards *.ttf?

    Great technique btw. So easy to implement.

    Copy & paste the code below to embed this comment.
  83. Chris: you’re seeing a cache bug in IE, where it maintains the original size of an image, even when that image is refreshed and changes dimensions. The only automatic fix for this issue, that I’ve found, is to change the URL of your image (your PHP filename) whenever you change the font size. That way your visitors don’t see the sizes of older headings that they’ve loaded before.

    Dru: Although the font rendering engine that PHP uses (Freetype) support mant font formats other than TTF, the image-generation library must be specifically tailored to either TTF or Postscript. In this case, for the widest audience, I chose TTF, but you could change the PHP script to use PS fonts very easily.

    Copy & paste the code below to embed this comment.
  84. I like it and can’t wait to implement in my next project.

    Copy & paste the code below to embed this comment.
  85. If I set hideFlicker to true, neither the images nor the text shows.

    This technique is truly remarkable. Thank you!

    Copy & paste the code below to embed this comment.
  86. For the end user, how does this affect the speed of the site? I know it’s server-based, and mileage will vary, but has anyone done speed tests for this?

    Thanks! Love the technique. I’ll have to use it in one of my next projects!

    Copy & paste the code below to embed this comment.
  87. Dru here again. What are some of the steps/things to do to debug? On my PowerBook (localhost) with php enabled – everything works perfectly.

    When I go to upload it to a server, only the heading.php?text=Put Text Here works.

    you can check it out here -> http://www.pingrip.com/_dru/DynamicText/

    Copy & paste the code below to embed this comment.
  88. Dru: You left out the test.png file. Safari doesn’t seem to care if it’s missing, but other browsers do.

    Copy & paste the code below to embed this comment.
  89. What if malicious people determined the path to the images and then hammered your site with calls to the heading.php program? Would there be a way to say unless the URI is not heading.php directly then generate the images?

    Copy & paste the code below to embed this comment.
  90. Anyone know if this will work with PHP version 4.1.2 and GD library version 1.6.2?

    Copy & paste the code below to embed this comment.
  91. A few people have mentioned this method’s vulnerability to denial-of-service attacks. By continually producing garbage strings of text, a hacker could eventually fill up a host’s available disk space.

    There are a number of solutions, but my favorite would be to have the PHP script check how much space is currently being used by the cache. If that value rises above a certain number of megabytes, the script could email the webmaster and also stop caching images until you clear out space for it. With such a fix, flooding would still slow the server down, and prevent caching, but it would not overload a hosting accounts disk space, and images would still be sent to real visitors.

    It’s worth noting that many CMSes are probably vulnerable to similar attacks. I think I could flood a MovableType or Wordpress installation with two million comments, but for most users this is a non-issue.

    Copy & paste the code below to embed this comment.
  92. Like this?
    http://www.stewartspeak.com/images/headings/illustrator.php?text=iG.STUDiO: Hi. This should not be allowed to happen…&selector;=#primary h2
    That should be blocked on the server, unless you are proud of serving your fonts to the World Wide Web – and we are down to copyright issues again – and wasting bandwidth, this time uncontrollably.
    Once again, great concept; implementation can be improved, but isn’t it always the case?

    Copy & paste the code below to embed this comment.
  93. Isn’t there a way to automate the detection/blocking of the domain, requesting the image? I am not profficient enough in PHP, but I believe, that many hit-counters are PHP-based, so there should be a relatively easy way of tracking a forein referrer.
    Unless you really want to monitor your image distribution personally, and possibly impair your own site by automatic interruption of service, correct me if I am wrong…

    Copy & paste the code below to embed this comment.
  94. This isn’t a copyright issue. I’m not breaking any laws by generating these images. Especially customized ones like those on my website. I’m not “serving fonts” I’m serving images.

    If you want to waste my bandwidth, there are better ways of doing it: I have larger files that you could continually download to blow my bandwidth cap. That’s a vulnerability of all small-to-midrange websites.

    Someone can use these PHP scripts to generate their own text from my website… Yes. There’s not too much I can do about that, but who really cares, either? My only concern is the security of my site from denial-of-service attacks, and I can limit that vulnerability by using the modifications I described above.

    If you’re seriously concerned about preventing people from generating bogus text (which only they will ever see), you can modify the script to check a “safe” file for allowed words. It would be trivial to get most CMSes (MovableType, Wordpress, etc) to generate one of these files for you.

    Copy & paste the code below to embed this comment.
  95. Would really like to get some help on this…I don’t know why it throwing this error..I even check if both the ImageCreate and ImageTTFBBox are there…Please Advise

    if(!function_exists(‘ImageCreate’) || !function_exists(‘ImageTTFBBox’))
      fatal_error(‘Error: Server does not support PHP image generation’) ;

    Copy & paste the code below to embed this comment.
  96. I’ve followed the guide to the letter but for some damn reason the PHP file keeps spitting out an “invalid color” error. The PHP code looks perfectly fine to me, and my variables are fine:
    $text_color = ‘#000000’ ;
    $background_color = ‘#ffffff’ ;

    Help me out, this is frustrating as hell!

    Copy & paste the code below to embed this comment.
  97. MT: I’m not sure if you just mistyped your code, but the variable is supposed to be named “font_color”, not “text_color”.

    For others getting errors like ‘C0d3 M0nk3y’ was, I recommend taking the ‘@’ symbols out of the PHP code. These symbols, when placed in front of a function call, tell PHP to not print out its internal error messages. For testing, though, it’s valuable to see what the “real” error is.

    Copy & paste the code below to embed this comment.
  98. I can’t seem to get it to render a + sign, as in KTU+A. Just comes out as a space. I know the fonts I’m using has the plus sign in it. Any ideas?

    Copy & paste the code below to embed this comment.
  99. I had a difficult time choosing the right approach for a certain web project. The design I got was “impossible” to implement without using flash or rendering the whole page as a png. Thank you for giving me this great idea.

    Copy & paste the code below to embed this comment.
  100. Stewart Rosenberger: For some reason $text_color is the variable listed in the actual ALA article, but in the source code it’s $font_color… I simply copied the variable from the article ;)

    Right, so I don’t get the error anymore, and instead I get nothing. Nothing appears when I try heading.php?text=ThisIsATest

    I’m out of ideas :(

    Copy & paste the code below to embed this comment.
  101. I’m mortified! A typo! Sorry about that, MT. Glad we got it worked out, though. I hope it didn’t affect anyone else.

    But it’s still not working for you, and that’s no good. If nothing’s appearing, I would suspect maybe a Javascript bug was introduced somewhere. Depending on your browser, you could check a Javascript debug screen for any errors…

    If you want to email me for more detailed help—outside of the ALA forum—I’d be more than happy to assist you, and anyone else who needs a hand getting this method customized. You can reach me through the contact form on my website.

    Copy & paste the code below to embed this comment.
  102. Yes I was worried about someone filling up the server, as remote as that is. I tried sending mail when the cache folder grew above a certain size, but does that ever send a lot of mail. Instead I set it to run the fatal error script.

    I’m not much of a programmer, and my web site would probably never fall under attack like this (unless somebody wanted to prove a point specifially to me) so displaying ugly fatal errors is ok to me. But it might not do for a higher quality site.

    Again, excellent script! One for the alistapart classics for sure!

    Copy & paste the code below to embed this comment.
  103. I’m still looking for a way to make charachters like å ä ö look nice. I have added that extra code to line 89, but it still doesn’t help…

    Does anyone have a clue?

    Copy & paste the code below to embed this comment.
  104. This kind of script isn’t a real news, as far as I can remember, k10k had a script like this. I wrote a very similar script which reads all the variables from the querystring and makes it easier to change fonts, sizes, and colors “on the fly”.
    The idea of storing images in a cache folder is great.

    Copy & paste the code below to embed this comment.
  105. Make sure you’re using a font that actually contains the special characters you need. Many freely available fonts do not contain the entire latin character set and are of limited use here.

    Here’s an example that uses your site as a template: http://www.stewartspeak.com/dtr/characters/

    Copy & paste the code below to embed this comment.
  106. —-
    I’m not much of a programmer, and my web site would probably never fall under attack like this (unless somebody wanted to prove a point specifially to me) so displaying ugly fatal errors is ok to me. But it might not do for a higher quality site.
    —-

    You can check $_SERVER[‘HTTP_REFERER’] and verify that it matches an array of allowed domains or urls to prevent other people from using this script from other sites

    Copy & paste the code below to embed this comment.
  107. Using Op7+ on http://spiralwinder.com/h_k.php the & is not getting converted to & and thus is not displaying properly.

    Any ideas on how to get Op to play nice?

    TIA,
    Brian

    Copy & paste the code below to embed this comment.
  108. possible to define font size in px rather than pt, as described by article?…..

    Copy & paste the code below to embed this comment.
  109. Im having trouble getting it to work, just like other people in this message. in IE the text disapears and is replaced with broken link images. In Firefox however, the text comes back, as an image, but in Arial or something… just the default font.

    I also went into php.ini and uncommented out the GD library extension, and modified the extensions path, but Im still getting broken links.

    has anyone who’s had this problem found a cure yet?
    Thanks
    Mark

    Copy & paste the code below to embed this comment.
  110. Brian: The Opera issue, relating to how Opera handles the “innerText” property of elements, is fixed now. The fixed Javascript file is linked to below.

    Mark: You’re describing the behavior of both those browsers when they cannot download an image. The “default font” you describe is IE showing you the ALT text for the image. Check the PHP script manually to see why it isn’t generating images correctly.

    I’ve also found that replacing the “escape()” function with “encodeURIComponent()”, as suggested by will break this script in IE5 because they do not support that function. So I have included that fix in the Javascript file below.

    Here is the newest version of the Javascript file, with some minor fixes (as addressed above): http://www.stewartspeak.com/dtr/replacement.js

    Copy & paste the code below to embed this comment.
  111. Hi,

    I was really excited by this facility. I was planning on using it for an image gallery, so the resizing of header’s text isn’t much of worry for me. Sadly, I am unable to get it working though.

    Myself and my host technician cannot understand why it isn’t working, as all files are in the same folder, and we have GD support.

    When I try to run the script by itself (http://www.poppymedia.co.uk/working/hendy/heading.php?text=hello) I get an error telling me the server couldn’t create the heading image. Oddly enough, these errors are generated as png’s using the script . . .

    Is there possibly something else that needs configuring at the server end? or in the php?

    Any help would be very much appreciated.

    Thanks.

    Copy & paste the code below to embed this comment.
  112. Kinda funny because I was almost ready to implement png images for text on a few of my dynamic sites, and then this article came out…

    Great job and great timing…

    Even implemented this on my blog.  www.rynoweb.com

    Copy & paste the code below to embed this comment.
  113. Ah! Thanks!
    I suspected it might have something to do with those fancy free fonts, then I used the more conservative “Garamond” instead but still got the same squares… I’ll have to examine my fonts more thoroughly in the future.

    Copy & paste the code below to embed this comment.
  114. …see the website http://james.cridland.net/

    That’s WEFT in all its glory. Shame that (in spite of being ratified by W3C) it’s not made it to any other browser apart from MSIE, though.

    Copy & paste the code below to embed this comment.
  115. Thought this might help someone…

    I had everything set up properly but my server kept returning a ‘server is missing the specified font’ message.

    I tried everything discussed in this thread to no avail – then I finally realized something – the font on my PC had a tff extension that was in uppercase. I changes .tff to .TFF in header.php and now everything is working fine!

    So just remember to check the actual extension of your font file.

    Thanks for this great method. I’m sure it will gain a lot more respect once it is in common use.

    Copy & paste the code below to embed this comment.
  116. It’ now working on PHP4.2.2 with gd 1.6, but if i set it to use an image to each word, it appears with no space between them, and if i put one image to all the phrase, i doesn’t wrap the line….how can i solve this?
    Thank You!

    Copy & paste the code below to embed this comment.
  117. I’ve been having problems getting this script going right. The images show up as broken X images. Any insight is appreciated!

    Copy & paste the code below to embed this comment.
  118. :-)

    Copy & paste the code below to embed this comment.
  119. If you’re getting server errors, or the images are not appearing at all (or as broken images, etc), you should try calling the PHP script directly.

    If this doesn’t give you a clear indication of what the problem is, open the PHP script in a text editor and remove all of the ‘@’ characters. Then try calling the script again; it should give you more descriptive error messages now.

    If you still can’t figure out how to get it to work, there is probably something slightly “off” about your server, and I would be happy to help you customize the script to your own purposes. Feel free to send me your questions ( Using this contact form : http://www.stewartspeak.com/contact/ ).

    Copy & paste the code below to embed this comment.
  120. http://test.alcotel.it/test.php?text=Test

    It Display nothing. The script fail when uses image function imho. Php error log returns no errors, error_reporting = E_ALL.
    This is phpinfo(): http://test.alcotel.it/info.php.

    Anyone with this problem?

    Copy & paste the code below to embed this comment.
  121. I’ve done my reading on GD Library (either for actual servers or on localhost). Luckily enough – it works on my PowerBook and some servers I have.

    I know that GD Library is installed on this particular server. However, I always get the message that the image cannot be generated. I took Mr. Rosenberger’s advice to omit the ‘@’ to get the detailed error message. I’ve done so and here’s what I get:

    http://www.onlineguru.com/john/DMVOL/sample-error.gif
    http://www.onlineguru.com/john/DMVOL/heading.php – will show that heading.php does actually work because it checks that there’s no text specified. When tested, it will result as an error.

    Here is the working version with the same files uploaded to a different location:

    http://www.pingrip.com/_dru/dmvonline/
    http://www.pingrip.com/_dru/dmvonline/heading.php?text=test

    Copy & paste the code below to embed this comment.
  122. A brilliant technique!

    As Andy said, the volume of connections and the resources required could cause a problem on busy sites.

    What if the script stored the images in a library on disk as it created them – when requested, first check the disk for ‘URLs Are Fun.png’, and only create it on the fly if a pre-built copy isn’t available.

    This way, a contributing author could pre-build all their own headings, just by being the first to browse their new content.

    Whaddya tink?

    Copy & paste the code below to embed this comment.
  123. Er – right… back on page 3. Forget I spoke!

    Copy & paste the code below to embed this comment.
  124. I’ve set up the text replacement, and it works fine. However, it simply outputs a series of different images, but they do not wrap.

    This question was asked on page 4 also, but no-one replied.

    Copy & paste the code below to embed this comment.
  125. When line-wrapping is turned on, the script will output a separate image for each word in the heading. Each of these images will be lined up, from their baselines. <img> elements are displayed using the inline model, by default, so they will line-wrap like regular text when their container becomes too narrow to fit them all on one line.

    Is your experience different? And, if so, can you show me an example of what’s going wrong?

    Copy & paste the code below to embed this comment.
  126. Stewart,

    Thanks for the updated js, that corrected my error in Op7+.

    In the same message you mention a fix for IE5.2/MAC but it didn’t remair the rendering for me (http://spiralwinder.com/) on MAC. What can I try next? IE5.2/MAC isn’t displaying the text or the image.

    TIA,
    Brian

    Copy & paste the code below to embed this comment.
  127. There’s nothing wrong with the replacement method. The issue your having with IE5.2/Mac is that your pages is overriding the replacement function by manually setting the “onload()” function of the <body> tag.

    Newer browsers support cleaner ways of launching code on-load, so this isn’t a problem with anything except IE5 (I think).

    My technique will piggyback on existing onload() functions, so as not to wipe them out. But it can’t prevent other functions—loaded after it—from wiping out the replacement function.

    I suggest that all pages avoid directly assigning a function to the “onload” trigger of a <body> tag, and instead use the method that I do. It prevents us from stepping on each other’s toes when more than one script needs to be executed.

    Copy & paste the code below to embed this comment.
  128. Great script, Stewart. I have lot of fun with this. However, Internet Explorer behaves weird (I’m not surprised…) – my header image (another image replacement technique) is flickering.
    Firefox 0.8 and Opera 7.50 are seating quiet. I have to tweak that.

    My test: http://hostinspace.com/blog/25/

    Copy & paste the code below to embed this comment.
  129. I’m trying to make this work in a Microsoft Content Management System environment. Unfortunately, the page content is pulled from a database and it seems that it’s rendered after the script is loaded. The result is a normal, boring h1 style.

    Any ideas?

    Copy & paste the code below to embed this comment.
  130. Everything works fine, but the rendered images for the words in the Headings are always together… any ideas?

    <h2>Hello World</h2> Looks like: HelloWorld

    Thank you.

    Copy & paste the code below to embed this comment.
  131. This technique is great I have just one complaint, some of the fonts I’ve tried with it are italic and have angled strokes that go outside of the character area. This results in the generated image ending before the actual character, so characters get partially cut off. how can I tell php to make the image area slightly larger to avoid this? Add some padding if you will?

    Copy & paste the code below to embed this comment.
  132. wondering if anyone could shed some light on the matter…

    I found this:
    http://hotwired.lycos.com/webmonkey/99/45/index0a.html
    (there’s a link to the OVERVIEW on the left, but that page has one of those annoying install pop-ups…)

    Can anyone tell me if how this method compares to the one we read (which was an amazing article by the way!!)

    I’m still at the basic level with CSS (trying to un-learn everything ELSE I know!) but it’s ALWAYS nice to come here and see what the Big Boys and Girls are up to :)

    Coos

    Copy & paste the code below to embed this comment.
  133. Coos: That Webmonkey article is pretty old. The only modern browser to support font-embedding is IE, using Microsoft’s private format. It also doesn’t allow for any graphical effects, such as those I use on my website’s headings http://www.stewartspeak.com/

    Mattress: Although most italicized/slanted fonts should work correctly, PHP’s font library does seem to get a few of them wrong. To add the appropriate padding, you’ll have to edit a few lines of the PHP script:

    In the following lines, substitute X for the amount of padding (in pixels) you wish to use.

    Line 82, Change:

    $image = @ImageCreate(abs($box2-$box0),abs($box5-$dip)) ;

    To:

    $image = @ImageCreate(abs($box2-$box0)+X+X,abs($box5-$dip)+X+X) ;

    And on line 93, Change:

    ImageTTFText($image,$font_size,0,$box0,abs($box5$box3)-$box1,

    To:

    ImageTTFText($image,$font_size,0,$box0+X,abs($box5$box3)-$box1+X,

    That should do the trick.

    Copy & paste the code below to embed this comment.
  134. I read this article in kind of a round about way….I had seen it on ALA but I just didn’t get what it did (didn’t read past the title) And then I stumbled on a   persons wordpress blog and was amazed at the cool title fonts. Came back and read this wonderful article. Wow!

    Long story short, I finally got it working and it is soooooo wonderfully cool.  now all I have to do is figure out how to get my CMS to use it.

    Copy & paste the code below to embed this comment.
  135. Hi, great script! Although I’ve installed on my server and it’s working using a URL such as heading.php?text=URLs Are Fun, I cannot get the script to work on my actual page using the JavaScript call in the header. I’ve created a test page with links to my source files if anyone would be so kind to see what may be wrong. Thanks!

    http://curtgranger.com/test_header.php

    Copy & paste the code below to embed this comment.
  136. Where you’ve written “sub2” in your javascript code, you should actuall have written “.sub2”

    The difference is that the first string targets the <sub2> tag (which doesn’t exist), and the second string targets any element of the class “sub2” (which you’ve set your span to).

    Copy & paste the code below to embed this comment.
  137. Awesome, that did it. Thank you. Did I say how great your script is?

    Copy & paste the code below to embed this comment.
  138. Stewart:

    First, I can’t tell you how much this technique is going to change my life. Thank you!

    My question is about point sizes in the php files. I’ve made a test at:

    http://www.americanmicrotruck.com/replace.htm

    The first line is the replaced text. The second line is a graphic with the same font and point size specified in the php files that I made in Photoshop.

    As you can see, yours are significantly larger. I know I can muck about with the php file and get it down to the size I want, but do you have any ideas on why the sizes are so different?

    Copy & paste the code below to embed this comment.
  139. Hi

    Great article I allready have a .net image control that im trying to apply this technique too.

    Copy & paste the code below to embed this comment.
  140. GD (the PHP image library) uses the Windows-default of 96 DPI setting when it prints out text. Photoshop, by default, uses the Macintosh-default of 72 DPI. That’s where your problem lies.

    You can’t tell GD to use 72 DPI without recompiling the library, but you can adjust your own input to accomodate this difference. By multiplying the point value you pass to PHP by 0.75, you should see results that match Photoshop.

    Alternatively, you can use tell Photoshop to use 96 DPI.

    Copy & paste the code below to embed this comment.
  141. This is great and I got it to work a treat even with my limited php/javascript knowledge! However when I reduced the text size the new smaller image seemed to ‘stretch’ to fill the area of the old image from the larger text size. This happened even when I deleted the imgs from the temporary internet folder. The only way I could get the text to reduce was to change the text itself so new images were created. What am I doing wrong?

    Copy & paste the code below to embed this comment.
  142. I was reading all that stuff and I was wondering something… sorry for asking here but… ;)

    Can you replace some text with text? :)
    I mean to have a header and replace it’s text with other text! :)
    or to “split” into segments and have each one with different styles!

    ex: <h1>Hello World</h1>
    and through Css make “Hello” blue and “World” Red! :)
    ?

    Copy & paste the code below to embed this comment.
  143. Hi, all.  Just tooting me own horn, here. toot toot!

    I created a script just like this last fall and wrote about it on my own website. Here is my version of same idea:

    http://engineering.jhu.edu/newtnotes/main_file.php/php-dev/75/

    Note that the script is quite configurable, and can be configured statically (internally) or dynamically (via CGI GET or POST vars)

    later…

    Copy & paste the code below to embed this comment.
  144. Like I said before, neat technique :).

    I’ve been pondering, and I realized I wanted to implement this technique using PHP only. That way, it’s easier to implement it in my templating system etc.

    A short explanation and source code can be found at

    http://www.codewarrior.nl/~bladibla/heading

    Copy & paste the code below to embed this comment.
  145. There was some discussion about misuse of php script that generates the text by accessing it directly with a ton of random text. I was trying to think of a way to protect it and this is as close as I could get it. If you hit:

    http://genonidesign.com/dynamic/heading.php?type=headline&text=only a test

    you will be denied. If you hit

    http://genonidesign.com/dynamic/

    it will work. On the index.php page I put the following at the top:

    <?php
    session_start(); // This connects to the existing session
    session_register (“pass”); // Create a session variable called pass
    $HTTP_SESSION_VARS [“pass”] = dyna; // Set pass = dyna
    ?>

    and then on the heading.php file I added:

    session_start(); // This connects to the existing session
    if ($pass != “dyna”) {
    fatal_error(‘Error: You do not have proper access.’) ;
    }

    The problem though is that as soon as a user hits the index.php and the session has started they now have direct access to the php script itself because the session variable “pass” which is set to “dyna” stays live.

    I’m basically trying to find a way to pass a hidden variable to the php script, and this works, but once the session begins I can’t figure out how to reassign that variable after the page loads so it’s no longer valid (so they can’t load the php script on its own).

    - Tom

    Copy & paste the code below to embed this comment.
  146. excellent article! plus an awesome read for the 20 page comments.

    thanks for making my sunday afternoon worthwhile. :)

    Copy & paste the code below to embed this comment.
  147. I have a few comments. It is a great concept with some powerful options. But…

    First some things I can’t figure out. If I want to replace more headings, say H1 to H3, do I need 3 heading.php files? Or can it be done otherwise?
    Second, If I change the fontsize but I dont change the text the images are not regenerated. So the old image will just be resised with very poor quality as a result.
    And that brings me to the last remark. If you choose a small size for the font (like 10 to 15) the result is very bad. The spacing and kerning is not that good and so is the aliasing. Since I don’t use that much 50 pt headings in my sites it is a bit disappointing. And photoshop gives far more options for spacing, kerning, leading, etc.

    So for large fonts it’s ok. For small fonts it is an easy tool but you will have to sacrifice a lot on the quality side.

    Copy & paste the code below to embed this comment.
  148. Why are so many people asking for .asp versions and .cfml version of this script, just use PHP!

    PHP is free, and runs on IIS and Apache.
    If you are a professional web developer, it’s an asset to have some php knowledge. Why not start now?

    Copy & paste the code below to embed this comment.
  149. Stewart,

    This is a fantastic technique, and if I can implement it in Java/JSP it will save me dozens of hours of work.

    Would any version of this technique use the GD library, or would a JSP version use the Java ImageWriter libraries, or some other such?  If a Java version would use GD, how would I call it from my Java code?

    I apologize if these are dumb questions.  I googled around for awhile and have found no pages that compare to this thread for useful info.  If anyone has any links about Java and GD, could you please post them?

    Thanks!

    OK
    DAH

    Copy & paste the code below to embed this comment.
  150. This is a neat idea.  I’d like to figure out how to make it appear as lovely in a screen reader as it does on the screen.  Home Page Reader <http://www-3.ibm.com/able/solution_offerings/hpr.html> reads each title twice. For example, “[Dynamic.][Text.][Replacement.]Dynamic Text Replacement”

    You write: “Once the HTML is finished loading, our script will search it for specified elements (<h2>, <span>, etc.) and replace the text inside of them with an <img> tag. This dynamic <img> tag has its alt attribute set to the original text,…”  It seems that for HPR, the text isn’t actually replaced with the image, HPR sees both the text and the alt-text.

    Also, a period causes speech synthesizers to pause.  The periods at the end of each alt-text cause dramatic pauses between each word in a heading (unless you were purposefully going for a Shatner effect).

    There will also be a pause between each alt-text. Perhaps you could put all of the words from a heading as the value of the alt attribute of the first image and use null (alt=”“) for the rest?

    Just some thoughts,
    —w

    Copy & paste the code below to embed this comment.
  151. My solution to the potential DOS attack issue, and accessing the script directly.

    Set a session (like Tom mentioned above) in the page calling the .js file (in index.php, or better yet, in a header file included in all the pages on your site.  The session sets a timestamp, and only allows access to heading.php for a set number of seconds after it is set. The sessionid is is passed to the script, and then passed to heading.php.  This configuration will work with or without cookies enabled (we have to pass the SID to the .js script, so it can pass the session id to heading.php because otherwise it won’t see the session if cookies are disabled), and will allow direct access to the heading.php script for only 30 seconds (can be increased or decreased) after the script is called from an actual page on your site.

    So after somebody loads http://www.yoursite.com/yourpage where an image replacement takes place, they will only be able to call http://www.yoursite.com/yourpage/heading.php?text=mytext for 30 seconds before it will error out, saving your site from a DOS attack, remote linkers, or people just trying to have fun :)  If they never hit an actual page on your site, they won’t have access to heading.php at all.


    Instructions for this modification: http://www.moonwell.com/misc/image_replacement.moonwell.txt

    Copy & paste the code below to embed this comment.
  152. Your example doesn’t work with Firefox 9.2.

    Copy & paste the code below to embed this comment.
  153. Firefox 9.2 defaults to allow javascripts but it does not default to allow javascripts to manipulate images.  If you change this in your options then this does work (albeit a little on the slow side. I don’t know what kind of server the example is running on).

    For the majority of those who use Firefox (possibly the best browser on Earth) they will not get to see this cool text replacement. JavaScript is great, but there is no guarantee that anything with JavaScript functionality will work on browser clients.

    I really like the concept of the text replacement, but is there anyway to do it without any JavaScript?

    Copy & paste the code below to embed this comment.
  154. For those who have followed step by step and still aren’t seeing the images being created: check that GD has FreeType support enabled.  The FreeType library is required for some methods used in the PHP script (notably imagettfbbox()).

    You can tell if it’s enabled by looking at the output of <? phpinfo(); ?>.  In the GD table, look for the following two values:

    FreeType Support: enabled
    FreeType Linkage: with freetype

    Copy & paste the code below to embed this comment.
  155. Hi,

    Great script. I liked the word wrap and flicker fixes. Why didnt I think of that! I was trying to so server side word wrapping.

    I have also been playing with image replacement using js and server side image generation using php with gd and freetype. I wrote my script about 6 months ago but then forgot about it. Only recently actually got round to using it on a site.

    I called it ImageStyle and it takes a slightly different approch. It has one file on the server. imagestyle.php and has two js files. One for the script that does the replacement in a similar way to this dynatext and another that defines the ‘image style sheet’ or iss for short. The rules in the iss are passed to the server script in the query string. The iss has a similar syntax to css and is the only files that needs to be modified. Here is an example.iss.js file.

    var imageStyleSheet = {
    h1:{
      font:‘ltromatic_bold’,
      size:‘24’,
      color:‘002244’,
      valign:‘top’,
      padding:‘10’,
      height:‘42’,
              background:‘mytexture.png’
    },
          h3:{
      font:‘KvBd’,
      size:‘12’,
      color:‘422f42’,
              background:‘333333’,
      valign:‘bottom’,
      padding:‘0’,
      reload:‘1’
    }

    };

    This makes it easy for designers to style pages without needing to change any php files. It also lets you define differnet iss files for different users. A standard one, another for larger text, and another for print.

    The other thing I was cooking up was direct client side cache access using the same caching key as the server side cache uses. With this the image repleacement script tries to load the image from the server side cache first and then calls imagestyle.php if it fails. This saves sever side resources.

    One more thing I want to look into is using client side flash for the image rendering server side shared font swfs. This could fall back to server side images if the user doesnt have flash.

    I’m interested in starting an open source project centered around these techniques if anyone is interested. We can work together over at sourceforge and come up with a kick arse accessible cross browser image replacement script. My only requirement is that it be done under an apache / bsd style licence, as im not keen on GPL. Anyone interested? luke@symbiosys.biz

    Copy & paste the code below to embed this comment.
  156. > I really like the concept of the text
    > replacement, but is there anyway to do
    > it without any JavaScript?

    Related to images, one of the most popular alternatives is the infamous Fahrner Image Replacement—but please see the corresponding ALA article by Joe Clark [1], it will explain its flaws.

    There are also several additional (and rather commendable) techniques, which are AFAIR quite good described at Stopdesign [2].


    [1] http://www.alistapart.com/articles/fir/
    [2] http://www.stopdesign.com/articles/replace_text/

    Copy & paste the code below to embed this comment.
  157. I have a cache folder on my localhost, do I need to set permissions on this folder? Im using OS X 10.2.8. Are my PHP GD settings incorrect or something? would be cool to get this working as it is a very cool function.

    Thanks in advance for any useful info.

    Copy & paste the code below to embed this comment.
  158. it appers you can kern the error messages, but is it possible to kern the dynamic text?

    Copy & paste the code below to embed this comment.
  159. We are using this script on our dynamic store and love it. I will be looking into the anti-DOS preventions suggested in this thread. Thanks everyone involved.

    Copy & paste the code below to embed this comment.
  160. When I use the heading.php directly an PNG-image with the error message “Error: The Server could not create heading image” appears. So, I think the script works in some way. But the replacement for the headers don`t work.

    Any idea?
    Thanks !

    Copy & paste the code below to embed this comment.
  161. This is an extension to Perry Johnson’s modifications which I find more convenient. This reduces the PHP script to just one, but needs to be modified everytime a new font is added.

    The PHP script has this in the beginning instead of the hard-coded values:

    $font_type = $_GET[‘font_type’];
    $font_size = $_GET[‘font_size’];
    $background_color = “#”.$_GET[‘background_color’];
    $font_color = “#”.$_GET[‘font_color’];

    switch ($font_type) {
      case “script”:
        $font_file = “myscriptfont.ttf”;
        break;
      case “solid”:
        $font_file = “mysolidfont.ttf”;
        break;
    }

    In replacement.js, replaced this code
    replaceSelector(“h2”,“heading.php”,true);

    to

    phpfile = ‘textrepl.php’;
    for (var i = 0; i < imageHeaders.length; i++) {
      replaceSelector(imageHeaders.selector,phpfile+’?f
    }

    the javascript in the main document will have this before the link to replacement.js:

        [removed]
          function imageHeader(selector,ftype,fsize,fcolor,fbgcolor,wordwrap){
            this.selector = selector;
            this.ftype = ftype;
            this.fsize = fsize;
            this.fcolor = fcolor;
            this.fbgcolor = fbgcolor;
            this.wordwrap = wordwrap;     
          }
          var imageHeaders = [
            new imageHeader(“h1”,“script”,“36”,“000000”,“FFFFFF”,true),
            new imageHeader(“h2”,“solid”,“14”,“000000”,“FFFFFF”,true),
          ]
        [removed]

    Copy & paste the code below to embed this comment.
  162. Now, in terms of the concern about security (or filling the cache with unwanted files), I have the following proposed solution: assign a password to your font types. This password would be appended or prepended to your text attributes and encrypted via md5.

    So the main document javascript would be modified to :
        [removed]
          function imageHeader(selector,ftype,fsize,fcolor,fbgcolor,wordwrap,passcode){
            this.selector = selector;
            this.ftype = ftype;
            this.fsize = fsize;
            this.fcolor = fcolor;
            this.fbgcolor = fbgcolor;
            this.wordwrap = wordwrap;     
            this.passcode = passcode;
          }
          var imageHeaders = [
            new imageHeader(“h1”,“script”,“36”,“000000”,“FFFFFF”,true,“6d198a2c629f38cdc6a96c4fcfabb357”),
            new imageHeader(“h2”,“solid”,“14”,“000000”,“FFFFFF”,true,“3d59fa35629f3h7f67a96c49cfabbab4”),
          ]
        [removed]

    accordingly, replacement.js will be modified to:
    phpfile = ‘textrepl.php’;
    for (var i = 0; i < imageHeaders.length; i++) {
      replaceSelector(imageHeaders.selector,phpfile+’?f
    }

    Now the following would be added to the php file :

    $passcodes = array(“script” => “foo1”, “solid” => “foo2”); //this could be saved in an external include file

    then add
    $pass = $_GET[‘pass’];

    $passhash = md5($passcodes[$font_type] . basename($font_file) . $font_size . $font_color .
          $background_color . $transparent_background . $text) ;

    if (!$pass || $pass !== $passhash) exit;

    Another php script with access restrictions could be created to determine what the passcode will be. Or if used in CMS, the passcode should be generated server-side and saved on the database.

    How easy would it be to crack this? Seems to work on my end. This method has a severe limitation, as that it will only work for wordwrap = false, because that setting does not break up the original string. Any suggestions?

    Copy & paste the code below to embed this comment.
  163. I just realized that the above security solution would require that every selector should match just one element, since the passcode is tied to that selector. Unless the texts are the same for each selector.

    Copy & paste the code below to embed this comment.
  164. i have different webspace on different servers. on one everything works just fine, on the other it doesn’t.
    it says “ERROR: The Server could not create this heading image”.

    phpinfo on that server says:
    PHP-version 4.3.1
    GD-support v.2

    any ideas?

    Copy & paste the code below to embed this comment.
  165. The last comment is yet another plea for help, because the script, standing alone, does not work.

    I wish to point out that someone yielded the solution above: Not only do you need PHP 4+ with GD 1.6 + installed, but the GD must also have Freetype support!

    So, if it is not working for you, use CPanel, the Terminal in Mac OS X, or whatever tool you need to recompile PHP with GD and Freetype support.

    Hopefully, that will solve things.

    Copy & paste the code below to embed this comment.
  166. thanks for your help, phpinfo came up with this:

    “GD Support
    enabled

    GD Version
    2.0 or higher

    FreeType Support
    enabled

    FreeType Linkage
    with freetype”

    you can see phpinfo here:
    http://boombap.net/phpinfo

    thanks in advance for any further help.

    Copy & paste the code below to embed this comment.
  167. I’m pritty new to css & w3c standards and the like…

    This stuff is amazing, some really talented people out there, i will definately be trying this method out on a few client sites..

    Thankyou..

    Copy & paste the code below to embed this comment.
  168. Well adding $DOCUMENT_ROOT. to the front of the font file bit eg $font_file=$DOCUMENT_ROOT.“font.ttf” ;
    gets rid of the “ERROR: The Server could not create this heading image”. error, but then another error “Error: The server is missing the specified font appears”

    Copy & paste the code below to embed this comment.
  169. Outstanding technique! I was thinking of using it for pull quotes in articles as well as in headlines, but ran across a question I haven’t seen asked anywhere else in the thread: Can multiple fonts be used in a single image?

    i.e., if I want to generate a small block of text where all elements are in #ABABAB Myriad Pro except for one or two words in #7B001A Myriad Black, then is there a way to map the <b> or <em> tag to that other font and color?

    Many thanks again for both the technique and any light you can shed on this question!

    Greg

    Copy & paste the code below to embed this comment.
  170. How hard would it be to adapt this technique to create static images for a web site that could be uploaded manually and magically drop into place, giving the same look, but having none of the dynamic caching issues to worry about?

    Copy & paste the code below to embed this comment.
  171. I am trying to use Perry Johnson’s modifications, it works fine in Firefox, but I am getting an error in IE “imageHeaders.selector in not an object”.
    Is anybody getting the same?

    Great script btw!

    Copy & paste the code below to embed this comment.
  172. typing error… doh

    Copy & paste the code below to embed this comment.
  173. Many thanks for this text! I didn’t know of this possibility and also I don’t have any use for it now I find this technique very interesting.

    Copy & paste the code below to embed this comment.
  174. What about using downloadable fonts? As far as I know, the @font-face {src: something;} declaration still works, and will download any truetype font from the server to use to render the page. Is this approach not recommended for some reason?

    Copy & paste the code below to embed this comment.
  175. Like someone mentioned way back there, you can use the HTTP_REFERER variable to supply dynamic text to your site only. I put this near the top of heading.php:

    if ( !isset($_SERVER[‘HTTP_REFERER’])
        || strpos($_SERVER[‘HTTP_REFERER’],
        DOMAIN_NAME) === false ) {

    header(‘HTTP/1.0 404 Not Found’);
    exit;
    }

    where DOMAIN_NAME is a constant defined elsewhere in an include (eg = www.mysite.net). Turn referrer logging off in Opera and you get no images, but I don’t know of any browsers that do this as standard; does anyone else know better?

    Also, this comes up with a blank page rather than a 404 Not Found page if I access it directly from any browser other than MSIE, is there any way to force the server to show its own 404 page for all browsers?

    Joel> I think only MS Internet Explorer understands downloadable fonts. You obviously haven’t read the previous 22 pages of discussion…

    Copy & paste the code below to embed this comment.
  176. I think the problem with this approach is that the http referer is supplied by the user agent. This means that a successful DoS attack is still possible by simply having the DoS program supply an http referer equal to what your script expects.

    Copy & paste the code below to embed this comment.
  177. Yes, that’s true. And if the pattern matching isn’t anchored to the left of the referrer string (as in my example above) it’s even easier because you can just add “?http://www.yourdtrsite.com” to the end of the referring site. It would probably deter an idle miscreant though.

    Copy & paste the code below to embed this comment.
  178. Really great little script.  Some advice culled from various places:

    use MS VOLT to convert TTF’s to Open format;
    place the TTF in the root of your webdir;
    HEADING.PHP: I had problems with the location of the TTF until I used this:
    $_SERVER[“DOCUMENT_ROOT”].’/thefont.ttf’ (don’t forget the slash in front of the font);

    Everything else works as advertised.  Great job!

    Copy & paste the code below to embed this comment.
  179. I am using this script on my webpage, and I set the cache directory to ‘cache’.

    I can’t seem to find a cache folder on my server with the images in them.  I tried specifying an absolute non-relative path, and that didn’t change anything.  I added some debugging code in there, so I’m sure that it’s always creating the image on the fly.  I tried removing all the @s to check for other errors that might be generated, and nothing.  It works perfectly, except that it doesn’t create any image files.

    The script lives at http://isaacschlueter.com/skins/isaac/_heading-side-sub-title.php?text=No2menR!(on fire)

    So, would the cached images be in
    http://isaacschlueter.com/skins/isaac/cache/
    or in
    http://isaacschlueter.com/cache/
    Or somewhere else entirely?

    Both folders exist and are chmoded 775.

    Any ideas out there in alaland?  Something I’m missing?  Thanks :)

    Copy & paste the code below to embed this comment.
  180. When viewing the demo, and also the site I am implementing this on, I notice that in the status bar of Mozilla, it never stops saying “Transferring data from www.lakewoodmidget.com…” – does anyone know why this is?

    Copy & paste the code below to embed this comment.
  181. Here’s how I got it to cache the images properly:
    1. Create a folder called “cache” which was in the same folder as the dtr php script.
    2. chmod that folder 777
    3. Set the $cache_folder = dirname(FILE).’/cache’;

    The load time goes down when it’s pulling a cached image, making the brief flash less noticeable.

    Copy & paste the code below to embed this comment.
  182. is this possible to accomplish with adobe type 1 fonts? (.PFB, .PFM)

    Copy & paste the code below to embed this comment.
  183. I had the same problem as Catherine, from 11 July 2004 @ 7:32am. When you change the font size, you have to recreate your header text, otherwise IE will stretch the image to the original height, even if you clear the cache, etc.

    Also, it is so slow to load, that in Netscape shows two broken image tags initially, which are then replaced by the images.

    I’m excited about this code, but with the 2nd problem especially I’m afraid to implement.

    Copy & paste the code below to embed this comment.
  184. Has anyone found a solution to the image display as an x-out on IE and displaying only the alternate text on mozilla?

    More info: The image creation is working great, it’s sitting there in the cache folder, and can be called by accessing the URL directly – mydomain.com/md5crypt_of_image.png

    But it won’t display when called directly from header.php on IE or Mozilla

    Have tried on a unix server and windows. When creating the image directly from the header.php script my local server is saying: The image “http://127.0.0.1/imagetest/header.php?text=test &selector=h2” cannot be displayed, because it contains errors

    But again the image is being created and stored in the cache folder.

    PHP v > 4.3
    GD2

    Anyone hit the same wall?

    Thanks!

    Copy & paste the code below to embed this comment.
  185. How is this method comparable to sIFR?

    Sorry if this question has already been addressed?

    Copy & paste the code below to embed this comment.
  186. Excellent article, tried implementing it on my own site today – went without a hitch. Looks fantastic too!

    Copy & paste the code below to embed this comment.
  187. Hi,

    A page with text replacement on it does not seem to finish loading when you view the page in Firefox 1.0 – you get the message “Transferring data from domainname” in the status bar rather than “Done”… is there anything that can be done to fix this?

    Works fine in IE

    James

    Copy & paste the code below to embed this comment.
  188. Fantastic stuff Stewart, thanks for sharing! Is there any way to adjust the wrapped line height (say, by vertically padding out the images). Also, this is probably a related issue, is there any way to refer to the images in the page by class or id so I could for example include or omit them from css img rules governing the rest of the page, could this be added to the js file? I know little of php or javascript so any assistance is much appreciated :-)

    Copy & paste the code below to embed this comment.
  189. I can’t seem to make this script work. I downloaded the complete script and saved it as h1.php (http://phpmor.ceep.dk/h1.php) and copied the font to the same folder, but it’s not working! Try for instance typing http://phpmor.ceep.dk/h1.php?text=hello, nothing.
    The only thing I’ve specified in the script is the first part

    $font_file = ‘absalom.ttf’ ;
    $font_size = 60 ;
    $font_color = ‘#000000’ ;
    $background_color = ‘#ffffff’ ;
    $transparent_background = true ;
    $cache_images = true ;
    $cache_folder = ‘cache’ ;

    Does anyone have an idea of what might be wrong?

    Thank you,

    Copy & paste the code below to embed this comment.
  190. Hi,
    I use alternate stylesheets on my site, and I’d like to use text replacement on only one specific alternate stylesheet.

    Anyone any idea, how this could be done?

    Copy & paste the code below to embed this comment.
  191. My box is linux rh 9
    I tried several fonts, including importing fonts from windows.

    Still cant settle the transformation from Hebrew text to images, only show as square images.

    Is there anyway I can get around this?
    Thanks

    Copy & paste the code below to embed this comment.
  192. See this page:

    http://www.whaleofadive.com/test.php

    DTR works as it should.

    Now let’s serve up the page as application/xhtml+xml thru the HTTP headers:

    if (isset($_SERVER[“HTTP_ACCEPT”]) && stristr($_SERVER[“HTTP_ACCEPT”], ‘application/xhtml+xml’)) {
    header(‘Content-Type: application/xhtml+xml; charset=ISO-8859-1’);
    }
    else {
    header(‘Content-Type: text/html; charset=ISO-8859-1’);
    }

    Look what we have:

    http://www.whaleofadive.com/test2.php

    If you’re using IE, you get the same result. But Firefox doesn’t display the transformed text in the second example. Is there a way around this?

    Copy & paste the code below to embed this comment.
  193. Found the fix for the problem mentioned above:

    http://www.experts-exchange.com/Web/Web_Languages/JavaScript/Q_20483232.html

    If you’re serving your pages as application/xhtml+xml, change [removed] as suggested (there are 2 instances in replacement.js) and you’re ok. Thing is, you’ll have to have two .js files – one for xhtml+xml (Firefox – the modified file) and the original replacement.js for MSIE. Heck, what’s PHP for, anyway?

    Copy & paste the code below to embed this comment.
  194. My ISP’s server has PHP 4.3.x, but I don’t know whether it has version 1.6 or higher of the the GD Graphics libarary. 

    heading.php passes the ImageCreate test, but goes no further than the call to ImageTTFBBox.

    Is this just an indication that I don’t have the right version of GD Graphics?  If so, shouldn’t this test be included at the beginning of heading.php?

    I have submitted an email to my ISP, but wondered if any of you know this answer.

    Your help is much appreciated.

    Copy & paste the code below to embed this comment.
  195. The script now works, re: Works, but not with the xhtml+xml MIME type. If anyone cares to know how (and why):

    http://www.whaleofadive.com/misc/dtr/

    Copy & paste the code below to embed this comment.
  196. Synergy> You can see your server’s GD library support with phpinfo(). It’s under “gd”.

    Copy & paste the code below to embed this comment.
  197. After my ISP told me that phpinfo() does not produce the correct results on the server my account is mounted on but that indeed the server the PHP runs on is 4.3.x and GD is 2.x and FreeType is enabled.

    Essentially, nothing appears on the screen (no error messages) and code stops after the call to @ImageTTFBBox.

    I am using the MIME types in the example here, sticking close to it until I see results. RegEx, is your code my solution?

    Also tried this possible solution from “matze”:
    change $font_file =“font.ttf” to
    $font_file=$DOCUMENT_ROOT.“font.ttf”
    When I substituted my font file this only resulted in the script not finding my font which it has been finding just fine.

    Also tried replacing
    $cache_folder = ‘cache’ ;
    with
    $cache_folder = dirname(FILE).’/cache’;
    as suggested on a PHP list.

    Helllp!

    Copy & paste the code below to embed this comment.
  198. my ISP told me that phpinfo() does not produce the correct results on the server my account is mounted on

    What the heck…?

    As for the MIME type, have you tried testing the script without sending HTTP headers or doing any browser sniffing, etc? Also, any chance you can give us a link to your test page?

    Copy & paste the code below to embed this comment.
  199. My demo is at:
    http://www.synprod.com/imagereplace/demo.html

    RegEx, I tool out the HTTP headers in demo.html as you suggested and I still don’t get the images.

    My only change to the Javascript file in Stewart’s example was to add:
    replaceSelector(“h1”,“heading.php”,true);
    since only “h2” was covered.

    “heading.php” is as in Stewart’s example.

    I made a few test changes to see if I could correct the problem, but restored all of them.

    As far as the phpinfo() goes, I can only offer this response from Speakeasy, my ISP:

    “Running phpinfo on grace [my server] will not give you the correct results. Our webcluster, where you go to upload your files, is simply a mount point on grace, grace is not the webserver. If you could run phpinfo from a web interface on our servers, that would give you accurate results.

    Our GD library does have FreeType enabled, and the version of PHP the webservers are using is 4.3.x.”

    Thanks for your help and for anyone else who might have a suggestion on how to proceed.

    Copy & paste the code below to embed this comment.
  200. Synergy, I think the script is working on your test page, except the images have the ‘text/html’ MIME type. Weird. Are you sure you left $mime-type in heading.php as image/png?

    Copy & paste the code below to embed this comment.
  201. I checked and I left my MIME type as image/png.

    Again, I appreciate your help with any suggestions that might break through this.

    RegEx (or anyone else), I would be happy to email my files if that might enable you to see directly what might be amiss.

    Copy & paste the code below to embed this comment.
  202. Or you can upload heading.php into your server as heading.txt. You can reach me by using the contact form at my site.

    Copy & paste the code below to embed this comment.
  203. Hey guys, do you mind addressing questions about implementation of DTR?  A wonk at b2evo suggested I give it a whirl because I want to display text in an Ancient Greek font complete with accents and other unusual diacritical marks.  So I followed the instructions and it ALMOST works—the swapout happens, and I get a PERFECT “alt” text, but the image doesn’t load—just an image placeholder, with a little bar for every character that should be there.  Any thoughts?

    Thanks.

    mikeyboy

    Copy & paste the code below to embed this comment.
  204. Ok, I hate not being able to figure things out for myself, so I read the article again—my server probably lacks support fot the GD graphics library.  I don’t yet even really know what that means—I’ve got their website open in another browser window right now to try to figure it out, and then I will go to my hosting service (the much-maligned Hostdime) and see what they have to say about GD graphics library support).

    Think I’m on the right track?

    Thanks again.

    mikeyboy

    Copy & paste the code below to embed this comment.
  205. I really liked this article and have found it really usefull. One problem I have found when putting it into practice is that the word spacing can not be controlled. Does anyone know how this could be done?

    Copy & paste the code below to embed this comment.
  206. Sorry for being rather remedial, but can anyone help with the syntax of using a class in the replaceSelector(“span”,“fontconvert.php”,true);
    line, i.e. if I want to replace only span class=“fancy” or something. Thanks.

    Copy & paste the code below to embed this comment.
  207. Use CSS selectors. For a span with class “fancy” use:

    replaceSelector(“span .fancy”,“fontconvert.php”,true);

    There’s a space between span and .fancy. I reccommend Eric Meyer’s “Cascading Style Sheets: the definitive guide” to you for learning about CSS. It’s a great reference on CSS 1 and 2.

    Copy & paste the code below to embed this comment.
  208. Thanks very much for the syntax help. I have the book you recommended, though more often I use Meyer’s CSS 2.0 Programmer’s Reference.

    Thanks again.

    Copy & paste the code below to embed this comment.
  209. I keep getting this error

    “Error: No Text Specified”

    I have the <h2> tags in my document to be replaced but it wont work. What am i missing?

    Copy & paste the code below to embed this comment.
  210. I found I had to write it withOUT the space for it to work.

    replaceSelector(“span.fancy”,“fontconvert.php”,true);

    Copy & paste the code below to embed this comment.
  211. This is a very interesting notion from my point of view, I am building a web site on obscure Fonts. I have tried to follow your (great) tutorial as closely as possible, but it didn’t work for me. Here is the page

    www.osop.org/textrep.htm

    Can any one tell from here whats going wrong???

    Thanks in advance John Maillard

    Copy & paste the code below to embed this comment.
  212. I really like this, and have used it on a site of mine…had one problem though:

    When I changed the text-size in the .php file and refreshed in IE, the image stayed the same size and the font went all pixely.  This doesn’t happen in Firefox.  This continued to happen after I deleted all my temporary internet files etc.

    Anyone else encounter this, or know whats happening?

    Copy & paste the code below to embed this comment.
  213. Great script. Discovered it only yesterday.
    First time I did something with PHP. Well.. did something… copied it and used other values. That’s it.
    It workes and I’m impressed.

    I had the idea to copy the fonts to a directory above root like common with databases. You don’t want to distribute your fonts. You just want to use them. So you don’t want the visitors to download them.

    For example you have the following 3 direcories on your ftp site.
    database – well it says it all
    www – the root directory of the website, here are the htm’s, asp’s, php’s and everything
    fonts – the font directory, available for the scripts but not for visitors of the site

    Is it easy to adjust the php script to use that dir? Should be, I guess, but I don’t know anything about php yet. 

    And is are there scripts online with all improvements discussed before included?
    I mean the security issues and easy maintanance improvements like just one php script instead of one for every variation.

    Marcel

    Copy & paste the code below to embed this comment.
  214. I managed to get a simple demo working in less than an hour. Pretty good for someone like me who’s just a hack at JavaScript and knows slightly more than zero about PHP.

    http://darrenwilson.com/test_tube/dynamic_text/

    I don’t know if it’s my font selection (I just used some freeware TTF fonts i had on my machine… most of my fonts are PostScript) but i’m experiencing some odd word spacing problems. Is this due to font selection or some other issue?

    Copy & paste the code below to embed this comment.
  215. congratulations for the article.

    Copy & paste the code below to embed this comment.
  216. After reading some of the previous discussion, i confirmed that the problem i’m experiencing with word spacing issues is entirely related to having word wrapping set to “true.” Turning off word wrapping makes everything space nicely.

    Has anybody come up with a solution that will allow word wrapping but preserve proper word spacing?

    Copy & paste the code below to embed this comment.
  217. Hi Stewart,
    I really appreciate your downtime – your earned it for that article alone >;o)

    Anyway I need help on this promising solution, maybe somebody else could have a look at my files.

    This is the problem:
    To call the script directly with
    http://www.crimeZZZ.net/demo/h1.php?text=eliZZZa
    works fine and produces the cache image.
    Called via the test page
    http://www.crimeZZZ.net/demo/demo.htm
    does not show anything and does not generate a cached image.
    The rest of the files named as in Stewart´s example.

    Up to now I checked the following:

    • Requested support from my provider – everything okay from his point
    • Tested in various browsers – same result

    I really don´t see the error – what am I missing???

    Great thanks for any help
    eliZZZa from Austria

    Copy & paste the code below to embed this comment.
  218. Hello Stewart, your script and your idea are absolutely awesome! A great way to make use of PHP’s powerful features.

    Unfortunately I was unable to make it work and since this (posting a comment here) seems to be the only way to get some kind of support (hopefully you’ll have a support forum at your new site) I thought I’d give it a try because I would really like to use it.

    I am using FireFox (Mozilla 1.7.3). My Apache server has PHP version 4.3.8 with GD enabled (it says version: bundled 2.0.23 compatible) and PNG support enabled. So I think I meet the requirements, don’t I?

    As far as settings I can’t see how I could have done anything wrong…

    I have looked at your on-line demo and copied your settings as a last try but I still don’t get anything.
    I have copied the test.png file to the same folder where the other files are and I have copied your entire replacement.js file to make sure it’s all the same as in your demo. I have named my PHP file h2.php and inside it I have set the path of the font to: ‘/home/username/domains/chaindlk.com/public_html/sources/text-replacement/JaggedDreams.ttf’
    (in this URL I have replaced my username with the word “username” for privacy). I know for sure that this is the correct path because:
    1. I have looked it up in the server’s documentation
    2. I have this path on a CGI file I am using and it works
    3. if I change the path your script gives me a “font missing” error, but with this path I simply don’t get anything at all

    I have also tried using absolute URLs (even though the articles instructs to use the path and not the url).

    As for fonts I have tried 5 different ones to make sure it wasn’t an issue with the font.
    I have tried:
    prefix.ttf
    lydianv.ttf
    JaggedDreams.ttf
    and then I thought of trying the OTF ones and went to http://freefonts.fateback.com where I have downloaded:
    JaggedDreams.otf
    JungleBurnout.otf

    Basically I don’t know what else to try.
    I have troubleshooted this as good as I could.

    Here is the link:
    http://www.chaindlk.com/sources/text-replacement/h2.php?text=test

    What else can I try?

    Also, if I ever get it to work (hopefully somebody will help me here) I have one question:
    is it safe to assume that on an apache server I can set $cache_folder to ‘var’ because (as far as I have read) that is Apache’s temporary files directory. If this is not correct and I leave it set to ‘cache’, would I have to create the directory inside the folder where all the files reside or would I need to create it in the root and give it a path (or an url)? Also would I need to chmod it to 777?

    I hope somebody will be able to answer my questions and make this gorgeous script work for me as well!

    Thanks

    Copy & paste the code below to embed this comment.
  219. I think I have figured out that this will NOT work unless the server has the TTF library support (FreeType library from freetype.org). Is this correct? Can somebody let me know? Thanks

    Copy & paste the code below to embed this comment.
  220. works great, but i have one big problem. when i work with text in tables the m$ internet explorer doesn´t makes a word warp.

    in firefox the word warp works, but there the script has problems with image generated numbers like “6.”

    outside of any tables, the word warp works also in ms ie…

    for example:
    http://www.joerg-wikinger.de/example.html

    Copy & paste the code below to embed this comment.
  221. The test.png was uploaded in wrong format (ASCII instead of binary) – that´s why it did not work.

    I am delighted by your solution!!!
    eliZZZa

    Copy & paste the code below to embed this comment.
  222. Trust me I understand, I use php and have for years so I talk till I’m blue in the face about how great it is, however the flipside to this coin is some companies are so M$ brainwashed that anything but asp or likewise technologies are shunned no matter how many advantages you can prove with your favorite language.  I’m a php programmer in the heart, but alas, my shop forces me to write asp to earn the paycheck…

    Copy & paste the code below to embed this comment.
  223. discovering this technique has really saved me a lot of time. I have been playing with it a bit today and am trying to find out if anyone has either of these two problems.
    1. I have several different span classes set to trigger the text replacement.
    for example-
    span.heading
    span.big
    etc.
    when I have checked the results in ie6 it only changes the first span.class it sees and the rest of them just come up as the normally formatted span.
    and
    2. in netscape 6 it does recognise every span.class listed and change to the new font but when the normally formatted span is viewed without the php/js links, it comes up with no space at all between words.
    the site in question is viewable at
    http://www.thepeartreeofbrookline.com
    thanks.

    Copy & paste the code below to embed this comment.
  224. Please help me get past “Error: The server could not create this heading image.”

    First off, here is the phpinfo:
    http://www.hai.org/imagereplace/info.php
    It seems to have all the FreeType support, GD version, etc. that is required.

    I am definitely passing the test of finding the font, but, since others who have had this problem have suggested it, I tried the following variations for $font_file:

    1. absolute address
    2. All the variations of document root addressing that have been mentioned in this discussion so far.

    The ONLY changes I have to the heading.php that Stuart provided is the name/location of the font and a font size of 36.

    I have traced the error to occurring with the call to @ImageTTFBBox but the discussions of that here have provided no answers.  Stuart?  Someone, please help.  I have spent way too much time on this without finding a solution.

    Copy & paste the code below to embed this comment.
  225. first i want say that this technique is great.

    i have a question about this:
    Stewart Rosenberger says at the the end of the article »… although getting rollovers to work would require more customization.«

    ist here any way to do rollovers? for examble to change the fontcolor on hover.

    would be perfect!

    Copy & paste the code below to embed this comment.
  226. Problem with this approach is that you can only use ttf fonts, not adobe fonts (I know this for a fact with ASP.NET and C#, and from what Ive gathered it is hard if not impossible to try to convert them to ttf; the software for that stuff is supposedely really expensive).

    I dont know about you guys, but all my fonts are adobe fonts.. You can use a similar approach with flash if you need more than just ttf fonts..

    The cool thing about using flash is that the swf is loaded once, then it can be used for your entire site since its cached.. The bad thing is that support for flash is sometimes questionable.. I go around this by just showing a crappy arial/tahoma/verdana H1-H6 heading whenever the user doesnt have it, and it works out fine.

    Check this link out… this is where I first saw it.

    http://sports.espn.go.com/nhl/news/story?id=1715637&partnersite=espn

    Here, look at the headline, its all in flash and the headline gets passed in as a querystring in the object/embedd tag.

    Copy & paste the code below to embed this comment.
  227. thank u for that nice script! :)

    Copy & paste the code below to embed this comment.
  228. Works like a charm but when navigating with browser buttons, dtr seems to replicate with no way of stopping… only on mac versions of IE 5.0+
    Anyone else getting/seeing this bug?

    Thanks.

    Copy & paste the code below to embed this comment.
  229. Sir, i just want a help from you that, could we make a text written on uppper side and lower side of image dynamically. If we insert a text from a textfiled called Upper side and other text from a textfield called “Lower side”. I want that the text enter in Upper side textfiled goes automatically at the upper side of image and same for lower side textfield , could it be possible from Javascript.

    Please look an example given at Url:
    http://www.ringcompany.com/designcenter.html


    Click on the right side image. Apopup will open.

    Insert username=amitk
    Password=weblink

    Click on saved design.

    Then click on the link “new1_25_11_04” provided below the link of “Design Name”


    This will show you the details of product. Click on next step.

    Click on Edit.

    This is the example of what i am taling about.

    Enter any text in Upper: or Lower textfields.

    This will show you on image at runtime.

    Please tell me that it is possible in PHP or Possible in Javascript.

    Early reply will be appreciated.

    I trust your site very much.

    Please reply soon.

    Copy & paste the code below to embed this comment.
  230. This caught my eye.

    After trying Shaun Inman’s IFR and injuring myself by the number of problems and lack of support, this script looks promising.

    But a few questions:
    1- How would I be able to get an image to occur in the output?
    (eg: a dotted line automatically to be inserted underneath the outputted image text)

    2- Can you change the case?
    (eg: Original text would be normal case, but final image should all be uppercase)

    If these problems can be ironed out then it would be a perfect script.

    Support welcome, Matthew.

    Copy & paste the code below to embed this comment.