Email conversation
From | Bill Aitken |
To | Me |
Subject | Dynamically create an image in javaScript |
Date | 2 May 2009 13:37 |
Hi Tarquin,
I'm an experienced programmer but fairly new to javaScript and I've noticed
your name cropiing up here and there as I Google for hints and tips during
the learning process. I have been able to a lot of what I want to do by this
means but I am a bit stuck now and wanted to see if you could shed any light
on what I propose to do.
I am building my first HTAs and I would really like to be able to declare a
new image as though I was about to preload it but, instead of pointing to a
file location, I would like to be able to create the image in code. There
are a number of reasons for this which I won't bore you with but it would
make my life a whole lot easier (and improve my Karma in general), if you
could say whether this is possible (I think that this wil be the case - I
could do it in two or three other languages but I don't think JS has the
functionality) or not.
Bearing in mind the caveats on your "contact me" page, I hope to hear from
you soon.
Bill
From | Me |
To | Bill Aitken |
Subject | Re: Dynamically create an image in javaScript |
Date | 3 May 2009 08:44 |
Bill,
> declare a new image as though I was about to preload it but, instead
> of pointing to a file location, I would like to be able to create the
> image in code.
There are a couple of ways of doing this, but both are subject to
browser limitations.
The first and most obvious approach is to create the image data in a
string (for example the data for a PNG image). Then use
encodeURIComponent on it and prepend the appropriate protocol
information and MIME type to make it a valid data: URI:
"data:image/png,image%20data%20goes%20here"
This can then be used as the .src of an image. However, IE only added
support for it in version 8 (and has a limit of just 32 KB), so if you
need support for earlier versions, it's not viable.
Another approach is to use a JavaScript URL as the SRC, where the return
value from the executed script is the image data:
var imagedata = "image data goes here";
image.src = 'javascript:imagedata';
However, this is not possible in most browsers, as it is a common XSS
attack vector, and is prohibited as a security precaution.
I was wondering if HTML 5 canvas might offer an alternative, but it
doesn't seem it can load image data directly (and it wouldn't work at
all in IE, since it does not support canvas). Looks like the above two
approaches are the only ones. Maybe I missed something, but in all cases
I could find, people were using the data: URI approach.
For what it's worth, canvas will probably provide the overall
functionality you are looking for - rendering an image based on data
created from JavaScript, but it wouldn't be done as a regular "new
Image()", and instead needs the data to be manipulated with the canvas API:
http://www.w3.org/TR/html5/the-canvas-element.html#the-canvas-element
SVG could also allow you to manipulate image vector information using
SVGDOM, and display that (use createElementNS to create SVG elements,
manipulate them with SVGDOM, and append the resulting SVG root element
to the document). However, IE and Konqueror also do not natively support
SVG. Both rely on plugins to provide that functionality, and you are
then at the mercy of whatever plugins the user does or does not have
installed, and can only use SVG images embedded initially in the
document as an <object>.
Data: URIs are currently your best bet, but you will have to drop IE 7
and earlier. For future use, canvas is probably the answer.
Mark 'Tarquin' Wilton-Jones - author of http://www.howtocreate.co.uk/
From | Bill Aitken |
To | Me |
Subject | Re: Dynamically create an image in javaScript |
Date | 3 May 2009 16:00 |
Tarquin,
Many thanks for such a speedy and comprehensive answer. In fact, I am
building an HTA, so what I have successfully tested is to take the image (a
gif in this instance) and convert it with a utility "what I wrote" to
convert it into a stream of 2-character hex strings. This, I embedded in my
javascript as a var and then used a script to turn it back into bytes and
save it to a local file which is then loaded as per normal. I just wanted
to avoid having to save it anywhere. The URI approach might just be the
thing.
Thank you again for your time. Have a great weekend.
Bill