Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations MikeeOK on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Dynamic client-side image creation 4

Status
Not open for further replies.
Dec 8, 2003
17,047
GB
A while ago, I found several resources about client-side dynamic image creation. I recently revisited these resources, and have spent a few minutes coming up with this small demo to illustrate the technique.

Browser support for this method is limited, unfortunately. Opera has no support for this method, IE will only support X-Bitmap creation, and NN has the best support - allowing dynamic creation of full-colour GIF images as well as X-Bitmap images. I didn't try JPG images, although I suspect NN may well support them, too.

Enough waffle... here's the code:

Code:
<html>
<head>
<script language=&quot;JavaScript&quot;>
<!--
	function hexToBinary(hexBytes)
	{
		var output = '';
		for (var loop=0; loop<hexBytes.length; loop+=2) output+=String.fromCharCode(eval('0x'+(hexBytes.substring(loop,loop+2)).toString(16)));
		return output;
	}

	var helloWorldGIF = '';
	helloWorldGIF += '47494638396164001400F7000000000008000010000010080018000018080018100021000021100821180029000029180831000031080031';
	helloWorldGIF += '10083118083900003910084208004218084A21105208005221105A08005A21106331186342086B4210730800732108732910733918735210';
	helloWorldGIF += '8400008442218C00008C42218C52189400009429109C08009C10089C31189C42219C6318A50000A50800A51008A54221A54A21AD0000AD10';
	helloWorldGIF += '08AD4A21AD6321AD7B18B54A21B55A29B56B21B56B29BD0000BD0800BD6329BD6B29BD7B21C60000C60800C64221C66331C67329C69C18CE';
	helloWorldGIF += '0000CE6B31D60000D60800D63918D65A29D66B31DE0800DE1808DE8429E70000E76331EF0000EF3118EF5229EF7B39EFBD18F73118F75229';
	helloWorldGIF += 'F75A29F77B39FF0000FF0800FF2110FF3118FF4A21FF5A29FF7331FF8439FF8442FF9439FFAD31FFBD29FFCE21FFDE18FFEF10FFFF08FFFF';
	helloWorldGIF += 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
	helloWorldGIF += 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
	helloWorldGIF += 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
	helloWorldGIF += 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
	helloWorldGIF += 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
	helloWorldGIF += 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
	helloWorldGIF += 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
	helloWorldGIF += 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C0000';
	helloWorldGIF += '0000640014000008FE00D5081C48B0A0C18308132A5CC8B061C23410234A9C48B1A2C58B18336ADC78118DC78F20438A1C49B2A4C9932853';
	helloWorldGIF += '963CC3B2254B002E5BC28C1973E6199B346326B0E2B20880222EAD20C84914A74B9B465D9A59CA742980A64C9F42852AD54CD5A95035D868';
	helloWorldGIF += '0AC20088A63634601D7BB569D5B24DCBA85DAB1600DBB56EDFBE8D5B86AEDCB72C36B035F0C300DB0D2CEE0AB6CB962E61B664122B4E0C60';
	helloWorldGIF += 'B1E2C689732C008040C7E3CB896B4C5E50C33199270814137940660111C50B9E64DEDC99B18F01A42193C9F1807209D9B23D8F192386B76F';
	helloWorldGIF += '00BB7B0B073E6608021CC5110CE14D5C0C711C067A8CE9717CB7EF3106AAECFE20628C880FBBABFE0CD88D638074EAD2C700C8A0E588FADD';
	helloWorldGIF += 'C697436FDEDCB7F030F8F3E307C0BF7F7FFC16AC901F0D14EC971F00F83D10437E3014A85F1816D0801F025184110502F8D18081166128C8';
	helloWorldGIF += 'A083002CC1611808422821872B9448E283FA81E1E28B2E0200E38B32823140162F5231408C34BA18001539063023182B7800861011B898C5';
	helloWorldGIF += '044264E1C10A3102E92215428251238F364A090615575E39E4176086092600628649E617FEF537A6996B8A79A6984A38F085072784798207';
	helloWorldGIF += '5F38A0449B6CA2E9269F7CBE59E6175E146A68A1001C6A68A25E147085A2882E5AA80053183A8500905E41E90195163A4501971A4AA9A598';
	helloWorldGIF += '7AC168A45E0CD0A917579C7A2AA4FE5DC42A6BAC00CC2A6BAD5D5CF082AC4E2040EBADB14AB06BAC2944606BAC15702081AD12705081ACC2';
	helloWorldGIF += 'CA5AECAFC0E69A82AC33E0DA85B6C772E1EDB7DE0200EEB7E2729144013C98DB800BE192EB2D0FE872C10301E98ECBC50801A430EE0B018C';
	helloWorldGIF += 'F02DBCE9CE5B6FB9ED9A7BC00C5C045100C1F682BB85140F7301B114003C1C31C415432C8302001030C2C4196F11720B0700A0400B164F2C';
	helloWorldGIF += 'B111014091F2165004608414126F41B2C928639C72C83B40D0B10921675C33CD104361F4D14827ADF4D24C37EDF4D35047DDB411481861F5';
	helloWorldGIF += 'D55867ADB5D5556FEDF5D760872DF6D857EF60F60E40989D36DA6AB7CDF6DB67AF2DB7DB73BF5DF7DD74E76DB73BDE78BFDDC2DF2D98F0B7';
	helloWorldGIF += 'E0810F6E78E188034EF8E287338EB8E390372EF9E393478E7808217080F9E69C77EE39E69A7F2EFAE8A4976EFAE99B0704003B';
	helloWorldGIF = hexToBinary(helloWorldGIF);

	var helloWorldXBM = '';
	helloWorldXBM += '#define image_width 100\n';
	helloWorldXBM += '#define image_height 20\n';
	helloWorldXBM += 'static char image_bits[] = { ';
	helloWorldXBM += '0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,';
	helloWorldXBM += '0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x01,0x01,0x20,0x01,';
	helloWorldXBM += '0x80,0x40,0x20,0x00,0x20,0x40,0x04,0xf0,0x00,0x01,0x01,0x20,0x01,0x80,0xa0,0x20,0x00,0x20,0x40,0x04,0xf0,0x00,';
	helloWorldXBM += '0x01,0x01,0x20,0x01,0x00,0xa1,0x10,0x00,0x20,0x40,0x04,0xf0,0x00,0x01,0xe1,0x20,0xe1,0x00,0xa1,0x10,0x0e,0x2d,';
	helloWorldXBM += '0x5c,0x04,0xf0,0x00,0x01,0x11,0x21,0x11,0x01,0x11,0x11,0x11,0x23,0x62,0x04,0xf0,0x00,0xff,0x09,0x22,0x09,0x02,';
	helloWorldXBM += '0x11,0x91,0x20,0x21,0x41,0x04,0xf0,0x00,0x01,0x09,0x22,0x09,0x02,0x12,0x89,0x20,0x21,0x41,0x04,0xf0,0x00,0x01,';
	helloWorldXBM += '0xf9,0x23,0x09,0x02,0x0a,0x8a,0x20,0x21,0x41,0x04,0xf0,0x00,0x01,0x09,0x20,0x09,0x02,0x0a,0x8a,0x20,0x21,0x41,';
	helloWorldXBM += '0x04,0xf0,0x00,0x01,0x09,0x22,0x09,0x02,0x0a,0x8a,0x20,0x21,0x41,0x04,0xf0,0x00,0x01,0x11,0x21,0x11,0x01,0x04,';
	helloWorldXBM += '0x04,0x11,0x21,0x62,0x00,0xf0,0x00,0x01,0xe1,0x20,0xe1,0x00,0x04,0x04,0x0e,0x21,0x5c,0x04,0xf0,0x00,0x00,0x00,';
	helloWorldXBM += '0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,';
	helloWorldXBM += '0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,';
	helloWorldXBM += '0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0';
	helloWorldXBM += ' };';
//-->
</script>
</head>

<body>
	GIF:<img src=&quot;javascript:helloWorldGIF;&quot; width=&quot;100&quot; height=&quot;20&quot;><br><br>
	XBitmap: <img src=&quot;javascript:helloWorldXBM;&quot; width=&quot;100&quot; height=&quot;20&quot;>
</body>
</html>

The data for the GIF image is the hex data you'd find if you viewed the image in any hex viewer program, such as WinHex. This is then converted to binary using the hexToBinarty function.

The data for the X-Bitmap image is plain text - this is what you would see if you viewed an X-Bitmap file in a hex viewer.

Incidentally, I found a page that used this technique to great effect - the Wolfenstein 5K game ( )... It's a small JavaScript version of Wolfenstein, will all images created dynamically client-side - in less than 5K. Pretty impressive!

Hope someone finds a use for these techniques.

Dan
 
that's insane! can you write a tutorial on how to speak GIF?



=========================================================
-jeff
try { succeed(); } catch(E) { tryAgain(); }
 
Tom,

Thanks for the feedback.

I do see a useful application, as it happens (one that hopefully I'll be posting in its completed state here in a few days or so)... I'm looking at creating a demo that can be downloaded as a single HTML file. If I use these embedded images, I don't have to worry about the user downloading extra things, etc.

I'm sure a top tipper such as yourself could also come up with some uses for such code.

Dan
 
Dan...

Great job on illustrating this technique. I will certainly be taking some of this code for use myself.

Tom...

Great job on putting someone off writing tips for others to learn from.

To answer your immediate question of whether I see any other applications for this. Of course...

I could use it to supply a logo on my html document that is emailed around (within the corporate intranet) - allowing users to print off the page without losing the corporate logo. We use IE for windows so it's perfect for that.

I could use it to build up an authentication number/word to activate your account when you sign up to my member only web site.

I could use it to avoid needing screen &quot;furniture&quot; images (as we currently use on our intranet to add bevelled corners to our floating &quot;pods&quot; of information).

I could use it to create inline &quot;special characters&quot; without the need for the user to download and install special language packs (again perfect for our intranet users who span the globe).

I could use it to generate &quot;on the fly&quot; bar codes (so a DB need only store the product number) - allowing the user to print barcodes as part of their intranet management system. For those interested... here is a URL that offers just such a solution using the very same technologies that Dan has described for us:
I think you need to step down off your high horse and reflect upon the nature of Dan's post. It is a learning tool... and people will learn from it.

Nobody said that it was the &quot;only&quot; way to do the job... and given it is browser specific I think we all accept that it falls into the realm of a specialist solution.

I do take offence to your comment: lowly types might try to use it to get around browsers that turn off images. For that reason I have flagged your followup as inappropriate and hope that the management look into this as a matter of course.

Regards,
Jeff

PS: If images are turned off on the browser, then they will not be loaded... regardless of whether you use this XBM format and Dan's illustrated solution.
 
There's also my goofy way of drawing using a virtual sketchpad:
faq216-3516

It's not the same as busting open the GIF standard -- more like an old-fashioned graphics display using RGB colors. Neat trick busting the GIF format open, though. Hm, isn't that supposed to be proprietary intel?

Cheers,


[monkey] Edward [monkey]

&quot;Cut a hole in the door. Hang a flap. Criminy, why didn't I think of this earlier?!&quot; -- inventor of the cat door
 
Very interesting technique, Dan. A star for you. It makes me want to delve deeper into JavaScript as I rarely us it now.

I like your ideas, BabyJeffy, especially the bar code one.

 
Great job on putting someone off writing tips for others to learn from.

My intent is not to &quot;put off&quot;, but to question why. I've seen this stuff before, and people's reaction is always something along the lines of, &quot;that's so cool, it'll revolutionize everything I do!&quot; In reality, it doesn't do much. I just wanted to put that in perspective. If you have a really useful application of this technique I'd love to hear it. The reality is that things like Wolf5k and the JavaScript Clock which Adam posted are mental masturbation for geeks rather than the best way to accomplish such things.

I could use it to supply a logo on my html document that is emailed around (within the corporate intranet) - allowing users to print off the page without losing the corporate logo. We use IE for windows so it's perfect for that.

As opposed to PDF, Word, or other available formats? As opposed to just posting the HTML on your intranet, with images linked in normal web fashion? This seems like a stretch to me, to be done just for the geek factor rather than usefulness.

I could use it to build up an authentication number/word to activate your account when you sign up to my member only web site.

Client-side authentication? Smart. I suppose you rely on client-side validation and sanitizing as well?

I could use it to avoid needing screen &quot;furniture&quot; images (as we currently use on our intranet to add bevelled corners to our floating &quot;pods&quot; of information).

Either way, you'll have to modify GIF/JPG images in a seperate image program. Using this technique, you'll then have to cut up the source and paste it in your code. Far simpler to just save the file and link it. XBM format is monochrome remember, so any dynamically generated corners will not be &quot;bevelled&quot; or have any other features besides black and white pixels. This is unless your browser of choice supports XPM format as well, but most don't.

I could use it to create inline &quot;special characters&quot; without the need for the user to download and install special language packs (again perfect for our intranet users who span the globe).

You can use CSS for that. Using JavaScript and XBM would first of all be lots of code, and the result would be an uncompressed format which would use entirely too much memory. Inefficient and not very useful considering the excellent alternatives.

I could use it to generate &quot;on the fly&quot; bar codes (so a DB need only store the product number)

Not widely applicable, but a fair example nonetheless. However, you can accomplish the same thing with server-side code using ImageMagick, etc., or even with one-pixel black and white images resized using JavaScript client-side. Still, you could possibly make the case for generating an XBM here maybe, though it is most likely not the most efficient way. Remember, the XBM is uncompressed whereas ImageMagick can generate compressed PNGs.

I think you need to step down off your high horse and reflect upon the nature of Dan's post. It is a learning tool... and people will learn from it.

I think you need to step off yours. I simply presented a counter point so that people will think twice before wasting their time implementing something which is the wrong approach to most problems they may try to apply it to. Case in point -- creating a library of inline special characters. Unless you're trying to win the 5k contest, it's only a fun fact, not a terribly useful feature.

I do take offence to your comment: lowly types might try to use it to get around browsers that turn off images. For that reason I have flagged your followup as inappropriate and hope that the management look into this as a matter of course.

I meant that it would probably be most useful to spammers (in which category I include web advertisements, etc), which are often blocked by various third-party programs and browser features because nearly everyone considers such techniques &quot;low&quot; and purveyors of such techniques &quot;low-life's&quot;, some of which may or may not be effected by this dynamic image technique. If you took offense it's because you misunderstood me or because you are in fact one of those people. I can't believe you red-flagged that.

Let's have some balance in our discussions and not reflexively jump on a band-wagon and flame everyone with a different opinion. I appreciate Dan's post about dynamic images, but simply want to point out the downside to such a technique as well. Let's face it -- it's almost universally inapplicable except for the geek factor. I think it's cool because I'm a geek like you. Just don't waste your company time trying to implement something using it. This is afterall a &quot;technical work forum for computer professionals&quot;. If you're going to post hobbyist code, you should say so.

Sincerely,

Tom Anderson
Order amid Chaos, Inc.
 
Gee, Tom... don't try so hard to make friends! If you have a better way to do things, then do it. Post your suggestion if you want, but don't stiffle other people's creative process by telling them it's crap.

You say your 'intent is not to &quot;put off&quot;'. If that's true, then I guess I should ignore your comment that it's &quot;mental masterbation for geeks&quot;. Maybe you're right, but unlike you I still have both hands on the keyboard.

Adam
while(ignorance==true){perpetuate(violence,fear,hatred);life--};
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top